FingerDetector.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using bbiwarg.Images;
  8. using bbiwarg.Utility;
  9. using Emgu.CV.Structure;
  10. using Emgu.CV;
  11. namespace bbiwarg.Detectors.Fingers
  12. {
  13. class FingerDetector
  14. {
  15. private DepthImage depthImage;
  16. private EdgeImage edgeImage;
  17. private FingerImage fingerImage;
  18. private List<FingerSliceTrail> horizontalFingerSliceTrails;
  19. private List<FingerSliceTrail> verticalFingerSliceTrails;
  20. private List<Finger> fingers;
  21. public List<Finger> Fingers { get { return fingers; } private set { fingers = value; } }
  22. public FingerDetector(DepthImage depthImage, EdgeImage edgeImage, FingerImage fingerImage)
  23. {
  24. this.depthImage = depthImage;
  25. this.edgeImage = edgeImage;
  26. this.fingerImage = fingerImage;
  27. findHorizontalFingerSliceTrails();
  28. findVerticalFingerSliceTrails();
  29. transformFingerSliceTrailsToFingers();
  30. }
  31. private void findHorizontalFingerSliceTrails()
  32. {
  33. horizontalFingerSliceTrails = new List<FingerSliceTrail>();
  34. int width = depthImage.getWidth();
  35. int height = depthImage.getHeight();
  36. int minFingerSize = 10;
  37. int maxFingerSize = 30;
  38. //search horizontal finger-slices
  39. for (int y = 0; y < height; y++)
  40. {
  41. int x = 0;
  42. while (x <= width - minFingerSize)
  43. {
  44. if (edgeImage.isEdgeAt(x, y) && depthImage.getDepthAt(x, y) > depthImage.getDepthAt(x + 1, y))
  45. {
  46. int sliceX1 = x;
  47. int maxSliceX2 = Math.Min(sliceX1 + maxFingerSize, width - 1);
  48. x++;
  49. while (x <= maxSliceX2)
  50. {
  51. if (edgeImage.isEdgeAt(x, y))
  52. {
  53. int sliceX2 = x;
  54. Vector2D sliceStart = new Vector2D(Math.Max(sliceX1 - 1, 0), y);
  55. Vector2D sliceEnd = new Vector2D(Math.Min(sliceX2 + 1, width - 1), y);
  56. FingerSlice fingerSlice = new FingerSlice(sliceStart, sliceEnd);
  57. if (fingerSlice.Size > minFingerSize && fingerSliceDepthTest(fingerSlice))
  58. {
  59. addHorizontalFingerSlice(fingerSlice);
  60. fingerImage.drawLine(fingerSlice.Line, FingerImageState.possibleFingerSlice);
  61. }
  62. break;
  63. }
  64. else x++;
  65. }
  66. }
  67. else
  68. x++;
  69. }
  70. }
  71. }
  72. private void findVerticalFingerSliceTrails()
  73. {
  74. verticalFingerSliceTrails = new List<FingerSliceTrail>();
  75. int width = depthImage.getWidth();
  76. int height = depthImage.getHeight();
  77. int minFingerSize = 10;
  78. int maxFingerSize = 30;
  79. //search vertical finger-slices
  80. for (int x = 0; x < width; x++)
  81. {
  82. int y = 0;
  83. while (y <= height - minFingerSize)
  84. {
  85. if (edgeImage.isEdgeAt(x, y) && depthImage.getDepthAt(x, y) > depthImage.getDepthAt(x, y + 1))
  86. {
  87. int sliceY1 = y;
  88. int maxSliceY2 = Math.Min(sliceY1 + maxFingerSize, height - 1);
  89. y++;
  90. while (y <= maxSliceY2)
  91. {
  92. if (edgeImage.isEdgeAt(x, y))
  93. {
  94. int sliceY2 = y;
  95. Vector2D sliceStart = new Vector2D(x, Math.Max(sliceY1 - 1, 0));
  96. Vector2D sliceEnd = new Vector2D(x, Math.Min(sliceY2 + 1, height - 1));
  97. FingerSlice fingerSlice = new FingerSlice(sliceStart, sliceEnd);
  98. if (fingerSlice.Size > minFingerSize && fingerSliceDepthTest(fingerSlice))
  99. {
  100. addVerticalFingerSlice(fingerSlice);
  101. fingerImage.drawLine(fingerSlice.Line, FingerImageState.possibleFingerSlice);
  102. }
  103. break;
  104. }
  105. else y++;
  106. }
  107. }
  108. else
  109. y++;
  110. }
  111. }
  112. }
  113. private void transformFingerSliceTrailsToFingers()
  114. {
  115. int minNumSlices = 15;
  116. Fingers = new List<Finger>();
  117. List<FingerSliceTrail> fingerSliceTrails = new List<FingerSliceTrail>();
  118. fingerSliceTrails.AddRange(horizontalFingerSliceTrails);
  119. fingerSliceTrails.AddRange(verticalFingerSliceTrails);
  120. foreach (FingerSliceTrail trail in fingerSliceTrails)
  121. {
  122. if (trail.NumSlices >= minNumSlices)
  123. {
  124. //reorder finger slice so that it goes tip->hand
  125. //TODO
  126. Finger finger = new Finger(trail);
  127. //filter double hits (horizontal+vertical finger)
  128. bool addFinger = true;
  129. for (int i = fingers.Count - 1; i >= 0; i--)
  130. {
  131. Finger f = fingers[i];
  132. Line2D lineA = finger.Line;
  133. Line2D lineB = f.Line;
  134. if(lineA.getVerticalDistanceTo(lineB) < 5 && lineA.getParallelDistanceTo(lineB) < 5)
  135. {
  136. if (finger.SliceTrail.NumSlices > f.SliceTrail.NumSlices)
  137. fingers.RemoveAt(i);
  138. else
  139. addFinger = false;
  140. }
  141. }
  142. if (addFinger)
  143. {
  144. fingers.Add(finger);
  145. fingerImage.drawFinger(finger, FingerImageState.fingerDetected);
  146. }
  147. }
  148. }
  149. }
  150. private bool fingerSliceDepthTest(FingerSlice fingerSlice)
  151. {
  152. Int16 depthStart = depthImage.getDepthAt((int)fingerSlice.Start.X, (int)fingerSlice.Start.Y);
  153. Int16 depthMid = depthImage.getDepthAt((int)fingerSlice.Mid.X, (int)fingerSlice.Mid.Y);
  154. Int16 depthEnd = depthImage.getDepthAt((int)fingerSlice.End.X, (int)fingerSlice.End.Y);
  155. return (depthStart > depthMid && depthMid < depthEnd);
  156. }
  157. private void addHorizontalFingerSlice(FingerSlice slice)
  158. {
  159. int maxYGap = 5;
  160. int maxXDifference = 5;
  161. bool assigned = false;
  162. foreach (FingerSliceTrail trail in horizontalFingerSliceTrails)
  163. {
  164. FingerSlice trailEnd = trail.End;
  165. if (slice.Mid.Y - trailEnd.Mid.Y <= maxYGap && Math.Abs(trailEnd.Mid.X - slice.Mid.X) <= maxXDifference)
  166. {
  167. trail.addSlice(slice);
  168. assigned = true;
  169. }
  170. }
  171. if (!assigned)
  172. horizontalFingerSliceTrails.Add(new FingerSliceTrail(slice));
  173. }
  174. private void addVerticalFingerSlice(FingerSlice slice)
  175. {
  176. int maxXGap = 5;
  177. int maxYDifference = 5;
  178. bool assigned = false;
  179. foreach (FingerSliceTrail trail in verticalFingerSliceTrails)
  180. {
  181. FingerSlice trailEnd = trail.End;
  182. if (slice.Mid.X - trailEnd.Mid.X <= maxXGap && Math.Abs(trailEnd.Mid.Y - slice.Mid.Y) <= maxYDifference)
  183. {
  184. trail.addSlice(slice);
  185. assigned = true;
  186. }
  187. }
  188. if (!assigned)
  189. verticalFingerSliceTrails.Add(new FingerSliceTrail(slice));
  190. }
  191. }
  192. }