Преглед на файлове

implemted fingerTracker

Alexander Hendrich преди 10 години
родител
ревизия
7bc49bd3f3

+ 1 - 0
bbiwarg/Constants.cs

@@ -39,6 +39,7 @@ namespace bbiwarg
         public static readonly int FingerMinSize = 5;
         public static readonly int FingerNumSlicesForRelativeDirection = FingerRemoveNumSlicesForCorrection;
         public static readonly int FingerNumFramesUntilTracked = 2;
+        public static readonly int FingerNumFramesUntilLost = 3;
         public static readonly int FingerOutSliceFactor = 10;
         public static readonly int FingerContourMargin = 2;
         public static readonly int FingerSliceOverlapFactor = 2;

+ 11 - 6
bbiwarg/Recognition/FingerRecognition/TrackedFinger.cs → bbiwarg/Recognition/FingerRecognition/FingerHistory.cs

@@ -14,28 +14,30 @@ namespace bbiwarg.Recognition.FingerRecognition
         Lost,
     }
 
-    class TrackedFinger
+    class FingerHistory
     {
         public List<Finger> Fingers { get; private set; }
         public List<TrackingState> States { get; private set; }
+        public Finger LastFinger { get; private set; }
         public Finger CurrentFinger { get { return Fingers[Fingers.Count - 1]; } }
         public TrackingState CurrentState { get { return States[States.Count - 1]; } }
 
 
-        public TrackedFinger(Finger finger)
+        public FingerHistory(Finger finger)
         {
             Fingers = new List<Finger>();
             States = new List<TrackingState>();
 
             Fingers.Add(finger);
             States.Add(TrackingState.Detected);
+            LastFinger = finger;
         }
 
         public void addFinger(Finger finger)
         {
             TrackingState previousState = CurrentState;
             TrackingState newState = TrackingState.None;
-            int numFramesSinceInState = getNumFramesSinceInState(previousState);
+            int numFramesInCurrentState = getNumFramesInCurrentState();
 
             if (finger == null)
                 newState = TrackingState.Lost;
@@ -43,7 +45,7 @@ namespace bbiwarg.Recognition.FingerRecognition
                 newState = TrackingState.Tracked;
             else if (previousState == TrackingState.Detected)
             {
-                if (numFramesSinceInState == Constants.FingerNumFramesUntilTracked)
+                if (numFramesInCurrentState == Constants.FingerNumFramesUntilTracked)
                     newState = TrackingState.Tracked;
                 else
                     newState = TrackingState.Detected;
@@ -51,14 +53,17 @@ namespace bbiwarg.Recognition.FingerRecognition
 
             Fingers.Add(finger);
             States.Add(newState);
+            if (finger != null)
+                LastFinger = finger;
         }
 
-        public int getNumFramesSinceInState(TrackingState state)
+        public int getNumFramesInCurrentState()
         {
+            TrackingState currentState = CurrentState;
             int count = 0;
             for (int i = States.Count - 1; i >= 0; i++)
             {
-                if (States[i] == state)
+                if (States[i] == currentState)
                     count++;
                 else
                     break;

+ 114 - 6
bbiwarg/Recognition/FingerRecognition/FingerTracker.cs

@@ -9,20 +9,128 @@ using bbiwarg.Graphics;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
+    struct FingerSimilarity
+    {
+        public float similarity;
+        public FingerHistory fingerHistory;
+        public Finger fingerDetected;
+    }
+
     class FingerTracker
     {
-        public List<TrackedFinger> TrackedFingers { get; private set; }
+        public List<FingerHistory> FingerHistories { get; private set; }
+        public List<Finger> Fingers { get; private set; }
+        private List<FingerSimilarity> similarities;
 
         public FingerTracker()
         {
-            TrackedFingers = new List<TrackedFinger>();
+            FingerHistories = new List<FingerHistory>();
+        }
+
+        public void updateTrackedFingers(List<Finger> detectedFingers)
+        {
+            if (FingerHistories.Count == 0)
+            {
+                foreach (Finger finger in detectedFingers)
+                    FingerHistories.Add(new FingerHistory(finger));
+            }
+            else
+            {
+                updateHistories(detectedFingers);
+                removeLongLostFingers();
+            }
+        }
+
+        private void updateHistories(List<Finger> detectedFingers)
+        {
+            Fingers = new List<Finger>();
+
+            List<FingerHistory> unasignedFingerHistories = new List<FingerHistory>();
+            foreach (FingerHistory fh in FingerHistories)
+                unasignedFingerHistories.Add(fh);
+
+            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);
+            }
+
+            //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<Finger> detectedFingers)
+        {
+            similarities = new List<FingerSimilarity>();
+
+            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);
+            }
         }
 
-        public void updateTrackedFingers(List<Finger> detectedFingers) {
-            Dictionary<TrackedFinger, Finger> assignments = new Dictionary<TrackedFinger, Finger>();
+        private void removeFingerDetectedFromSimilarities(Finger removeFinger)
+        {
+            for (int i = similarities.Count - 1; i >= 0; i--)
+            {
+                if (similarities[i].fingerDetected == removeFinger)
+                    similarities.RemoveAt(i);
+            }
+        }
 
-            foreach (TrackedFinger tf in TrackedFingers) {
-                Finger bestFit = tf.findBestFit()
+        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);
             }
         }
     }

+ 1 - 1
bbiwarg/VideoHandle.cs

@@ -191,7 +191,7 @@ namespace bbiwarg
 
             //detect touchEvents
             Timer.start("touchDetection");
-            touchDetector = new TouchDetector(fingerTracker.TrackedFingers, depthImage, OutputImages[0]);
+            touchDetector = new TouchDetector(fingerTracker.Fingers, depthImage, OutputImages[0]);
             if (palmDetector.PalmQuad != null)
                 palmTouchDetector = new PalmTouchDetector(touchDetector.TouchEvents, palmDetector.PalmQuad);
             Timer.stop("touchDetection");

+ 1 - 1
bbiwarg/bbiwarg.csproj

@@ -72,7 +72,7 @@
     <Compile Include="Recognition\FingerRecognition\FingerSliceTrail.cs" />
     <Compile Include="Recognition\FingerRecognition\FingerSlice.cs" />
     <Compile Include="Recognition\FingerRecognition\FingerTracker.cs" />
-    <Compile Include="Recognition\FingerRecognition\TrackedFinger.cs" />
+    <Compile Include="Recognition\FingerRecognition\FingerHistory.cs" />
     <Compile Include="Recognition\HandRecognition\Hand.cs" />
     <Compile Include="Recognition\HandRecognition\HandDetector.cs" />
     <Compile Include="Recognition\PalmRecognition\PalmDetector.cs" />