/fontes/fontes/Assets/KinectScripts/Filters/ClippedLegsFilter.cs

https://bitbucket.org/gcgmm/mm_2018-1_not_equipe-7 · C# · 235 lines · 138 code · 43 blank · 54 comment · 22 complexity · eb37f121456a6cc543487a3bbfd3494b MD5 · raw file

  1. //------------------------------------------------------------------------------
  2. // <copyright file="SkeletonJointsFilterClippedLegs.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. //------------------------------------------------------------------------------
  6. using UnityEngine;
  7. using System;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. /// <summary>
  11. /// FilterClippedLegs smooths out leg joint positions when the skeleton is clipped
  12. /// by the bottom of the camera FOV. Inferred joint positions from the skeletal tracker
  13. /// can occasionally be noisy or erroneous, based on limited depth image pixels from the
  14. /// parts of the legs in view. This filter applies a lot of smoothing using a double
  15. /// exponential filter, letting through just enough leg movement to show a kick or high step.
  16. /// Based on the amount of leg that is clipped/inferred, the smoothed data is feathered into the
  17. /// skeleton output data.
  18. /// </summary>
  19. public class ClippedLegsFilter
  20. {
  21. // The blend weights when all leg joints are tracked.
  22. private readonly Vector3 allTracked;
  23. // The blend weights when the foot is inferred or not tracked.
  24. private readonly Vector3 footInferred;
  25. // The blend weights when ankle and below are inferred or not tracked.
  26. private readonly Vector3 ankleInferred;
  27. // The blend weights when knee and below are inferred or not tracked.
  28. private readonly Vector3 kneeInferred;
  29. // The joint position filter.
  30. private JointPositionsFilter filterJoints;
  31. // The timed lerp for the left knee.
  32. private TimedLerp lerpLeftKnee;
  33. // The timed lerp for the left ankle.
  34. private TimedLerp lerpLeftAnkle;
  35. // The timed lerp for the left foot.
  36. private TimedLerp lerpLeftFoot;
  37. /// The timed lerp for the right knee.
  38. private TimedLerp lerpRightKnee;
  39. // The timed lerp for the right ankle.
  40. private TimedLerp lerpRightAnkle;
  41. // The timed lerp for the right foot.
  42. private TimedLerp lerpRightFoot;
  43. // The local skeleton with leg filtering applied.
  44. private KinectWrapper.NuiSkeletonData filteredSkeleton;
  45. // Initializes a new instance of the class.
  46. public ClippedLegsFilter()
  47. {
  48. this.lerpLeftKnee = new TimedLerp();
  49. this.lerpLeftAnkle = new TimedLerp();
  50. this.lerpLeftFoot = new TimedLerp();
  51. this.lerpRightKnee = new TimedLerp();
  52. this.lerpRightAnkle = new TimedLerp();
  53. this.lerpRightFoot = new TimedLerp();
  54. this.filterJoints = new JointPositionsFilter();
  55. this.filteredSkeleton = new KinectWrapper.NuiSkeletonData();
  56. // knee, ankle, foot blend amounts
  57. this.allTracked = new Vector3(0.0f, 0.0f, 0.0f); // All joints are tracked
  58. this.footInferred = new Vector3(0.0f, 0.0f, 1.0f); // foot is inferred
  59. this.ankleInferred = new Vector3(0.5f, 1.0f, 1.0f); // ankle is inferred
  60. this.kneeInferred = new Vector3(1.0f, 1.0f, 1.0f); // knee is inferred
  61. Reset();
  62. }
  63. // Resets filter state to defaults.
  64. public void Reset()
  65. {
  66. // set up a really floaty double exponential filter - we want maximum smoothness
  67. this.filterJoints.Init(0.5f, 0.3f, 1.0f, 1.0f, 1.0f);
  68. this.lerpLeftKnee.Reset();
  69. this.lerpLeftAnkle.Reset();
  70. this.lerpLeftFoot.Reset();
  71. this.lerpRightKnee.Reset();
  72. this.lerpRightAnkle.Reset();
  73. this.lerpRightFoot.Reset();
  74. }
  75. // Implements the per-frame filter logic for the arms up patch.
  76. public bool FilterSkeleton(ref KinectWrapper.NuiSkeletonData skeleton, float deltaNuiTime)
  77. {
  78. // if (null == skeleton)
  79. // {
  80. // return false;
  81. // }
  82. // exit early if we lose tracking on the entire skeleton
  83. if (skeleton.eTrackingState != KinectWrapper.NuiSkeletonTrackingState.SkeletonTracked)
  84. {
  85. filterJoints.Reset();
  86. }
  87. KinectHelper.CopySkeleton(ref skeleton, ref filteredSkeleton);
  88. filterJoints.UpdateFilter(ref filteredSkeleton);
  89. // Update lerp state with the current delta NUI time.
  90. this.lerpLeftKnee.Tick(deltaNuiTime);
  91. this.lerpLeftAnkle.Tick(deltaNuiTime);
  92. this.lerpLeftFoot.Tick(deltaNuiTime);
  93. this.lerpRightKnee.Tick(deltaNuiTime);
  94. this.lerpRightAnkle.Tick(deltaNuiTime);
  95. this.lerpRightFoot.Tick(deltaNuiTime);
  96. // Exit early if we do not have a valid body basis - too much of the skeleton is invalid.
  97. if ((!KinectHelper.IsTracked(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.HipCenter)) ||
  98. (!KinectHelper.IsTrackedOrInferred(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.HipLeft)) ||
  99. (!KinectHelper.IsTrackedOrInferred(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.HipRight)))
  100. {
  101. return false;
  102. }
  103. // Determine if the skeleton is clipped by the bottom of the FOV.
  104. bool clippedBottom = (skeleton.dwQualityFlags & (int)KinectWrapper.FrameEdges.Bottom) != 0;
  105. // Select a mask for the left leg depending on which joints are not tracked.
  106. // These masks define how much of the filtered joint positions should be blended
  107. // with the raw positions. Based on the tracking state of the leg joints, we apply
  108. // more filtered data as more joints lose tracking.
  109. Vector3 leftLegMask = this.allTracked;
  110. if (!KinectHelper.IsTracked(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.KneeLeft))
  111. {
  112. leftLegMask = this.kneeInferred;
  113. }
  114. else if (!KinectHelper.IsTracked(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.AnkleLeft))
  115. {
  116. leftLegMask = this.ankleInferred;
  117. }
  118. else if (!KinectHelper.IsTracked(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.FootLeft))
  119. {
  120. leftLegMask = this.footInferred;
  121. }
  122. // Select a mask for the right leg depending on which joints are not tracked.
  123. Vector3 rightLegMask = this.allTracked;
  124. if (!KinectHelper.IsTracked(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.KneeRight))
  125. {
  126. rightLegMask = this.kneeInferred;
  127. }
  128. else if (!KinectHelper.IsTracked(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.AnkleRight))
  129. {
  130. rightLegMask = this.ankleInferred;
  131. }
  132. else if (!KinectHelper.IsTracked(skeleton, (int)KinectWrapper.NuiSkeletonPositionIndex.FootRight))
  133. {
  134. rightLegMask = this.footInferred;
  135. }
  136. // If the skeleton is not clipped by the bottom of the FOV, cut the filtered data
  137. // blend in half.
  138. float clipMask = clippedBottom ? 1.0f : 0.5f;
  139. // Apply the mask values to the joints of each leg, by placing the mask values into the lerp targets.
  140. this.lerpLeftKnee.SetEnabled(leftLegMask.x * clipMask);
  141. this.lerpLeftAnkle.SetEnabled(leftLegMask.y * clipMask);
  142. this.lerpLeftFoot.SetEnabled(leftLegMask.z * clipMask);
  143. this.lerpRightKnee.SetEnabled(rightLegMask.x * clipMask);
  144. this.lerpRightAnkle.SetEnabled(rightLegMask.y * clipMask);
  145. this.lerpRightFoot.SetEnabled(rightLegMask.z * clipMask);
  146. // The bSkeletonUpdated flag tracks whether we have modified the output skeleton or not.
  147. bool skeletonUpdated = false;
  148. // Apply lerp to the left knee, which will blend the raw joint position with the filtered joint position based on the current lerp value.
  149. if (this.lerpLeftKnee.IsLerpEnabled())
  150. {
  151. int jointIndex = (int)KinectWrapper.NuiSkeletonPositionIndex.KneeLeft;
  152. KinectHelper.LerpAndApply(ref skeleton, jointIndex, (Vector3)filteredSkeleton.SkeletonPositions[jointIndex], lerpLeftKnee.SmoothValue, KinectWrapper.NuiSkeletonPositionTrackingState.Tracked);
  153. skeletonUpdated = true;
  154. }
  155. // Apply lerp to the left ankle.
  156. if (this.lerpLeftAnkle.IsLerpEnabled())
  157. {
  158. int jointIndex = (int)KinectWrapper.NuiSkeletonPositionIndex.AnkleLeft;
  159. KinectHelper.LerpAndApply(ref skeleton, jointIndex, (Vector3)filteredSkeleton.SkeletonPositions[jointIndex], lerpLeftAnkle.SmoothValue, KinectWrapper.NuiSkeletonPositionTrackingState.Tracked);
  160. skeletonUpdated = true;
  161. }
  162. // Apply lerp to the left foot.
  163. if (this.lerpLeftFoot.IsLerpEnabled())
  164. {
  165. int jointIndex = (int)KinectWrapper.NuiSkeletonPositionIndex.FootLeft;
  166. KinectHelper.LerpAndApply(ref skeleton, jointIndex, (Vector3)filteredSkeleton.SkeletonPositions[jointIndex], lerpLeftFoot.SmoothValue, KinectWrapper.NuiSkeletonPositionTrackingState.Inferred);
  167. skeletonUpdated = true;
  168. }
  169. // Apply lerp to the right knee.
  170. if (this.lerpRightKnee.IsLerpEnabled())
  171. {
  172. int jointIndex = (int)KinectWrapper.NuiSkeletonPositionIndex.KneeRight;
  173. KinectHelper.LerpAndApply(ref skeleton, jointIndex, (Vector3)filteredSkeleton.SkeletonPositions[jointIndex], lerpRightKnee.SmoothValue, KinectWrapper.NuiSkeletonPositionTrackingState.Tracked);
  174. skeletonUpdated = true;
  175. }
  176. // Apply lerp to the right ankle.
  177. if (this.lerpRightAnkle.IsLerpEnabled())
  178. {
  179. int jointIndex = (int)KinectWrapper.NuiSkeletonPositionIndex.AnkleRight;
  180. KinectHelper.LerpAndApply(ref skeleton, jointIndex, (Vector3)filteredSkeleton.SkeletonPositions[jointIndex], lerpRightAnkle.SmoothValue, KinectWrapper.NuiSkeletonPositionTrackingState.Tracked);
  181. skeletonUpdated = true;
  182. }
  183. // Apply lerp to the right foot.
  184. if (this.lerpRightFoot.IsLerpEnabled())
  185. {
  186. int jointIndex = (int)KinectWrapper.NuiSkeletonPositionIndex.FootRight;
  187. KinectHelper.LerpAndApply(ref skeleton, jointIndex, (Vector3)filteredSkeleton.SkeletonPositions[jointIndex], lerpRightFoot.SmoothValue, KinectWrapper.NuiSkeletonPositionTrackingState.Inferred);
  188. skeletonUpdated = true;
  189. }
  190. return skeletonUpdated;
  191. }
  192. }