FingerDetector.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Drawing;
  7. using Emgu.CV;
  8. using Emgu.CV.Structure;
  9. using bbiwarg.Images;
  10. namespace bbiwarg.Detectors.Fingers
  11. {
  12. class FingerDetector
  13. {
  14. private DepthImage depthImage;
  15. private EdgeImage edgeImage;
  16. private bool[,] possibleFingerPoints;
  17. private bool[,] fingerPoints;
  18. private List<Finger> possibleFingers;
  19. private List<Finger> fingers;
  20. public FingerDetector(DepthImage depthImage, EdgeImage edgeImage) {
  21. this.depthImage = depthImage;
  22. this.edgeImage = edgeImage;
  23. findPossibleFingerPoints();
  24. findPossibleFingers();
  25. setFingers();
  26. setFingerPoints();
  27. }
  28. public bool isPossibleFingerPointAt(int x, int y) {
  29. return possibleFingerPoints[x, y];
  30. }
  31. public bool isFingerPointAt(int x, int y) {
  32. return fingerPoints[x, y];
  33. }
  34. public List<Finger> getFingers() {
  35. return fingers;
  36. }
  37. private void findPossibleFingerPoints()
  38. {
  39. int width = depthImage.getWidth();
  40. int height = depthImage.getHeight();
  41. int maxFingerSize = 30;
  42. int minFingerSize = 10;
  43. possibleFingerPoints = new bool[width, height];
  44. for (int y = 0; y < height; y++) {
  45. for (int x = 0; x < width; x++) {
  46. if (edgeImage.isEdgeAt(x,y)) {
  47. //search horizontal
  48. bool edgeRightFound = false;
  49. int edgeRightX = x + minFingerSize;
  50. while (!edgeRightFound && edgeRightX < width) {
  51. if (edgeImage.isEdgeAt(edgeRightX,y))
  52. edgeRightFound = true;
  53. else
  54. edgeRightX++;
  55. }
  56. if (edgeRightFound){
  57. int midX = (edgeRightX + x) / 2;
  58. Int16 depthLeft = depthImage.getDepthAt(x, y);
  59. Int16 depthMid = depthImage.getDepthAt(midX, y);
  60. Int16 depthRight = depthImage.getDepthAt(edgeRightX, y);
  61. if ((edgeRightX - x) < maxFingerSize && depthLeft > depthMid && depthMid < depthRight) {
  62. possibleFingerPoints[midX, y] = true;
  63. }
  64. }
  65. //search vertical
  66. bool edgeBottomFound = false;
  67. int edgeBottomY = y + minFingerSize;
  68. while (!edgeBottomFound && edgeBottomY < height) {
  69. if (edgeImage.isEdgeAt(x, edgeBottomY))
  70. edgeBottomFound = true;
  71. else
  72. edgeBottomY++;
  73. }
  74. if (edgeBottomFound) {
  75. int midY = (edgeBottomY + y) / 2;
  76. Int16 depthTop = depthImage.getDepthAt(x, y);
  77. Int16 depthMid = depthImage.getDepthAt(x, midY);
  78. Int16 depthBottom = depthImage.getDepthAt(x, edgeBottomY);
  79. if ((edgeBottomY - y) < maxFingerSize && depthTop > depthMid && depthMid < depthBottom) {
  80. possibleFingerPoints[x, midY] = true;
  81. }
  82. }
  83. }
  84. }
  85. }
  86. }
  87. private void findPossibleFingers()
  88. {
  89. int width = depthImage.getWidth();
  90. int height = depthImage.getHeight();
  91. float maxDistanceTogether = 5.0f;
  92. possibleFingers = new List<Finger>();
  93. for (int y = 0; y < height; y++)
  94. {
  95. for (int x = 0; x < width; x++)
  96. {
  97. if (possibleFingerPoints[x, y])
  98. {
  99. Int16 depth = depthImage.getDepthAt(x, y);
  100. FingerPoint fingerPoint = new FingerPoint(x,y,depth);
  101. float minDistanceValue = float.MaxValue;
  102. int minDistanceIndex = 0;
  103. for (int i = 0; i < possibleFingers.Count; i++)
  104. {
  105. float distance = possibleFingers[i].getMinDistance(fingerPoint);
  106. if (distance < minDistanceValue)
  107. {
  108. minDistanceValue = distance;
  109. minDistanceIndex = i;
  110. }
  111. }
  112. if (minDistanceValue < maxDistanceTogether)
  113. {
  114. possibleFingers[minDistanceIndex].addFingerPoint(fingerPoint);
  115. }
  116. else
  117. {
  118. possibleFingers.Add(new Finger(fingerPoint));
  119. }
  120. }
  121. }
  122. }
  123. }
  124. private void setFingers()
  125. {
  126. int width = depthImage.getWidth();
  127. int height = depthImage.getHeight();
  128. float minFingerLength = 20.0f;
  129. fingers = new List<Finger>();
  130. foreach (Finger finger in possibleFingers)
  131. {
  132. float length = finger.getLength();
  133. if (length > minFingerLength)
  134. {
  135. fingers.Add(finger);
  136. }
  137. }
  138. }
  139. private void setFingerPoints() {
  140. int width = depthImage.getWidth();
  141. int height = depthImage.getHeight();
  142. fingerPoints = new bool[width, height];
  143. foreach (Finger finger in fingers) {
  144. PointF lineEndPoint1 = finger.getLineEndPoint1();
  145. PointF lineEndPoint2 = finger.getLineEndPoint2();
  146. drawFingerPointLine(lineEndPoint1, lineEndPoint2);
  147. }
  148. }
  149. private void drawFingerPointLine(PointF start, PointF end)
  150. {
  151. int width = depthImage.getWidth();
  152. int height = depthImage.getHeight();
  153. // bresenham from wikipedia
  154. int xstart = (int)start.X, xend = (int)end.X, ystart = (int)start.Y, yend = (int)end.Y;
  155. int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
  156. /* Entfernung in beiden Dimensionen berechnen */
  157. dx = xend - xstart;
  158. dy = yend - ystart;
  159. /* Vorzeichen des Inkrements bestimmen */
  160. incx = dx < 0 ? -1 : 1;
  161. incy = dy < 0 ? -1 : 1;
  162. if (dx < 0) dx = -dx;
  163. if (dy < 0) dy = -dy;
  164. /* feststellen, welche Entfernung größer ist */
  165. if (dx > dy)
  166. {
  167. /* x ist schnelle Richtung */
  168. pdx = incx; pdy = 0; /* pd. ist Parallelschritt */
  169. ddx = incx; ddy = incy; /* dd. ist Diagonalschritt */
  170. es = dy; el = dx; /* Fehlerschritte schnell, langsam */
  171. }
  172. else
  173. {
  174. /* y ist schnelle Richtung */
  175. pdx = 0; pdy = incy; /* pd. ist Parallelschritt */
  176. ddx = incx; ddy = incy; /* dd. ist Diagonalschritt */
  177. es = dx; el = dy; /* Fehlerschritte schnell, langsam */
  178. }
  179. /* Initialisierungen vor Schleifenbeginn */
  180. x = xstart;
  181. y = ystart;
  182. err = el / 2;
  183. fingerPoints[Math.Min(width - 1, Math.Max(0, x)), Math.Min(height - 1, Math.Max(0, y))] = true;
  184. /* Pixel berechnen */
  185. for (t = 0; t < el; ++t) /* t zaehlt die Pixel, el ist auch Anzahl */
  186. {
  187. /* Aktualisierung Fehlerterm */
  188. err -= es;
  189. if (err < 0)
  190. {
  191. /* Fehlerterm wieder positiv (>=0) machen */
  192. err += el;
  193. /* Schritt in langsame Richtung, Diagonalschritt */
  194. x += ddx;
  195. y += ddy;
  196. }
  197. else
  198. {
  199. /* Schritt in schnelle Richtung, Parallelschritt */
  200. x += pdx;
  201. y += pdy;
  202. }
  203. fingerPoints[Math.Min(width - 1, Math.Max(0, x)), Math.Min(height - 1, Math.Max(0, y))] = true;
  204. }
  205. }
  206. }
  207. }