Hand.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Emgu.CV;
  8. using Emgu.CV.Structure;
  9. using bbiwarg.Recognition.FingerRecognition;
  10. using bbiwarg.Utility;
  11. using bbiwarg.Recognition.Tracking;
  12. using bbiwarg.Recognition.PalmRecognition;
  13. namespace bbiwarg.Recognition.HandRecognition
  14. {
  15. public enum HandSide
  16. {
  17. Undefined = 0,
  18. Right = 1,
  19. Left = 2
  20. }
  21. class Hand : TrackableObject
  22. {
  23. public List<ConvexityDefect> ConvexityDefects { get; private set; }
  24. public Vector2D Centroid { get; private set; }
  25. public Image<Gray, byte> Mask { get; private set; }
  26. public List<Finger> Fingers { get; private set; }
  27. public ConvexityDefect ThumbDefect { get; private set; }
  28. public Palm Palm { get; private set; }
  29. public HandSide Side { get; private set; }
  30. public Hand(Image<Gray, byte> mask, Finger finger)
  31. {
  32. Mask = mask;
  33. Fingers = new List<Finger>();
  34. addFinger(finger);
  35. findCentroids();
  36. }
  37. public bool isInside(Vector2D point)
  38. {
  39. return (Mask.Data[point.IntY, point.IntX, 0] != 0);
  40. }
  41. public void addFinger(Finger finger)
  42. {
  43. Fingers.Add(finger);
  44. }
  45. public void mergeWith(Hand mergeHand)
  46. {
  47. extendMask(mergeHand.Mask);
  48. Fingers.AddRange(mergeHand.Fingers);
  49. foreach (Finger finger in Fingers)
  50. {
  51. finger.setHand(this);
  52. }
  53. findCentroids();
  54. }
  55. public void extendMask(Image<Gray, byte> extendMask)
  56. {
  57. Mask = Mask.Or(extendMask);
  58. findCentroids();
  59. }
  60. public void fillOverlappingFingers(List<Finger> otherFingers)
  61. {
  62. foreach (Finger finger in otherFingers)
  63. {
  64. FingerSliceTrail trail = null;
  65. foreach (FingerSlice slice in finger.SliceTrail.Slices)
  66. {
  67. Vector2D out1 = slice.Start.moveWithinBound(slice.Direction.getInverse(), Parameters.FingerContourMargin);
  68. Vector2D out2 = slice.End.moveWithinBound(slice.Direction, Parameters.FingerContourMargin);
  69. if (isInside(out1) && isInside(out2))
  70. {
  71. if (trail == null)
  72. trail = new FingerSliceTrail(slice);
  73. else
  74. trail.addSlice(slice);
  75. }
  76. }
  77. if (trail != null)
  78. Mask.FillConvexPoly(trail.getContour(Parameters.FingerOutMargin).ToArray(), new Gray(1));
  79. }
  80. Mask = Mask.Dilate(1);
  81. }
  82. public void findThumbDefect()
  83. {
  84. if (isThumbOnly())
  85. {
  86. findConvexityDefects();
  87. filterThumbDefect();
  88. }
  89. determineHandSide();
  90. }
  91. public void setPalm(Palm palm)
  92. {
  93. Palm = palm;
  94. }
  95. private bool isThumbOnly()
  96. {
  97. return (Fingers.Count == 1);
  98. }
  99. private void findConvexityDefects()
  100. {
  101. MemStorage ms = new MemStorage();
  102. Contour<Point> contour = Mask.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL);
  103. List<MCvConvexityDefect> mcvConvexityDefects = new List<MCvConvexityDefect>(contour.GetConvexityDefacts(ms, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE));
  104. ConvexityDefects = new List<ConvexityDefect>();
  105. foreach (MCvConvexityDefect defect in mcvConvexityDefects)
  106. ConvexityDefects.Add(new ConvexityDefect(defect));
  107. ms.Clear();
  108. }
  109. private void filterThumbDefect()
  110. {
  111. if (ConvexityDefects.Count > 0)
  112. {
  113. ConvexityDefects.Sort((cd1, cd2) => (cd2.Depth.CompareTo(cd1.Depth)));
  114. Finger thumb = Fingers[0];
  115. foreach (ConvexityDefect defect in ConvexityDefects)
  116. {
  117. if (defect.isPossibleThumbDefect(thumb))
  118. {
  119. ThumbDefect = defect;
  120. break;
  121. }
  122. }
  123. }
  124. }
  125. private void determineHandSide()
  126. {
  127. if (ThumbDefect != null)
  128. {
  129. if (ThumbDefect.VectorShort.crossProduct(ThumbDefect.VectorLong) > 0)
  130. Side = HandSide.Left;
  131. else
  132. Side = HandSide.Right;
  133. }
  134. else
  135. Side = HandSide.Undefined;
  136. }
  137. private void findCentroids()
  138. {
  139. //find centroid
  140. MCvPoint2D64f gravityCenter = Mask.GetMoments(true).GravityCenter;
  141. Centroid = new Vector2D((float)gravityCenter.x, (float)gravityCenter.y);
  142. }
  143. }
  144. }