FingerTracker.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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.Graphics;
  9. using bbiwarg.Utility;
  10. namespace bbiwarg.Recognition.FingerRecognition
  11. {
  12. struct FingerSimilarity
  13. {
  14. public float similarity;
  15. public FingerHistory fingerHistory;
  16. public Finger fingerDetected;
  17. }
  18. class FingerTracker
  19. {
  20. public List<FingerHistory> FingerHistories { get; private set; }
  21. public List<Finger> Fingers { get; private set; }
  22. private List<FingerSimilarity> similarities;
  23. public FingerTracker()
  24. {
  25. reset();
  26. }
  27. public void reset()
  28. {
  29. FingerHistories = new List<FingerHistory>();
  30. Fingers = new List<Finger>();
  31. }
  32. public void updateTrackedFingers(List<Finger> detectedFingers, OutputImage outputImage)
  33. {
  34. if (FingerHistories.Count == 0)
  35. {
  36. foreach (Finger finger in detectedFingers)
  37. {
  38. FingerHistory fh = new FingerHistory(finger);
  39. FingerHistories.Add(fh);
  40. Logger.log("Finger #" + fh.ID + " detected", Logger.LogSubject.FingerTracker);
  41. }
  42. }
  43. else
  44. {
  45. updateHistories(detectedFingers);
  46. removeLongLostFingers();
  47. }
  48. drawFingers(outputImage);
  49. drawFingerIDs(outputImage);
  50. }
  51. private void updateHistories(List<Finger> detectedFingers)
  52. {
  53. Fingers = new List<Finger>();
  54. List<FingerHistory> unasignedFingerHistories = new List<FingerHistory>();
  55. foreach (FingerHistory fh in FingerHistories)
  56. unasignedFingerHistories.Add(fh);
  57. List<Finger> unasignedDetectedFingers = new List<Finger>();
  58. foreach (Finger f in detectedFingers)
  59. unasignedDetectedFingers.Add(f);
  60. createSimilarities(detectedFingers);
  61. while (similarities.Count > 0)
  62. {
  63. FingerSimilarity maxSimilarity = similarities[0];
  64. FingerHistory fingerHistory = maxSimilarity.fingerHistory;
  65. Finger fingerDetected = maxSimilarity.fingerDetected;
  66. fingerHistory.addFinger(fingerDetected);
  67. Fingers.Add(fingerDetected);
  68. unasignedFingerHistories.Remove(fingerHistory);
  69. unasignedDetectedFingers.Remove(fingerDetected);
  70. removeConcurringFingerSimilarities(maxSimilarity);
  71. }
  72. //add new fingerHistory for each new unmatched finger
  73. foreach (Finger finger in unasignedDetectedFingers)
  74. {
  75. FingerHistory fh = new FingerHistory(finger);
  76. FingerHistories.Add(fh);
  77. Logger.log("Finger #" + fh.ID + " detected", Logger.LogSubject.FingerTracker);
  78. }
  79. //add null finger to TrackedFingers that haven't found a match in this frame (status tracked->lost)
  80. foreach (FingerHistory fh in unasignedFingerHistories)
  81. {
  82. if (fh.CurrentState != TrackingState.Lost)
  83. Logger.log("Finger #" + fh.ID + " lost", Logger.LogSubject.FingerTracker);
  84. fh.addFinger(null);
  85. }
  86. }
  87. private void createSimilarities(List<Finger> detectedFingers)
  88. {
  89. similarities = new List<FingerSimilarity>();
  90. foreach (FingerHistory fh in FingerHistories)
  91. {
  92. foreach (Finger fingerDetected in detectedFingers)
  93. {
  94. float similarity = fingerDetected.getSimilarity(fh.LastFinger);
  95. if (similarity > Constants.FingerMinSimilarityForTracking)
  96. {
  97. FingerSimilarity fs = new FingerSimilarity();
  98. fs.similarity = similarity;
  99. fs.fingerHistory = fh;
  100. fs.fingerDetected = fingerDetected;
  101. similarities.Add(fs);
  102. }
  103. }
  104. }
  105. similarities.Sort((fs1, fs2) => fs2.similarity.CompareTo(fs1.similarity));
  106. }
  107. private void removeConcurringFingerSimilarities(FingerSimilarity removeSimilarity)
  108. {
  109. for (int i = similarities.Count - 1; i >= 0; i--)
  110. {
  111. FingerSimilarity currentSimilarity = similarities[i];
  112. if (currentSimilarity.fingerHistory == removeSimilarity.fingerHistory || currentSimilarity.fingerDetected == removeSimilarity.fingerDetected)
  113. similarities.RemoveAt(i);
  114. }
  115. }
  116. private void removeFingerDetectedFromSimilarities(Finger removeFinger)
  117. {
  118. for (int i = similarities.Count - 1; i >= 0; i--)
  119. {
  120. if (similarities[i].fingerDetected == removeFinger)
  121. similarities.RemoveAt(i);
  122. }
  123. }
  124. private void removeLongLostFingers()
  125. {
  126. for (int i = FingerHistories.Count - 1; i >= 0; i--)
  127. {
  128. FingerHistory fh = FingerHistories[i];
  129. if (fh.CurrentState == TrackingState.Lost && fh.getNumFramesInCurrentState() >= Constants.FingerNumFramesUntilLost)
  130. {
  131. FingerHistories.RemoveAt(i);
  132. Logger.log("Finger #" + fh.ID + " deleted", Logger.LogSubject.FingerTracker);
  133. }
  134. }
  135. }
  136. private void drawFingers(OutputImage outputImage)
  137. {
  138. foreach (Finger finger in Fingers)
  139. {
  140. finger.draw(outputImage, true);
  141. }
  142. }
  143. private void drawFingerIDs(OutputImage outputImage)
  144. {
  145. foreach (FingerHistory fh in FingerHistories)
  146. {
  147. if (fh.CurrentFinger != null)
  148. {
  149. Finger f = fh.CurrentFinger;
  150. outputImage.drawText(f.MidPoint.IntX, f.MidPoint.IntY, fh.ID.ToString(), Constants.FingerIDColor);
  151. }
  152. }
  153. }
  154. }
  155. }