ソースを参照

added fingerTracker (first draft) and fingerImage

Alexander Hendrich 10 年 前
コミット
6a45334a5a

+ 17 - 0
bbiwarg/Detectors/Fingers/Finger.cs

@@ -78,6 +78,23 @@ namespace bbiwarg.Detectors.Fingers
             return minDinstance;
         }
 
+        public bool isSimilarTo(Finger compareFinger) {
+            PointF center = new PointF((lineEndPoint1.X + lineEndPoint2.X) / 2, (lineEndPoint1.Y + lineEndPoint2.Y) / 2);
+            PointF compareCenter = new PointF((compareFinger.getLineEndPoint1().X+compareFinger.getLineEndPoint2().X)/2, (compareFinger.getLineEndPoint1().Y+compareFinger.getLineEndPoint2().Y)/2);
+
+            float xDiff = center.X - compareCenter.X;
+            float yDiff = center.Y - compareCenter.Y;
+            float centerDistance = (float)Math.Sqrt(xDiff * xDiff + yDiff * yDiff);
+            float maxCenterDistance = 40;
+
+            if (centerDistance > maxCenterDistance)
+                return false;
+
+
+            return true;
+            
+        }
+
         private void updateLine() {
             //update direction+pointonline
             PointF[] pointArray = new PointF[fingerPoints.Count];

+ 7 - 83
bbiwarg/Detectors/Fingers/FingerDetector.cs

@@ -14,14 +14,14 @@ namespace bbiwarg.Detectors.Fingers
     {
         private DepthImage depthImage;
         private EdgeImage edgeImage;
-        private bool[,] possibleFingerPoints;
-        private bool[,] fingerPoints;
+        private FingerImage fingerImage;
         private List<Finger> possibleFingers;
         private List<Finger> fingers;
 
-        public FingerDetector(DepthImage depthImage, EdgeImage edgeImage) {
+        public FingerDetector(DepthImage depthImage, EdgeImage edgeImage, FingerImage fingerImage) {
             this.depthImage = depthImage;
             this.edgeImage = edgeImage;
+            this.fingerImage = fingerImage;
 
             findPossibleFingerPoints();
             findPossibleFingers();
@@ -29,14 +29,6 @@ namespace bbiwarg.Detectors.Fingers
             setFingerPoints();
         }
 
-        public bool isPossibleFingerPointAt(int x, int y) {
-            return possibleFingerPoints[x, y];
-        }
-
-        public bool isFingerPointAt(int x, int y) {
-            return fingerPoints[x, y];
-        }
-
         public List<Finger> getFingers() {
             return fingers;
         }
@@ -47,7 +39,6 @@ namespace bbiwarg.Detectors.Fingers
             int height = depthImage.getHeight();
             int maxFingerSize = 30;
             int minFingerSize = 10;
-            possibleFingerPoints = new bool[width, height];
 
             for (int y = 0; y < height; y++) {
                 for (int x = 0; x < width; x++) {
@@ -69,7 +60,7 @@ namespace bbiwarg.Detectors.Fingers
                             Int16 depthRight = depthImage.getDepthAt(edgeRightX, y);
 
                             if ((edgeRightX - x) < maxFingerSize && depthLeft > depthMid && depthMid < depthRight) {
-                                possibleFingerPoints[midX, y] = true;
+                                fingerImage.setFingerAt(midX, y, FingerImageState.possibleFinger);
                             } 
                         }
 
@@ -90,7 +81,7 @@ namespace bbiwarg.Detectors.Fingers
                             Int16 depthBottom = depthImage.getDepthAt(x, edgeBottomY);
 
                             if ((edgeBottomY - y) < maxFingerSize && depthTop > depthMid && depthMid < depthBottom) {
-                                possibleFingerPoints[x, midY] = true;
+                                fingerImage.setFingerAt(x, midY, FingerImageState.possibleFinger);
                             }
 
                         }
@@ -110,7 +101,7 @@ namespace bbiwarg.Detectors.Fingers
             {
                 for (int x = 0; x < width; x++)
                 {
-                    if (possibleFingerPoints[x, y])
+                    if (fingerImage.getStateAt(x,y) == FingerImageState.possibleFinger)
                     {
                         Int16 depth = depthImage.getDepthAt(x, y);
                         FingerPoint fingerPoint = new FingerPoint(x,y,depth);
@@ -158,78 +149,11 @@ namespace bbiwarg.Detectors.Fingers
         private void setFingerPoints() {
             int width = depthImage.getWidth();
             int height = depthImage.getHeight();
-            fingerPoints = new bool[width, height];
 
             foreach (Finger finger in fingers) {
                 PointF lineEndPoint1 = finger.getLineEndPoint1();
                 PointF lineEndPoint2 = finger.getLineEndPoint2();
-                drawFingerPointLine(lineEndPoint1, lineEndPoint2);
-            }
-        }
-
-
-
-        private void drawFingerPointLine(PointF start, PointF end)
-        {
-            int width = depthImage.getWidth();
-            int height = depthImage.getHeight();
-
-            // bresenham from wikipedia
-            int xstart = (int)start.X, xend = (int)end.X, ystart = (int)start.Y, yend = (int)end.Y;
-            int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
-
-            /* Entfernung in beiden Dimensionen berechnen */
-            dx = xend - xstart;
-            dy = yend - ystart;
-
-            /* Vorzeichen des Inkrements bestimmen */
-            incx = dx < 0 ? -1 : 1;
-            incy = dy < 0 ? -1 : 1;
-            if (dx < 0) dx = -dx;
-            if (dy < 0) dy = -dy;
-
-            /* feststellen, welche Entfernung größer ist */
-            if (dx > dy)
-            {
-                /* x ist schnelle Richtung */
-                pdx = incx; pdy = 0;    /* pd. ist Parallelschritt */
-                ddx = incx; ddy = incy; /* dd. ist Diagonalschritt */
-                es = dy; el = dx;   /* Fehlerschritte schnell, langsam */
-            }
-            else
-            {
-                /* y ist schnelle Richtung */
-                pdx = 0; pdy = incy; /* pd. ist Parallelschritt */
-                ddx = incx; ddy = incy; /* dd. ist Diagonalschritt */
-                es = dx; el = dy;   /* Fehlerschritte schnell, langsam */
-            }
-
-            /* Initialisierungen vor Schleifenbeginn */
-            x = xstart;
-            y = ystart;
-            err = el / 2;
-            fingerPoints[Math.Min(width - 1, Math.Max(0, x)), Math.Min(height - 1, Math.Max(0, y))] = true;
-
-            /* Pixel berechnen */
-            for (t = 0; t < el; ++t) /* t zaehlt die Pixel, el ist auch Anzahl */
-            {
-                /* Aktualisierung Fehlerterm */
-                err -= es;
-                if (err < 0)
-                {
-                    /* Fehlerterm wieder positiv (>=0) machen */
-                    err += el;
-                    /* Schritt in langsame Richtung, Diagonalschritt */
-                    x += ddx;
-                    y += ddy;
-                }
-                else
-                {
-                    /* Schritt in schnelle Richtung, Parallelschritt */
-                    x += pdx;
-                    y += pdy;
-                }
-                fingerPoints[Math.Min(width - 1, Math.Max(0, x)), Math.Min(height - 1, Math.Max(0, y))] = true;
+                fingerImage.drawLine(lineEndPoint1, lineEndPoint2, FingerImageState.fingerDetected);
             }
         }
 

+ 74 - 0
bbiwarg/Detectors/Fingers/FingerTracker.cs

@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using bbiwarg.Images;
+
+namespace bbiwarg.Detectors.Fingers
+{
+    class FingerTracker
+    {
+        private FingerImage fingerImage;
+        private List<Finger>[] detectedFingers;
+        private List<Finger> trackedFingers;
+        private int framesUntilTracked;
+
+        public FingerTracker() {
+            framesUntilTracked = 5;
+            detectedFingers = new List<Finger>[framesUntilTracked];
+
+            for (int i = 0; i < framesUntilTracked; i++)
+            {
+                detectedFingers[i] = new List<Finger>();
+            }
+        }
+
+        public List<Finger> getFingers() {
+            return trackedFingers;
+        }
+
+        public void setDetectedTouchEventsThisFrame(List<Finger> detectedFingersThisFrame, FingerImage fingerImage)
+        {
+            this.fingerImage = fingerImage;
+
+            for (int i = (framesUntilTracked - 1); i > 0; i--)
+            {
+                detectedFingers[i] = detectedFingers[i - 1];
+            }
+            detectedFingers[0] = detectedFingersThisFrame;
+
+
+            findTrackedFingers();
+        }
+
+        private void findTrackedFingers()
+        {
+            trackedFingers = new List<Finger>();
+
+            foreach (Finger finger in detectedFingers[0])
+            {
+                bool tracked = true;
+                for (int i = 1; i < framesUntilTracked; i++)
+                {
+                    if (!hasSimilarFingerInFrame(finger, i)) tracked = false;
+                }
+                if (tracked)
+                {
+                    fingerImage.drawLine(finger.getLineEndPoint1(), finger.getLineEndPoint2(), FingerImageState.fingerTracked);
+                    trackedFingers.Add(finger);
+                }
+            }
+        }
+
+        private bool hasSimilarFingerInFrame(Finger finger, int frame) {
+            foreach (Finger f in detectedFingers[frame])
+            {
+                if (finger.isSimilarTo(f))
+                    return true;
+            }
+
+            return false;
+        }
+    }
+}

+ 1 - 1
bbiwarg/Detectors/Touch/TouchDetector.cs

@@ -33,7 +33,7 @@ namespace bbiwarg.Detectors.Touch
                 {
                     PointF direction = finger.getDirection();
                     float directionFactor = -10;
-                    PointF tep = new PointF(Math.Max(tipPoint.getX() + directionFactor*direction.X, 0), Math.Min(tipPoint.getY() + directionFactor*direction.Y, 0));
+                    PointF tep = new PointF(Math.Min(Math.Max(tipPoint.getX() + directionFactor*direction.X, 0), depthImage.getWidth()), Math.Min(Math.Max(tipPoint.getY() + directionFactor*direction.Y, 0), depthImage.getHeight()));
                     
 
                     touchImage.setTouchAt((int)tep.X, (int)tep.Y, TouchImageState.touchDetected);

+ 6 - 0
bbiwarg/Detectors/Touch/TouchEvent.cs

@@ -40,5 +40,11 @@ namespace bbiwarg.Detectors.Touch
             float distance = (float)Math.Sqrt(xDiff * xDiff + yDiff * yDiff);
             return distance;
         }
+
+        public bool isSimilarTo(TouchEvent compareTouchEvent) {
+            float maxDistance = 20;
+            float distance = getDistanceTo(compareTouchEvent);
+            return (distance < maxDistance);
+        }
     }
 }

+ 2 - 9
bbiwarg/Detectors/Touch/TouchTracker.cs

@@ -23,7 +23,7 @@ namespace bbiwarg.Detectors.Touch
             }
         }
 
-        public List<TouchEvent> getTrackedTouchEvents() {
+        public List<TouchEvent> getTouchEvents() {
             return trackedTouchEvents;
         }
 
@@ -58,18 +58,11 @@ namespace bbiwarg.Detectors.Touch
 
         private bool hasSimilarTouchEventInFrame(TouchEvent touchEvent, int frame) {
             foreach (TouchEvent te in detectedTouchEvents[frame]) {
-                float distance = touchEvent.getDistanceTo(te);
-                if (compareTouchEvents(touchEvent, te))
+                if (touchEvent.isSimilarTo(te))
                     return true;
             }
 
             return false;
         }
-
-        private bool compareTouchEvents(TouchEvent te1, TouchEvent te2) {
-            float maxDistance = 20;
-            float distance = te1.getDistanceTo(te2);
-            return (distance < maxDistance);
-        }
     }
 }

+ 4 - 2
bbiwarg/Graphics/OutputWindow.cs

@@ -124,10 +124,12 @@ namespace bbiwarg.Graphics
                     depthTextureData[index + 2] = blue;
 
                     //edgeTexture
+                    FingerImageState fis = videoHandle.getFingerImageStateAt(x,y);
                     red = green = blue = 0;
                     if (videoHandle.isEdgeAt(x, y)) blue = Int16.MaxValue;
-                    else if (videoHandle.isFingerPointAt(x, y)) green = Int16.MaxValue;
-                    else if (videoHandle.isPossibleFingerPointAt(x, y)) red = Int16.MaxValue;
+                    else if (fis == FingerImageState.fingerTracked) green = Int16.MaxValue;
+                    else if (fis == FingerImageState.fingerDetected) red = blue = Int16.MaxValue;
+                    else if (fis == FingerImageState.possibleFinger) red = Int16.MaxValue;
 
                     edgeTextureData[index] = red;
                     edgeTextureData[index + 1] = green;

+ 98 - 0
bbiwarg/Images/FingerImage.cs

@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Emgu.CV;
+using Emgu.CV.Structure;
+namespace bbiwarg.Images
+{
+    public enum FingerImageState {
+        none = 0,
+        possibleFinger = 1,
+        fingerDetected = 2,
+        fingerTracked = 3
+    }
+
+    class FingerImage
+    {
+        private Image<Gray, Int16> image;
+
+        public FingerImage(DepthImage depthImage) {
+            this.image = depthImage.getImage().CopyBlank();
+        }
+
+        public void setFingerAt(int x, int y, FingerImageState fis) {
+            image.Data[y, x, 0] = (Int16) fis;
+        }
+
+        public FingerImageState getStateAt(int x, int y) {
+            return (FingerImageState)image.Data[y, x, 0];
+        }
+
+        public void drawLine(PointF start, PointF end, FingerImageState state)
+        {
+            int width = image.Width;
+            int height = image.Height;
+
+            // bresenham from wikipedia
+            int xstart = (int)start.X, xend = (int)end.X, ystart = (int)start.Y, yend = (int)end.Y;
+            int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
+
+            /* Entfernung in beiden Dimensionen berechnen */
+            dx = xend - xstart;
+            dy = yend - ystart;
+
+            /* Vorzeichen des Inkrements bestimmen */
+            incx = dx < 0 ? -1 : 1;
+            incy = dy < 0 ? -1 : 1;
+            if (dx < 0) dx = -dx;
+            if (dy < 0) dy = -dy;
+
+            /* feststellen, welche Entfernung größer ist */
+            if (dx > dy)
+            {
+                /* x ist schnelle Richtung */
+                pdx = incx; pdy = 0;    /* pd. ist Parallelschritt */
+                ddx = incx; ddy = incy; /* dd. ist Diagonalschritt */
+                es = dy; el = dx;   /* Fehlerschritte schnell, langsam */
+            }
+            else
+            {
+                /* y ist schnelle Richtung */
+                pdx = 0; pdy = incy; /* pd. ist Parallelschritt */
+                ddx = incx; ddy = incy; /* dd. ist Diagonalschritt */
+                es = dx; el = dy;   /* Fehlerschritte schnell, langsam */
+            }
+
+            /* Initialisierungen vor Schleifenbeginn */
+            x = xstart;
+            y = ystart;
+            err = el / 2;
+            setFingerAt(Math.Min(width - 1, Math.Max(0, x)), Math.Min(height - 1, Math.Max(0, y)), state);
+
+            /* Pixel berechnen */
+            for (t = 0; t < el; ++t) /* t zaehlt die Pixel, el ist auch Anzahl */
+            {
+                /* Aktualisierung Fehlerterm */
+                err -= es;
+                if (err < 0)
+                {
+                    /* Fehlerterm wieder positiv (>=0) machen */
+                    err += el;
+                    /* Schritt in langsame Richtung, Diagonalschritt */
+                    x += ddx;
+                    y += ddy;
+                }
+                else
+                {
+                    /* Schritt in schnelle Richtung, Parallelschritt */
+                    x += pdx;
+                    y += pdy;
+                }
+                setFingerAt(Math.Min(width - 1, Math.Max(0, x)), Math.Min(height - 1, Math.Max(0, y)), state);
+            }
+        }
+    }
+}

+ 1 - 1
bbiwarg/MainBBWIWARG.cs

@@ -12,7 +12,7 @@ namespace bbiwarg
     {
         static void Main(string[] args)
         {
-            IInputProvider inputProvider = new IisuInputProvider("..\\..\\videos\\14.skv");
+            IInputProvider inputProvider = new IisuInputProvider("..\\..\\videos\\touch\\4.skv");
             VideoHandle videoHandle = new VideoHandle(inputProvider);
             videoHandle.start();
 

+ 13 - 15
bbiwarg/VideoHandle.cs

@@ -23,9 +23,12 @@ namespace bbiwarg
         private DepthImage depthImage;
         private EdgeImage edgeImage;
         private TouchImage touchImage;
+        private FingerImage fingerImage;
 
         private FingerDetector fingerDetector;
         private TouchDetector touchDetector;
+
+        private FingerTracker fingerTracker;
         private TouchTracker touchTracker;
 
         public VideoHandle(IInputProvider inputProvider) {
@@ -33,6 +36,7 @@ namespace bbiwarg
 
             //initialize trackers
             touchTracker = new TouchTracker();
+            fingerTracker = new FingerTracker();
         }
 
         public void start() {
@@ -82,12 +86,8 @@ namespace bbiwarg
             return edgeImage.isEdgeAt(x, y);
         }
 
-        public bool isPossibleFingerPointAt(int x, int y) {
-            return fingerDetector.isPossibleFingerPointAt(x, y);
-        }
-
-        public bool isFingerPointAt(int x, int y) {
-            return fingerDetector.isFingerPointAt(x, y);
+        public FingerImageState getFingerImageStateAt(int x, int y) {
+            return fingerImage.getStateAt(x, y);
         }
 
         public TouchImageState getTouchImageStateAt(int x, int y) {
@@ -110,19 +110,17 @@ namespace bbiwarg
             }
             depthImage = new DepthImage(width, height, image);
 
-            //create edgeImage
+            //create images
             edgeImage = new EdgeImage(depthImage);
-
-            //detect fingers
-            fingerDetector = new FingerDetector(depthImage, edgeImage);
-
-            //create touchImage
             touchImage = new TouchImage(depthImage);
+            fingerImage = new FingerImage(depthImage);
 
-            //detect touchEvents
-            touchDetector = new TouchDetector(fingerDetector.getFingers(), depthImage, touchImage);
+            //detect+track fingers
+            fingerDetector = new FingerDetector(depthImage, edgeImage, fingerImage);
+            fingerTracker.setDetectedTouchEventsThisFrame(fingerDetector.getFingers(), fingerImage);
 
-            //track touchEvents
+            //detect+track touchEvents
+            touchDetector = new TouchDetector(fingerTracker.getFingers(), depthImage, touchImage);
             touchTracker.setDetectedTouchEventsThisFrame(touchDetector.getTouchEvents(), touchImage);
         }
     }

+ 2 - 0
bbiwarg/bbiwarg.csproj

@@ -69,10 +69,12 @@
     <Compile Include="Detectors\Fingers\Finger.cs" />
     <Compile Include="Detectors\Fingers\FingerDetector.cs" />
     <Compile Include="Detectors\Fingers\FingerPoint.cs" />
+    <Compile Include="Detectors\Fingers\FingerTracker.cs" />
     <Compile Include="Detectors\Touch\TouchDetector.cs" />
     <Compile Include="Detectors\Touch\TouchEvent.cs" />
     <Compile Include="Detectors\Touch\TouchTracker.cs" />
     <Compile Include="Graphics\OutputWindow.cs" />
+    <Compile Include="Images\FingerImage.cs" />
     <Compile Include="Images\DepthImage.cs" />
     <Compile Include="Images\EdgeImage.cs" />
     <Compile Include="Images\TouchImage.cs" />