Browse Source

finger detection now works with 3D widths (prevents arm being detected asa finger)

Alexander Hendrich 11 years ago
parent
commit
1feaf6dbdf

+ 1 - 1
bbiwarg/Input/InputHandling/InputHandler.cs

@@ -59,7 +59,7 @@ namespace bbiwarg.Input.InputHandling
             coordinateConverter = new CoordinateConverter(ImageSize, inputProvider.HFOV, inputProvider.VFOV);
             resetFlag = false;
 
-            fingerDetector = new FingerDetector();
+            fingerDetector = new FingerDetector(coordinateConverter);
             handDetector = new HandDetector();
             palmDetector = new PalmDetector();
             touchDetector = new TouchDetector();

+ 7 - 6
bbiwarg/Parameters.cs

@@ -36,9 +36,9 @@ namespace bbiwarg
         public static readonly String DebugWindowTitle = "BBIWARG - DebugOutput";
 
         // glasses window
-        public static readonly bool GlassesWindowEnabled = true;
+        public static readonly bool GlassesWindowEnabled = false;
         public static readonly int GlassesWindowUpdateInterval = 1000 / 30; // 30fps
-        public static readonly String GlassesWindowTitle = "BBIWARG - GlassesOutput";
+        public static readonly String GlassesWindowTitle = "BBIWARG - GlassesOuty   put";
         public static readonly int GlassesWindowNumCalibrationPoints = 20;
 
         // TUIO
@@ -66,9 +66,10 @@ namespace bbiwarg
         public static readonly int FingerStepSize = 1;
         public static readonly int FingerMaxGapCounter = 3;
         public static readonly int FingerMaxSliceDifferencePerStep = 5;
-        public static readonly int FingerMinNumSlices = 25 / FingerStepSize;
-        public static readonly int FingerMaxWidth = 30;
-        public static readonly int FingerMinWidth = 2;
+        public static readonly int FingerMinNumSlices = 20 / FingerStepSize;
+        public static readonly float FingerMaxWidth3D = 35f;
+        public static readonly int FingerMaxWidth2D = 30; // TODO remove and replace with 3Dwidth
+        public static readonly int FingerMinWidth2D = 2;
         public static readonly int FingerRemoveNumSlicesForCorrection = 10 / FingerStepSize;
         public static readonly int FingerNumSlicesForRelativeDirection = FingerRemoveNumSlicesForCorrection;
         public static readonly int FingerOutMargin = 6;
@@ -93,7 +94,7 @@ namespace bbiwarg
         public static readonly float HandMinSize = 0.01f;
         public static readonly float HandExtensionMaxRelativeSize = 0.5f * HandMaxSize;
         public static readonly int HandExtendMaxDifference = 40;
-        public static readonly float HandThumbDefectMaxDistanceToThumb = FingerMaxWidth;
+        public static readonly float HandThumbDefectMaxDistanceToThumb = Parameters.FingerMaxWidth2D;
         public static readonly float HandThumbDefectMinThumbShortLengthRatio = 0.75f;
         public static readonly float HandThumbDefectMaxThumbShortLengthRatio = 1.1f;
         public static readonly float HandThumbDefectMinShortLongLengthRatio = 0.3f;

+ 28 - 16
bbiwarg/Recognition/FingerRecognition/FingerDetector.cs

@@ -15,11 +15,16 @@ namespace bbiwarg.Recognition.FingerRecognition
 {
     class FingerDetector
     {
+        private CoordinateConverter coordinateConverter;
         private DepthImage depthImage;
         private EdgeImage edgeImageOriginal;
         private EdgeImage edgeImageAdapted;
         private List<Finger> fingers;
 
+        public FingerDetector(CoordinateConverter coordinateConverter) {
+            this.coordinateConverter = coordinateConverter;
+        }
+
         public void detectFingers(FrameData frameData)
         {
             depthImage = frameData.DepthImage;
@@ -97,9 +102,7 @@ namespace bbiwarg.Recognition.FingerRecognition
                     }
                 }
             }
-
             return null;
-
         }
 
         private FingerSliceTrail expandTrail(FingerSliceTrail trail, bool reversed = false)
@@ -147,34 +150,43 @@ namespace bbiwarg.Recognition.FingerRecognition
         {
             if (edgeImageAdapted.isRoughEdgeAt(position)) return null;
 
+            Int16 depth = depthImage.getDepthAt(position);
+            int maxWidth2D = (int)coordinateConverter.convertLength3Dto2D(Parameters.FingerMaxWidth3D, depth);
+
             Vector2D dirStart = direction.getOrthogonal(reversed);
             Vector2D dirEnd = direction.getOrthogonal(!reversed);
 
-            Vector2D start = edgeImageAdapted.findNextRoughEdge(position, dirStart, Parameters.FingerMaxWidth);
+            Vector2D startPositionStart = position + 0.5f*Parameters.FingerMinWidth2D * dirStart;
+            Vector2D start = edgeImageAdapted.findNextRoughEdge(startPositionStart, dirStart, maxWidth2D);
             if (start == null) return null;
 
-            Vector2D end = edgeImageAdapted.findNextRoughEdge(position, dirEnd, Parameters.FingerMaxWidth);
+            Vector2D endPositionStart = position + 0.5f*Parameters.FingerMinWidth2D * dirEnd;
+            Vector2D end = edgeImageAdapted.findNextRoughEdge(position, dirEnd, maxWidth2D);
             if (end == null) return null;
-            
-            return getFingerSlice(start, end);
+
+            FingerSlice slice = new FingerSlice(start, end);
+            if (!fingerSliceDepthTest(slice) || slice.Length > maxWidth2D)
+                return null;
+
+            return slice;
         }
+
         private FingerSlice findFingerSliceFromStartEdge(Vector2D start, Vector2D direction)
         {
-            Vector2D searchStart = start + Parameters.FingerContourMargin * direction;
-            Vector2D end = edgeImageAdapted.findNextRoughEdge(searchStart, direction, Parameters.FingerMaxWidth);
+            Vector2D searchStart = start + Parameters.FingerMinWidth2D * direction;
+
+            Int16 depth = depthImage.getDepthAt(start);
+            int maxWidth2D = (int)coordinateConverter.convertLength3Dto2D(Parameters.FingerMaxWidth3D, depth);
+
+            Vector2D end = edgeImageAdapted.findNextRoughEdge(searchStart, direction, maxWidth2D);
             if (end == null)
                 return null;
 
-            return getFingerSlice(start, end);
-        }
-
-        private FingerSlice getFingerSlice(Vector2D start, Vector2D end)
-        {
             FingerSlice slice = new FingerSlice(start, end);
-            if (slice.Length >= Parameters.FingerMinWidth && slice.Length <= Parameters.FingerMaxWidth && fingerSliceDepthTest(slice))
-                return slice;
+            if (!fingerSliceDepthTest(slice))
+                return null;
 
-            return null;
+            return slice;
         }
 
         private bool fingerSliceDepthTest(FingerSlice slice)

+ 1 - 1
bbiwarg/Recognition/PalmRecognition/PalmDetector.cs

@@ -124,7 +124,7 @@ namespace bbiwarg.Recognition.PalmRecognition
                 Vector2D below = fingersUpper.copy();
                 handBelow = false;
                 int distance = 0;
-                while (!handBelow && distance < Parameters.FingerMaxWidth && below.isInBound(depthImage.Size))
+                while (!handBelow && distance < Parameters.FingerMaxWidth2D && below.isInBound(depthImage.Size))
                 {
                     handBelow = hand.isInside(below);
                     below += lowerDirection;

+ 12 - 3
bbiwarg/Utility/CoordinateConverter.cs

@@ -24,11 +24,11 @@ namespace bbiwarg.Utility
             vRatio = (float)Math.Tan(vfov / 2);
         }
 
-        public Vector3D convert(Vector2D p, float depth) {
-            return convert(p.X, p.Y, depth);
+        public Vector3D convertCoordinate2Dto3D(Vector2D p, float depth) {
+            return convertCoordinate2Dto3D(p.X, p.Y, depth);
         }
 
-        public Vector3D convert(float x, float y, float depth)
+        public Vector3D convertCoordinate2Dto3D(float x, float y, float depth)
         {
             float deltaX = 2 * ((x / imageSize.Width) - 0.5f);
             float deltaY = -2 * ((y / imageSize.Height) - 0.5f);
@@ -45,5 +45,14 @@ namespace bbiwarg.Utility
 
             return new Vector3D(x3, y3, z3);
         }
+
+        public float convertLength3Dto2D(float length, float depth) {
+            float fullLengthX = (float)(2 * Math.Cos(hfov / 2) * depth);
+            float fullLengthY = (float)(2 * Math.Cos(vfov / 2) * depth);
+            float fullLengthDiagonal = (float)Math.Sqrt(Math.Pow(fullLengthX, 2) + Math.Pow(fullLengthY, 2));
+
+            float ratio = length / fullLengthDiagonal;
+            return ratio * imageSize.DiagonalLength;
+        }
     }
 }