Browse Source

documented Recognition.PalmRecognition

Alexander Hendrich 10 years ago
parent
commit
24f22c06e8

+ 1 - 1
bbiwarg/Recognition/HandRecognition/HandTracker.cs

@@ -38,7 +38,7 @@ namespace bbiwarg.Recognition.HandRecognition
         /// </summary>
         /// <param name="trackedHand">the tracked hand</param>
         /// <param name="detectedHand">the detected hand</param>
-        /// <returns></returns>
+        /// <returns>the similarity</returns>
         public override float calculateSimilarity(TrackedHand trackedHand, Hand detectedHand)
         {
             return getPositionSimilarity(trackedHand.CentroidPrediction, detectedHand.Centroid, Parameters.HandTrackerMaxCentroidRelativeMove);

+ 60 - 0
bbiwarg/Recognition/PalmRecognition/Palm.cs

@@ -9,6 +9,9 @@ using bbiwarg.Recognition.Tracking;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
+    /// <summary>
+    /// The handedness of the palm.
+    /// </summary>
     public enum HandSide
     {
         Undefined = 0,
@@ -16,17 +19,61 @@ namespace bbiwarg.Recognition.PalmRecognition
         Left = 2
     }
 
+    /// <summary>
+    /// Represents a palm (each hand with one finger (thumb) has palm)
+    /// </summary>
     public class Palm : TrackableObject
     {
+        /// <summary>
+        /// the hand belonging to this palm
+        /// </summary>
         public Hand Hand { get; private set; }
+
+        /// <summary>
+        /// the thumb's convexity defect
+        /// </summary>
         public ConvexityDefect ThumbDefect { get; private set; }
+
+        /// <summary>
+        /// the handedness
+        /// </summary>
         public HandSide HandSide { get; private set; }
+
+        /// <summary>
+        /// the position of the upper wrist (top left corner for left hand, top right for right hand)
+        /// </summary>
         public Vector2D WristUpper { get; private set; }
+
+        /// <summary>
+        /// the position of the upper fingers (top right for left hand, top left for left hannd)
+        /// </summary>
         public Vector2D FingersUpper { get; private set; }
+
+        /// <summary>
+        /// the position of the fingers lower (bottom right for left hand, bottom left for right hand)
+        /// </summary>
         public Vector2D FingersLower { get; private set; }
+
+        /// <summary>
+        /// the position of the wrist lower (bottom left for left hand, bottom right for right hand)
+        /// </summary>
         public Vector2D WristLower { get; private set; }
+
+        /// <summary>
+        /// the quadrangle of the four palm points
+        /// </summary>
         public Quadrangle Quad { get; private set; }
 
+        /// <summary>
+        /// Initializes a new instance of the Palm class.
+        /// </summary>
+        /// <param name="hand">The hand.</param>
+        /// <param name="thumbDefect">The thumb defect.</param>
+        /// <param name="handSide">The handedness.</param>
+        /// <param name="wristUpper">The wrist upper position.</param>
+        /// <param name="fingersUpper">The fingers upper positition.</param>
+        /// <param name="fingersLower">The fingers lower position.</param>
+        /// <param name="wristLower">The wrist lower position.</param>
         public Palm(Hand hand, ConvexityDefect thumbDefect, HandSide handSide, Vector2D wristUpper, Vector2D fingersUpper, Vector2D fingersLower, Vector2D wristLower)
         {
             Hand = hand;
@@ -42,6 +89,11 @@ namespace bbiwarg.Recognition.PalmRecognition
             createQuad();
         }
 
+        /// <summary>
+        /// Gets the relative position [0-1;0-1] from an absolue position.
+        /// </summary>
+        /// <param name="absolutePosition">the absolute position</param>
+        /// <returns>the relative position</returns>
         public Vector2D getRelativePosition(Vector2D absolutePosition)
         {
             Vector2D relativePosition = Quad.getRelativePosition(absolutePosition);
@@ -51,11 +103,19 @@ namespace bbiwarg.Recognition.PalmRecognition
             return new Vector2D(x, y);
         }
 
+        /// <summary>
+        /// Checks if the position is inside the palm (with a tolerance)
+        /// </summary>
+        /// <param name="position">the absolute position</param>
+        /// <returns>wether the position is inside the palm</returns>
         public bool isInside(Vector2D position)
         {
             return Quad.isInside(position, Parameters.PalmInsideTolerance);
         }
 
+        /// <summary>
+        /// Creates the palm quadrangle
+        /// </summary>
         private void createQuad()
         {
             if (HandSide == HandSide.Left)

+ 65 - 2
bbiwarg/Recognition/PalmRecognition/PalmDetector.cs

@@ -14,12 +14,30 @@ using Emgu.CV.Structure;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
+    /// <summary>
+    /// Detects palms by iterating over each hand, if the hand has exactly one finger (possible thumb) it calculates its convexity defects and checks if there is a convexity defect that matches the requirements for a thumb defect. If a thumb defect is found, the four palm points are generated and a new palm is created.
+    /// </summary>
     class PalmDetector
     {
+        /// <summary>
+        /// the depth image of the current frame
+        /// </summary>
         private DepthImage depthImage;
+
+        /// <summary>
+        /// the hands in the current frame
+        /// </summary>
         private List<Hand> hands;
+
+        /// <summary>
+        /// the palms in the current frames
+        /// </summary>
         private List<Palm> palms;
 
+        /// <summary>
+        /// Detects palms in the current frame and stores them in frameData.detectedPalms
+        /// </summary>
+        /// <param name="frameData">the current frame</param>
         public void detectPalms(FrameData frameData)
         {
             depthImage = frameData.DepthImage;
@@ -30,6 +48,9 @@ namespace bbiwarg.Recognition.PalmRecognition
             frameData.DetectedPalms = palms;
         }
 
+        /// <summary>
+        /// Find Palms by checking each hand with only one finger, if that finger is a thumb.
+        /// </summary>
         private void findPalms()
         {
             palms = new List<Palm>();
@@ -48,6 +69,11 @@ namespace bbiwarg.Recognition.PalmRecognition
             }
         }
 
+        /// <summary>
+        /// Gets the convexity Defects from a hand mask.
+        /// </summary>
+        /// <param name="hand">the hand</param>
+        /// <returns>the conveixty defects</returns>
         private List<ConvexityDefect> findConvexityDefects(Hand hand)
         {
             List<ConvexityDefect> convexityDefects;
@@ -63,6 +89,12 @@ namespace bbiwarg.Recognition.PalmRecognition
             return convexityDefects;
         }
 
+        /// <summary>
+        /// Checks all convexity defects sorted by length if they match the thumb defect requirements and returns the first match or null if none match.
+        /// </summary>
+        /// <param name="thumb">the possible thumb</param>
+        /// <param name="convexityDefects">the convexity defects</param>
+        /// <returns></returns>
         private ConvexityDefect findThumbDefect(Finger thumb, List<ConvexityDefect> convexityDefects)
         {
             convexityDefects.Sort((cd1, cd2) => (cd2.Depth.CompareTo(cd1.Depth)));
@@ -74,6 +106,12 @@ namespace bbiwarg.Recognition.PalmRecognition
             return null;
         }
 
+        /// <summary>
+        /// Finds the four palm points and creates a new palm
+        /// </summary>
+        /// <param name="hand">the hand of the palm</param>
+        /// <param name="thumbDefect">the convexity defect of the thumb</param>
+        /// <returns>a new palm</returns>
         private Palm createPalm(Hand hand, ConvexityDefect thumbDefect)
         {
             HandSide side = determineHandSide(thumbDefect);
@@ -83,12 +121,17 @@ namespace bbiwarg.Recognition.PalmRecognition
             float palmLength = wristUpper.getDistanceTo(fingersUpper);
             Vector2D directionWristFingers = thumbDefect.VectorLong.normalize();
             Vector2D directionUpperLower = thumbDefect.VectorLong.getOrthogonal(side == HandSide.Right).normalize();
-            Vector2D wristLower = wristUpper + palmWidth*directionUpperLower;
+            Vector2D wristLower = wristUpper + palmWidth * directionUpperLower;
             Vector2D fingersLower = wristUpper + 0.75f * palmLength * directionWristFingers + 0.75f * palmWidth * directionUpperLower;
 
             return new Palm(hand, thumbDefect, side, wristUpper, fingersUpper, fingersLower, wristLower);
         }
 
+        /// <summary>
+        /// Determines the handedness of the palm's hand
+        /// </summary>
+        /// <param name="thumbDefect">the convexity defect of the thumb</param>
+        /// <returns>the handedness of the palm's hand</returns>
         private HandSide determineHandSide(ConvexityDefect thumbDefect)
         {
             if (thumbDefect.VectorShort.crossProduct(thumbDefect.VectorLong) < 0)
@@ -97,11 +140,17 @@ namespace bbiwarg.Recognition.PalmRecognition
                 return HandSide.Left;
         }
 
+        /// <summary>
+        /// Finds the upper wrist end by walking from the defect.Inner towards the wrist direction, until it reaches the hand boundaries.
+        /// </summary>
+        /// <param name="hand">the hand</param>
+        /// <param name="thumbDefect">the convexity defect of the thumb</param>
+        /// <returns>the position of the upper wrist end</returns>
         private Vector2D findWristUpper(Hand hand, ConvexityDefect thumbDefect)
         {
             Vector2D wristDirection = thumbDefect.VectorLong.getInverse().normalize();
             Vector2D wristUpper = thumbDefect.Inner;
-            Vector2D wristUpperNext = wristUpper + 5*wristDirection;
+            Vector2D wristUpperNext = wristUpper + 5 * wristDirection;
             while (wristUpperNext.isInBound(depthImage.Size) && hand.isInside(wristUpperNext))
             {
                 wristUpper = wristUpperNext;
@@ -110,6 +159,13 @@ namespace bbiwarg.Recognition.PalmRecognition
             return wristUpper;
         }
 
+        /// <summary>
+        /// Finds the upper finger end by walking from the defect.OuterLong in the finger direction, until it reaches the end of the middle finger below.
+        /// </summary>
+        /// <param name="hand">the hand</param>
+        /// <param name="thumbDefect">the convexity defect of the thumb</param>
+        /// <param name="side">the handedness</param>
+        /// <returns>the position of the upper fingers end</returns>
         private Vector2D findFingersUpper(Hand hand, ConvexityDefect thumbDefect, HandSide side)
         {
             Vector2D fingersDirection = thumbDefect.VectorLong.normalize();
@@ -133,6 +189,13 @@ namespace bbiwarg.Recognition.PalmRecognition
             return fingersUpper;
         }
 
+        /// <summary>
+        /// Gets the palm width by checking for the maximum orthogonal length withing the hand along multiple positions on the index finger (defect.inner<->defect.outerLong)
+        /// </summary>
+        /// <param name="hand">the hand</param>
+        /// <param name="thumbDefect">the convexity defect of the thumb</param>
+        /// <param name="side">the handedness</param>
+        /// <returns>the palm width</returns>
         private float findPalmWidth(Hand hand, ConvexityDefect thumbDefect, HandSide side)
         {
             Vector2D lowerDirection = thumbDefect.VectorLong.getOrthogonal(side == HandSide.Right).normalize();

+ 27 - 0
bbiwarg/Recognition/PalmRecognition/PalmTracker.cs

@@ -9,19 +9,37 @@ using bbiwarg.Utility;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
+    /// <summary>
+    /// Keeps track of palms over a period of time.
+    /// </summary>
     class PalmTracker : Tracker<Palm, TrackedPalm>
     {
+
+        /// <summary>
+        /// Initializes a new instance of the PalmTracker class.
+        /// </summary>
+        /// <param name="imageSize">Size of the input image.</param>
         public PalmTracker(ImageSize imageSize)
             : base(imageSize)
         {
         }
 
+        /// <summary>
+        /// Updates the tracked palms with the detected palms in the current frame and stores the (optimized) results in frameData.trackedPalms
+        /// </summary>
+        /// <param name="frameData"></param>
         public void trackPalms(FrameData frameData)
         {
             trackObjects(frameData.DetectedPalms);
             frameData.TrackedPalms = getOptimizedPalms();
         }
 
+        /// <summary>
+        /// Calculates the similarity [0-1] of a tracked palm and a detected palm
+        /// </summary>
+        /// <param name="trackedPalm">the tracked palm</param>
+        /// <param name="detectedPalm">the detected palm</param>
+        /// <returns>the similarity</returns>
         public override float calculateSimilarity(TrackedPalm trackedPalm, Palm detectedPalm)
         {
             float handSimilarity = (detectedPalm.Hand.TrackID == trackedPalm.LastObject.Hand.TrackID) ? 1 : 0;
@@ -33,11 +51,20 @@ namespace bbiwarg.Recognition.PalmRecognition
             return handSimilarity * wristUpperSimilarity * wristLowerSimilarity * fingersUpperSimilarity * fingersLowerSimilarity;
         }
 
+        /// <summary>
+        /// Creates a TrackedPalm
+        /// </summary>
+        /// <param name="detectedPalm">the detected palm</param>
+        /// <returns>a new TrackedPalm</returns>
         protected override TrackedPalm createTrackedObject(Palm detectedPalm)
         {
             return new TrackedPalm(idPool.getNextUnusedID(), detectedPalm, Parameters.PalmTrackerNumFramesDetectedUntilTracked, Parameters.PalmTrackerNumFramesLostUntilDeleted);
         }
 
+        /// <summary>
+        /// Gets all optimized representations of all tracked palms.
+        /// </summary>
+        /// <returns>all tracked palms</returns>
         private List<Palm> getOptimizedPalms()
         {
             List<Palm> optimizedPalms = new List<Palm>();

+ 55 - 0
bbiwarg/Recognition/PalmRecognition/TrackedPalm.cs

@@ -9,19 +9,63 @@ using bbiwarg.Utility;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
+    /// <summary>
+    /// Represents a palm that ist tracked for several frames.
+    /// </summary>
     class TrackedPalm : TrackedObject<Palm>
     {
+        /// <summary>
+        /// the kalman filter for the wrist upper prediction
+        /// </summary>
         private Kalman2DPositionFilter wristUpperKalman;
+
+        /// <summary>
+        /// the kalman filter for the wrist lower prediction
+        /// </summary>
         private Kalman2DPositionFilter wristLowerKalman;
+
+        /// <summary>
+        /// the kalman filter for the fingers upper prediction
+        /// </summary>
         private Kalman2DPositionFilter fingersUpperKalman;
+
+        /// <summary>
+        /// the kalman filter for the fingers lower prediction
+        /// </summary>
         private Kalman2DPositionFilter fingersLowerKalman;
 
+        /// <summary>
+        /// the predicted position of the wrist upper
+        /// </summary>
         public Vector2D WristUpperPrediction { get { return wristUpperKalman.getPrediction(); } }
+
+        /// <summary>
+        /// the predicted position of the wrist lower
+        /// </summary>
         public Vector2D WristLowerPrediction { get { return wristLowerKalman.getPrediction(); } }
+
+        /// <summary>
+        /// the predicted position of the fingers upper
+        /// </summary>
         public Vector2D FingersUpperPrediction { get { return fingersUpperKalman.getPrediction(); } }
+
+        /// <summary>
+        /// the predicted position of the fingers lower
+        /// </summary>
         public Vector2D FingersLowerPrediction { get { return fingersLowerKalman.getPrediction(); } }
+
+        /// <summary>
+        /// the optimized palm (using predicted palm points)
+        /// </summary>
         public Palm OptimizedPalm { get; private set; }
 
+        /// <summary>
+        /// Initializes a new instance of the TrackedPalm class.
+        /// </summary>
+        /// <param name="id">The track ID.</param>
+        /// <param name="detectedPalm">The detected palm.</param>
+        /// <param name="numFramesDetectedUntilTracked">The number of consecutive frames detected until the palm is considered tracked.</param>
+        /// <param name="numFramesLostUntilDeleted">The number of consecutive frames lost until the palm is deleted.</param>
         public TrackedPalm(int id, Palm detectedPalm, int numFramesDetectedUntilTracked, int numFramesLostUntilDeleted)
             : base(id, detectedPalm, numFramesDetectedUntilTracked, numFramesLostUntilDeleted)
         {
@@ -38,6 +82,10 @@ namespace bbiwarg.Recognition.PalmRecognition
             logStateChange();
         }
 
+        /// <summary>
+        /// Updates the tracked palm with the given palm, logs the statechange, updates the palm point predictions and the optimized palm.
+        /// </summary>
+        /// <param name="detectedPalm"></param>
         public override void updateFrame(Palm detectedPalm)
         {
             base.updateFrame(detectedPalm);
@@ -56,11 +104,18 @@ namespace bbiwarg.Recognition.PalmRecognition
             }
         }
 
+        /// <summary>
+        /// Updates the optimized palm by creating a new palm with the predicted palm points
+        /// </summary>
+        /// <param name="detectedPalm"></param>
         private void updateOptimizedPalm(Palm detectedPalm)
         {
             OptimizedPalm = new Palm(detectedPalm.Hand, detectedPalm.ThumbDefect, detectedPalm.HandSide, WristUpperPrediction, FingersUpperPrediction, FingersLowerPrediction, WristLowerPrediction);
         }
 
+        /// <summary>
+        /// logs the state change
+        /// </summary>
         private void logStateChange()
         {
             String stateAsString = CurrentState.ToString().ToLower();