Browse Source

documented Recognition.HandRecognition

Alexander Hendrich 10 years ago
parent
commit
b03865876c

+ 1 - 1
bbiwarg/Recognition/FingerRecognition/FingerTracker.cs

@@ -10,7 +10,7 @@ using bbiwarg.Input.InputHandling;
 namespace bbiwarg.Recognition.FingerRecognition
 {
     /// <summary>
-    /// Tracks fingers over  multiple frames.
+    /// Keeps track of fingers over a period of time.
     /// </summary>
     class FingerTracker : Tracker<Finger, TrackedFinger>
     {

+ 46 - 1
bbiwarg/Recognition/HandRecognition/Hand.cs

@@ -13,13 +13,36 @@ using bbiwarg.Recognition.PalmRecognition;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
+    /// <summary>
+    /// Represents a Hand.
+    /// </summary>
     public class Hand : TrackableObject
     {
+        /// <summary>
+        /// the center of gravity of the hand
+        /// </summary>
         public Vector2D Centroid { get; private set; }
+
+        /// <summary>
+        /// a mask of the hand (0=outside, 1=in hand)
+        /// </summary>
         public Image<Gray, byte> Mask { get; private set; }
+
+        /// <summary>
+        /// the fingers belonging to the hand
+        /// </summary>
         public List<Finger> Fingers { get; private set; }
+
+        /// <summary>
+        /// the palm belonging to the hand
+        /// </summary>
         public Palm Palm { get; set; }
 
+        /// <summary>
+        /// Initializes a new instance of the Hand class.
+        /// </summary>
+        /// <param name="mask">The mask.</param>
+        /// <param name="fingers">The fingers.</param>
         public Hand(Image<Gray, byte> mask, List<Finger> fingers)
         {
             Mask = mask;
@@ -29,11 +52,20 @@ namespace bbiwarg.Recognition.HandRecognition
                 finger.Hand = this;
         }
 
+        /// <summary>
+        /// Checks wether a given point is inside the hand.
+        /// </summary>
+        /// <param name="point">the point</param>
+        /// <returns>wether the point is inside the hand</returns>
         public bool isInside(Vector2D point)
         {
             return (Mask.Data[point.IntY, point.IntX, 0] != 0);
         }
 
+        /// <summary>
+        /// Merges another Hand to this hand by extending the mask and adding the fingers.
+        /// </summary>
+        /// <param name="mergeHand">the other hand</param>
         public void mergeWith(Hand mergeHand)
         {
             extendMask(mergeHand.Mask);
@@ -42,13 +74,23 @@ namespace bbiwarg.Recognition.HandRecognition
                 finger.Hand = this;
         }
 
+        /// <summary>
+        /// Extends the mask.
+        /// </summary>
+        /// <param name="extendMask">the mask of the extension</param>
         public void extendMask(Image<Gray, byte> extendMask)
         {
             Mask = Mask.Or(extendMask);
         }
 
-        public void fillOverlappingFingers(List<Finger> otherFingers, ImageSize imageSize)
+        /// <summary>
+        /// Fills the Hand mask defects caused by overlapping fingers.
+        /// </summary>
+        /// <param name="otherFingers">list of fingers that don't belong to this hand</param>
+        public void fillOverlappingFingers(List<Finger> otherFingers)
         {
+            ImageSize imageSize = new ImageSize(Mask.Width, Mask.Height);
+
             foreach (Finger finger in otherFingers)
             {
                 FingerSliceTrail trail = null;
@@ -73,6 +115,9 @@ namespace bbiwarg.Recognition.HandRecognition
             Mask = Mask.Dilate(1);
         }
 
+        /// <summary>
+        /// Finds the hands centroid (center of gravity).
+        /// </summary>
         public void findCentroid()
         {
             MCvPoint2D64f gravityCenter = Mask.GetMoments(true).GravityCenter;

+ 62 - 1
bbiwarg/Recognition/HandRecognition/HandDetector.cs

@@ -16,14 +16,40 @@ using Emgu.CV.Structure;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
+    /// <summary>
+    /// Finds Hands by iterating over all fingers and flooding them. Each filled region is considered to be one hand and each finger belongs to one hand. To improve the hand contours, the hand mask are filled with the defects caused by overlapping fingers.
+    /// </summary>
     class HandDetector
     {
+        /// <summary>
+        /// the depth image of the current frame
+        /// </summary>
         private DepthImage depthImage;
+
+        /// <summary>
+        /// the modified depth image of the current frame (hand flooding changes depth image)
+        /// </summary>
         private Image<Gray, byte> modifiedHandDepthImage;
+
+        /// <summary>
+        /// the fingers in the current frame
+        /// </summary>
         private List<Finger> fingers;
+
+        /// <summary>
+        /// a mapping of hands and list of fingers, that don't belong to that specific hand
+        /// </summary>
         private Dictionary<Hand, List<Finger>> otherHandsFingers;
+
+        /// <summary>
+        /// the hands in the current frame
+        /// </summary>
         private List<Hand> hands;
 
+        /// <summary>
+        /// Detects Hands in the current frame and stores found hands in frameData.detectedHands
+        /// </summary>
+        /// <param name="frameData">the current frame</param>
         public void detectHands(FrameData frameData)
         {
             depthImage = frameData.DepthImage;
@@ -37,6 +63,9 @@ namespace bbiwarg.Recognition.HandRecognition
             frameData.DetectedHands = hands;
         }
 
+        /// <summary>
+        /// Creates the modified hand image. The image is a copy of the original depth image with a contour around each finger (to prevent floodfill from filling through fingers).
+        /// </summary>
         private void createModifiedHandEdgeImage()
         {
             modifiedHandDepthImage = depthImage.Image.Copy();
@@ -49,6 +78,9 @@ namespace bbiwarg.Recognition.HandRecognition
             }
         }
 
+        /// <summary>
+        /// Finds hands by flood filling from each finger (mask). All unassigned fingers that lie within the hand are assigned to the hand, all other fingers are mapped as fingers that don't belong to that specific hand.
+        /// </summary>
         private void findHands()
         {
             hands = new List<Hand>();
@@ -80,6 +112,11 @@ namespace bbiwarg.Recognition.HandRecognition
             }
         }
 
+        /// <summary>
+        /// Flood fills from a given point and returns the filled area as mask.
+        /// </summary>
+        /// <param name="p">flood fill starting point</param>
+        /// <returns>the filled area as mask</returns>
         private Image<Gray, byte> getHandMask(Vector2D p)
         {
             Image<Gray, byte> mask = new Image<Gray, byte>(depthImage.Size.Width + 2, depthImage.Size.Height + 2);
@@ -88,12 +125,18 @@ namespace bbiwarg.Recognition.HandRecognition
             return mask.Copy(new Rectangle(1, 1, depthImage.Size.Width, depthImage.Size.Height));
         }
 
+        /// <summary>
+        /// Fixes overlapping fingers by merging two hands if they are seperated by a finger and/or fills holes caused by overlapping fingers.
+        /// </summary>
         private void fixOverlappingFingers()
         {
             extendOrMergeThroughOverlappingFingers();
             fillOverlappingFingers();
         }
 
+        /// <summary>
+        /// Merges two hands if they are seperatd by an overlapping finger or extends the hand mask through an overlapping finger.
+        /// </summary>
         private void extendOrMergeThroughOverlappingFingers()
         {
             List<Hand> mergedHands = new List<Hand>();
@@ -156,14 +199,26 @@ namespace bbiwarg.Recognition.HandRecognition
                 hands.Remove(mergedHand);
         }
 
+        /// <summary>
+        /// Merges two hands together and updates the list of other hands fingers.
+        /// </summary>
+        /// <param name="hand">the first hand (other hand will be merged to this one)</param>
+        /// <param name="mergeHand">the second hand (this hand will be dropped afterwards)</param>
         private void mergeToHand(Hand hand, Hand mergeHand)
         {
             hand.mergeWith(mergeHand);
 
             foreach (Finger finger in mergeHand.Fingers)
                 otherHandsFingers[hand].Remove(finger);
+
+            otherHandsFingers.Remove(mergeHand);
         }
 
+        /// <summary>
+        /// Extends the hand mask of a given hand by flood filling starting from the given point.
+        /// </summary>
+        /// <param name="hand">the hand that should be extended</param>
+        /// <param name="p">the flood fill starting point</param>
         private void extendToHand(Hand hand, Vector2D p)
         {
             Image<Gray, byte> extendMask = getHandMask(p);
@@ -173,14 +228,20 @@ namespace bbiwarg.Recognition.HandRecognition
                 hand.extendMask(extendMask);
         }
 
+        /// <summary>
+        /// Fills holes caused by overlapping fingers.
+        /// </summary>
         private void fillOverlappingFingers()
         {
             foreach (Hand hand in hands)
             {
-                hand.fillOverlappingFingers(otherHandsFingers[hand], depthImage.Size);
+                hand.fillOverlappingFingers(otherHandsFingers[hand]);
             }
         }
 
+        /// <summary>
+        /// Finds the hands centroids.
+        /// </summary>
         private void findCentroids() {
             foreach (Hand hand in hands)
                 hand.findCentroid();

+ 22 - 0
bbiwarg/Recognition/HandRecognition/HandTracker.cs

@@ -9,24 +9,46 @@ using bbiwarg.Utility;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
+    /// <summary>
+    /// Keeps track of hands over a period of time.
+    /// </summary>
     class HandTracker : Tracker<Hand, TrackedHand>
     {
+        /// <summary>
+        /// Initializes a new instance of the HandTracker class.
+        /// </summary>
+        /// <param name="imageSize">Size of the input image.</param>
         public HandTracker(ImageSize imageSize)
             : base(imageSize)
         {
         }
 
+        /// <summary>
+        /// Updates the TrackedHands with the detected hands in the current frame and stores the results in frameData.trackedFingers.
+        /// </summary>
+        /// <param name="frameData">the current frame</param>
         public void trackHands(FrameData frameData)
         {
             trackObjects(frameData.DetectedHands);
             frameData.TrackedHands = getCurrentObjectsWithState(TrackingState.Tracked);
         }
 
+        /// <summary>
+        /// Calculates the similarity [0-1] of a tracked Hand and a detected Hand.
+        /// </summary>
+        /// <param name="trackedHand">the tracked hand</param>
+        /// <param name="detectedHand">the detected hand</param>
+        /// <returns></returns>
         public override float calculateSimilarity(TrackedHand trackedHand, Hand detectedHand)
         {
             return getPositionSimilarity(trackedHand.CentroidPrediction, detectedHand.Centroid, Parameters.HandTrackerMaxCentroidRelativeMove);
         }
 
+        /// <summary>
+        /// Creates a TrackedHand.
+        /// </summary>
+        /// <param name="detectedObject">the detected hand</param>
+        /// <returns>a Trackedhand</returns>
         protected override TrackedHand createTrackedObject(Hand detectedObject)
         {
             return new TrackedHand(idPool.getNextUnusedID(), detectedObject, Parameters.HandTrackerNumFramesDetectedUntilTracked, Parameters.HandTrackerNumFramesLostUntilDeleted);

+ 23 - 0
bbiwarg/Recognition/HandRecognition/TrackedHand.cs

@@ -8,12 +8,28 @@ using bbiwarg.Utility;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
+    /// <summary>
+    /// Represents a hand that is tracked for several frames
+    /// </summary>
     class TrackedHand : TrackedObject<Hand>
     {
+        /// <summary>
+        /// the kalman filter for the centroid prediction
+        /// </summary>
         private Kalman2DPositionFilter centroidKalman;
 
+        /// <summary>
+        /// predicted position of the centroid
+        /// </summary>
         public Vector2D CentroidPrediction { get { return centroidKalman.getPrediction(); } }
 
+        /// <summary>
+        /// Initializes a new instance of the TrackedHand class.
+        /// </summary>
+        /// <param name="id">The track ID.</param>
+        /// <param name="detectedHand">The detected hand.</param>
+        /// <param name="numFramesDetectedUntilTracked">The number of consecutive frames detected until the hand is considered to be tracked.</param>
+        /// <param name="numFramesLostUntilDeleted">The number of consecutive frames lost until the hand should be deleted.</param>
         public TrackedHand(int id, Hand detectedHand, int numFramesDetectedUntilTracked, int numFramesLostUntilDeleted)
             : base(id, detectedHand, numFramesDetectedUntilTracked, numFramesLostUntilDeleted)
         {
@@ -23,6 +39,10 @@ namespace bbiwarg.Recognition.HandRecognition
             logStateChange();
         }
 
+        /// <summary>
+        /// Updates the tracked hand with the given hand, logs the state change and updates the centroid  prediction (kalman filter)
+        /// </summary>
+        /// <param name="detectedHand">the detected hand</param>
         public override void updateFrame(Hand detectedHand)
         {
             base.updateFrame(detectedHand);
@@ -34,6 +54,9 @@ namespace bbiwarg.Recognition.HandRecognition
                 centroidKalman.getCorrectedPosition(detectedHand.Centroid);
         }
 
+        /// <summary>
+        /// logs the state change
+        /// </summary>
         private void logStateChange()
         {
             String stateAsString = CurrentState.ToString().ToLower();