using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using bbiwarg.Images; using bbiwarg.Graphics; namespace bbiwarg.Recognition.FingerRecognition { struct FingerSimilarity { public float similarity; public FingerHistory fingerHistory; public Finger fingerDetected; } class FingerTracker { public List FingerHistories { get; private set; } public List Fingers { get; private set; } private List similarities; public FingerTracker() { FingerHistories = new List(); } public void updateTrackedFingers(List detectedFingers) { if (FingerHistories.Count == 0) { foreach (Finger finger in detectedFingers) FingerHistories.Add(new FingerHistory(finger)); } else { updateHistories(detectedFingers); removeLongLostFingers(); } } private void updateHistories(List detectedFingers) { Fingers = new List(); List unasignedFingerHistories = new List(); foreach (FingerHistory fh in FingerHistories) unasignedFingerHistories.Add(fh); List unasignedDetectedFingers = new List(); foreach (Finger f in detectedFingers) unasignedDetectedFingers.Add(f); createSimilarities(detectedFingers); while (similarities.Count > 0) { FingerSimilarity maxSimilarity = similarities[0]; FingerHistory fingerHistory = maxSimilarity.fingerHistory; Finger fingerDetected = maxSimilarity.fingerDetected; fingerHistory.addFinger(fingerDetected); Fingers.Add(fingerDetected); unasignedFingerHistories.Remove(fingerHistory); unasignedDetectedFingers.Remove(fingerDetected); removeConcurringFingerSimilarities(maxSimilarity); } //add new fingerHistory for each new unmatched finger foreach (Finger f in unasignedDetectedFingers) { FingerHistories.Add(new FingerHistory(f)); } //add null finger to TrackedFingers that haven't found a match in this frame (status tracked->lost) foreach (FingerHistory fh in unasignedFingerHistories) { fh.addFinger(null); } } private void createSimilarities(List detectedFingers) { similarities = new List(); foreach (FingerHistory fh in FingerHistories) { foreach (Finger fingerDetected in detectedFingers) { float similarity = fingerDetected.getSimilarity(fh.LastFinger); if (similarity > Constants.FingerMinSimilarityForTracking) { FingerSimilarity fs = new FingerSimilarity(); fs.similarity = similarity; fs.fingerHistory = fh; fs.fingerDetected = fingerDetected; similarities.Add(fs); } } } similarities.Sort((fs1, fs2) => fs1.similarity.CompareTo(fs2.similarity)); } private void removeConcurringFingerSimilarities(FingerSimilarity removeSimilarity) { for (int i = similarities.Count - 1; i >= 0; i--) { FingerSimilarity currentSimilarity = similarities[i]; if (currentSimilarity.fingerHistory == removeSimilarity.fingerHistory || currentSimilarity.fingerDetected == removeSimilarity.fingerDetected) similarities.RemoveAt(i); } } private void removeFingerDetectedFromSimilarities(Finger removeFinger) { for (int i = similarities.Count - 1; i >= 0; i--) { if (similarities[i].fingerDetected == removeFinger) similarities.RemoveAt(i); } } private void removeLongLostFingers() { for (int i = FingerHistories.Count - 1; i >= 0; i--) { FingerHistory tf = FingerHistories[i]; if (tf.CurrentState == TrackingState.Lost && tf.getNumFramesInCurrentState() >= Constants.FingerNumFramesUntilLost) FingerHistories.RemoveAt(i); } } } }