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