t1 / TFDContents / Assets / KinectScripts / VisualGestureManager.cs @ 9
이력 | 보기 | 이력해설 | 다운로드 (23.5 KB)
| 1 |
using UnityEngine; |
|---|---|
| 2 |
using System; |
| 3 |
using System.Collections; |
| 4 |
using System.Collections.Generic; |
| 5 |
using System.IO; |
| 6 |
using System.Text; |
| 7 |
#if !(UNITY_WSA_10_0 && NETFX_CORE) |
| 8 |
using Microsoft.Kinect.VisualGestureBuilder; |
| 9 |
using Windows.Kinect; |
| 10 |
#endif |
| 11 |
|
| 12 |
/// <summary> |
| 13 |
/// This interface needs to be implemented by all visual gesture listeners |
| 14 |
/// </summary> |
| 15 |
public interface VisualGestureListenerInterface |
| 16 |
{
|
| 17 |
/// <summary> |
| 18 |
/// Invoked when a continuous gesture reports progress >= minConfidence |
| 19 |
/// </summary> |
| 20 |
/// <param name="userId">User ID</param> |
| 21 |
/// <param name="userIndex">User index</param> |
| 22 |
/// <param name="gesture">Gesture name</param> |
| 23 |
/// <param name="progress">Gesture progress [0..1]</param> |
| 24 |
void GestureInProgress(long userId, int userIndex, string gesture, float progress); |
| 25 |
|
| 26 |
/// <summary> |
| 27 |
/// Invoked when a discrete gesture is completed. |
| 28 |
/// </summary> |
| 29 |
/// <returns><c>true</c>, if the gesture detection must be restarted, <c>false</c> otherwise.</returns> |
| 30 |
/// <param name="userId">User ID</param> |
| 31 |
/// <param name="userIndex">User index</param> |
| 32 |
/// <param name="gesture">Gesture name</param> |
| 33 |
/// <param name="confidence">Gesture confidence [0..1]</param> |
| 34 |
bool GestureCompleted(long userId, int userIndex, string gesture, float confidence); |
| 35 |
} |
| 36 |
|
| 37 |
/// <summary> |
| 38 |
/// Visual gesture data container. |
| 39 |
/// </summary> |
| 40 |
public struct VisualGestureData |
| 41 |
{
|
| 42 |
public long userId; |
| 43 |
public float timestamp; |
| 44 |
public string gestureName; |
| 45 |
public bool isDiscrete; |
| 46 |
public bool isContinuous; |
| 47 |
public bool isComplete; |
| 48 |
//public bool isResetting; |
| 49 |
public bool isProcessed; |
| 50 |
public float confidence; |
| 51 |
public float progress; |
| 52 |
public float lastTimestamp; |
| 53 |
} |
| 54 |
|
| 55 |
/// <summary> |
| 56 |
/// Visual gesture manager is the component that manages the visual (VGB) gestures. |
| 57 |
/// </summary> |
| 58 |
public class VisualGestureManager : MonoBehaviour |
| 59 |
{
|
| 60 |
[Tooltip("Index of the player, tracked by this component. 0 means the 1st player, 1 - the 2nd one, 2 - the 3rd one, etc.")]
|
| 61 |
public int playerIndex = 0; |
| 62 |
|
| 63 |
[Tooltip("File name of the VG database, used by the visual gesture recognizer. The file will be copied from Resources, if does not exist.")]
|
| 64 |
public string gestureDatabase = string.Empty; |
| 65 |
|
| 66 |
[Tooltip("List of the tracked visual gestures. If left empty, all gestures found in the database will be tracked.")]
|
| 67 |
public List<string> gestureNames = new List<string>(); |
| 68 |
|
| 69 |
[Tooltip("Minimum confidence required, to consider discrete gestures as completed. Confidence varies between 0.0 and 1.0.")]
|
| 70 |
public float minConfidence = 0.1f; |
| 71 |
|
| 72 |
[Tooltip("List of the visual gesture listeners in the scene. If the list is empty, the available gesture listeners will be detected at the scene start up.")]
|
| 73 |
public List<MonoBehaviour> visualGestureListeners; |
| 74 |
|
| 75 |
[Tooltip("GUI-Text to display the VG-manager debug messages.")]
|
| 76 |
public GUIText debugText; |
| 77 |
|
| 78 |
|
| 79 |
// primary user ID, as reported by KinectManager |
| 80 |
private long primaryUserID = 0; |
| 81 |
|
| 82 |
// gesture data holders for each tracked gesture |
| 83 |
private Dictionary<string, VisualGestureData> gestureData = new Dictionary<string, VisualGestureData>(); |
| 84 |
|
| 85 |
#if !(UNITY_WSA_10_0 && NETFX_CORE) |
| 86 |
|
| 87 |
// gesture frame source which should be tied to a body tracking ID |
| 88 |
private VisualGestureBuilderFrameSource vgbFrameSource = null; |
| 89 |
|
| 90 |
// gesture frame reader which will handle gesture events |
| 91 |
private VisualGestureBuilderFrameReader vgbFrameReader = null; |
| 92 |
|
| 93 |
#endif |
| 94 |
|
| 95 |
// primary sensor data structure |
| 96 |
//private KinectInterop.SensorData sensorData = null; |
| 97 |
|
| 98 |
// Bool to keep track of whether visual-gesture system has been initialized |
| 99 |
private bool isVisualGestureInitialized = false; |
| 100 |
|
| 101 |
// The single instance of VisualGestureManager |
| 102 |
private static VisualGestureManager instance; |
| 103 |
|
| 104 |
|
| 105 |
/// <summary> |
| 106 |
/// Gets the single VisualGestureManager instance. |
| 107 |
/// </summary> |
| 108 |
/// <value>The VisualGestureManager instance.</value> |
| 109 |
public static VisualGestureManager Instance |
| 110 |
{
|
| 111 |
get |
| 112 |
{
|
| 113 |
return instance; |
| 114 |
} |
| 115 |
} |
| 116 |
|
| 117 |
/// <summary> |
| 118 |
/// Determines whether the visual-gesture manager was successfully initialized. |
| 119 |
/// </summary> |
| 120 |
/// <returns><c>true</c> if visual-gesture manager was successfully initialized; otherwise, <c>false</c>.</returns> |
| 121 |
public bool IsVisualGestureInitialized() |
| 122 |
{
|
| 123 |
return isVisualGestureInitialized; |
| 124 |
} |
| 125 |
|
| 126 |
/// <summary> |
| 127 |
/// Gets the skeleton ID of the tracked user, or 0 if no user was associated with the gestures. |
| 128 |
/// </summary> |
| 129 |
/// <returns>The skeleton ID of the tracked user.</returns> |
| 130 |
public long GetTrackedUserID() |
| 131 |
{
|
| 132 |
return primaryUserID; |
| 133 |
} |
| 134 |
|
| 135 |
/// <summary> |
| 136 |
/// Gets the list of detected gestures. |
| 137 |
/// </summary> |
| 138 |
/// <returns>The list of detected gestures.</returns> |
| 139 |
public List<string> GetGesturesList() |
| 140 |
{
|
| 141 |
return gestureNames; |
| 142 |
} |
| 143 |
|
| 144 |
/// <summary> |
| 145 |
/// Gets the count of detected gestures. |
| 146 |
/// </summary> |
| 147 |
/// <returns>The count of detected gestures.</returns> |
| 148 |
public int GetGesturesCount() |
| 149 |
{
|
| 150 |
return gestureNames.Count; |
| 151 |
} |
| 152 |
|
| 153 |
/// <summary> |
| 154 |
/// Gets the gesture name at specified index, or empty string if the index is out of range. |
| 155 |
/// </summary> |
| 156 |
/// <returns>The gesture name at specified index.</returns> |
| 157 |
/// <param name="i">The index</param> |
| 158 |
public string GetGestureAtIndex(int i) |
| 159 |
{
|
| 160 |
if(i >= 0 && i < gestureNames.Count) |
| 161 |
{
|
| 162 |
return gestureNames[i]; |
| 163 |
} |
| 164 |
|
| 165 |
return string.Empty; |
| 166 |
} |
| 167 |
|
| 168 |
/// <summary> |
| 169 |
/// Determines whether the given gesture is in the list of detected gestures. |
| 170 |
/// </summary> |
| 171 |
/// <returns><c>true</c> if the given gesture is in the list of detected gestures; otherwise, <c>false</c>.</returns> |
| 172 |
/// <param name="gestureName">Gesture name.</param> |
| 173 |
public bool IsTrackingGesture(string gestureName) |
| 174 |
{
|
| 175 |
return gestureNames.Contains(gestureName); |
| 176 |
} |
| 177 |
|
| 178 |
/// <summary> |
| 179 |
/// Determines whether the specified discrete gesture is completed. |
| 180 |
/// </summary> |
| 181 |
/// <returns><c>true</c> if the specified discrete gesture is completed; otherwise, <c>false</c>.</returns> |
| 182 |
/// <param name="gestureName">Gesture name</param> |
| 183 |
/// <param name="bResetOnComplete">If set to <c>true</c>, resets the gesture state.</param> |
| 184 |
public bool IsGestureCompleted(string gestureName, bool bResetOnComplete) |
| 185 |
{
|
| 186 |
if(gestureNames.Contains(gestureName)) |
| 187 |
{
|
| 188 |
VisualGestureData data = gestureData[gestureName]; |
| 189 |
|
| 190 |
if(data.userId != 0 && data.isDiscrete && data.isComplete && /**!data.isProcessed &&*/ data.confidence >= minConfidence) |
| 191 |
{
|
| 192 |
if(bResetOnComplete) |
| 193 |
{
|
| 194 |
//data.isResetting = true; |
| 195 |
data.isProcessed = true; |
| 196 |
gestureData[gestureName] = data; |
| 197 |
} |
| 198 |
|
| 199 |
return true; |
| 200 |
} |
| 201 |
} |
| 202 |
|
| 203 |
return false; |
| 204 |
} |
| 205 |
|
| 206 |
/// <summary> |
| 207 |
/// Gets the confidence of the specified discrete gesture, in range [0, 1]. |
| 208 |
/// </summary> |
| 209 |
/// <returns>The gesture confidence.</returns> |
| 210 |
/// <param name="gestureName">Gesture name</param> |
| 211 |
public float GetGestureConfidence(string gestureName) |
| 212 |
{
|
| 213 |
if(gestureNames.Contains(gestureName)) |
| 214 |
{
|
| 215 |
VisualGestureData data = gestureData[gestureName]; |
| 216 |
|
| 217 |
if(data.userId != 0 && data.isDiscrete) |
| 218 |
{
|
| 219 |
return data.confidence; |
| 220 |
} |
| 221 |
} |
| 222 |
|
| 223 |
return 0f; |
| 224 |
} |
| 225 |
|
| 226 |
/// <summary> |
| 227 |
/// Gets the progress of the specified continuous gesture, in range [0, 1]. |
| 228 |
/// </summary> |
| 229 |
/// <returns>The gesture progress.</returns> |
| 230 |
/// <param name="gestureName">Gesture name</param> |
| 231 |
public float GetGestureProgress(string gestureName) |
| 232 |
{
|
| 233 |
if(gestureNames.Contains(gestureName)) |
| 234 |
{
|
| 235 |
VisualGestureData data = gestureData[gestureName]; |
| 236 |
|
| 237 |
if(data.userId != 0 && data.isContinuous) |
| 238 |
{
|
| 239 |
return data.progress; |
| 240 |
} |
| 241 |
} |
| 242 |
|
| 243 |
return 0f; |
| 244 |
} |
| 245 |
|
| 246 |
/// <summary> |
| 247 |
/// Resets the gesture state. |
| 248 |
/// </summary> |
| 249 |
/// <returns><c>true</c>, if gesture state was reset, <c>false</c> if gesture was not found.</returns> |
| 250 |
/// <param name="gestureName">Gesture name.</param> |
| 251 |
public bool ResetGesture(string gestureName) |
| 252 |
{
|
| 253 |
if(gestureNames.Contains(gestureName)) |
| 254 |
{
|
| 255 |
VisualGestureData data = gestureData[gestureName]; |
| 256 |
|
| 257 |
//data.isResetting = true; |
| 258 |
data.isProcessed = true; |
| 259 |
gestureData[gestureName] = data; |
| 260 |
|
| 261 |
return true; |
| 262 |
} |
| 263 |
|
| 264 |
return false; |
| 265 |
} |
| 266 |
|
| 267 |
|
| 268 |
// gets all gesture dara as csv line |
| 269 |
public string GetGestureDataAsCsv(char delimiter) |
| 270 |
{
|
| 271 |
if (!isVisualGestureInitialized) |
| 272 |
return string.Empty; |
| 273 |
|
| 274 |
// create the output string |
| 275 |
StringBuilder sbBuf = new StringBuilder(); |
| 276 |
//const char delimiter = ','; |
| 277 |
|
| 278 |
sbBuf.Append("vg").Append(delimiter);
|
| 279 |
sbBuf.Append(gestureNames.Count).Append(delimiter); |
| 280 |
|
| 281 |
foreach (string gestureName in gestureNames) |
| 282 |
{
|
| 283 |
VisualGestureData data = gestureData[gestureName]; |
| 284 |
|
| 285 |
if (data.userId != 0 && data.lastTimestamp != data.timestamp) |
| 286 |
{
|
| 287 |
sbBuf.Append(data.userId).Append(delimiter); |
| 288 |
sbBuf.AppendFormat("{0:F3}", data.timestamp).Append(delimiter);
|
| 289 |
sbBuf.Append(data.gestureName).Append(delimiter); |
| 290 |
sbBuf.Append(data.isDiscrete ? 1 : 0).Append(delimiter); |
| 291 |
sbBuf.Append(data.isContinuous ? 1 : 0).Append(delimiter); |
| 292 |
sbBuf.Append(data.isComplete ? 1 : 0).Append(delimiter); |
| 293 |
sbBuf.AppendFormat("{0:F3}", data.confidence).Append(delimiter);
|
| 294 |
sbBuf.AppendFormat("{0:F3}", data.progress).Append(delimiter);
|
| 295 |
|
| 296 |
data.lastTimestamp = data.timestamp; |
| 297 |
|
| 298 |
gestureData[gestureName] = data; |
| 299 |
} |
| 300 |
else |
| 301 |
{
|
| 302 |
sbBuf.Append(0).Append(delimiter); |
| 303 |
} |
| 304 |
} |
| 305 |
|
| 306 |
// remove the last delimiter |
| 307 |
if(sbBuf.Length > 0 && sbBuf[sbBuf.Length - 1] == delimiter) |
| 308 |
{
|
| 309 |
sbBuf.Remove(sbBuf.Length - 1, 1); |
| 310 |
} |
| 311 |
|
| 312 |
return sbBuf.ToString(); |
| 313 |
} |
| 314 |
|
| 315 |
// sets gesture data arrays from a csv line |
| 316 |
public bool SetGestureDataFromCsv(string sCsvLine, char[] delimiters) |
| 317 |
{
|
| 318 |
if(sCsvLine.Length == 0) |
| 319 |
return false; |
| 320 |
|
| 321 |
// split the csv line in parts |
| 322 |
//char[] delimiters = { ',' };
|
| 323 |
string[] alCsvParts = sCsvLine.Split(delimiters); |
| 324 |
|
| 325 |
if(alCsvParts.Length < 1 || alCsvParts[0] != "vg") |
| 326 |
return false; |
| 327 |
|
| 328 |
int iIndex = 1; |
| 329 |
int iLength = alCsvParts.Length; |
| 330 |
|
| 331 |
if (iLength < (iIndex + 1)) |
| 332 |
return false; |
| 333 |
|
| 334 |
// number of gestures |
| 335 |
int gestureCount = 0; |
| 336 |
int.TryParse(alCsvParts[iIndex], out gestureCount); |
| 337 |
iIndex++; |
| 338 |
|
| 339 |
if (gestureCount > 0) |
| 340 |
{
|
| 341 |
for (int i = 0; i < gestureCount && iLength >= (iIndex + 1); i++) |
| 342 |
{
|
| 343 |
long userId = 0; |
| 344 |
long.TryParse(alCsvParts[iIndex], out userId); |
| 345 |
iIndex++; |
| 346 |
|
| 347 |
if (userId != 0 && iLength >= (iIndex + 7)) |
| 348 |
{
|
| 349 |
int discrete = 0, continuous = 0, complete = 0; |
| 350 |
float timestamp = 0f, confidence = 0f, progress = 0f; |
| 351 |
|
| 352 |
float.TryParse(alCsvParts[iIndex], out timestamp); |
| 353 |
string gestureName = alCsvParts[iIndex + 1]; |
| 354 |
|
| 355 |
int.TryParse(alCsvParts[iIndex + 2], out discrete); |
| 356 |
int.TryParse(alCsvParts[iIndex + 3], out continuous); |
| 357 |
int.TryParse(alCsvParts[iIndex + 4], out complete); |
| 358 |
|
| 359 |
float.TryParse(alCsvParts[iIndex + 5], out confidence); |
| 360 |
float.TryParse(alCsvParts[iIndex + 6], out progress); |
| 361 |
iIndex += 7; |
| 362 |
|
| 363 |
if (!gestureNames.Contains(gestureName)) |
| 364 |
{
|
| 365 |
gestureNames.Add(gestureName); |
| 366 |
|
| 367 |
VisualGestureData newData = new VisualGestureData(); |
| 368 |
newData.gestureName = gestureName; |
| 369 |
gestureData[gestureName] = newData; |
| 370 |
} |
| 371 |
|
| 372 |
VisualGestureData data = gestureData[gestureName]; |
| 373 |
data.userId = userId; |
| 374 |
data.timestamp = timestamp; |
| 375 |
|
| 376 |
data.isDiscrete = (discrete != 0); |
| 377 |
data.isContinuous = (continuous != 0); |
| 378 |
data.isComplete = (complete != 0); |
| 379 |
|
| 380 |
data.confidence = confidence; |
| 381 |
float prevProgress = data.progress; |
| 382 |
data.progress = progress; |
| 383 |
|
| 384 |
if(data.isDiscrete) |
| 385 |
{
|
| 386 |
if(data.isProcessed && !data.isComplete) |
| 387 |
{
|
| 388 |
//data.isResetting = false; |
| 389 |
data.isProcessed = false; |
| 390 |
} |
| 391 |
} |
| 392 |
else if(data.isContinuous) |
| 393 |
{
|
| 394 |
if(data.isProcessed && data.progress >= minConfidence && data.progress != prevProgress) |
| 395 |
{
|
| 396 |
//data.isResetting = false; |
| 397 |
data.isProcessed = false; |
| 398 |
} |
| 399 |
} |
| 400 |
|
| 401 |
gestureData[gestureName] = data; |
| 402 |
} |
| 403 |
} |
| 404 |
|
| 405 |
} |
| 406 |
|
| 407 |
return true; |
| 408 |
} |
| 409 |
|
| 410 |
//----------------------------------- end of public functions --------------------------------------// |
| 411 |
|
| 412 |
void Awake() |
| 413 |
{
|
| 414 |
instance = this; |
| 415 |
} |
| 416 |
|
| 417 |
#if !(UNITY_WSA_10_0 && NETFX_CORE) |
| 418 |
|
| 419 |
void Start() |
| 420 |
{
|
| 421 |
try |
| 422 |
{
|
| 423 |
// get sensor data |
| 424 |
KinectManager kinectManager = KinectManager.Instance; |
| 425 |
KinectInterop.SensorData sensorData = kinectManager != null ? kinectManager.GetSensorData() : null; |
| 426 |
|
| 427 |
if(sensorData == null || sensorData.sensorInterface == null) |
| 428 |
{
|
| 429 |
throw new Exception("Visual gesture tracking cannot be started, because the KinectManager is missing or not initialized.");
|
| 430 |
} |
| 431 |
|
| 432 |
if(sensorData.sensorInterface.GetSensorPlatform() != KinectInterop.DepthSensorPlatform.KinectSDKv2) |
| 433 |
{
|
| 434 |
throw new Exception("Visual gesture tracking is only supported by Kinect SDK v2");
|
| 435 |
} |
| 436 |
|
| 437 |
// ensure the needed dlls are in place and face tracking is available for this interface |
| 438 |
bool bNeedRestart = false; |
| 439 |
if(IsVisualGesturesAvailable(ref bNeedRestart)) |
| 440 |
{
|
| 441 |
if(bNeedRestart) |
| 442 |
{
|
| 443 |
KinectInterop.RestartLevel(gameObject, "VG"); |
| 444 |
return; |
| 445 |
} |
| 446 |
} |
| 447 |
else |
| 448 |
{
|
| 449 |
throw new Exception("Visual gesture tracking is not supported!");
|
| 450 |
} |
| 451 |
|
| 452 |
// initialize visual gesture tracker |
| 453 |
if (!InitVisualGestures()) |
| 454 |
{
|
| 455 |
throw new Exception("Visual gesture tracking could not be initialized.");
|
| 456 |
} |
| 457 |
|
| 458 |
// try to automatically detect the available gesture listeners in the scene |
| 459 |
if(visualGestureListeners.Count == 0) |
| 460 |
{
|
| 461 |
MonoBehaviour[] monoScripts = FindObjectsOfType(typeof(MonoBehaviour)) as MonoBehaviour[]; |
| 462 |
|
| 463 |
foreach(MonoBehaviour monoScript in monoScripts) |
| 464 |
{
|
| 465 |
// if(typeof(VisualGestureListenerInterface).IsAssignableFrom(monoScript.GetType()) && |
| 466 |
// monoScript.enabled) |
| 467 |
if((monoScript is VisualGestureListenerInterface) && monoScript.enabled) |
| 468 |
{
|
| 469 |
visualGestureListeners.Add(monoScript); |
| 470 |
} |
| 471 |
} |
| 472 |
} |
| 473 |
|
| 474 |
isVisualGestureInitialized = true; |
| 475 |
} |
| 476 |
catch(DllNotFoundException ex) |
| 477 |
{
|
| 478 |
Debug.LogError(ex.ToString()); |
| 479 |
if(debugText != null) |
| 480 |
debugText.text = "Please check the Kinect and VGB-Library installations."; |
| 481 |
} |
| 482 |
catch (Exception ex) |
| 483 |
{
|
| 484 |
Debug.LogError(ex.ToString()); |
| 485 |
if(debugText != null) |
| 486 |
debugText.text = ex.Message; |
| 487 |
} |
| 488 |
} |
| 489 |
|
| 490 |
void OnDestroy() |
| 491 |
{
|
| 492 |
if(isVisualGestureInitialized) |
| 493 |
{
|
| 494 |
// finish visual gesture tracking |
| 495 |
FinishVisualGestures(); |
| 496 |
} |
| 497 |
|
| 498 |
isVisualGestureInitialized = false; |
| 499 |
instance = null; |
| 500 |
} |
| 501 |
|
| 502 |
void Update() |
| 503 |
{
|
| 504 |
if(isVisualGestureInitialized) |
| 505 |
{
|
| 506 |
KinectManager kinectManager = KinectManager.Instance; |
| 507 |
if(kinectManager && kinectManager.IsInitialized()) |
| 508 |
{
|
| 509 |
primaryUserID = kinectManager.GetUserIdByIndex(playerIndex); |
| 510 |
} |
| 511 |
|
| 512 |
// update visual gesture tracking |
| 513 |
if(UpdateVisualGestures(primaryUserID)) |
| 514 |
{
|
| 515 |
// process the gestures |
| 516 |
foreach(string gestureName in gestureNames) |
| 517 |
{
|
| 518 |
if(gestureData.ContainsKey(gestureName)) |
| 519 |
{
|
| 520 |
VisualGestureData data = gestureData[gestureName]; |
| 521 |
|
| 522 |
if(data.userId != 0 && !data.isProcessed && data.isComplete && data.confidence >= minConfidence) |
| 523 |
{
|
| 524 |
//Debug.Log(gestureName + "-gesture detected."); |
| 525 |
int userIndex = kinectManager ? kinectManager.GetUserIndexById(data.userId) : -1; |
| 526 |
|
| 527 |
foreach(VisualGestureListenerInterface listener in visualGestureListeners) |
| 528 |
{
|
| 529 |
if(listener.GestureCompleted(data.userId, userIndex, data.gestureName, data.confidence)) |
| 530 |
{
|
| 531 |
//data.isResetting = true; |
| 532 |
data.isProcessed = true; |
| 533 |
gestureData[gestureName] = data; |
| 534 |
} |
| 535 |
} |
| 536 |
} |
| 537 |
else if(data.userId != 0 && !data.isProcessed && data.progress >= minConfidence) |
| 538 |
{
|
| 539 |
//Debug.Log(gestureName + "-gesture progres: " + data.progress); |
| 540 |
int userIndex = kinectManager ? kinectManager.GetUserIndexById(data.userId) : -1; |
| 541 |
|
| 542 |
foreach(VisualGestureListenerInterface listener in visualGestureListeners) |
| 543 |
{
|
| 544 |
listener.GestureInProgress(data.userId, userIndex, data.gestureName, data.progress); |
| 545 |
|
| 546 |
//data.isResetting = true; |
| 547 |
data.isProcessed = true; |
| 548 |
gestureData[gestureName] = data; |
| 549 |
} |
| 550 |
} |
| 551 |
} |
| 552 |
} |
| 553 |
|
| 554 |
} |
| 555 |
|
| 556 |
} |
| 557 |
} |
| 558 |
|
| 559 |
private bool IsVisualGesturesAvailable(ref bool bNeedRestart) |
| 560 |
{
|
| 561 |
bool bOneCopied = false, bAllCopied = true; |
| 562 |
string sTargetPath = "."; |
| 563 |
|
| 564 |
if(!KinectInterop.Is64bitArchitecture()) |
| 565 |
{
|
| 566 |
// 32 bit |
| 567 |
sTargetPath = KinectInterop.GetTargetDllPath(".", false) + "/";
|
| 568 |
|
| 569 |
Dictionary<string, string> dictFilesToUnzip = new Dictionary<string, string>(); |
| 570 |
dictFilesToUnzip["Kinect20.VisualGestureBuilder.dll"] = sTargetPath + "Kinect20.VisualGestureBuilder.dll"; |
| 571 |
dictFilesToUnzip["KinectVisualGestureBuilderUnityAddin.dll"] = sTargetPath + "KinectVisualGestureBuilderUnityAddin.dll"; |
| 572 |
dictFilesToUnzip["vgbtechs/AdaBoostTech.dll"] = sTargetPath + "vgbtechs/AdaBoostTech.dll"; |
| 573 |
dictFilesToUnzip["vgbtechs/RFRProgressTech.dll"] = sTargetPath + "vgbtechs/RFRProgressTech.dll"; |
| 574 |
dictFilesToUnzip["msvcp110.dll"] = sTargetPath + "msvcp110.dll"; |
| 575 |
dictFilesToUnzip["msvcr110.dll"] = sTargetPath + "msvcr110.dll"; |
| 576 |
|
| 577 |
KinectInterop.UnzipResourceFiles(dictFilesToUnzip, "KinectV2UnityAddin.x86.zip", ref bOneCopied, ref bAllCopied); |
| 578 |
} |
| 579 |
else |
| 580 |
{
|
| 581 |
//Debug.Log("Face - x64-architecture.");
|
| 582 |
sTargetPath = KinectInterop.GetTargetDllPath(".", true) + "/";
|
| 583 |
|
| 584 |
Dictionary<string, string> dictFilesToUnzip = new Dictionary<string, string>(); |
| 585 |
dictFilesToUnzip["Kinect20.VisualGestureBuilder.dll"] = sTargetPath + "Kinect20.VisualGestureBuilder.dll"; |
| 586 |
dictFilesToUnzip["KinectVisualGestureBuilderUnityAddin.dll"] = sTargetPath + "KinectVisualGestureBuilderUnityAddin.dll"; |
| 587 |
dictFilesToUnzip["vgbtechs/AdaBoostTech.dll"] = sTargetPath + "vgbtechs/AdaBoostTech.dll"; |
| 588 |
dictFilesToUnzip["vgbtechs/RFRProgressTech.dll"] = sTargetPath + "vgbtechs/RFRProgressTech.dll"; |
| 589 |
dictFilesToUnzip["msvcp110.dll"] = sTargetPath + "msvcp110.dll"; |
| 590 |
dictFilesToUnzip["msvcr110.dll"] = sTargetPath + "msvcr110.dll"; |
| 591 |
|
| 592 |
KinectInterop.UnzipResourceFiles(dictFilesToUnzip, "KinectV2UnityAddin.x64.zip", ref bOneCopied, ref bAllCopied); |
| 593 |
} |
| 594 |
|
| 595 |
bNeedRestart = (bOneCopied && bAllCopied); |
| 596 |
|
| 597 |
return true; |
| 598 |
} |
| 599 |
|
| 600 |
private bool InitVisualGestures() |
| 601 |
{
|
| 602 |
KinectManager kinectManager = KinectManager.Instance; |
| 603 |
KinectInterop.SensorData sensorData = kinectManager != null ? kinectManager.GetSensorData() : null; |
| 604 |
|
| 605 |
Kinect2Interface kinectInterface = sensorData.sensorInterface as Kinect2Interface; |
| 606 |
KinectSensor kinectSensor = kinectInterface != null ? kinectInterface.kinectSensor : null; |
| 607 |
|
| 608 |
if(kinectSensor == null) |
| 609 |
return false; |
| 610 |
|
| 611 |
if(gestureDatabase == string.Empty) |
| 612 |
{
|
| 613 |
Debug.LogError("Please specify gesture database file!");
|
| 614 |
return false; |
| 615 |
} |
| 616 |
|
| 617 |
// copy the gesture database file from Resources, if available |
| 618 |
if(!File.Exists(gestureDatabase)) |
| 619 |
{
|
| 620 |
TextAsset textRes = Resources.Load(gestureDatabase, typeof(TextAsset)) as TextAsset; |
| 621 |
|
| 622 |
if(textRes != null && textRes.bytes.Length != 0) |
| 623 |
{
|
| 624 |
File.WriteAllBytes(gestureDatabase, textRes.bytes); |
| 625 |
} |
| 626 |
} |
| 627 |
|
| 628 |
// create the vgb source |
| 629 |
vgbFrameSource = VisualGestureBuilderFrameSource.Create(kinectSensor, 0); |
| 630 |
|
| 631 |
// open the reader |
| 632 |
vgbFrameReader = vgbFrameSource != null ? vgbFrameSource.OpenReader() : null; |
| 633 |
if(vgbFrameReader != null) |
| 634 |
{
|
| 635 |
vgbFrameReader.IsPaused = true; |
| 636 |
} |
| 637 |
|
| 638 |
using (VisualGestureBuilderDatabase database = VisualGestureBuilderDatabase.Create(gestureDatabase)) |
| 639 |
{
|
| 640 |
if(database == null) |
| 641 |
{
|
| 642 |
Debug.LogError("Gesture database not found: " + gestureDatabase);
|
| 643 |
return false; |
| 644 |
} |
| 645 |
|
| 646 |
// check if we need to load all gestures |
| 647 |
bool bAllGestures = (gestureNames.Count == 0); |
| 648 |
|
| 649 |
foreach (Gesture gesture in database.AvailableGestures) |
| 650 |
{
|
| 651 |
bool bAddGesture = bAllGestures || gestureNames.Contains(gesture.Name); |
| 652 |
|
| 653 |
if(bAddGesture) |
| 654 |
{
|
| 655 |
string sGestureName = gesture.Name; |
| 656 |
vgbFrameSource.AddGesture(gesture); |
| 657 |
|
| 658 |
if(!gestureNames.Contains(sGestureName)) |
| 659 |
{
|
| 660 |
gestureNames.Add(sGestureName); |
| 661 |
} |
| 662 |
|
| 663 |
if(!gestureData.ContainsKey(sGestureName)) |
| 664 |
{
|
| 665 |
VisualGestureData data = new VisualGestureData(); |
| 666 |
data.gestureName = sGestureName; |
| 667 |
data.timestamp = Time.realtimeSinceStartup; |
| 668 |
|
| 669 |
data.isDiscrete = (gesture.GestureType == GestureType.Discrete); |
| 670 |
data.isContinuous = (gesture.GestureType == GestureType.Continuous); |
| 671 |
|
| 672 |
gestureData.Add(sGestureName, data); |
| 673 |
} |
| 674 |
} |
| 675 |
} |
| 676 |
} |
| 677 |
|
| 678 |
return true; |
| 679 |
} |
| 680 |
|
| 681 |
private void FinishVisualGestures() |
| 682 |
{
|
| 683 |
if (vgbFrameReader != null) |
| 684 |
{
|
| 685 |
vgbFrameReader.Dispose(); |
| 686 |
vgbFrameReader = null; |
| 687 |
} |
| 688 |
|
| 689 |
if (vgbFrameSource != null) |
| 690 |
{
|
| 691 |
vgbFrameSource.Dispose(); |
| 692 |
vgbFrameSource = null; |
| 693 |
} |
| 694 |
|
| 695 |
if(gestureData != null) |
| 696 |
{
|
| 697 |
gestureData.Clear(); |
| 698 |
} |
| 699 |
} |
| 700 |
|
| 701 |
private bool UpdateVisualGestures(long userId) |
| 702 |
{
|
| 703 |
if(vgbFrameSource == null || vgbFrameReader == null) |
| 704 |
return false; |
| 705 |
|
| 706 |
bool wasPaused = vgbFrameReader.IsPaused; |
| 707 |
vgbFrameSource.TrackingId = (ulong)userId; |
| 708 |
vgbFrameReader.IsPaused = (userId == 0); |
| 709 |
|
| 710 |
if(vgbFrameReader.IsPaused) |
| 711 |
{
|
| 712 |
if(!wasPaused) |
| 713 |
{
|
| 714 |
// clear the gesture states |
| 715 |
foreach (Gesture gesture in vgbFrameSource.Gestures) |
| 716 |
{
|
| 717 |
if(gestureData.ContainsKey(gesture.Name)) |
| 718 |
{
|
| 719 |
VisualGestureData data = gestureData[gesture.Name]; |
| 720 |
|
| 721 |
data.userId = 0; |
| 722 |
data.isComplete = false; |
| 723 |
//data.isResetting = false; |
| 724 |
data.isProcessed = false; |
| 725 |
data.confidence = 0f; |
| 726 |
data.progress = 0f; |
| 727 |
data.timestamp = Time.realtimeSinceStartup; |
| 728 |
|
| 729 |
gestureData[gesture.Name] = data; |
| 730 |
} |
| 731 |
} |
| 732 |
} |
| 733 |
|
| 734 |
return false; |
| 735 |
} |
| 736 |
|
| 737 |
VisualGestureBuilderFrame frame = vgbFrameReader.CalculateAndAcquireLatestFrame(); |
| 738 |
|
| 739 |
if(frame != null) |
| 740 |
{
|
| 741 |
Dictionary<Gesture, DiscreteGestureResult> discreteResults = frame.DiscreteGestureResults; |
| 742 |
Dictionary<Gesture, ContinuousGestureResult> continuousResults = frame.ContinuousGestureResults; |
| 743 |
|
| 744 |
if (discreteResults != null) |
| 745 |
{
|
| 746 |
foreach (Gesture gesture in discreteResults.Keys) |
| 747 |
{
|
| 748 |
if(gesture.GestureType == GestureType.Discrete && gestureData.ContainsKey(gesture.Name)) |
| 749 |
{
|
| 750 |
DiscreteGestureResult result = discreteResults[gesture]; |
| 751 |
VisualGestureData data = gestureData[gesture.Name]; |
| 752 |
|
| 753 |
data.userId = vgbFrameSource.IsTrackingIdValid ? (long)vgbFrameSource.TrackingId : 0; |
| 754 |
data.isComplete = result.Detected; |
| 755 |
data.confidence = result.Confidence; |
| 756 |
data.timestamp = Time.realtimeSinceStartup; |
| 757 |
|
| 758 |
//Debug.Log(string.Format ("{0} - {1}, confidence: {2:F0}%", data.gestureName, data.isComplete ? "Yes" : "No", data.confidence * 100f));
|
| 759 |
|
| 760 |
if(data.isProcessed && !data.isComplete) |
| 761 |
{
|
| 762 |
//data.isResetting = false; |
| 763 |
data.isProcessed = false; |
| 764 |
} |
| 765 |
|
| 766 |
gestureData[gesture.Name] = data; |
| 767 |
} |
| 768 |
} |
| 769 |
} |
| 770 |
|
| 771 |
if (continuousResults != null) |
| 772 |
{
|
| 773 |
foreach (Gesture gesture in continuousResults.Keys) |
| 774 |
{
|
| 775 |
if(gesture.GestureType == GestureType.Continuous && gestureData.ContainsKey(gesture.Name)) |
| 776 |
{
|
| 777 |
ContinuousGestureResult result = continuousResults[gesture]; |
| 778 |
VisualGestureData data = gestureData[gesture.Name]; |
| 779 |
|
| 780 |
data.userId = vgbFrameSource.IsTrackingIdValid ? (long)vgbFrameSource.TrackingId : 0; |
| 781 |
float prevProgress = data.progress; |
| 782 |
data.progress = result.Progress; |
| 783 |
data.timestamp = Time.realtimeSinceStartup; |
| 784 |
|
| 785 |
if(data.isProcessed && data.progress >= minConfidence && data.progress != prevProgress) |
| 786 |
{
|
| 787 |
//data.isResetting = false; |
| 788 |
data.isProcessed = false; |
| 789 |
} |
| 790 |
|
| 791 |
gestureData[gesture.Name] = data; |
| 792 |
} |
| 793 |
} |
| 794 |
} |
| 795 |
|
| 796 |
frame.Dispose(); |
| 797 |
frame = null; |
| 798 |
} |
| 799 |
|
| 800 |
return true; |
| 801 |
} |
| 802 |
|
| 803 |
#endif |
| 804 |
} |