HandDetector.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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 bbiwarg.Images;
  8. using bbiwarg.Recognition.FingerRecognition;
  9. using bbiwarg.Graphics;
  10. using bbiwarg.Utility;
  11. using Emgu.CV;
  12. using Emgu.CV.Structure;
  13. namespace bbiwarg.Recognition.HandRecognition
  14. {
  15. class HandDetector
  16. {
  17. private DepthImage depthImage;
  18. private EdgeImage edgeImage;
  19. private Image<Gray, byte> modifiedHandDepthImage;
  20. private List<Finger> fingers;
  21. public List<Hand> Hands { get; private set; }
  22. public Image<Gray, byte> HandMask { get; private set; }
  23. public HandDetector(DepthImage depthImage, EdgeImage edgeImage, List<Finger> fingers)
  24. {
  25. this.depthImage = depthImage;
  26. this.edgeImage = edgeImage;
  27. this.fingers = fingers;
  28. createModifiedHandEdgeImage();
  29. findHands();
  30. setZIndexes();
  31. createHandMask();
  32. findThumbDefects();
  33. }
  34. private void createModifiedHandEdgeImage()
  35. {
  36. modifiedHandDepthImage = depthImage.Image.Copy();
  37. foreach (Finger finger in fingers)
  38. {
  39. Point[] contour = finger.InnerContour.ToArray();
  40. modifiedHandDepthImage.DrawPolyline(contour, false, new Gray(0), 2);
  41. }
  42. }
  43. private void findHands()
  44. {
  45. int width = edgeImage.Width;
  46. int height = edgeImage.Height;
  47. int maxArea = width * height;
  48. Hands = new List<Hand>();
  49. foreach (Finger finger in fingers)
  50. {
  51. bool newHand = true;
  52. foreach (Hand hand in Hands)
  53. {
  54. if (hand.isInside(finger.HandPoint))
  55. {
  56. hand.addFinger(finger);
  57. finger.setHand(hand);
  58. newHand = false;
  59. break;
  60. }
  61. }
  62. if (newHand)
  63. {
  64. Image<Gray, byte> mask = new Image<Gray, byte>(width + 2, height + 2);
  65. MCvConnectedComp comp = new MCvConnectedComp();
  66. CvInvoke.cvFloodFill(modifiedHandDepthImage, finger.HandPoint, new MCvScalar(255), new MCvScalar(Constants.HandFloodFillDownDiff), new MCvScalar(Constants.HandFloodFillUpDiff), out comp, Emgu.CV.CvEnum.CONNECTIVITY.EIGHT_CONNECTED, Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, mask);
  67. if (comp.area < maxArea * Constants.HandMaxSize)
  68. {
  69. Image<Gray, byte> cropedMask = mask.Copy(new Rectangle(1, 1, width, height));
  70. Hand hand = new Hand(cropedMask, finger);
  71. Hands.Add(hand);
  72. finger.setHand(hand);
  73. }
  74. }
  75. }
  76. }
  77. private void setZIndexes()
  78. {
  79. //sort depending on depth of centroid (far->near)
  80. Hands.Sort((h1, h2) => depthImage.getDepthAt(h2.CentroidInHand).CompareTo(depthImage.getDepthAt(h1.CentroidInHand)));
  81. for (int i = 0; i < Hands.Count; i++)
  82. Hands[i].setZIndex(i);
  83. }
  84. private void createHandMask()
  85. {
  86. HandMask = new Image<Gray, byte>(depthImage.Width, depthImage.Height);
  87. foreach (Hand hand in Hands)
  88. HandMask = HandMask.Or(hand.Mask);
  89. }
  90. private void findThumbDefects()
  91. {
  92. foreach (Hand hand in Hands)
  93. hand.findThumbDefect();
  94. }
  95. }
  96. }