Jelajahi Sumber

Merge branch 'master' of https://git.tk.informatik.tu-darmstadt.de/etri-smartspaces

Conflicts:
	bbiwarg/Detectors/Palm/PalmDetector.cs
	bbiwarg/Graphics/OutputWindow.cs
	bbiwarg/Images/DepthImage.cs
	bbiwarg/Images/EdgeImage.cs
	bbiwarg/InputProvider/IisuInputProvider.cs
	bbiwarg/InputProvider/InputFrame.cs
	bbiwarg/VideoHandle.cs
Daniel Kauth 10 tahun lalu
induk
melakukan
dc64f501d0

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

@@ -21,6 +21,23 @@ namespace bbiwarg.Detectors.Fingers
             SliceTrail = sliceTrail;
         }
 
+        public Point[] getPolygon()
+        {
+            List<Point> pointsA = new List<Point>();
+            List<Point> pointsB = new List<Point>();
+            //int numSlices = SliceTrail.NumSlices;
+            //for (int i = 0; i < numSlices; i++)
+            foreach (FingerSlice slice in SliceTrail.Slices)
+            {
+                pointsA.Add(slice.Start);
+                pointsB.Add(slice.End);
+            }
+
+            pointsB.Reverse();
+            pointsA.AddRange(pointsB);
+            return pointsA.ToArray();
+        }
+
         //TODO: redo (not use similarity but actual distances and angle instead)
         public float getSimilarity(Finger compareFinger)
         {

+ 189 - 139
bbiwarg/Detectors/Fingers/FingerDetector.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Drawing;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -16,211 +17,260 @@ namespace bbiwarg.Detectors.Fingers
         private DepthImage depthImage;
         private EdgeImage edgeImage;
         private FingerImage fingerImage;
-        private List<FingerSliceTrail> horizontalFingerSliceTrails;
-        private List<FingerSliceTrail> verticalFingerSliceTrails;
         public List<Finger> Fingers { get; private set; }
 
-
         public FingerDetector(DepthImage depthImage, EdgeImage edgeImage, FingerImage fingerImage)
         {
             this.depthImage = depthImage;
-            this.edgeImage = edgeImage;
+            this.edgeImage = edgeImage.copy();
             this.fingerImage = fingerImage;
 
-            findHorizontalFingerSliceTrails();
-            findVerticalFingerSliceTrails();
-            transformFingerSliceTrailsToFingers();
+            findFingers();
         }
 
-        private void findHorizontalFingerSliceTrails()
+        private void findFingers()
         {
-
-            horizontalFingerSliceTrails = new List<FingerSliceTrail>();
-
+            int minNumSlices = 20;
             int width = depthImage.Width;
             int height = depthImage.Height;
+            int maxX = width - 1;
+            int maxY = height - 1;
 
-            int minFingerSize = 10;
-            int maxFingerSize = 30;
+            Fingers = new List<Finger>();
 
-            //search horizontal finger-slices
-            for (int y = 0; y < height; y++)
+            for (int y = 1; y < maxY; y++)
             {
-                int x = 0;
-                while (x <= width - minFingerSize)
+                for (int x = 1; x < maxX; x++)
                 {
-                    if (edgeImage.isEdgeAt(x, y) && depthImage.getDepthAt(x, y) > depthImage.getDepthAt(x + 1, y))
+                    if (edgeImage.isEdgeAt(x, y))
                     {
-                        int sliceX1 = x;
-                        int maxSliceX2 = Math.Min(sliceX1 + maxFingerSize, width - 1);
-                        x++;
-                        while (x <= maxSliceX2)
+                        Vector2D edgePoint = new Vector2D(x, y);
+                        Vector2D edgeDirection = getEdgeDirection(edgePoint);
+                        if (edgeDirection != null)
                         {
-                            if (edgeImage.isEdgeAt(x, y))
+                            Vector2D dir = edgeDirection.getOrthogonal(true);
+                            if (depthImage.getDepthAt(edgePoint - dir) < depthImage.getDepthAt(edgePoint + dir))
+                                dir = dir.getInverse();
+
+                            FingerSlice slice = findFingerSliceFromStartEdge(edgePoint, dir);
+                            if (slice != null)
                             {
-                                int sliceX2 = x;
-                                Vector2D sliceStart = new Vector2D(Math.Max(sliceX1 - 1, 0), y);
-                                Vector2D sliceEnd = new Vector2D(Math.Min(sliceX2 + 1, width - 1), y);
-                                FingerSlice fingerSlice = new FingerSlice(sliceStart, sliceEnd);
-                                if (fingerSlice.Size > minFingerSize && fingerSliceDepthTest(fingerSlice))
-                                {
-                                    addHorizontalFingerSlice(fingerSlice);
-                                    fingerImage.drawLine(fingerSlice.LineSegment, FingerImageState.possibleFingerSlice);
-                                }
-                                break;
+                                FingerSliceTrail trail = findFingerSliceTrail(slice, edgeDirection);
+                                if (trail != null && trail.NumSlices > minNumSlices)
+                                    createFingerFromTrail(trail);
                             }
-                            else x++;
                         }
                     }
-                    else
-                        x++;
-
                 }
             }
         }
 
-        private void findVerticalFingerSliceTrails()
+        private Vector2D getEdgeDirection(Vector2D edgePoint)
         {
-            verticalFingerSliceTrails = new List<FingerSliceTrail>();
+            int x = edgePoint.IntX;
+            int y = edgePoint.IntY;
 
-            int width = depthImage.Width;
-            int height = depthImage.Height;
+            if (edgeImage.isEdgeAt(x, y - 1) && edgeImage.isEdgeAt(x, y + 1)) return new Vector2D(0, 1);
+            else if (edgeImage.isEdgeAt(x - 1, y) && edgeImage.isEdgeAt(x + 1, y)) return new Vector2D(1, 0);
+            else if (edgeImage.isEdgeAt(x - 1, y - 1) && edgeImage.isEdgeAt(x + 1, y + 1)) return new Vector2D(1, 1).normalize();
+            else if (edgeImage.isEdgeAt(x + 1, y - 1) && edgeImage.isEdgeAt(x - 1, y + 1)) return new Vector2D(1, -1).normalize();
+            else return null;
+        }
 
-            int minFingerSize = 10;
-            int maxFingerSize = 30;
+        private FingerSliceTrail findFingerSliceTrail(FingerSlice startSlice, Vector2D startDirection)
+        {
+            int minNumSlicesForCorrection = 15;
+            int numRemoveForCorrection = 3;
+
+            int maxX = depthImage.Width - 1;
+            int maxY = depthImage.Height - 1;
+
+            FingerSliceTrail trail = new FingerSliceTrail(startSlice);
 
-            //search vertical finger-slices
-            for (int x = 0; x < width; x++)
+            Vector2D position = startSlice.Mid + startDirection;
+            Vector2D direction = startDirection;
+
+            if (position.isWithin(0, 0, maxX, maxY))
             {
-                int y = 0;
-                while (y <= height - minFingerSize)
+                FingerSlice nextSlice = findFingerSliceFromMid(position, direction);
+                if (nextSlice != null)
                 {
-                    if (edgeImage.isEdgeAt(x, y) && depthImage.getDepthAt(x, y) > depthImage.getDepthAt(x, y + 1))
+                    trail.addSlice(nextSlice);
+                    trail = expandTrail(trail);
+
+                    if (trail.NumSlices > minNumSlicesForCorrection)
                     {
-                        int sliceY1 = y;
-                        int maxSliceY2 = Math.Min(sliceY1 + maxFingerSize, height - 1);
-                        y++;
-                        while (y <= maxSliceY2)
-                        {
-                            if (edgeImage.isEdgeAt(x, y))
-                            {
-                                int sliceY2 = y;
-                                Vector2D sliceStart = new Vector2D(x, Math.Max(sliceY1 - 1, 0));
-                                Vector2D sliceEnd = new Vector2D(x, Math.Min(sliceY2 + 1, height - 1));
-                                FingerSlice fingerSlice = new FingerSlice(sliceStart, sliceEnd);
-                                if (fingerSlice.Size > minFingerSize && fingerSliceDepthTest(fingerSlice))
-                                {
-                                    addVerticalFingerSlice(fingerSlice);
-                                    fingerImage.drawLine(fingerSlice.LineSegment, FingerImageState.possibleFingerSlice);
-                                }
-                                break;
-                            }
-                            else y++;
-                        }
+                        trail.Slices.Reverse();
+                        trail.Slices.RemoveRange(0, numRemoveForCorrection);
+                        trail = expandTrail(trail);
+                        trail.Slices.Reverse();
+                        return trail;
                     }
-                    else
-                        y++;
-
                 }
             }
+
+            return null;
+
         }
 
-        private void transformFingerSliceTrailsToFingers()
+        private FingerSliceTrail expandTrail(FingerSliceTrail trail)
         {
-            int minNumSlices = 15;
+            int maxX = depthImage.Width - 1;
+            int maxY = depthImage.Height - 1;
 
-            Fingers = new List<Finger>();
-            List<FingerSliceTrail> fingerSliceTrails = new List<FingerSliceTrail>();
-            fingerSliceTrails.AddRange(horizontalFingerSliceTrails);
-            fingerSliceTrails.AddRange(verticalFingerSliceTrails);
+            int numDirectionsForAverage = 10;
+
+            List<Vector2D> directions = new List<Vector2D>();
+            int numDirections = Math.Min(trail.NumSlices - 1, numDirectionsForAverage);
+            for (int i = 0; i < numDirections; i++)
+            {
+                directions.Add(trail.Slices[i + 1].Mid - trail.Slices[i].Mid);
+            }
+
+            Vector2D currentDirection = Vector2D.mean(directions).normalize();
+            Vector2D currentPosition = trail.End.Mid + currentDirection;
+
+            int gapCounter = 0;
+            int numSlices = trail.NumSlices;
 
-            foreach (FingerSliceTrail trail in fingerSliceTrails)
+            FingerSlice lastSlice = trail.End;
+            FingerSlice nextSlice;
+
+            while (currentPosition.isWithin(0, 0, maxX, maxY) && gapCounter <= Math.Min(numSlices / 2, 10))
             {
-                if (trail.NumSlices >= minNumSlices)
+                nextSlice = findFingerSliceFromMid(currentPosition, currentDirection);
+                if (nextSlice != null && (nextSlice.Length < lastSlice.Length + 5 && nextSlice.Length > lastSlice.Length - 5))
                 {
-                    //reorder finger slice so that it goes tip->hand
-                    /*Int16 depthAtTip = depthImage.getDepthAt((int)trail.Start.Mid.X, (int)trail.Start.Mid.Y);
-                    Int16 depthAtHand = depthImage.getDepthAt((int)trail.End.Mid.X, (int)trail.End.Mid.Y);
-                    if (depthAtTip < depthAtHand)
-                        trail.reverse();*/
-                    
-                    Finger finger = new Finger(trail);
-
-                    //filter double hits (horizontal+vertical finger)
-                    bool addFinger = true;
-                    for (int i = Fingers.Count - 1; i >= 0; i--)
-                    {
-                        Finger f = Fingers[i];
-                        Utility.LineSegment2D lineA = finger.LineSegment;
-                        Utility.LineSegment2D lineB = f.LineSegment;
+                    gapCounter = 0;
+                    numSlices++;
+                    trail.addSlice(nextSlice);
+                    directions.Add((nextSlice.Mid - lastSlice.Mid));
 
-                        if(lineA.getVerticalDistanceTo(lineB) < 5 && lineA.getParallelDistanceTo(lineB) < 5)
-                        {
-                            if (finger.SliceTrail.NumSlices > f.SliceTrail.NumSlices)
-                                Fingers.RemoveAt(i);
-                            else
-                                addFinger = false;
-                        }
-                    }
+                    if (directions.Count == numDirectionsForAverage)
+                        directions.RemoveAt(0);
 
-                    if (addFinger)
-                    {
-                        Fingers.Add(finger);
-                        fingerImage.drawFinger(finger, FingerImageState.fingerDetected);
-                    }
+                    currentDirection = Vector2D.mean(directions).normalize();
+                    currentPosition = nextSlice.Mid + currentDirection;
 
+                    lastSlice = nextSlice;
+                }
+                else
+                {
+                    gapCounter++;
+                    currentPosition += currentDirection;
                 }
-
             }
 
+            return trail;
         }
 
-        private bool fingerSliceDepthTest(FingerSlice fingerSlice)
+        private FingerSlice findFingerSliceFromMid(Vector2D position, Vector2D direction)
         {
-            Int16 depthStart = depthImage.getDepthAt(fingerSlice.Start);
-            Int16 depthMid = depthImage.getDepthAt(fingerSlice.Mid);
-            Int16 depthEnd = depthImage.getDepthAt(fingerSlice.End);
-            return (depthStart > depthMid && depthMid < depthEnd);
+            if (edgeImage.isEdgeAt(position)) return null;
+
+            Vector2D dirStart = direction.getOrthogonal(true);
+            Vector2D dirEnd = direction.getOrthogonal(false);
+
+            Vector2D start = findNextEdge(position, dirStart);
+            if (start == null) return null;
+
+            Vector2D end = findNextEdge(position, dirEnd);
+            if (end == null) return null;
+
+            return getFingerSlice(start, end);
+        }
+        private FingerSlice findFingerSliceFromStartEdge(Vector2D start, Vector2D direction)
+        {
+
+            Vector2D end = findNextEdge(start, direction);
+            if (end == null) return null;
+
+            return getFingerSlice(start, end);
         }
 
-        private void addHorizontalFingerSlice(FingerSlice slice)
+        private Vector2D findNextEdge(Vector2D start, Vector2D direction)
         {
-            int maxYGap = 5;
-            int maxXDifference = 5;
+            int maxX = depthImage.Width - 1;
+            int maxY = depthImage.Height - 1;
+
+            int maxFingerSize = 30;
+
+            int maxStepsX;
+            if (direction.X > 0)
+                maxStepsX = (int)((maxX - start.X) / direction.X);
+            else if (direction.X < 0)
+                maxStepsX = (int)(start.X / Math.Abs(direction.X));
+            else
+                maxStepsX = int.MaxValue;
+
+            int maxStepsY;
+            if (direction.Y > 0)
+                maxStepsY = (int)((maxY - start.Y) / direction.Y);
+            else if (direction.Y < 0)
+                maxStepsY = (int)(start.Y / Math.Abs(direction.Y));
+            else
+                maxStepsY = int.MaxValue;
 
-            bool assigned = false;
-            foreach (FingerSliceTrail trail in horizontalFingerSliceTrails)
+            int maxStepsLength = (int)(maxFingerSize / direction.Length);
+
+            int maxSteps = Math.Min(maxStepsLength, Math.Min(maxStepsX, maxStepsY));
+
+            Vector2D end = new Vector2D(start);
+            for (int i = 0; i < maxSteps; i++)
             {
-                FingerSlice trailEnd = trail.End;
-                if (slice.Mid.Y - trailEnd.Mid.Y <= maxYGap && Math.Abs(trailEnd.Mid.X - slice.Mid.X) <= maxXDifference)
+                end += direction;
+
+                if (edgeImage.isEdgeAt(end))
                 {
-                    trail.addSlice(slice);
-                    assigned = true;
+                    return end;
                 }
             }
 
-            if (!assigned)
-                horizontalFingerSliceTrails.Add(new FingerSliceTrail(slice));
+            return null;
         }
 
-        private void addVerticalFingerSlice(FingerSlice slice)
+        private FingerSlice getFingerSlice(Vector2D start, Vector2D end)
         {
-            int maxXGap = 5;
-            int maxYDifference = 5;
+            int maxX = depthImage.Width - 1;
+            int maxY = depthImage.Height - 1;
 
-            bool assigned = false;
-            foreach (FingerSliceTrail trail in verticalFingerSliceTrails)
-            {
-                FingerSlice trailEnd = trail.End;
-                if (slice.Mid.X - trailEnd.Mid.X <= maxXGap && Math.Abs(trailEnd.Mid.Y - slice.Mid.Y) <= maxYDifference)
-                {
-                    trail.addSlice(slice);
-                    assigned = true;
-                }
-            }
+            int minFingerSize = 5;
+            int maxFingerSize = 30;
+
+            Vector2D direction = (end - start).normalize();
+            Vector2D beforeStart = start - direction;
+            Vector2D behindEnd = end + direction;
+
+            start = beforeStart.isWithin(0, 0, maxX, maxY) ? beforeStart : start;
+            end = behindEnd.isWithin(0, 0, maxX, maxY) ? behindEnd : end;
+
+            FingerSlice slice = new FingerSlice(start, end);
+            if (slice.Length >= minFingerSize && slice.Length <= maxFingerSize && fingerSliceDepthTest(slice))
+                return slice;
+
+            return null;
+        }
+
+        private bool fingerSliceDepthTest(FingerSlice fingerSlice)
+        {
+            Int16 depthStart = depthImage.getDepthAt(fingerSlice.Start);
+            Int16 depthMid = depthImage.getDepthAt(fingerSlice.Mid);
+            Int16 depthEnd = depthImage.getDepthAt(fingerSlice.End);
+            return (depthStart > depthMid && depthMid < depthEnd);
+        }
+
+        private void createFingerFromTrail(FingerSliceTrail trail)
+        {
+            Finger finger = new Finger(trail);
+
+            //add finger
+            Fingers.Add(finger);
+
+            //draw finger
+            fingerImage.drawFinger(finger, FingerImageState.fingerDetected);
 
-            if (!assigned)
-                verticalFingerSliceTrails.Add(new FingerSliceTrail(slice));
+            //remove edges around detected finger to improve performance
+            edgeImage.removeFingerEdges(finger);
         }
     }
 }

+ 6 - 3
bbiwarg/Detectors/Fingers/FingerSlice.cs

@@ -12,13 +12,16 @@ namespace bbiwarg.Detectors.Fingers
         public Vector2D Start { get; private set; }
         public Vector2D Mid { get; private set; }
         public Vector2D End { get; private set; }
-        public LineSegment2D LineSegment { get { return new LineSegment2D(Start, End); } }
-        public float Size { get { return Start.getDistanceTo(End); } }
+        public LineSegment2D LineSegment { get; private set; }
+        public float Length { get; private set; }
 
-        public FingerSlice(Vector2D start, Vector2D end) {
+        public FingerSlice(Vector2D start, Vector2D end)
+        {
             Start = start;
             End = end;
             Mid = (start + end) / 2;
+            LineSegment = new LineSegment2D(Start, End);
+            Length = Start.getDistanceTo(End); ;
         }
 
     }

+ 0 - 4
bbiwarg/Detectors/Fingers/FingerSliceTrail.cs

@@ -25,9 +25,5 @@ namespace bbiwarg.Detectors.Fingers
         {
             Slices.Add(slice);
         }
-
-        public void reverse() {
-            Slices.Reverse();
-        }
     }
 }

+ 9 - 5
bbiwarg/Detectors/Fingers/FingerTracker.cs

@@ -14,7 +14,8 @@ namespace bbiwarg.Detectors.Fingers
         private int framesUntilTracked;
         public List<Finger> TrackedFingers { get; private set; }
 
-        public FingerTracker() {
+        public FingerTracker()
+        {
             framesUntilTracked = 3;
             detectedFingers = new List<Finger>[framesUntilTracked];
             TrackedFingers = new List<Finger>();
@@ -55,7 +56,7 @@ namespace bbiwarg.Detectors.Fingers
                     {
                         tracked = false;
                         break;
-                       
+
                     }
                 }
                 if (tracked)
@@ -66,12 +67,15 @@ namespace bbiwarg.Detectors.Fingers
             }
         }
 
-        private Finger getMostSimilarFingerInFrame(Finger finger, int frame) {
+        private Finger getMostSimilarFingerInFrame(Finger finger, int frame)
+        {
             Finger mostSimilarFinger = null;
             float maxSimilarity = 0;
-            foreach (Finger f in detectedFingers[frame]) {
+            foreach (Finger f in detectedFingers[frame])
+            {
                 float similarity = finger.getSimilarity(f);
-                if (similarity > maxSimilarity) {
+                if (similarity > maxSimilarity)
+                {
                     mostSimilarFinger = f;
                     maxSimilarity = similarity;
                 }

+ 2 - 1
bbiwarg/Detectors/Palm/PalmDetector.cs

@@ -49,7 +49,8 @@ namespace bbiwarg.Detectors.Palm
             this.edgeImage = edgeImage;
             this.palmImage = palmImage;
 
-            handImage = depthImage.Image.ThresholdBinaryInv(new Gray(depthImage.getMaxDepth() - 1), new Gray(1)).Convert<Gray, Byte>();
+            // dst = (src > 254) ? 0 : 1
+            handImage = depthImage.Image.ThresholdBinaryInv(new Gray(254), new Gray(1)).Convert<Gray, Byte>();
 
             fingers = getFingersWithoutThumb(detectedFingers);
             buildPointingHandMask();

+ 6 - 3
bbiwarg/Detectors/Touch/PalmTouchDetector.cs

@@ -13,12 +13,15 @@ namespace bbiwarg.Detectors.Touch
     {
         public List<PalmTouchEvent> PalmTouchEvents { get; private set; }
 
-        public PalmTouchDetector(List<TouchEvent> touchEvents, Quadrangle palmQuad) {
+        public PalmTouchDetector(List<TouchEvent> touchEvents, Quadrangle palmQuad)
+        {
             PalmTouchEvents = new List<PalmTouchEvent>();
 
-            foreach (TouchEvent touchEvent in touchEvents) {
+            foreach (TouchEvent touchEvent in touchEvents)
+            {
                 Vector2D relativePos = palmQuad.getRelativePosition(touchEvent.Position);
-                if (relativePos.X >= 0 && relativePos.X <= 1.0 && relativePos.Y >= 0 && relativePos.Y <= 1.0) {
+                if (relativePos.X >= 0 && relativePos.X <= 1.0 && relativePos.Y >= 0 && relativePos.Y <= 1.0)
+                {
                     PalmTouchEvent pte = new PalmTouchEvent(touchEvent.Position, relativePos, touchEvent.FloodValue, touchEvent.Finger);
                     PalmTouchEvents.Add(pte);
                 }

+ 20 - 13
bbiwarg/Detectors/Touch/TouchDetector.cs

@@ -18,17 +18,19 @@ namespace bbiwarg.Detectors.Touch
         private DepthImage depthImage;
         private TouchImage touchImage;
         private List<Finger> fingers;
-        public List<TouchEvent> TouchEvents {get; private set;}
+        public List<TouchEvent> TouchEvents { get; private set; }
 
-        public TouchDetector(List<Finger> fingers, DepthImage depthImage, TouchImage touchImage) {
+        public TouchDetector(List<Finger> fingers, DepthImage depthImage, TouchImage touchImage)
+        {
             this.depthImage = depthImage;
             this.touchImage = touchImage;
             this.fingers = fingers;
             this.TouchEvents = new List<TouchEvent>();
             float floodValueThreshold = 0.5f;
 
-            foreach (Finger finger in fingers) {
-                 Vector2D tipPoint = finger.Tip;
+            foreach (Finger finger in fingers)
+            {
+                Vector2D tipPoint = finger.Tip;
 
                 float floodValue = getFloodValue(tipPoint);
                 if (floodValue > floodValueThreshold)
@@ -38,7 +40,7 @@ namespace bbiwarg.Detectors.Touch
                     float directionFactor = 10;
                     float x = HelperFunctions.thresholdRange<float>(0, depthImage.Width - 1, tipPoint.X + directionFactor * direction.X);
                     float y = HelperFunctions.thresholdRange<float>(0, depthImage.Height - 1, tipPoint.Y + directionFactor * direction.Y);
-                    Vector2D tep = new Vector2D(x,y);
+                    Vector2D tep = new Vector2D(x, y);
 
                     touchImage.setStateAt(tep, TouchImageState.touchDetected);
                     TouchEvent touchEvent = new TouchEvent(tep, floodValue, finger);
@@ -47,11 +49,12 @@ namespace bbiwarg.Detectors.Touch
             }
         }
 
-        private float getFloodValue(Point touchPoint) {
+        private float getFloodValue(Point touchPoint)
+        {
             int searchSize = 15;
             int maxDepthDifference = 20;
             Int16 fingerDiameter = 5;
-            Int16 depthAtTouch = (Int16) (depthImage.getDepthAt(touchPoint) + fingerDiameter);
+            Int16 depthAtTouch = (Int16)(depthImage.getDepthAt(touchPoint) + fingerDiameter);
 
             int minX = Math.Max(touchPoint.X - searchSize, 0);
             int maxX = Math.Min(touchPoint.X + searchSize, depthImage.Width);
@@ -60,11 +63,14 @@ namespace bbiwarg.Detectors.Touch
 
             int matchedPixels = 0;
             int countedPixels = 0;
-            for (int x = minX; x < maxX; x++) {
-                for (int y = minY; y < maxY; y++) {
-                    Int16 depth = depthImage.getDepthAt(x,y);
+            for (int x = minX; x < maxX; x++)
+            {
+                for (int y = minY; y < maxY; y++)
+                {
+                    Int16 depth = depthImage.getDepthAt(x, y);
                     touchImage.setStateAt(x, y, TouchImageState.touchArea);
-                    if (Math.Abs(depthAtTouch - depth) < maxDepthDifference) {
+                    if (Math.Abs(depthAtTouch - depth) < maxDepthDifference)
+                    {
                         matchedPixels++;
                         touchImage.setStateAt(x, y, TouchImageState.touchAreaMatched);
                     }
@@ -75,11 +81,12 @@ namespace bbiwarg.Detectors.Touch
             float rel = (float)matchedPixels / (float)countedPixels;
 
             //status bar (% of matched pixels) -> green
-            for (int x = minX; x < minX + (maxX-minX)*rel; x++) {
+            for (int x = minX; x < minX + (maxX - minX) * rel; x++)
+            {
                 touchImage.setStateAt(x, maxY - 1, TouchImageState.touchAreaStatusBar);
             }
 
-                return rel;
+            return rel;
         }
     }
 }

+ 4 - 2
bbiwarg/Detectors/Touch/TouchEvent.cs

@@ -14,13 +14,15 @@ namespace bbiwarg.Detectors.Touch
         public float FloodValue { get; private set; }
         public Finger Finger { get; private set; }
 
-        public TouchEvent(Vector2D position, float floodValue, Finger finger) {
+        public TouchEvent(Vector2D position, float floodValue, Finger finger)
+        {
             Position = position;
             FloodValue = floodValue;
             Finger = finger;
         }
 
-        public bool isSimilarTo(TouchEvent compareTouchEvent) {
+        public bool isSimilarTo(TouchEvent compareTouchEvent)
+        {
             float maxDistance = 20;
             float distance = Position.getDistanceTo(compareTouchEvent.Position);
             return (distance < maxDistance);

+ 19 - 10
bbiwarg/Detectors/Touch/TouchTracker.cs

@@ -14,20 +14,24 @@ namespace bbiwarg.Detectors.Touch
         private int framesUntilTracked;
         public List<TouchEvent> TrackedTouchEvents;
 
-        public TouchTracker() {
+        public TouchTracker()
+        {
             framesUntilTracked = 2;
             detectedTouchEvents = new List<TouchEvent>[framesUntilTracked];
 
-            for (int i = 0; i < framesUntilTracked; i++) {
+            for (int i = 0; i < framesUntilTracked; i++)
+            {
                 detectedTouchEvents[i] = new List<TouchEvent>();
             }
         }
 
-        public void setDetectedTouchEventsThisFrame(List<TouchEvent> touchEventsThisFrame, TouchImage touchImage) {
+        public void setDetectedTouchEventsThisFrame(List<TouchEvent> touchEventsThisFrame, TouchImage touchImage)
+        {
             this.touchImage = touchImage;
 
-            for (int i = (framesUntilTracked-1); i > 0; i--) {
-                detectedTouchEvents[i] = detectedTouchEvents[i - 1]; 
+            for (int i = (framesUntilTracked - 1); i > 0; i--)
+            {
+                detectedTouchEvents[i] = detectedTouchEvents[i - 1];
             }
             detectedTouchEvents[0] = touchEventsThisFrame;
 
@@ -35,12 +39,15 @@ namespace bbiwarg.Detectors.Touch
             findTrackedTouches();
         }
 
-        private void findTrackedTouches() {
+        private void findTrackedTouches()
+        {
             TrackedTouchEvents = new List<TouchEvent>();
 
-            foreach (TouchEvent te in detectedTouchEvents[0]) {
+            foreach (TouchEvent te in detectedTouchEvents[0])
+            {
                 bool tracked = true;
-                for (int i = 1; i < framesUntilTracked; i++) {
+                for (int i = 1; i < framesUntilTracked; i++)
+                {
                     if (!hasSimilarTouchEventInFrame(te, i)) tracked = false;
                 }
                 if (tracked)
@@ -52,8 +59,10 @@ namespace bbiwarg.Detectors.Touch
             }
         }
 
-        private bool hasSimilarTouchEventInFrame(TouchEvent touchEvent, int frame) {
-            foreach (TouchEvent te in detectedTouchEvents[frame]) {
+        private bool hasSimilarTouchEventInFrame(TouchEvent touchEvent, int frame)
+        {
+            foreach (TouchEvent te in detectedTouchEvents[frame])
+            {
                 if (touchEvent.isSimilarTo(te))
                     return true;
             }

+ 4 - 2
bbiwarg/Graphics/KalmanDemo.cs

@@ -50,8 +50,10 @@ namespace bbiwarg.Graphics
 
             Int16[] textureData = new Int16[3 * width * height];
             int index = 0;
-            for (int y = 0; y < height; ++y) {
-                for (int x = 0; x < width; ++x) {
+            for (int y = 0; y < height; ++y)
+            {
+                for (int x = 0; x < width; ++x)
+                {
                     textureData[index + 0] = image.Data[y, x, 2];
                     textureData[index + 1] = image.Data[y, x, 1];
                     textureData[index + 2] = image.Data[y, x, 0];

+ 18 - 12
bbiwarg/Graphics/OutputWindow.cs

@@ -9,12 +9,11 @@ using OpenTK;
 using OpenTK.Graphics.OpenGL;
 using bbiwarg.Images;
 using bbiwarg.Detectors.Touch;
+using bbiwarg.Utility;
 
 using Emgu.CV;
 using Emgu.CV.Structure;
 
-using bbiwarg.Utility;
-
 namespace bbiwarg.Graphics
 {
     class OutputWindow : GameWindow
@@ -26,15 +25,15 @@ namespace bbiwarg.Graphics
         private bool paused = false;
         private long timeSpacePressed, timeLeftPressed, timeRightPressed;
         private Stopwatch watch;
-        private TouchEventVisualizer touchEventVisualizer;
+
+        private const int numImages = 3;
 
         public OutputWindow(VideoHandle videoHandle)
-            : base(3 * videoHandle.Width, videoHandle.Height)
+            : base((int) (1.5 * numImages * videoHandle.Width), (int) (1.5 * videoHandle.Height))
         {
             this.videoHandle = videoHandle;
             watch = new Stopwatch();
             watch.Start();
-            touchEventVisualizer = new TouchEventVisualizer();
         }
 
         protected override void OnLoad(EventArgs e)
@@ -77,8 +76,6 @@ namespace bbiwarg.Graphics
         {
             base.OnResize(e);
             
-            const int numImages = 3;
-
             int screenWidth = ClientRectangle.Width;
             int screenHeight = ClientRectangle.Height;
 
@@ -98,6 +95,8 @@ namespace bbiwarg.Graphics
 
         protected override void OnRenderFrame(FrameEventArgs e)
         {
+            Timer.start("onRenderFrame");
+
             base.OnRenderFrame(e);
             GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
             Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, -Vector3.UnitZ, Vector3.UnitY);
@@ -156,16 +155,18 @@ namespace bbiwarg.Graphics
 
             if (changedFrame || !videoHandle.sourceIsMovie())
             {
-                foreach (PalmTouchEvent ev in videoHandle.getPalmTouchEvents())
+                /*foreach (PalmTouchEvent ev in videoHandle.getTouchEvents())
                 {
                     //Console.WriteLine("touch at " + ev.Position + " -> " + ev.RelativePalmPosition);
                     //touchVisualizer.addTouchEvent(ev);
-                }
+                }*/
             }
 
             if (videoHandle.sourceIsMovie())
                 Title = "BBIWARG - Output (Frame " + videoHandle.getCurrentMovieFrame() + ")";
 
+
+            Timer.start("outputTextures");
             //draw textures
             Int16[] depthTextureData = new Int16[3 * videoHandle.Width * videoHandle.Height];
             Int16[] edgeTextureData = new Int16[3 * videoHandle.Width * videoHandle.Height];
@@ -279,19 +280,24 @@ namespace bbiwarg.Graphics
             GL.TexCoord2(0, 1); GL.Vertex3(1, 1, -1);
             GL.End();
 
-            GL.Enable(EnableCap.Texture2D);
+            /*GL.Enable(EnableCap.Texture2D);
             GL.BindTexture(TextureTarget.Texture2D, touchEventTextureID);
             GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, videoHandle.Width, videoHandle.Height, 0, PixelFormat.Rgb, PixelType.Short, 
-                touchEventVisualizer.getTextureData(videoHandle.Width, videoHandle.Height));
+                kalmanDemo.getTextureData(videoHandle.Width, videoHandle.Height));
             GL.Begin(PrimitiveType.Quads);
             GL.Color3(1.0, 1.0, 1.0);
             GL.TexCoord2(0, 0); GL.Vertex3(2, 0, -1);
             GL.TexCoord2(1, 0); GL.Vertex3(3, 0, -1);
             GL.TexCoord2(1, 1); GL.Vertex3(3, 1, -1);
             GL.TexCoord2(0, 1); GL.Vertex3(2, 1, -1);
-            GL.End();
+            GL.End();*/
 
             SwapBuffers();
+            Timer.stop("outputTextures");
+
+            Timer.stop("onRenderFrame");
+
+            Timer.outputAll();
         }
 
     }

+ 10 - 31
bbiwarg/Images/DepthImage.cs

@@ -7,13 +7,11 @@ using System.Threading.Tasks;
 using Emgu.CV;
 using Emgu.CV.Structure;
 
-using System.Diagnostics;
-
 namespace bbiwarg.Images
 {
     class DepthImage
     {
-        public Image<Gray, Int16> Image { get; private set; }
+        public Image<Gray, byte> Image { get; private set; }
         public int Width { get; private set; }
         public int Height { get; private set; }
         public Int16 MinDepth { get; private set; }
@@ -21,18 +19,15 @@ namespace bbiwarg.Images
 
         public DepthImage(Image<Gray, Int16> image)
         {
-            this.Image = image;
             Width = image.Width;
             Height = image.Height;
 
-            //smooth
-            this.Image = image.SmoothMedian(3);
-            
             //threshold min&maxDepth
-            MinDepth = (Int16)findMinDepth();
-            MaxDepth = (Int16)(MinDepth + 200);
+            MinDepth = findMinDepth(image);
+            MaxDepth = (Int16)(MinDepth + 200); // max = minDepth+255 (else it can't fit whole range in byte image)
 
-            thresholdDepth(MaxDepth);
+            //smooth+threshold
+            Image = image.SmoothMedian(3).ThresholdTrunc(new Gray(MaxDepth)).Convert<Gray, byte>();
         }
 
         public Int16 getDepthAt(Point point)
@@ -42,7 +37,7 @@ namespace bbiwarg.Images
 
         public Int16 getDepthAt(int x, int y)
         {
-            return Image.Data[y, x, 0];
+            return (Int16)(MinDepth + Image.Data[y, x, 0]);
         }
 
         public void setDepthAt(Point point, Int16 depth)
@@ -52,7 +47,7 @@ namespace bbiwarg.Images
 
         public void setDepthAt(int x, int y, Int16 depth)
         {
-            Image.Data[y, x, 0] = depth;
+            Image.Data[y, x, 0] = (byte)(depth - MinDepth);
         }
 
         public float getRelativeDepthAt(Point point)
@@ -66,32 +61,16 @@ namespace bbiwarg.Images
             return (getDepthAt(x, y) - MinDepth) / minMaxInterval;
         }
 
-        public Int16 getMinDepth()
-        {
-            return MinDepth;
-        }
-
-        public Int16 getMaxDepth()
-        {
-            return MaxDepth;
-        }
-
-        private Int16 findMinDepth()
+        private Int16 findMinDepth(Image<Gray, Int16> image)
         {
             // min and max values
             double[] min, max;
             // min and max locations
             Point[] minLoc, maxLoc;
 
-            Image.MinMax(out min, out max, out minLoc, out maxLoc);
-            
-            return (Int16) min[0];
-        }
+            image.MinMax(out min, out max, out minLoc, out maxLoc);
 
-        private void thresholdDepth(Int16 max)
-        {
-            // newDepth = (depth > max) ? max : depth;
-            Image = Image.ThresholdTrunc(new Gray(max));
+            return (Int16)min[0];
         }
     }
 }

+ 29 - 11
bbiwarg/Images/EdgeImage.cs

@@ -1,10 +1,12 @@
 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.Detectors.Fingers;
 
 using System.Diagnostics;
 using bbiwarg.Utility;
@@ -13,23 +15,39 @@ namespace bbiwarg.Images
 {
     class EdgeImage
     {
-        public Image<Gray, byte> Image { get; private set; }
+        public Image<Gray, Byte> Image { get; private set; }
 
-        public EdgeImage(DepthImage depthImage) 
+        public EdgeImage(DepthImage depthImage)
         {
-            int minDepth = depthImage.getMinDepth();
-            int maxDepth = depthImage.getMaxDepth();
+            // no more scaling to [0, 255]?
+            Image = depthImage.Image.Canny(100, 75, 3);
+        }
+
+        public EdgeImage(Image<Gray, Byte> edgeImage)
+        {
+            Image = edgeImage;
+        }
+
+        public bool isEdgeAt(Point point)
+        {
+            return isEdgeAt(point.X, point.Y);
+        }
+
+        public bool isEdgeAt(int x, int y)
+        {
+            return (Image.Data[y, x, 0] > 0);
+        }
 
-            Image<Gray, Int16> depthImageInt16 = depthImage.Image.Clone();
-            depthImageInt16 = depthImageInt16.Sub(new Gray(minDepth));
-            depthImageInt16 = depthImageInt16.Mul(Byte.MaxValue / (maxDepth - minDepth));
-            Image<Gray, Byte> depthImageByte = depthImageInt16.Convert<Gray, Byte>();
+        public void removeFingerEdges(Finger finger)
+        {
+            Point[] polygon = finger.getPolygon();
 
-            Image = depthImageByte.Canny(100, 75, 3);
+            Image.FillConvexPoly(polygon, new Gray(0));
         }
 
-        public bool isEdgeAt(int x, int y) {
-            return (Image.Data[y,x,0] > 0);
+        public EdgeImage copy()
+        {
+            return new EdgeImage(Image.Copy());
         }
     }
 }

+ 10 - 5
bbiwarg/Images/FingerImage.cs

@@ -11,7 +11,8 @@ using bbiwarg.Detectors.Fingers;
 
 namespace bbiwarg.Images
 {
-    public enum FingerImageState {
+    public enum FingerImageState
+    {
         none = 0,
         possibleFingerSlice = 1,
         fingerSlice = 2,
@@ -23,17 +24,21 @@ namespace bbiwarg.Images
     {
         private Image<Gray, byte> image;
 
-        public FingerImage(int width, int height) {
+        public FingerImage(int width, int height)
+        {
             image = new Image<Gray, byte>(width, height);
         }
 
-        public FingerImageState getStateAt(int x, int y) {
+        public FingerImageState getStateAt(int x, int y)
+        {
             return (FingerImageState)image.Data[y, x, 0];
         }
 
-        public void drawFinger(Finger finger, FingerImageState state) {
+        public void drawFinger(Finger finger, FingerImageState state)
+        {
             FingerSliceTrail trail = finger.SliceTrail;
-            for (int i = 0; i < trail.NumSlices; i++) {
+            for (int i = 0; i < trail.NumSlices; i++)
+            {
                 drawLine(trail.Slices[i].LineSegment, FingerImageState.fingerSlice);
             }
             drawLine(finger.LineSegment, state);

+ 10 - 14
bbiwarg/Images/PalmImage.cs

@@ -51,27 +51,23 @@ namespace bbiwarg.Images
 
         public void drawGrid(Vector2D a, Vector2D b, Vector2D c, Vector2D d)
         {
-            int columnCount = 4;
-            int rowCount = 3;
+            int numRows = 4;
+            int numColumns = 3;
 
-        
+            Vector2D relAB = (b - a) / numRows;
+            Vector2D relDC = (c - d) / numRows;
+            Vector2D relBC = (c - b) / numColumns;
+            Vector2D relAD = (d - a) / numColumns;
 
-            Vector2D bc = c - b;
-            for (int i = 1; i < columnCount; i++)
+            for (int i = 1; i < numRows; i++)
             {
-                Vector2D bci = b + (bc * ((float)i/columnCount));
-                Vector2D adi = a + (bc * ((float)i/columnCount));
-                drawLine(new LineSegment2DF(bci, adi), PalmImageState.palmGrid);
+                drawLine(new Emgu.CV.Structure.LineSegment2DF(a + i * relAB, d + i * relDC), PalmImageState.palmGrid);
             }
 
-            Vector2D ab = b - a;
-            for (int i = 1; i < rowCount; i++)
+            for (int i = 1; i < numColumns; i++)
             {
-                Vector2D abi = a + (ab * ((float)i / rowCount));
-                Vector2D dci = d + (ab * ((float)i / rowCount));
-                drawLine(new LineSegment2DF(abi, dci), PalmImageState.palmGrid);
+                drawLine(new Emgu.CV.Structure.LineSegment2DF(a + i * relAD, b + i * relBC), PalmImageState.palmGrid);
             }
-
         }
     }
 }

+ 3 - 2
bbiwarg/Images/TouchImage.cs

@@ -30,7 +30,8 @@ namespace bbiwarg.Images
             image = new Image<Gray, byte>(width, height);
         }
 
-        public void setStateAt(Point point, TouchImageState state) {
+        public void setStateAt(Point point, TouchImageState state)
+        {
             setStateAt(point.X, point.Y, state);
         }
 
@@ -41,7 +42,7 @@ namespace bbiwarg.Images
             int size = 5;
             if (state == TouchImageState.touchTracked || state == TouchImageState.touchDetected)
             {
-                image.Draw(new CircleF(new System.Drawing.PointF(x, y), size), new Gray((byte) state), 0);
+                image.Draw(new CircleF(new System.Drawing.PointF(x, y), size), new Gray((byte)state), 0);
             }
         }
 

+ 1 - 2
bbiwarg/InputProvider/IisuInputProvider.cs

@@ -25,7 +25,7 @@ namespace bbiwarg.InputProviders
         //data
         private IDataHandle<Iisu.Data.IImageData> depthImage;
 
-        public IisuInputProvider(String moviePath = "") 
+        public IisuInputProvider(String moviePath = "")
         {
             if (moviePath.Length != 0)
             {
@@ -136,7 +136,6 @@ namespace bbiwarg.InputProviders
         }
 
         // other
-
         public void pauseMovie()
         {
             if (sourceIsMovie)

+ 1 - 1
bbiwarg/Utility/Kalman2DPositionFilter.cs

@@ -24,7 +24,7 @@ namespace bbiwarg.Utility
             kalman = new Kalman(4, 2, 0);
 
             // initial state (x, y, v_x, v_y)
-            Matrix<float> initialState = new Matrix<float>(new float[] { initialPosition.X, initialPosition.Y, 0.0f, 0.0f});
+            Matrix<float> initialState = new Matrix<float>(new float[] { initialPosition.X, initialPosition.Y, 0.0f, 0.0f });
             kalman.CorrectedState = initialState;
 
             // transition matrix 

+ 2 - 1
bbiwarg/Utility/Line2D.cs

@@ -18,7 +18,8 @@ namespace bbiwarg.Utility
         public Vector2D PointOnLine { get; private set; }
         public Vector2D Direction { get; private set; }
 
-        public Line2D(Vector2D pointOnLine, Vector2D direction) {
+        public Line2D(Vector2D pointOnLine, Vector2D direction)
+        {
             PointOnLine = pointOnLine;
             Direction = direction.normalize();
         }

+ 1 - 1
bbiwarg/Utility/LineSegment2D.cs

@@ -12,7 +12,7 @@ namespace bbiwarg.Utility
         public Vector2D P1 { get; private set; }
         public Vector2D P2 { get; private set; }
         public Line2D Line { get; private set; }
-        public float Length { get { return P1.getDistanceTo(P2); }}
+        public float Length { get { return P1.getDistanceTo(P2); } }
 
         public LineSegment2D(Vector2D p1, Vector2D p2)
         {

+ 1 - 1
bbiwarg/Utility/Quadrangle.cs

@@ -10,7 +10,7 @@ namespace bbiwarg.Utility
 {
     class Quadrangle
     {
-        public Vector2D[] Vertices { get { return new Vector2D[4] {BottomLeft, TopLeft, TopRight, BottomRight}; } }
+        public Vector2D[] Vertices { get { return new Vector2D[4] { BottomLeft, TopLeft, TopRight, BottomRight }; } }
         public Vector2D BottomLeft { get; private set; }
         public Vector2D TopLeft { get; private set; }
         public Vector2D TopRight { get; private set; }

+ 52 - 0
bbiwarg/Utility/Timer.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bbiwarg.Utility
+{
+    class Timer
+    {
+        private static Dictionary<String, Stopwatch> stopwatches = new Dictionary<string, Stopwatch>();
+        private static Dictionary<String, double> minTimes = new Dictionary<string, double>();
+        private static Dictionary<String, double> maxTimes = new Dictionary<string, double>();
+        private static Dictionary<String, double> sumTimes = new Dictionary<string, double>();
+        private static Dictionary<String, int> numTimes = new Dictionary<string, int>();
+
+        public static void start(String name) {
+            if (!stopwatches.ContainsKey(name))
+            {
+                stopwatches.Add(name, new Stopwatch());
+                minTimes.Add(name, int.MaxValue);
+                maxTimes.Add(name, 0);
+                sumTimes.Add(name, 0);
+                numTimes.Add(name, 0);
+            }
+            stopwatches[name].Restart();
+        }
+
+        public static void stop(String name) {
+            stopwatches[name].Stop();
+            double time = Math.Round((double)stopwatches[name].ElapsedTicks / (double)Stopwatch.Frequency * 1000.0, 2);
+            if (time < minTimes[name]) minTimes[name] = time;
+            if (time > maxTimes[name]) maxTimes[name] = time;
+            sumTimes[name] += time;
+            numTimes[name]++;
+        }
+
+        public static void output(String name) {
+            Console.WriteLine("name:" + name + "\t" + "mean:" + Math.Round(sumTimes[name] / Math.Max(numTimes[name], 1), 2) + "\t" + "min:" + minTimes[name] + "\t" + "max:" + maxTimes[name]);
+        }
+
+        public static void outputAll() {
+            Console.WriteLine("---TIMERS-START---");
+            foreach (String name in stopwatches.Keys) {
+                output(name);
+            }
+            Console.WriteLine("---TIMERS-END---");
+        }
+
+    }
+}

+ 29 - 3
bbiwarg/Utility/Vector2D.cs

@@ -21,6 +21,12 @@ namespace bbiwarg.Utility
             Y = y;
         }
 
+        public Vector2D(Vector2D vec)
+        {
+            X = vec.X;
+            Y = vec.Y;
+        }
+
         public Vector2D(Point point)
         {
             X = point.X;
@@ -64,12 +70,31 @@ namespace bbiwarg.Utility
 
         public Vector2D normalize()
         {
-            return new Vector2D(X / Length, Y / Length);
+            float length = Length;
+            return new Vector2D(X / length, Y / length);
+        }
+
+        public bool isWithin(float minX, float minY, float maxX, float maxY)
+        {
+            return (X >= minX && Y >= minY && X <= maxX && Y <= maxY);
+        }
+
+        public Vector2D getOrthogonal(bool side)
+        {
+            if (side)
+                return new Vector2D(Y, -X);
+            else
+                return new Vector2D(-Y, X);
+        }
+
+        public Vector2D getInverse()
+        {
+            return new Vector2D(-X, -Y);
         }
 
         public override string ToString()
         {
-            return "(" + X + ", " + Y + ")";
+            return "(" + X + "|" + Y + ")";
         }
 
         public static Vector2D operator *(float scalar, Vector2D vector)
@@ -112,7 +137,8 @@ namespace bbiwarg.Utility
             return new PointF(vec.X, vec.Y);
         }
 
-        public static implicit operator Point(Vector2D vec) {
+        public static implicit operator Point(Vector2D vec)
+        {
             return new Point(vec.IntX, vec.IntY);
         }
 

+ 45 - 37
bbiwarg/VideoHandle.cs

@@ -4,12 +4,12 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Diagnostics;
+using bbiwarg.Utility;
 using bbiwarg.Detectors.Fingers;
 using bbiwarg.Detectors.Palm;
 using bbiwarg.Detectors.Touch;
 using bbiwarg.Images;
 using bbiwarg.InputProviders;
-using bbiwarg.Utility;
 using Emgu.CV;
 using Emgu.CV.Structure;
 
@@ -36,7 +36,8 @@ namespace bbiwarg
         private FingerTracker fingerTracker;
         private TouchTracker touchTracker;
 
-        public VideoHandle(IInputProvider inputProvider) {
+        public VideoHandle(IInputProvider inputProvider)
+        {
             this.inputProvider = inputProvider;
 
             //initialize trackers
@@ -44,14 +45,16 @@ namespace bbiwarg
             fingerTracker = new FingerTracker();
         }
 
-        public void start() {
+        public void start()
+        {
             inputProvider.init();
             inputProvider.start();
             inputProvider.updateFrame();
             processFrameUpdate();
         }
-       
-        public void stop() {
+
+        public void stop()
+        {
             inputProvider.stop();
         }
 
@@ -82,9 +85,6 @@ namespace bbiwarg
 
         public void nextFrame()
         {
-            Stopwatch sw = new Stopwatch();
-            sw.Start();
-
             if (inputProvider.isActive())
             {
                 inputProvider.releaseFrame();
@@ -95,24 +95,25 @@ namespace bbiwarg
             {
                 inputProvider.stop();
             }
-
-            //Console.WriteLine("time for frame: {0} ms", HelperFunctions.getElapsedMilliseconds(sw));
-            //Console.WriteLine();
         }
 
-        public Int16 getDepthAt(int x, int y) {
+        public Int16 getDepthAt(int x, int y)
+        {
             return depthImage.getDepthAt(x, y);
         }
 
-        public float getRelativeDepth(int x, int y) {
+        public float getRelativeDepth(int x, int y)
+        {
             return depthImage.getRelativeDepthAt(x, y);
         }
 
-        public bool isEdgeAt(int x, int y) {
+        public bool isEdgeAt(int x, int y)
+        {
             return edgeImage.isEdgeAt(x, y);
         }
 
-        public FingerImageState getFingerImageStateAt(int x, int y) {
+        public FingerImageState getFingerImageStateAt(int x, int y)
+        {
             return fingerImage.getStateAt(x, y);
         }
 
@@ -121,7 +122,8 @@ namespace bbiwarg
             return palmImage.getStateAt(x, y);
         }
 
-        public TouchImageState getTouchImageStateAt(int x, int y) {
+        public TouchImageState getTouchImageStateAt(int x, int y)
+        {
             return touchImage.getStateAt(x, y);
         }
 
@@ -132,51 +134,57 @@ namespace bbiwarg
 
         private void processFrameUpdate()
         {
-            Stopwatch sw = new Stopwatch();
-            
+            Timer.start("processFrameUpdate");
+
             //read data from inputProvider
-            sw.Start();
+            Timer.start("readInputData");
             inputFrame = inputProvider.getInputFrame();
             Width = inputFrame.Width;
             Height = inputFrame.Height;
-            //Console.WriteLine("    time for input frame:          {0} ms", HelperFunctions.getElapsedMilliseconds(sw));
+            Timer.stop("readInputData");
 
             //create depthImage
-            sw.Restart();
+            Timer.start("createDepthImage");
             Image<Gray, Int16> image = new Image<Gray, Int16>(Width, Height, Width * 2, inputFrame.RawDepthData);
-            //Console.WriteLine("    time for depth image creation: {0} ms", HelperFunctions.getElapsedMilliseconds(sw));
-
-            sw.Restart();
             depthImage = new DepthImage(image);
-            //Console.WriteLine("    time for DepthImage:           {0} ms", HelperFunctions.getElapsedMilliseconds(sw));
+            Timer.stop("createDepthImage");
 
             //create images
-            sw.Restart();
+            Timer.start("createOtherImages");
             edgeImage = new EdgeImage(depthImage);
             touchImage = new TouchImage(Width, Height);
             fingerImage = new FingerImage(Width, Height);
             palmImage = new PalmImage(Width, Height);
-            //Console.WriteLine("    time for images:               {0} ms", HelperFunctions.getElapsedMilliseconds(sw));
+            Timer.stop("createOtherImages");
 
-            //detect+track fingers
-            sw.Restart();
+            //detect fingers
+            Timer.start("fingerDetection");
             fingerDetector = new FingerDetector(depthImage, edgeImage, fingerImage);
+            Timer.stop("fingerDetection");
+
+            //track fingers
+            Timer.start("fingerTracking");
             fingerTracker.setDetectedTouchEventsThisFrame(fingerDetector.Fingers, fingerImage);
-            //Console.WriteLine("    time for finger detection:     {0} ms", HelperFunctions.getElapsedMilliseconds(sw));
+            Timer.stop("fingerTracking");
 
             //detect palm
-            sw.Restart();
+            Timer.start("palmDetection");
             palmDetector = new PalmDetector(depthImage, edgeImage, fingerDetector.Fingers, palmImage);
-            //Console.WriteLine("    time for palm detection:       {0} ms", HelperFunctions.getElapsedMilliseconds(sw));
+            Timer.stop("palmDetection");
 
-            //detect+track touchEvents
-            sw.Restart();
+            //detect touchEvents
+            Timer.start("touchDetection");
             touchDetector = new TouchDetector(fingerTracker.TrackedFingers, depthImage, touchImage);
-            if(palmDetector.PalmQuad != null)
+            if (palmDetector.PalmQuad != null)
                 palmTouchDetector = new PalmTouchDetector(touchDetector.TouchEvents, palmDetector.PalmQuad);
+            Timer.stop("touchDetection");
+
+            //track touchEvents
+            Timer.start("touchTracking");
             touchTracker.setDetectedTouchEventsThisFrame(touchDetector.TouchEvents, touchImage);
-            //Console.WriteLine("    time for touch detection:      {0} ms", HelperFunctions.getElapsedMilliseconds(sw));
+            Timer.stop("touchTracking");
+
+            Timer.stop("processFrameUpdate");
         }
     }
 }
- 

+ 1 - 0
bbiwarg/bbiwarg.csproj

@@ -94,6 +94,7 @@
     <Compile Include="Utility\Line2D.cs" />
     <Compile Include="Utility\LineSegment2D.cs" />
     <Compile Include="Utility\Quadrangle.cs" />
+    <Compile Include="Utility\Timer.cs" />
     <Compile Include="Utility\Vector2D.cs" />
     <Compile Include="VideoHandle.cs" />
   </ItemGroup>