Finger.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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.Images;
  10. using bbiwarg.Utility;
  11. namespace bbiwarg.Detectors.Fingers
  12. {
  13. class Finger
  14. {
  15. private List<Vector<int>> fingerPoints;
  16. private bool lineUpToDate = false;
  17. private Vector<float> direction;
  18. private Vector<float> pointOnLine;
  19. private Vector<float> lineEndPoint1;
  20. private Vector<float> lineEndPoint2;
  21. private Vector<int> tipPoint;
  22. private Vector<int> handPoint;
  23. private float length;
  24. public Finger(Vector<int> fingerPoint)
  25. {
  26. fingerPoints = new List<Vector<int>>();
  27. addFingerPoint(fingerPoint);
  28. }
  29. public Vector<float> getLineEndPoint1()
  30. {
  31. if (!lineUpToDate) updateLine();
  32. return lineEndPoint1;
  33. }
  34. public Vector<float> getLineEndPoint2()
  35. {
  36. if (!lineUpToDate) updateLine();
  37. return lineEndPoint2;
  38. }
  39. public Vector<float> getDirection()
  40. {
  41. if (!lineUpToDate) updateLine();
  42. return direction;
  43. }
  44. public Vector<int> getTipPoint()
  45. {
  46. if (!lineUpToDate) updateLine();
  47. return tipPoint;
  48. }
  49. public float getLength()
  50. {
  51. if (!lineUpToDate) updateLine();
  52. return length;
  53. }
  54. public void addFingerPoint(Vector<int> fingerPoint)
  55. {
  56. fingerPoints.Add(fingerPoint);
  57. lineUpToDate = false;
  58. }
  59. public float getMinDistance(Vector<int> fingerPoint)
  60. {
  61. float minDinstance = float.MaxValue;
  62. foreach (Vector<int> fp in fingerPoints)
  63. {
  64. float distance = fingerPoint.subDistance(fp, 2);
  65. if (distance < minDinstance)
  66. {
  67. minDinstance = distance;
  68. }
  69. }
  70. return minDinstance;
  71. }
  72. public float getSimilarity(Finger compareFinger) {
  73. /*//startDistance
  74. float maxStartDistance = 100;
  75. float xDiffStart = lineEndPoint1.X - compareFinger.getLineEndPoint1().X;
  76. float yDiffStart = lineEndPoint1.X - compareFinger.getLineEndPoint1().Y;
  77. float startDistance = (float)Math.Sqrt(xDiffStart * xDiffStart + yDiffStart * yDiffStart);
  78. float startSimilarity = Math.Max(1 - (startDistance / maxStartDistance), 0);
  79. //endDistance
  80. float maxEndDistance = 50;
  81. float xDiffEnd = lineEndPoint2.X - compareFinger.getLineEndPoint2().X;
  82. float yDiffEnd = lineEndPoint2.X - compareFinger.getLineEndPoint2().Y;
  83. float endDistance = (float)Math.Sqrt(xDiffEnd * xDiffEnd + yDiffEnd * yDiffEnd);
  84. float endSimilarity = Math.Max(1 - (endDistance / maxEndDistance), 0);
  85. //direction
  86. return (0.2f*startSimilarity + 0.8f*endSimilarity)*/;
  87. return 1.0f;
  88. }
  89. private void updateLine() {
  90. //update direction+pointonline
  91. PointF[] pointArray = new PointF[fingerPoints.Count];
  92. int i = 0;
  93. foreach (Vector<int> fp in fingerPoints)
  94. {
  95. pointArray[i] = new PointF(fp.x, fp.y);
  96. ++i;
  97. }
  98. PointF tempDirection;
  99. PointF tempPointOnLine;
  100. PointCollection.Line2DFitting(pointArray, Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_L2, out tempDirection, out tempPointOnLine);
  101. direction = new Vector<float>(new float[2]{tempDirection.X, tempDirection.Y});
  102. pointOnLine = new Vector<float>(new float[2] { tempPointOnLine.X, tempPointOnLine.Y });
  103. Vector<int> fp1 = fingerPoints[0];
  104. Vector<int> fp2 = fingerPoints[0];
  105. length = 0.0f;
  106. foreach (Vector<int> fp in fingerPoints) {
  107. float distanceToFP1 = fp.subDistance(fp1,2);
  108. float distanceToFP2 = fp.subDistance(fp2,2);
  109. if (length < distanceToFP1 && distanceToFP1 >= distanceToFP2)
  110. {
  111. fp2 = fp;
  112. length = distanceToFP1;
  113. }
  114. else if (length < distanceToFP2 && distanceToFP2 > distanceToFP1)
  115. {
  116. fp1 = fp;
  117. length = distanceToFP2;
  118. }
  119. }
  120. if (fp1.y < fp2.y)
  121. {
  122. tipPoint = fp1;
  123. handPoint = fp2;
  124. }
  125. else
  126. {
  127. tipPoint = fp2;
  128. handPoint = fp1;
  129. }
  130. //update start+end
  131. lineEndPoint1 = projectToLine(tipPoint);
  132. lineEndPoint2 = projectToLine(handPoint);
  133. lineUpToDate = true;
  134. }
  135. private Vector<float> projectToLine(Vector<int> p)
  136. {
  137. float px = p.x, py = p.y, dx = direction.x, dy = direction.y, ox = pointOnLine.x, oy = pointOnLine.y;
  138. float diffx = px - ox;
  139. float diffy = py - oy;
  140. float diff_d = (diffx * dx + diffy * dy);
  141. float d_d = (dx * dx + dy * dy);
  142. float q = diff_d / d_d;
  143. float newX = ox + q * dx;
  144. float newY = oy + q * dy;
  145. return new Vector<float>(new float[2]{newX, newY});
  146. }
  147. }
  148. }