Alexander Hendrich 10 years ago
parent
commit
2e83039462

+ 0 - 316
bbiwarg/DepthImage.cs

@@ -1,316 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Emgu.CV;
-using Emgu.CV.Structure;
-
-namespace bbiwarg
-{
-    class DepthImage
-    {
-        private int width;
-        private int height;
-        private Image<Gray, Int16> image;
-        private Image<Gray, Int16> edges;
-        private bool[,] fingerPoints;
-        private List<Finger> fingers;
-
-        private Int16 minDepth;
-        private Int16 maxDepth;
-
-        public DepthImage(int width, int height, Image<Gray, Int16> image) {
-            this.width = width;
-            this.height = height;
-            this.image = image;
-
-            Stopwatch sw = new Stopwatch();
-            sw.Start();
-
-            this.image = this.image.SmoothMedian(3);
-            //minDepth
-            findMinDepth();
-
-            //maxDepth
-            maxDepth = (Int16)(minDepth + 200);
-            thresholdDepth(minDepth, maxDepth);
-
-            //edges
-            calculateEdges();
-
-            //findFingerPoints
-            findFingerPoints();
-
-            //findFingers
-            findFingers();
-
-            sw.Stop();
-            Console.WriteLine(sw.ElapsedMilliseconds);
-
-        }
-
-        public int getWidth() {
-            return width;
-        }
-
-        public int getHeight() {
-            return height;
-        }
-
-        public Int16 getMinDepth() {
-            return minDepth;
-        }
-
-        public Int16 getMaxDepth() {
-            return maxDepth;
-        }
-
-        public Int16 getDepthAt(int x, int y) {
-            return image.Data[y, x, 0];
-        }
-
-        public Int16 getEdgeAt(int x, int y)
-        {
-            return edges.Data[y, x, 0];
-        }
-
-        public bool isFingerPoint(int x, int y) {
-            return fingerPoints[x, y];
-        }
-
-        private void setDepthAt(int x, int y, Int16 value) {
-            image.Data[y, x, 0] = value;
-        }
-
-        private void findMinDepth() {
-            minDepth = Int16.MaxValue;
-            for (int x = 0; x < width; ++x)
-            {
-                for (int y = 0; y < height; ++y)
-                {
-                    Int16 depth = getDepthAt(x,y);
-                    if (depth < minDepth)
-                        minDepth = depth;
-                }
-            }
-        }
-
-        private void thresholdDepth(int min, int max)
-        {
-            image = image.ThresholdToZero(new Gray(min));
-            image = image.ThresholdTrunc(new Gray(max));
-
-            for (int x = 0; x < width; ++x)
-            {
-                for (int y = 0; y < height; ++y)
-                {
-                    if (getDepthAt(x, y) == 0)
-                        setDepthAt(x, y, (short)max);
-                }
-            }
-        }
-
-        private void calculateEdges() {
-            Image<Gray, Byte> tmp = image.Convert<Byte>(delegate(Int16 depth) { return (byte)(((depth - minDepth) * Byte.MaxValue) / (maxDepth - minDepth)); });
-            Image<Gray, byte> tmp2 = tmp.Canny(100, 75, 3);
-            edges = tmp2.Convert<Int16>(delegate(byte depth) { if(depth > 0) {return Int16.MaxValue;} else {return 0;}});//((depth * Int16.MaxValue) / Byte.MaxValue); });
-        }
-
-        private void findFingerPoints()
-        {
-            int maxFingerSize = 30;
-            int minFingerSize = 10;
-            fingerPoints = new bool[width, height];
-
-            for (int y = 0; y < height; y++) {
-                for (int x = 0; x < width; x++) {
-                    if (getEdgeAt(x, y) > 0) {
-                        //search horizontal
-                        bool edgeRightFound = false;
-                        int edgeRightX = x + minFingerSize;
-                        while (!edgeRightFound && edgeRightX < width) {
-                            if (getEdgeAt(edgeRightX, y) > 0)
-                                edgeRightFound = true;
-                            else
-                                edgeRightX++;
-                        }
-
-                        if (edgeRightFound){
-                            int midX = (edgeRightX + x) / 2;
-                            Int16 depthLeft = getDepthAt(x, y);
-                            Int16 depthMid = getDepthAt(midX, y);
-                            Int16 depthRight = getDepthAt(edgeRightX, y);
-
-                            if ((edgeRightX - x) < maxFingerSize && depthLeft > depthMid && depthMid < depthRight) {
-                                fingerPoints[midX, y] = true;
-                            } 
-                        }
-
-                        //search vertical
-                        bool edgeBottomFound = false;
-                        int edgeBottomY = y + minFingerSize;
-                        while (!edgeBottomFound && edgeBottomY < height) {
-                            if (getEdgeAt(x, edgeBottomY) > 0)
-                                edgeBottomFound = true;
-                            else
-                                edgeBottomY++;
-                        }
-
-                        if (edgeBottomFound) {
-                            int midY = (edgeBottomY + y) / 2;
-                            Int16 depthTop = getDepthAt(x, y);
-                            Int16 depthMid = getDepthAt(x, midY);
-                            Int16 depthBottom = getDepthAt(x, edgeBottomY);
-
-                            if ((edgeBottomY - y) < maxFingerSize && depthTop > depthMid && depthMid < depthBottom) {
-                                fingerPoints[x, midY] = true;
-                            }
-
-                        }
-
-                        //x = edgeRightX - 1; // better performance but looses some points (skips x-values where it has already found a horizontal-fingerPoint, but it will miss any vertical-fingerPoints in this area)
-                    }
-                }
-            }
-        }
-
-        private void findFingers() {
-            float maxDistanceTogether = 5.0f;
-            float minFingerLength = 20.0f;
-            List<Finger> possibleFingers = new List<Finger>();
-
-            for (int y = 0; y < height; y++) {
-                for (int x = 0; x < width; x++) {
-                    if (fingerPoints[x, y]) {
-                        Point fingerPoint = new Point(x,y);
-                        float minDistanceValue = float.MaxValue;
-                        int minDistanceIndex = 0;
-                        for (int i = 0; i < possibleFingers.Count; i++)
-                        {
-                            float distance = possibleFingers[i].getMinDistance(fingerPoint);
-                            if (distance < minDistanceValue) {
-                                minDistanceValue = distance;
-                                minDistanceIndex = i;
-                            }
-                        }
-                        if (minDistanceValue < maxDistanceTogether)
-                        {
-                            possibleFingers[minDistanceIndex].add(fingerPoint);
-                        }
-                        else 
-                        {
-                            possibleFingers.Add(new Finger(fingerPoint));
-                        }
-                    }
-                }
-            }
-
-            fingers = new List<Finger>();
-            fingerPoints = new bool[width, height];
-            foreach (Finger finger in possibleFingers) {
-                float length = finger.getLength();
-                if (length > minFingerLength)
-                {
-                    fingers.Add(finger);
-                    
-                    /*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;
-            }
-        }
-    }
-}

+ 110 - 0
bbiwarg/Detectors/Finger/Finger.cs

@@ -0,0 +1,110 @@
+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;
+using bbiwarg.Images;
+
+namespace bbiwarg.Detectors.Finger
+{
+    class Finger
+    {
+        private List<FingerPoint> fingerPoints;
+        private FingerPoint nearest;
+        private FingerPoint farthest;
+        private PointF direction;
+        private PointF pointOnLine;
+        private PointF start;
+        private PointF end;
+
+        public Finger(FingerPoint fingerPoint)
+        {
+            fingerPoints = new List<FingerPoint>();
+            nearest = fingerPoint;
+            farthest = fingerPoint;
+            addFingerPoint(fingerPoint);
+        }
+
+        public FingerPoint getNearest()
+        {
+            return nearest;
+        }
+
+        public FingerPoint getFarthest()
+        {
+            return farthest;
+        }
+
+        public PointF getStart() {
+            return start;
+        }
+
+        public PointF getEnd() {
+            return end;
+        }
+
+        public void addFingerPoint(FingerPoint fingerPoint)
+        {
+            fingerPoints.Add(fingerPoint);
+
+            //update nearest
+            if (fingerPoint.getDepth() < nearest.getDepth()) nearest = fingerPoint;
+
+            //update farthest
+            if (fingerPoint.getDepth() > farthest.getDepth()) farthest = fingerPoint;
+
+            //update direction+pointonline
+            PointF[] pointArray = new PointF[fingerPoints.Count];
+            int i = 0;
+            foreach (FingerPoint fp in fingerPoints)
+            {
+                pointArray[i] = new PointF(fp.getX(), fp.getY());
+                ++i;
+            }
+            PointCollection.Line2DFitting(pointArray, Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_L2, out direction, out pointOnLine);
+
+            //update start+end
+            start = projectToLine(new PointF(farthest.getX(), farthest.getY()));
+            end = projectToLine(new PointF(nearest.getX(), nearest.getY()));
+        }
+
+        public float getMinDistance(FingerPoint fingerPoint)
+        {
+            float minDinstance = float.MaxValue;
+            foreach (FingerPoint fp in fingerPoints)
+            {
+                float distance = fp.getDistanceTo(fingerPoint);
+                if (distance < minDinstance)
+                {
+                    minDinstance = distance;
+                }
+            }
+
+            return minDinstance;
+        }
+
+        public float getLength()
+        {
+            FingerPoint fp1 = getNearest();
+            FingerPoint fp2 = getFarthest();
+            float distance = fp1.getDistanceTo(fp2);
+            return distance;
+        }
+
+        private PointF projectToLine(PointF p)
+        {
+            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);
+        }
+    }
+}

+ 233 - 0
bbiwarg/Detectors/Finger/FingerDetector.cs

@@ -0,0 +1,233 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Drawing;
+using Emgu.CV;
+using Emgu.CV.Structure;
+using bbiwarg.Images;
+
+namespace bbiwarg.Detectors.Finger
+{
+    class FingerDetector
+    {
+        private DepthImage depthImage;
+        private EdgeImage edgeImage;
+        private bool[,] possibleFingerPoints;
+        private bool[,] fingerPoints;
+        private List<Finger> possibleFingers;
+        private List<Finger> fingers;
+
+        public FingerDetector(DepthImage depthImage, EdgeImage edgeImage) {
+            this.depthImage = depthImage;
+            this.edgeImage = edgeImage;
+
+            findPossibleFingerPoints();
+            findPossibleFingers();
+            setFingers();
+            setFingerPoints();
+        }
+
+        public bool isPossibleFingerPointAt(int x, int y) {
+            return possibleFingerPoints[x, y];
+        }
+
+        public bool isFingerPointAt(int x, int y) {
+            return fingerPoints[x, y];
+        }
+
+        private void findPossibleFingerPoints()
+        {
+            int width = depthImage.getWidth();
+            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++) {
+                    if (edgeImage.isEdgeAt(x,y)) {
+                        //search horizontal
+                        bool edgeRightFound = false;
+                        int edgeRightX = x + minFingerSize;
+                        while (!edgeRightFound && edgeRightX < width) {
+                            if (edgeImage.isEdgeAt(edgeRightX,y))
+                                edgeRightFound = true;
+                            else
+                                edgeRightX++;
+                        }
+
+                        if (edgeRightFound){
+                            int midX = (edgeRightX + x) / 2;
+                            Int16 depthLeft = depthImage.getDepthAt(x, y);
+                            Int16 depthMid = depthImage.getDepthAt(midX, y);
+                            Int16 depthRight = depthImage.getDepthAt(edgeRightX, y);
+
+                            if ((edgeRightX - x) < maxFingerSize && depthLeft > depthMid && depthMid < depthRight) {
+                                possibleFingerPoints[midX, y] = true;
+                            } 
+                        }
+
+                        //search vertical
+                        bool edgeBottomFound = false;
+                        int edgeBottomY = y + minFingerSize;
+                        while (!edgeBottomFound && edgeBottomY < height) {
+                            if (edgeImage.isEdgeAt(x, edgeBottomY))
+                                edgeBottomFound = true;
+                            else
+                                edgeBottomY++;
+                        }
+
+                        if (edgeBottomFound) {
+                            int midY = (edgeBottomY + y) / 2;
+                            Int16 depthTop = depthImage.getDepthAt(x, y);
+                            Int16 depthMid = depthImage.getDepthAt(x, midY);
+                            Int16 depthBottom = depthImage.getDepthAt(x, edgeBottomY);
+
+                            if ((edgeBottomY - y) < maxFingerSize && depthTop > depthMid && depthMid < depthBottom) {
+                                possibleFingerPoints[x, midY] = true;
+                            }
+
+                        }
+                    }
+                }
+            }
+        }
+
+        private void findPossibleFingers()
+        {
+            int width = depthImage.getWidth();
+            int height = depthImage.getHeight();
+            float maxDistanceTogether = 5.0f;
+            possibleFingers = new List<Finger>();
+
+            for (int y = 0; y < height; y++)
+            {
+                for (int x = 0; x < width; x++)
+                {
+                    if (possibleFingerPoints[x, y])
+                    {
+                        Int16 depth = depthImage.getDepthAt(x, y);
+                        FingerPoint fingerPoint = new FingerPoint(x,y,depth);
+                        float minDistanceValue = float.MaxValue;
+                        int minDistanceIndex = 0;
+                        for (int i = 0; i < possibleFingers.Count; i++)
+                        {
+                            float distance = possibleFingers[i].getMinDistance(fingerPoint);
+                            if (distance < minDistanceValue)
+                            {
+                                minDistanceValue = distance;
+                                minDistanceIndex = i;
+                            }
+                        }
+                        if (minDistanceValue < maxDistanceTogether)
+                        {
+                            possibleFingers[minDistanceIndex].addFingerPoint(fingerPoint);
+                        }
+                        else
+                        {
+                            possibleFingers.Add(new Finger(fingerPoint));
+                        }
+                    }
+                }
+            }
+        }
+
+        private void setFingers()
+        {   
+            int width = depthImage.getWidth();
+            int height = depthImage.getHeight();
+            float minFingerLength = 20.0f;
+            fingers = new List<Finger>();
+
+            foreach (Finger finger in possibleFingers)
+            {
+                float length = finger.getLength();
+                if (length > minFingerLength)
+                {
+                    fingers.Add(finger);
+                }
+            }      
+        }
+
+        private void setFingerPoints() {
+            int width = depthImage.getWidth();
+            int height = depthImage.getHeight();
+            fingerPoints = new bool[width, height];
+
+            foreach (Finger finger in fingers) {
+                PointF start = finger.getStart();
+                PointF end = finger.getEnd();
+                drawFingerPointLine(start, end);
+            }
+        }
+
+
+
+        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;
+            }
+        }
+
+    }
+}

+ 41 - 0
bbiwarg/Detectors/Finger/FingerPoint.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bbiwarg.Detectors.Finger
+{
+    class FingerPoint
+    {
+        private int x;
+        private int y;
+        private Int16 depth;
+
+        public FingerPoint(int x, int y, Int16 depth) {
+            this.x = x;
+            this.y = y;
+            this.depth = depth;
+        }
+
+        public int getX() {
+            return x;
+        }
+
+        public int getY() {
+            return y;
+        }
+
+        public Int16 getDepth() {
+            return depth;
+        }
+
+        public float getDistanceTo(FingerPoint fingerPoint) {
+            int xDiff = x - fingerPoint.x;
+            int yDiff = y - fingerPoint.y;
+            float distance = (float)Math.Sqrt(xDiff * xDiff + yDiff * yDiff);
+            return distance;
+        }
+
+    }
+}

+ 0 - 95
bbiwarg/Finger.cs

@@ -1,95 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bbiwarg
-{
-    class Finger
-    {
-        private List<Point> fingerPoints;
-
-        public Finger(Point fingerPoint) {
-            fingerPoints = new List<Point>();
-            fingerPoints.Add(fingerPoint);
-        }
-
-        public float getMinDistance(Point fingerPoint) {
-            float minDinstance = float.MaxValue;
-            foreach(Point fp in fingerPoints) {
-                int xDiff = fp.X-fingerPoint.X;
-                int yDiff = fp.Y-fingerPoint.Y;
-                float distance = (float)Math.Sqrt(xDiff*xDiff + yDiff*yDiff);
-                if(distance < minDinstance) {
-                    minDinstance = distance;
-                }
-            }
-
-            return minDinstance;
-        }
-
-        public void add(Point fingerPoint) {
-            fingerPoints.Add(fingerPoint);
-        }
-
-        public float getLength() {
-            int minX = int.MaxValue;
-            int maxX = int.MinValue;
-            int minY = int.MaxValue;
-            int maxY = int.MinValue;
-            foreach (Point fingerPoint in fingerPoints) {
-                if (fingerPoint.X < minX) minX = fingerPoint.X;
-                if (fingerPoint.X > maxX) maxX = fingerPoint.X;
-                if (fingerPoint.Y < minY) minY = fingerPoint.Y;
-                if (fingerPoint.Y > maxY) maxY = fingerPoint.Y;
-            }
-
-            int xDiff = maxX-minX;
-            int yDiff = maxY-minY;
-
-            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;
-        }
-    }
-}

+ 14 - 18
bbiwarg/Graphics/OutputWindow.cs

@@ -71,34 +71,30 @@ namespace bbiwarg.Graphics
             videoHandle.nextFrame();
 
             //draw textures
-            DepthImage depthImage = videoHandle.getDepthImage();
-            Int16 minDepth = depthImage.getMinDepth();
-            Int16 maxDepth = depthImage.getMaxDepth();
-            Int64 minMaxInterval = (Int16) Math.Max(maxDepth - minDepth, 1);
-            Int16[] depthTextureData = new Int16[3 * depthImage.getWidth() * depthImage.getHeight()];
-            Int16[] edgeTextureData = new Int16[3 * depthImage.getWidth() * depthImage.getHeight()];
+            Int16[] depthTextureData = new Int16[3 * videoHandle.getWidth() * videoHandle.getHeight()];
+            Int16[] edgeTextureData = new Int16[3 * videoHandle.getWidth() * videoHandle.getHeight()];
             int index = 0;
 
-            for (int y = 0; y < depthImage.getHeight(); ++y)
+            for (int y = 0; y < videoHandle.getHeight(); ++y)
             {
-                for (int x = 0; x < depthImage.getWidth(); ++x)
+                for (int x = 0; x < videoHandle.getWidth(); ++x)
                 {
                     //depthTexture
-                    Int16 depth = Math.Min(depthImage.getDepthAt(x, y), maxDepth);
-                    Int16 scaledDepth =  (Int16)(Int16.MaxValue - (((int)depth - minDepth) * (int)Int16.MaxValue / minMaxInterval));
+                    Int16 scaledDepth = (Int16) ((1.0f - videoHandle.getRelativeDepth(x, y)) * Int16.MaxValue);
                     depthTextureData[index] = scaledDepth;
                     depthTextureData[index + 1] = scaledDepth;
                     depthTextureData[index + 2] = scaledDepth;
 
                     //edgeTexture
-                    Int16 edge = depthImage.getEdgeAt(x, y);
-                    Int16 fingerPoint;
-                    if (depthImage.isFingerPoint(x, y)) fingerPoint = Int16.MaxValue;
-                    else fingerPoint = 0;
-
-                    edgeTextureData[index] = fingerPoint;
-                    edgeTextureData[index + 1] = fingerPoint;
-                    edgeTextureData[index + 2] = edge;
+                    Int16 red = 0;
+                    Int16 green = 0;
+                    Int16 blue = 0;
+                    if (videoHandle.isEdgeAt(x, y)) blue = Int16.MaxValue;
+                    if (videoHandle.isFingerPointAt(x, y)) red = green = Int16.MaxValue;
+
+                    edgeTextureData[index] = red;
+                    edgeTextureData[index + 1] = green;
+                    edgeTextureData[index + 2] = blue;
 
                     index += 3;
                 }

+ 89 - 0
bbiwarg/Images/DepthImage.cs

@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Emgu.CV;
+using Emgu.CV.Structure;
+
+namespace bbiwarg.Images
+{
+    class DepthImage
+    {
+        private int width;
+        private int height;
+        private Image<Gray, Int16> image;
+        private Int16 minDepth;
+        private Int16 maxDepth;
+
+        public DepthImage(int width, int height, Image<Gray, Int16> image) {
+            this.width = width;
+            this.height = height;
+            this.image = image;
+
+            //smooth
+            this.image = image.SmoothMedian(3);
+
+            //threshold min&maxDepth
+            minDepth = findMinDepth();
+            maxDepth = (Int16) (minDepth + 200);
+            thresholdDepth(minDepth, maxDepth);
+
+        }
+
+        public Int16 getDepthAt(int x, int y) {
+            return image.Data[y, x, 0];
+        }
+
+        public float getRelativeDepth(int x, int y) {
+            float minMaxInterval = Math.Max(maxDepth - minDepth, 1);
+            return (getDepthAt(x, y)-minDepth) / minMaxInterval;
+        }
+
+        public Int16 getMinDepth() {
+            return minDepth;
+        }
+
+        public Int16 getMaxDepth() {
+            return maxDepth;
+        }
+
+        public int getWidth() {
+            return width;
+        }
+
+        public int getHeight() {
+            return height;
+        }
+
+        public Image<Gray, Int16> getImage() {
+            return image;
+        }
+
+        private Int16 findMinDepth() {
+            minDepth = Int16.MaxValue;
+            for (int x = 0; x < width; ++x)
+            {
+                for (int y = 0; y < height; ++y)
+                {
+                    Int16 depth = getDepthAt(x, y);
+                    if (depth < minDepth)
+                        minDepth = depth;
+                }
+            }
+            return minDepth;
+        }
+
+        private void thresholdDepth(Int16 min, Int16 max) {
+            for (int x = 0; x < width; ++x)
+            {
+                for (int y = 0; y < height; ++y)
+                {
+                    Int16 depth = getDepthAt(x, y);
+                    if (depth > max || depth < min)
+                        image.Data[y, x, 0] = max;
+                }
+            }
+        }
+    }
+}

+ 27 - 0
bbiwarg/Images/EdgeImage.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Emgu.CV;
+using Emgu.CV.Structure;
+
+namespace bbiwarg.Images
+{
+    class EdgeImage
+    {
+        private Image<Gray, Byte> image;
+
+        public EdgeImage(DepthImage depthImage) {
+            int minDepth = depthImage.getMinDepth();
+            int maxDepth = depthImage.getMaxDepth();
+            Image<Gray, Int16> depthImageInt16 = depthImage.getImage();
+            Image<Gray, Byte> depthImageByte = depthImageInt16.Convert<Byte>(delegate(Int16 depth) { return (byte)(((depth - minDepth) * Byte.MaxValue) / (maxDepth - minDepth)); });
+            image = depthImageByte.Canny(100, 75, 3);
+        }
+
+        public bool isEdgeAt(int x, int y) {
+            return (image.Data[y,x,0] > 0);
+        }
+    }
+}

+ 0 - 9
bbiwarg/InputProvider/InputFrame.cs

@@ -78,14 +78,5 @@ namespace bbiwarg.InputProviders
 
             return Color.FromArgb(alpha, red, green, blue);
         }
-
-        public DepthImage getDepthImage() {
-            Image<Gray, Int16> image = new Image<Gray, Int16>(width, height);
-            for (int i = 0; i < depthData.Length; ++i)
-            {
-                image.Data[i / width, i % width, 0] = depthData[i];
-            }
-            return new DepthImage(width, height, image);
-        }
     }
 }

+ 61 - 8
bbiwarg/VideoHandle.cs

@@ -3,7 +3,12 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using System.Diagnostics;
+using bbiwarg.Detectors.Finger;
+using bbiwarg.Images;
 using bbiwarg.InputProviders;
+using Emgu.CV;
+using Emgu.CV.Structure;
 
 namespace bbiwarg
 {
@@ -11,7 +16,13 @@ namespace bbiwarg
     {
         private IInputProvider inputProvider;
         private InputFrame inputFrame;
+
+        private int width;
+        private int height;
         private DepthImage depthImage;
+        private EdgeImage edgeImage;
+
+        private FingerDetector fingerDetector;
 
         public VideoHandle(IInputProvider inputProvider) {
             this.inputProvider = inputProvider;
@@ -21,8 +32,7 @@ namespace bbiwarg
             inputProvider.init();
             inputProvider.start();
             inputProvider.updateFrame();
-            inputFrame = inputProvider.getInputFrame();
-            depthImage = inputFrame.getDepthImage();
+            processFrameUpdate();
         }
        
         public void stop() {
@@ -35,8 +45,7 @@ namespace bbiwarg
             {
                 inputProvider.releaseFrame();
                 inputProvider.updateFrame();
-                inputFrame = inputProvider.getInputFrame();
-                depthImage = inputFrame.getDepthImage();
+                processFrameUpdate();
             }
             else
             {
@@ -46,16 +55,60 @@ namespace bbiwarg
 
         public int getWidth()
         {
-            return inputFrame.getWidth();
+            return width;
         }
 
         public int getHeight()
         {
-            return inputFrame.getHeight();
+            return height;
+        }
+
+        public Int16 getDepthAt(int x, int y) {
+            return depthImage.getDepthAt(x, y);
+        }
+
+        public float getRelativeDepth(int x, int y) {
+            return depthImage.getRelativeDepth(x, y);
+        }
+
+        public bool isEdgeAt(int x, int y) {
+            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 DepthImage getDepthImage() {
-            return depthImage;
+        private void processFrameUpdate()
+        {
+            Stopwatch sw = new Stopwatch();
+            sw.Start();
+            //read data from inputProvider
+            inputFrame = inputProvider.getInputFrame();
+            width = inputFrame.getWidth();
+            height = inputFrame.getHeight();
+
+            //create depthImage
+            Image<Gray, Int16> image = new Image<Gray, Int16>(width, height);
+            for (int x = 0; x < width; x++) {
+                for (int y = 0; y < height; y++) {
+                    image.Data[y, x, 0] = inputFrame.getDepthAt(x, y);
+                }
+            }
+            depthImage = new DepthImage(width, height, image);
+
+            //create edgeImage
+            edgeImage = new EdgeImage(depthImage);
+
+            //detect fingers
+            fingerDetector = new FingerDetector(depthImage, edgeImage);
+
+            sw.Stop();
+            Console.WriteLine(sw.ElapsedMilliseconds);
         }
     }
 }

+ 5 - 2
bbiwarg/bbiwarg.csproj

@@ -66,9 +66,12 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="DepthImage.cs" />
-    <Compile Include="Finger.cs" />
+    <Compile Include="Detectors\Finger\Finger.cs" />
+    <Compile Include="Detectors\Finger\FingerDetector.cs" />
+    <Compile Include="Detectors\Finger\FingerPoint.cs" />
     <Compile Include="Graphics\OutputWindow.cs" />
+    <Compile Include="Images\DepthImage.cs" />
+    <Compile Include="Images\EdgeImage.cs" />
     <Compile Include="InputProvider\InputFrame.cs" />
     <Compile Include="InputProvider\IInputProvider.cs" />
     <Compile Include="InputProvider\IisuInputProvider.cs" />