|
@@ -9,79 +9,129 @@ using bbiwarg.Graphics;
|
|
|
|
|
|
namespace bbiwarg.Recognition.FingerRecognition
|
|
|
{
|
|
|
+ struct FingerSimilarity
|
|
|
+ {
|
|
|
+ public float similarity;
|
|
|
+ public FingerHistory fingerHistory;
|
|
|
+ public Finger fingerDetected;
|
|
|
+ }
|
|
|
+
|
|
|
class FingerTracker
|
|
|
{
|
|
|
- private OutputImage outputImage;
|
|
|
- private List<Finger>[] detectedFingers;
|
|
|
- private int framesUntilTracked;
|
|
|
- public List<Finger> TrackedFingers { get; private set; }
|
|
|
+ public List<FingerHistory> FingerHistories { get; private set; }
|
|
|
+ public List<Finger> Fingers { get; private set; }
|
|
|
+ private List<FingerSimilarity> similarities;
|
|
|
|
|
|
public FingerTracker()
|
|
|
{
|
|
|
- framesUntilTracked = Constants.FingerNumFramesUntilTracked;
|
|
|
- detectedFingers = new List<Finger>[framesUntilTracked];
|
|
|
- TrackedFingers = new List<Finger>();
|
|
|
+ FingerHistories = new List<FingerHistory>();
|
|
|
+ }
|
|
|
|
|
|
- for (int i = 0; i < framesUntilTracked; i++)
|
|
|
+ public void updateTrackedFingers(List<Finger> detectedFingers)
|
|
|
+ {
|
|
|
+ if (FingerHistories.Count == 0)
|
|
|
+ {
|
|
|
+ foreach (Finger finger in detectedFingers)
|
|
|
+ FingerHistories.Add(new FingerHistory(finger));
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- detectedFingers[i] = new List<Finger>();
|
|
|
+ updateHistories(detectedFingers);
|
|
|
+ removeLongLostFingers();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void setDetectedTouchEventsThisFrame(List<Finger> detectedFingersThisFrame, OutputImage outputImage)
|
|
|
+ private void updateHistories(List<Finger> detectedFingers)
|
|
|
{
|
|
|
- this.outputImage = outputImage;
|
|
|
+ Fingers = new List<Finger>();
|
|
|
+
|
|
|
+ List<FingerHistory> unasignedFingerHistories = new List<FingerHistory>();
|
|
|
+ foreach (FingerHistory fh in FingerHistories)
|
|
|
+ unasignedFingerHistories.Add(fh);
|
|
|
|
|
|
- for (int i = (framesUntilTracked - 1); i > 0; i--)
|
|
|
+ List<Finger> unasignedDetectedFingers = new List<Finger>();
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ foreach (Finger f in unasignedDetectedFingers)
|
|
|
{
|
|
|
- detectedFingers[i] = detectedFingers[i - 1];
|
|
|
+ FingerHistories.Add(new FingerHistory(f));
|
|
|
}
|
|
|
- detectedFingers[0] = detectedFingersThisFrame;
|
|
|
|
|
|
+
|
|
|
+ foreach (FingerHistory fh in unasignedFingerHistories)
|
|
|
+ {
|
|
|
+ fh.addFinger(null);
|
|
|
+ }
|
|
|
|
|
|
- findTrackedFingers();
|
|
|
}
|
|
|
|
|
|
- private void findTrackedFingers()
|
|
|
+ private void createSimilarities(List<Finger> detectedFingers)
|
|
|
{
|
|
|
- TrackedFingers = new List<Finger>();
|
|
|
+ similarities = new List<FingerSimilarity>();
|
|
|
|
|
|
- foreach (Finger finger in detectedFingers[0])
|
|
|
+ foreach (FingerHistory fh in FingerHistories)
|
|
|
{
|
|
|
- bool tracked = true;
|
|
|
- Finger mostSimilarLastFrame = finger;
|
|
|
- for (int i = 1; i < framesUntilTracked; i++)
|
|
|
+ foreach (Finger fingerDetected in detectedFingers)
|
|
|
{
|
|
|
- Finger mostSimilarThisFrame = getMostSimilarFingerInFrame(mostSimilarLastFrame, i);
|
|
|
- if (mostSimilarThisFrame == null || mostSimilarLastFrame.getSimilarity(mostSimilarThisFrame) < Constants.FingerMinSimilarityForTracking)
|
|
|
+ float similarity = fingerDetected.getSimilarity(fh.LastFinger);
|
|
|
+ if (similarity > Constants.FingerMinSimilarityForTracking)
|
|
|
{
|
|
|
- tracked = false;
|
|
|
- break;
|
|
|
-
|
|
|
+ FingerSimilarity fs = new FingerSimilarity();
|
|
|
+ fs.similarity = similarity;
|
|
|
+ fs.fingerHistory = fh;
|
|
|
+ fs.fingerDetected = fingerDetected;
|
|
|
+ similarities.Add(fs);
|
|
|
}
|
|
|
}
|
|
|
- if (tracked)
|
|
|
- {
|
|
|
- outputImage.drawLineSegment(finger.LineSegment, Constants.FingerTrackedColor);
|
|
|
- TrackedFingers.Add(finger);
|
|
|
- }
|
|
|
}
|
|
|
+
|
|
|
+ similarities.Sort((fs1, fs2) => fs1.similarity.CompareTo(fs2.similarity));
|
|
|
}
|
|
|
|
|
|
- private Finger getMostSimilarFingerInFrame(Finger finger, int frame)
|
|
|
+ private void removeConcurringFingerSimilarities(FingerSimilarity removeSimilarity)
|
|
|
{
|
|
|
- Finger mostSimilarFinger = null;
|
|
|
- float maxSimilarity = 0;
|
|
|
- foreach (Finger f in detectedFingers[frame])
|
|
|
+ for (int i = similarities.Count - 1; i >= 0; i--)
|
|
|
{
|
|
|
- float similarity = finger.getSimilarity(f);
|
|
|
- if (similarity > maxSimilarity)
|
|
|
- {
|
|
|
- mostSimilarFinger = f;
|
|
|
- maxSimilarity = similarity;
|
|
|
- }
|
|
|
+ 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);
|
|
|
}
|
|
|
- return mostSimilarFinger;
|
|
|
}
|
|
|
}
|
|
|
}
|