PalmDetector.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using bbiwarg.Recognition.HandRecognition;
  7. using bbiwarg.Utility;
  8. using Emgu.CV.Structure;
  9. using Emgu.CV;
  10. namespace bbiwarg.Recognition.PalmRecognition
  11. {
  12. class PalmDetector
  13. {
  14. private List<Hand> hands;
  15. private List<Hand> palmHands;
  16. public List<Palm> Palms { get; private set; }
  17. public PalmDetector(List<Hand> hands)
  18. {
  19. this.hands = hands;
  20. findPalmHands();
  21. createPalms();
  22. }
  23. private void findPalmHands()
  24. {
  25. palmHands = new List<Hand>();
  26. foreach (Hand hand in hands)
  27. {
  28. if (hand.ThumbDefect != null)
  29. palmHands.Add(hand);
  30. }
  31. }
  32. private void createPalms()
  33. {
  34. Palms = new List<Palm>();
  35. foreach (Hand palmHand in palmHands)
  36. {
  37. ConvexityDefect thumbDefect = palmHand.ThumbDefect;
  38. Vector2D directionWristFinger = thumbDefect.VectorLong.normalize();
  39. Vector2D directionFingerWrist = directionWristFinger.getInverse();
  40. Vector2D directionUpperLower = directionWristFinger.getOrthogonal(palmHand.Side == HandSide.Right);
  41. Vector2D directionLowerUpper = directionUpperLower.getInverse();
  42. //handLength
  43. Vector2D handLength = 1.5f * thumbDefect.VectorLong;
  44. //fingersUpper
  45. Vector2D fingersUpper = thumbDefect.OuterLong;
  46. bool handBelow = true;
  47. while (handBelow && fingersUpper.isInBound())
  48. {
  49. fingersUpper += directionWristFinger;
  50. Vector2D below = fingersUpper.copy();
  51. bool handBelowFound = false;
  52. while (!handBelowFound && below.getDistanceTo(fingersUpper) < 2 * Parameters.FingerMaxWidth && below.isInBound())
  53. {
  54. below += directionUpperLower;
  55. handBelowFound = palmHand.isInside(below);
  56. }
  57. handBelow = handBelowFound;
  58. }
  59. //wristUpper
  60. Vector2D wristUpper = thumbDefect.Inner + 5 * directionFingerWrist;
  61. while (wristUpper.isInBound() && palmHand.isInside(wristUpper))
  62. wristUpper += directionFingerWrist;
  63. //handWidth
  64. Vector2D handWidth = getHandWidth(palmHand, directionUpperLower);
  65. //wristLower
  66. Vector2D wristLower = wristUpper + handWidth;
  67. //fingersLower
  68. Vector2D fingersLower = wristLower + 0.75f * handLength - 0.25f * handWidth;
  69. Palm palm = new Palm(palmHand, wristUpper, wristLower, fingersLower, fingersUpper);
  70. Palms.Add(palm);
  71. palmHand.setPalm(palm);
  72. }
  73. }
  74. private Vector2D getHandWidth(Hand palmHand, Vector2D directionUpperLower)
  75. {
  76. Vector2D lineStart = palmHand.ThumbDefect.Inner;
  77. Vector2D lineEnd = palmHand.ThumbDefect.OuterLong;
  78. Vector2D step = (lineEnd - lineStart) / Parameters.PalmNumPositionsForHandWidth;
  79. Vector2D currentStart = lineStart;
  80. Vector2D maxWidth = null;
  81. float maxWidthLength = float.MinValue;
  82. for (int i = 0; i < Parameters.PalmNumPositionsForHandWidth; i++)
  83. {
  84. Vector2D lower = currentStart + 10 * directionUpperLower;
  85. while (lower.isInBound() && palmHand.isInside(lower))
  86. lower += directionUpperLower;
  87. Vector2D width = (lower - currentStart);
  88. float length = width.Length;
  89. if (length > maxWidthLength)
  90. {
  91. maxWidth = width;
  92. maxWidthLength = length;
  93. }
  94. currentStart += step;
  95. }
  96. return maxWidth;
  97. }
  98. }
  99. }