Pārlūkot izejas kodu

finger tip/hand detection now works properly

Alexander Hendrich 10 gadi atpakaļ
vecāks
revīzija
2b98347e66

+ 3 - 1
bbiwarg/Constants.cs

@@ -18,6 +18,7 @@ namespace bbiwarg
         public static readonly Color FingerSliceColor = Color.Magenta;
         public static readonly Color FingerDetectedColor = ColorDetected;
         public static readonly Color FingerTrackedColor = ColorTracked;
+        public static readonly Color FingerOutSliceColor = Color.DarkSlateGray;
 
         public static readonly Color TouchEventDetectedColor = ColorDetected;
         public static readonly Color TouchEventTrackedColor = ColorTracked;
@@ -37,7 +38,7 @@ namespace bbiwarg
 
         // finger detection
         public static readonly int FingerStepSize = 2;
-        public static readonly int FingerMinNumSlices = 7;
+        public static readonly int FingerMinNumSlices = 10;
         public static readonly int FingerRemoveNumSlicesForCorrection = 3;
         public static readonly int FingerMaxGapCounter = 10;
         public static readonly int FingerMaxSliceDifferencePerStep = 8;
@@ -45,6 +46,7 @@ namespace bbiwarg
         public static readonly int FingerMinSize = 5;
         public static readonly int FingerNumSlicesForRelativeDirection = 5;
         public static readonly int FingerNumFramesUntilTracked = 2;
+        public static readonly int FingerOutSliceFactor = 4;
         public static readonly float FingerMinSimilarityForTracking = 0.75f;
 
         // palm detection

+ 61 - 5
bbiwarg/Detectors/FingerDetection/FingerDetector.cs

@@ -36,7 +36,7 @@ namespace bbiwarg.Detectors.FingerDetection
 
             Fingers = new List<Finger>();
 
-            for (int y = 1; y < maxY; y+=5) //y++ for 100% coverage, but y+=5 for 99% coverage and 3 times better perfomance
+            for (int y = 1; y < maxY; y += 5) //y++ for 100% coverage, but y+=5 for 99% coverage and 3 times better perfomance
             {
                 for (int x = 1; x < maxX; x++)
                 {
@@ -169,7 +169,7 @@ namespace bbiwarg.Detectors.FingerDetection
             return getFingerSlice(start, end);
         }
 
-        private Vector2D findNextEdge(Vector2D start, Vector2D direction)
+        private Vector2D findNextEdge(Vector2D start, Vector2D direction, bool stopAtMaxFingerSize = true, bool returnBoundIfNoEdge = false)
         {
             int maxX = depthImage.Width - 1;
             int maxY = depthImage.Height - 1;
@@ -190,9 +190,10 @@ namespace bbiwarg.Detectors.FingerDetection
             else
                 maxStepsY = int.MaxValue;
 
-            int maxStepsLength = (int)(Constants.FingerMaxSize / direction.Length);
+            int maxSteps = Math.Min(maxStepsX, maxStepsY);
 
-            int maxSteps = Math.Min(maxStepsLength, Math.Min(maxStepsX, maxStepsY));
+            if (stopAtMaxFingerSize)
+                maxSteps = Math.Min(maxSteps, (int)(Constants.FingerMaxSize / direction.Length));
 
             Vector2D end = new Vector2D(start);
             for (int i = 0; i < maxSteps; i++)
@@ -204,7 +205,11 @@ namespace bbiwarg.Detectors.FingerDetection
                     return end;
                 }
             }
-            return null;
+
+            if (returnBoundIfNoEdge)
+                return end;
+            else
+                return null;
         }
 
         private FingerSlice getFingerSlice(Vector2D start, Vector2D end)
@@ -233,6 +238,10 @@ namespace bbiwarg.Detectors.FingerDetection
 
         private void createFingerFromTrail(FingerSliceTrail trail)
         {
+            //bring finger in correct direction Tip->Hand
+            trail = orderTrailTipToHand(trail);
+
+            //create finger
             Finger finger = new Finger(trail);
 
             //add finger
@@ -245,6 +254,53 @@ namespace bbiwarg.Detectors.FingerDetection
             edgeImage.removeFingerEdges(finger);
         }
 
+        private FingerSlice findOutSlice(Vector2D start, Vector2D direction)
+        {
+            int maxX = depthImage.Width - 1;
+            int maxY = depthImage.Height - 1;
+
+            Vector2D dirOrth1 = direction.getOrthogonal(true);
+            Vector2D dirOrth2 = direction.getOrthogonal(false);
+
+            Vector2D outPoint = (start + Constants.FingerOutSliceFactor * Constants.FingerStepSize * direction).moveInBound(0, 0, maxX, maxY);
+            Vector2D p1 = findNextEdge(outPoint, dirOrth1, false, true);
+            Vector2D p2 = findNextEdge(outPoint, dirOrth2, false, true);
+
+            FingerSlice slice = new FingerSlice(p1, p2);
+
+            outputImage.drawLineSegment(slice.LineSegment, Constants.FingerOutSliceColor);
+
+            return slice;
+        }
+
+        private FingerSliceTrail orderTrailTipToHand(FingerSliceTrail trail)
+        {
+            int maxX = depthImage.Width - 1;
+            int maxY = depthImage.Height - 1;
+
+            FingerSlice start = trail.Start;
+            FingerSlice end = trail.End;
+
+            Vector2D direction = (end.Mid - start.Mid).normalize();
+
+            FingerSlice startOutSlice = findOutSlice(start.Mid, -1 * direction);
+            FingerSlice endOutSlice = findOutSlice(end.Mid, direction);
+
+            float startOutLength = float.MaxValue;
+            float endOutLength = float.MaxValue;
+
+            if (!startOutSlice.Start.isOnBound(0, 0, maxX, maxY) && startOutSlice.End.isOnBound(0, 0, maxX, maxY))
+                startOutLength = startOutSlice.Length;
+
+            if (!endOutSlice.Start.isOnBound(0, 0, maxX, maxY) && endOutSlice.End.isOnBound(0, 0, maxX, maxY))
+                endOutLength = endOutSlice.Length;
+
+            if (startOutLength < endOutLength)
+                trail.Slices.Reverse();
+
+            return trail;
+        }
+
         private void drawDetectedFinger(Finger finger)
         {
             FingerSliceTrail trail = finger.SliceTrail;

+ 1 - 1
bbiwarg/Detectors/HandDetection/HandDetector.cs

@@ -26,7 +26,7 @@ namespace bbiwarg.Detectors.HandDetection
         }
 
         private void detectHands() {
-            Image<Gray, byte> image = edgeImage.Image.Copy();
+            Image<Gray, byte> image = edgeImage.Image.Copy().Mul(255);
 
             //draw top finger slice
             foreach (Finger finger in fingers) {

+ 4 - 0
bbiwarg/Utility/Vector2D.cs

@@ -93,6 +93,10 @@ namespace bbiwarg.Utility
             return new Vector2D(x, y);
         }
 
+        public bool isOnBound(float minX, float minY, float maxX, float maxY) {
+            return (IntX == minX || IntX == maxX || IntY == minY || IntY == maxY);
+        }
+
         public Vector2D getOrthogonal(bool side)
         {
             if (side)