Browse Source

Added line fitting to finger points and start/end points based on depth.

Daniel Kauth 11 years ago
parent
commit
c5fe1acc11
3 changed files with 129 additions and 2 deletions
  1. 92 1
      bbiwarg/DepthImage.cs
  2. 36 0
      bbiwarg/Finger.cs
  3. 1 1
      bbiwarg/MainBBWIWARG.cs

+ 92 - 1
bbiwarg/DepthImage.cs

@@ -215,10 +215,101 @@ namespace bbiwarg
                 if (length > minFingerLength)
                 {
                     fingers.Add(finger);
-                    foreach (Point fingerPoint in finger.getFingerPoints()) {
+                    
+                    /*foreach (Point fingerPoint in finger.getFingerPoints()) {
                         fingerPoints[fingerPoint.X, fingerPoint.Y] = true;
+                    }*/
+
+                    List<Point> points = finger.getFingerPoints();
+
+                    PointF[] pointArray = new PointF[points.Count];
+                    int i = 0;
+                    foreach (Point p in points) {
+                        pointArray[i] = new PointF(p.X, p.Y);
+                        ++i;
                     }
+
+                    PointF direction, pointOnLine;
+                    PointCollection.Line2DFitting(pointArray, Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_L2, out direction, out pointOnLine);
+
+                    PointF start = projectToLine(finger.getFarthest(this), direction, pointOnLine);
+                    PointF end = projectToLine(finger.getNearest(this), direction, pointOnLine);
+                    setFingerPoints(start, end);
+                }
+            }
+        }
+
+        private PointF projectToLine(PointF p, PointF direction, PointF pointOnLine)
+        {
+            float px = p.X, py = p.Y, dx = direction.X, dy = direction.Y, ox = pointOnLine.X, oy = pointOnLine.Y;
+            float diffx = px - ox;
+            float diffy = py - oy;
+
+            float diff_d = (diffx * dx + diffy * dy);
+            float d_d = (dx * dx + dy * dy);
+            float q = diff_d / d_d;
+
+            return new PointF(ox + q * dx, oy + q * dy);
+        }
+
+        private void setFingerPoints(PointF start, PointF end)
+        {
+            // 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(getWidth() - 1, Math.Max(0, x)), Math.Min(getHeight() - 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(getWidth() - 1, Math.Max(0, x)), Math.Min(getHeight() - 1, Math.Max(0, y))] = true;
             }
         }
     }

+ 36 - 0
bbiwarg/Finger.cs

@@ -52,6 +52,42 @@ namespace bbiwarg
             return (float)Math.Sqrt(xDiff * xDiff + yDiff * yDiff);
         }
 
+        public int getNumPoints()
+        {
+            return fingerPoints.Count;
+        }
+
+        public Point getNearest(DepthImage image)
+        {
+            Point nearest = new Point(0, 0);
+            Int16 minDepth = Int16.MaxValue;
+            foreach (Point p in fingerPoints)
+            {
+                Int16 d = image.getDepthAt(p.X, p.Y);
+                if (d < minDepth) {
+                    minDepth = d;
+                    nearest = p;
+                }
+            }
+            return nearest;
+        }
+
+        public Point getFarthest(DepthImage image)
+        {
+            Point farthest = new Point(0, 0);
+            Int16 maxDepth = 0;
+            foreach (Point p in fingerPoints)
+            {
+                Int16 d = image.getDepthAt(p.X, p.Y);
+                if (d > maxDepth)
+                {
+                    maxDepth = d;
+                    farthest = p;
+                }
+            }
+            return farthest;
+        }
+
         public List<Point> getFingerPoints() {
             return fingerPoints;
         }

+ 1 - 1
bbiwarg/MainBBWIWARG.cs

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