Browse Source

Made output much faster.

Daniel Kauth 10 years ago
parent
commit
8e86a71198

+ 15 - 5
bbiwarg/Detectors/Fingers/FingerDetector.cs

@@ -16,14 +16,14 @@ namespace bbiwarg.Detectors.Fingers
     {
         private DepthImage depthImage;
         private EdgeImage edgeImage;
-        private FingerImage fingerImage;
+        private OutputImage outputImage;
         public List<Finger> Fingers { get; private set; }
 
-        public FingerDetector(DepthImage depthImage, EdgeImage edgeImage, FingerImage fingerImage)
+        public FingerDetector(DepthImage depthImage, EdgeImage edgeImage, OutputImage outputImage)
         {
             this.depthImage = depthImage;
             this.edgeImage = edgeImage.copy();
-            this.fingerImage = fingerImage;
+            this.outputImage = outputImage;
 
             findFingers();
         }
@@ -267,10 +267,20 @@ namespace bbiwarg.Detectors.Fingers
             Fingers.Add(finger);
 
             //draw finger
-            fingerImage.drawFinger(finger, FingerImageState.fingerDetected);
-
+            drawDetectedFinger(finger);
+        
             //remove edges around detected finger to improve performance
             edgeImage.removeFingerEdges(finger);
         }
+
+        private void drawDetectedFinger(Finger finger)
+        {
+            FingerSliceTrail trail = finger.SliceTrail;
+            for (int i = 0; i < trail.NumSlices; i++)
+            {
+                outputImage.drawLineSegment(trail.Slices[i].LineSegment, 255, 0, 255);
+            }
+            outputImage.drawLineSegment(finger.LineSegment, 255, 0, 0);
+        }
     }
 }

+ 4 - 4
bbiwarg/Detectors/Fingers/FingerTracker.cs

@@ -9,7 +9,7 @@ namespace bbiwarg.Detectors.Fingers
 {
     class FingerTracker
     {
-        private FingerImage fingerImage;
+        private OutputImage outputImage;
         private List<Finger>[] detectedFingers;
         private int framesUntilTracked;
         public List<Finger> TrackedFingers { get; private set; }
@@ -26,9 +26,9 @@ namespace bbiwarg.Detectors.Fingers
             }
         }
 
-        public void setDetectedTouchEventsThisFrame(List<Finger> detectedFingersThisFrame, FingerImage fingerImage)
+        public void setDetectedTouchEventsThisFrame(List<Finger> detectedFingersThisFrame, OutputImage outputImage)
         {
-            this.fingerImage = fingerImage;
+            this.outputImage = outputImage;
 
             for (int i = (framesUntilTracked - 1); i > 0; i--)
             {
@@ -61,7 +61,7 @@ namespace bbiwarg.Detectors.Fingers
                 }
                 if (tracked)
                 {
-                    fingerImage.drawLine(finger.LineSegment, FingerImageState.fingerTracked);
+                    outputImage.drawLineSegment(finger.LineSegment, 0, 255, 0);
                     TrackedFingers.Add(finger);
                 }
             }

+ 29 - 6
bbiwarg/Detectors/Palm/PalmDetector.cs

@@ -21,7 +21,7 @@ namespace bbiwarg.Detectors.Palm
         private int width, height;
         private DepthImage depthImage;
         private EdgeImage edgeImage;
-        private PalmImage palmImage;
+        private OutputImage outputImage;
 
         private Image<Gray, Byte> handImage;
         private Image<Gray, Byte> pointingHandMask;
@@ -39,7 +39,7 @@ namespace bbiwarg.Detectors.Palm
 
         public Quadrangle PalmQuad;
 
-        public PalmDetector(DepthImage depthImage, EdgeImage edgeImage, List<Finger> detectedFingers, PalmImage palmImage)
+        public PalmDetector(DepthImage depthImage, EdgeImage edgeImage, List<Finger> detectedFingers, OutputImage outputImage)
         {
             // TODO: determine which fingers are index or thumb-fingers and detect palm in thumb-hand
 
@@ -47,7 +47,7 @@ namespace bbiwarg.Detectors.Palm
             height = depthImage.Height;
             this.depthImage = depthImage;
             this.edgeImage = edgeImage;
-            this.palmImage = palmImage;
+            this.outputImage = outputImage;
 
             // dst = (src > (MaxDepth - MinDepth)) ? 0 : 1
             handImage = depthImage.Image.ThresholdBinaryInv(new Gray(depthImage.MaxDepth - depthImage.MinDepth - 1), new Gray(1)).Convert<Gray, Byte>();
@@ -244,15 +244,38 @@ namespace bbiwarg.Detectors.Palm
 
         private void draw()
         {
-            palmImage.drawContour(palmContour);
+            outputImage.drawContour(palmContour, 255, 0, 0);
+            outputImage.drawPoints(palmContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE), 0, 255, 0);
 
             if (PalmQuad != null)
             {
                 Vector2D[] vertices = PalmQuad.Vertices;
                 for (int i = 0; i < 4; ++i)
-                    palmImage.drawLine(new LineSegment2DF(vertices[i], vertices[(i + 1) % 4]), PalmImageState.palmRect);
+                    outputImage.drawLineSegment(new bbiwarg.Utility.LineSegment2D(vertices[i], vertices[(i + 1) % 4]), 0, 0, 255);
 
-                palmImage.drawGrid(new Vector2D(vertices[0]), new Vector2D(vertices[1]), new Vector2D(vertices[2]), new Vector2D(vertices[3]));
+                drawGrid(new Vector2D(vertices[0]), new Vector2D(vertices[1]), new Vector2D(vertices[2]), new Vector2D(vertices[3]));
+            }
+        }
+
+        
+        private void drawGrid(Vector2D a, Vector2D b, Vector2D c, Vector2D d)
+        {
+            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;
+
+            for (int i = 1; i < numRows; i++)
+            {
+                outputImage.drawLineSegment(new bbiwarg.Utility.LineSegment2D(a + i * relAB, d + i * relDC), 80, 80, 255);
+            }
+
+            for (int i = 1; i < numColumns; i++)
+            {
+                outputImage.drawLineSegment(new bbiwarg.Utility.LineSegment2D(a + i * relAD, b + i * relBC), 80, 80, 255);
             }
         }
     }

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

@@ -16,14 +16,14 @@ namespace bbiwarg.Detectors.Touch
     class TouchDetector
     {
         private DepthImage depthImage;
-        private TouchImage touchImage;
+        private OutputImage outputImage;
         private List<Finger> fingers;
         public List<TouchEvent> TouchEvents { get; private set; }
 
-        public TouchDetector(List<Finger> fingers, DepthImage depthImage, TouchImage touchImage)
+        public TouchDetector(List<Finger> fingers, DepthImage depthImage, OutputImage outputImage)
         {
             this.depthImage = depthImage;
-            this.touchImage = touchImage;
+            this.outputImage = outputImage;
             this.fingers = fingers;
             this.TouchEvents = new List<TouchEvent>();
             float floodValueThreshold = 0.5f;
@@ -42,7 +42,7 @@ namespace bbiwarg.Detectors.Touch
                     float y = HelperFunctions.thresholdRange<float>(0, depthImage.Height - 1, tipPoint.Y + directionFactor * direction.Y);
                     Vector2D tep = new Vector2D(x, y);
 
-                    touchImage.setStateAt(tep, TouchImageState.touchDetected);
+                    outputImage.fillCircle(tep.IntX, tep.IntY, 5, 0, 127, 0);
                     TouchEvent touchEvent = new TouchEvent(tep, floodValue, finger);
                     TouchEvents.Add(touchEvent);
                 }
@@ -68,11 +68,11 @@ namespace bbiwarg.Detectors.Touch
                 for (int y = minY; y < maxY; y++)
                 {
                     Int16 depth = depthImage.getDepthAt(x, y);
-                    touchImage.setStateAt(x, y, TouchImageState.touchArea);
+                    outputImage.drawPixel(x, y, 50, 50, 50);
                     if (Math.Abs(depthAtTouch - depth) < maxDepthDifference)
                     {
                         matchedPixels++;
-                        touchImage.setStateAt(x, y, TouchImageState.touchAreaMatched);
+                        outputImage.drawPixel(x, y, 50, 50, 255);
                     }
                     countedPixels++;
                 }
@@ -83,7 +83,7 @@ namespace bbiwarg.Detectors.Touch
             //status bar (% of matched pixels) -> green
             for (int x = minX; x < minX + (maxX - minX) * rel; x++)
             {
-                touchImage.setStateAt(x, maxY - 1, TouchImageState.touchAreaStatusBar);
+                outputImage.drawPixel(x, maxY - 1, 0, 255, 0);
             }
 
             return rel;

+ 4 - 5
bbiwarg/Detectors/Touch/TouchTracker.cs

@@ -9,7 +9,7 @@ namespace bbiwarg.Detectors.Touch
 {
     class TouchTracker
     {
-        private TouchImage touchImage;
+        private OutputImage outputImage;
         private List<TouchEvent>[] detectedTouchEvents;
         private int framesUntilTracked;
         public List<TouchEvent> TrackedTouchEvents;
@@ -25,9 +25,9 @@ namespace bbiwarg.Detectors.Touch
             }
         }
 
-        public void setDetectedTouchEventsThisFrame(List<TouchEvent> touchEventsThisFrame, TouchImage touchImage)
+        public void setDetectedTouchEventsThisFrame(List<TouchEvent> touchEventsThisFrame, OutputImage outputImage)
         {
-            this.touchImage = touchImage;
+            this.outputImage = outputImage;
 
             for (int i = (framesUntilTracked - 1); i > 0; i--)
             {
@@ -52,9 +52,8 @@ namespace bbiwarg.Detectors.Touch
                 }
                 if (tracked)
                 {
-                    touchImage.setStateAt(te.Position, TouchImageState.touchTracked);
+                    outputImage.fillCircle(te.Position.IntX, te.Position.IntY, 5, 127, 0, 0);
                     TrackedTouchEvents.Add(te);
-                    //Console.WriteLine("touch tracked at x:" + te.getX() + " y:" + te.getY() + " [floodValue:" + te.getFloodValue() + "]");
                 }
             }
         }

+ 50 - 0
bbiwarg/Graphics/OutputImage.cs

@@ -0,0 +1,50 @@
+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;
+
+namespace bbiwarg.Images
+{
+    class OutputImage
+    {
+        public Image<Rgb, byte> Image { get; private set; }
+
+        public OutputImage(int width, int height)
+        {
+            Image = new Image<Rgb, byte>(width, height);
+        }
+
+        public void drawLineSegment(bbiwarg.Utility.LineSegment2D lineSegment, byte r, byte g, byte b, int thickness = 1)
+        {
+            Image.Draw(new LineSegment2D(lineSegment.P1, lineSegment.P2), new Rgb(r, g, b), thickness);
+        }
+
+        public void drawContour(Contour<Point> contour, byte r, byte g, byte b, int thickness = 1)
+        {
+            Image.Draw(contour, new Rgb(r, g, b), thickness);
+        }
+
+        public void drawPoints(Seq<Point> points, byte r, byte g, byte b, int thickness = 1)
+        {
+            Image.Draw(points, new Rgb(r, g, b), thickness);
+        }
+
+        public void drawPixel(int x, int y, byte r, byte g, byte b)
+        {
+            Image.Data[y, x, 0] = r;
+            Image.Data[y, x, 1] = g;
+            Image.Data[y, x, 2] = b;
+        }
+
+        public void fillCircle(int x, int y, float radius, byte r, byte g, byte b)
+        {
+            Image.Draw(new CircleF(new PointF(x, y), radius), new Rgb(r, g, b), 0);
+        }
+    }
+}

+ 21 - 161
bbiwarg/Graphics/OutputWindow.cs

@@ -19,17 +19,13 @@ namespace bbiwarg.Graphics
     class OutputWindow : GameWindow
     {
         private VideoHandle videoHandle;
-        private uint depthTextureID;
-        private uint edgeTextureID;
-        private uint touchEventTextureID;
+        private uint textureId;
         private bool paused = false;
         private long timeSpacePressed, timeLeftPressed, timeRightPressed;
         private Stopwatch watch;
 
-        private const int numImages = 3;
-
         public OutputWindow(VideoHandle videoHandle)
-            : base((int) (1.5 * numImages * videoHandle.Width), (int) (1.5 * videoHandle.Height))
+            : base((int) (1.5 * videoHandle.OutputImages.Length * videoHandle.Width), (int) (1.5 * videoHandle.Height))
         {
             this.videoHandle = videoHandle;
             watch = new Stopwatch();
@@ -49,27 +45,13 @@ namespace bbiwarg.Graphics
             //Depth Test 
             GL.Enable(EnableCap.DepthTest);
 
-            // Textures
+            // Texture
             GL.Enable(EnableCap.Texture2D);
 
-            //depthTexture
-            GL.GenTextures(1, out depthTextureID);
-            GL.BindTexture(TextureTarget.Texture2D, depthTextureID);
+            GL.GenTextures(1, out textureId);
+            GL.BindTexture(TextureTarget.Texture2D, textureId);
             GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
             GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
-
-            //edgetexture
-            GL.GenTextures(1, out edgeTextureID);
-            GL.BindTexture(TextureTarget.Texture2D, edgeTextureID);
-            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
-            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
-
-            //touch event texture
-            GL.GenTextures(1, out touchEventTextureID);
-            GL.BindTexture(TextureTarget.Texture2D, touchEventTextureID);
-            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
-            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
-
         }
 
         protected override void OnResize(EventArgs e)
@@ -83,12 +65,12 @@ namespace bbiwarg.Graphics
             int imageHeight = videoHandle.Height;
             float imageAspectRatio = (float)imageWidth / (float)imageHeight;
 
-            int heightForWidth = (int) ((float) screenWidth / ((float) numImages * imageAspectRatio));
+            int heightForWidth = (int) ((float) screenWidth / ((float) videoHandle.OutputImages.Length * imageAspectRatio));
 
             GL.Viewport(0, (screenHeight - heightForWidth) / 2, screenWidth, heightForWidth);
 
             // top left at (0,0) every image from (i, j) to (i + 1, j + 1)
-            Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, 3, 1, 0, 0.001f, 10f);
+            Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, videoHandle.OutputImages.Length, 1, 0, 0.001f, 10f);
             GL.MatrixMode(MatrixMode.Projection);
             GL.LoadMatrix(ref projection);
         }
@@ -103,8 +85,6 @@ namespace bbiwarg.Graphics
             GL.MatrixMode(MatrixMode.Modelview);
             GL.LoadMatrix(ref modelview);
 
-            bool changedFrame = false;
-
             const int autoRepeatDelay = 100; // ms
             if (videoHandle.sourceIsMovie())
             {
@@ -129,7 +109,6 @@ namespace bbiwarg.Graphics
                         videoHandle.unpauseMovie();
                         videoHandle.nextFrame();
                         videoHandle.pauseMovie();
-                        changedFrame = true;
                     }
                     else if (OpenTK.Input.Keyboard.GetState().IsKeyDown(OpenTK.Input.Key.Left) && (elapsed - timeLeftPressed) >= autoRepeatDelay)
                     {
@@ -139,13 +118,11 @@ namespace bbiwarg.Graphics
                         videoHandle.nextFrame();
                         videoHandle.reversePlay();
                         videoHandle.pauseMovie();
-                        changedFrame = true;
                     }
                 }
                 else
                 {
                     videoHandle.nextFrame();
-                    changedFrame = true;
                 }
             }
             else
@@ -153,145 +130,28 @@ namespace bbiwarg.Graphics
                 videoHandle.nextFrame();
             }
 
-            if (changedFrame || !videoHandle.sourceIsMovie())
-            {
-                /*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];
-            int index = 0;
-
-            for (int y = 0; y < videoHandle.Height; ++y)
+            GL.Enable(EnableCap.Texture2D);
+                
+            int imageIndex = 0;
+            foreach (OutputImage image in videoHandle.OutputImages)
             {
-                for (int x = 0; x < videoHandle.Width; ++x)
-                {
-                    Int16 red = 0;
-                    Int16 green = 0;
-                    Int16 blue = 0;
-
-                    //depthTexture
-                    float relDepth = videoHandle.getRelativeDepth(x, y);
-                    red = green = blue = (Int16)((1.0f - videoHandle.getRelativeDepth(x, y)) * Int16.MaxValue);
-
-                    // palm
-                    switch (videoHandle.getPalmImageStateAt(x, y))
-                    {
-                        case PalmImageState.palmContour:
-                            red = Int16.MaxValue;
-                            blue = green = 0;
-                            break;
-                        case PalmImageState.palmRect:
-                            blue = Int16.MaxValue;
-                            red = green = 0;
-                            break;
-                        case PalmImageState.thumbLine:
-                        case PalmImageState.wristLine:
-                            green = Int16.MaxValue;
-                            blue = red = 0;
-                            break;
-                        case PalmImageState.palmGrid:
-                            green = (Int16)(green / 2 + Int16.MaxValue / 2);
-                            blue = (Int16)(blue / 2 + Int16.MaxValue / 2);
-                            red = (Int16)(red / 2 + Int16.MaxValue / 2);
-                            break;
-                    }
-
-                    // touch
-                    switch (videoHandle.getTouchImageStateAt(x, y))
-                    {
-                        case TouchImageState.touchArea:
-                            red = (Int16)(red / 2);
-                            green = (Int16)(green / 2);
-                            blue = (Int16)(blue / 2);
-                            break;
-                        case TouchImageState.touchAreaMatched:
-                            red = (Int16)(red / 2);
-                            green = (Int16)(green / 2);
-                            blue = Int16.MaxValue;
-                            break;
-                        case TouchImageState.touchAreaStatusBar:
-                            red = (Int16)(red / 2);
-                            green = Int16.MaxValue;
-                            blue = (Int16)(blue / 2);
-                            break;
-                        case TouchImageState.touchDetected:
-                            red = (Int16)(red / 2);
-                            blue = (Int16)(blue / 2);
-                            green = (Int16)(green / 2 + Int16.MaxValue / 2);
-                            break;
-                        case TouchImageState.touchTracked:
-                            red = (Int16)(red / 2 + Int16.MaxValue / 2);
-                            green = (Int16)(green / 2);
-                            blue = (Int16)(blue / 2);
-                            break;
-                    }
-
-                    depthTextureData[index] = red;
-                    depthTextureData[index + 1] = green;
-                    depthTextureData[index + 2] = blue;
-
-                    //edgeTexture
-                    FingerImageState fis = videoHandle.getFingerImageStateAt(x, y);
-                    red = green = blue = 0;
-                    if (videoHandle.isEdgeAt(x, y)) blue = Int16.MaxValue;
-                    else if (fis == FingerImageState.fingerTracked) green = Int16.MaxValue;
-                    else if (fis == FingerImageState.fingerDetected) red = Int16.MaxValue;
-                    else if (fis == FingerImageState.fingerSlice) red = blue = Int16.MaxValue;
-                    else if (fis == FingerImageState.possibleFingerSlice) red = Int16.MaxValue;
-
-                    edgeTextureData[index] = red;
-                    edgeTextureData[index + 1] = green;
-                    edgeTextureData[index + 2] = blue;
-
-                    index += 3;
-                }
+                GL.BindTexture(TextureTarget.Texture2D, textureId);
+                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, videoHandle.Width, videoHandle.Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, image.Image.MIplImage.imageData);
+                GL.Begin(PrimitiveType.Quads);
+                GL.Color3(1.0, 1.0, 1.0);
+                GL.TexCoord2(0, 0); GL.Vertex3(0 + imageIndex, 0, -1);
+                GL.TexCoord2(1, 0); GL.Vertex3(1 + imageIndex, 0, -1);
+                GL.TexCoord2(1, 1); GL.Vertex3(1 + imageIndex, 1, -1);
+                GL.TexCoord2(0, 1); GL.Vertex3(0 + imageIndex, 1, -1);
+                GL.End();
+                ++imageIndex;
             }
 
-            GL.Enable(EnableCap.Texture2D);
-            GL.BindTexture(TextureTarget.Texture2D, edgeTextureID);
-            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, videoHandle.Width, videoHandle.Height, 0, PixelFormat.Rgb, PixelType.Short, edgeTextureData);
-            GL.Begin(PrimitiveType.Quads);
-            GL.Color3(1.0, 1.0, 1.0);
-            GL.TexCoord2(0, 0); GL.Vertex3(0, 0, -1);
-            GL.TexCoord2(1, 0); GL.Vertex3(1, 0, -1);
-            GL.TexCoord2(1, 1); GL.Vertex3(1, 1, -1);
-            GL.TexCoord2(0, 1); GL.Vertex3(0, 1, -1);
-            GL.End();
-
-            GL.Enable(EnableCap.Texture2D);
-            GL.BindTexture(TextureTarget.Texture2D, depthTextureID);
-            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, videoHandle.Width, videoHandle.Height, 0, PixelFormat.Rgb, PixelType.Short, depthTextureData);
-            GL.Begin(PrimitiveType.Quads);
-            GL.Color3(1.0, 1.0, 1.0);
-            GL.TexCoord2(0, 0); GL.Vertex3(1, 0, -1);
-            GL.TexCoord2(1, 0); GL.Vertex3(2, 0, -1);
-            GL.TexCoord2(1, 1); GL.Vertex3(2, 1, -1);
-            GL.TexCoord2(0, 1); GL.Vertex3(1, 1, -1);
-            GL.End();
-
-            /*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, 
-                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();*/
-
             Timer.start("swapBuffers");
             SwapBuffers();
             Timer.stop("swapBuffers");

+ 5 - 1
bbiwarg/Images/DepthImage.cs

@@ -17,7 +17,7 @@ namespace bbiwarg.Images
         public Int16 MinDepth { get; private set; }
         public Int16 MaxDepth { get; private set; }
 
-        public DepthImage(Image<Gray, Int16> image)
+        public DepthImage(Image<Gray, Int16> image, OutputImage outputImage)
         {
             Width = image.Width;
             Height = image.Height;
@@ -28,6 +28,10 @@ namespace bbiwarg.Images
 
             //smooth+threshold (dst = (src > (MaxDepth - MinDepth)) ? MaxDepth - MinDepth : src)
             Image = image.SmoothMedian(3).Sub(new Gray(MinDepth)).ThresholdTrunc(new Gray(MaxDepth - MinDepth)).Convert<Gray, byte>();
+
+            // draw depth
+            Image<Gray, byte> tmpDepth = (MaxDepth - MinDepth) - Image;
+            outputImage.Image[0] = outputImage.Image[1] = outputImage.Image[2] = tmpDepth;
         }
 
         public Int16 getDepthAt(Point point)

+ 4 - 1
bbiwarg/Images/EdgeImage.cs

@@ -17,10 +17,13 @@ namespace bbiwarg.Images
     {
         public Image<Gray, Byte> Image { get; private set; }
 
-        public EdgeImage(DepthImage depthImage)
+        public EdgeImage(DepthImage depthImage, OutputImage outputImage)
         {
             // no more scaling to [0, 255]?
             Image = depthImage.Image.Canny(100, 75, 3);
+
+            // draw blue edges in outputImage
+            outputImage.Image[2] = Image.ThresholdBinary(new Gray(0), new Gray(1)).Mul(255);
         }
 
         public EdgeImage(Image<Gray, Byte> edgeImage)

+ 0 - 52
bbiwarg/Images/FingerImage.cs

@@ -1,52 +0,0 @@
-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.Utility;
-using bbiwarg.Detectors.Fingers;
-
-namespace bbiwarg.Images
-{
-    public enum FingerImageState
-    {
-        none = 0,
-        possibleFingerSlice = 1,
-        fingerSlice = 2,
-        fingerDetected = 3,
-        fingerTracked = 4
-    }
-
-    class FingerImage
-    {
-        private Image<Gray, byte> image;
-
-        public FingerImage(int width, int height)
-        {
-            image = new Image<Gray, byte>(width, height);
-        }
-
-        public FingerImageState getStateAt(int x, int y)
-        {
-            return (FingerImageState)image.Data[y, x, 0];
-        }
-
-        public void drawFinger(Finger finger, FingerImageState state)
-        {
-            FingerSliceTrail trail = finger.SliceTrail;
-            for (int i = 0; i < trail.NumSlices; i++)
-            {
-                drawLine(trail.Slices[i].LineSegment, FingerImageState.fingerSlice);
-            }
-            drawLine(finger.LineSegment, state);
-        }
-
-        public void drawLine(Utility.LineSegment2D line, FingerImageState state)
-        {
-            image.Draw(new LineSegment2DF(line.P1, line.P2), new Gray((byte)state), 1);
-        }
-    }
-}

+ 0 - 73
bbiwarg/Images/PalmImage.cs

@@ -1,73 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using Emgu.CV;
-using Emgu.CV.Structure;
-using System.Drawing;
-
-using bbiwarg.Detectors.Fingers;
-using bbiwarg.Utility;
-using bbiwarg.Detectors.Touch;
-
-namespace bbiwarg.Images
-{
-    public enum PalmImageState
-    {
-        none = 0,
-        palmContour = 1,
-        wristLine = 2,
-        thumbLine = 3,
-        palmRect = 4,
-        palmGrid = 5
-    }
-
-    class PalmImage
-    {
-        private Image<Gray, Byte> image;
-
-        public PalmImage(int width, int height)
-        {
-            image = new Image<Gray, byte>(width, height);
-        }
-
-        public PalmImageState getStateAt(int x, int y)
-        {
-            return (PalmImageState)image.Data[y, x, 0];
-        }
-
-        public void drawContour(Contour<Point> contour)
-        {
-            image.Draw(contour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE), new Gray((byte)PalmImageState.palmContour), 1);
-            //image.Draw(contour, new Gray((byte)PalmImageState.palmContour), 1);
-        }
-
-        public void drawLine(LineSegment2DF line, PalmImageState state)
-        {
-            image.Draw(line, new Gray((byte)state), 1);
-        }
-
-        public void drawGrid(Vector2D a, Vector2D b, Vector2D c, Vector2D d)
-        {
-            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;
-
-            for (int i = 1; i < numRows; i++)
-            {
-                drawLine(new Emgu.CV.Structure.LineSegment2DF(a + i * relAB, d + i * relDC), PalmImageState.palmGrid);
-            }
-
-            for (int i = 1; i < numColumns; i++)
-            {
-                drawLine(new Emgu.CV.Structure.LineSegment2DF(a + i * relAD, b + i * relBC), PalmImageState.palmGrid);
-            }
-        }
-    }
-}

+ 0 - 55
bbiwarg/Images/TouchImage.cs

@@ -1,55 +0,0 @@
-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.Utility;
-
-namespace bbiwarg.Images
-{
-    public enum TouchImageState
-    {
-        none = 0,
-        touchArea = 1,
-        touchAreaMatched = 2,
-        touchAreaStatusBar = 3,
-        touchDetected = 4,
-        touchTracked = 5
-    }
-
-    class TouchImage
-    {
-        private Image<Gray, byte> image;
-
-        public TouchImage(int width, int height)
-        {
-            image = new Image<Gray, byte>(width, height);
-        }
-
-        public void setStateAt(Point point, TouchImageState state)
-        {
-            setStateAt(point.X, point.Y, state);
-        }
-
-        public void setStateAt(int x, int y, TouchImageState state)
-        {
-            image.Data[y, x, 0] = (byte)state;
-
-            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);
-            }
-        }
-
-
-        public TouchImageState getStateAt(int x, int y)
-        {
-            return (TouchImageState)image.Data[y, x, 0];
-        }
-    }
-}

+ 25 - 47
bbiwarg/VideoHandle.cs

@@ -22,12 +22,12 @@ namespace bbiwarg
 
         public int Width { get; private set; }
         public int Height { get; private set; }
+
+        public OutputImage[] OutputImages { get; private set; }
+        
         private DepthImage depthImage;
         private EdgeImage edgeImage;
-        private PalmImage palmImage;
-        private TouchImage touchImage;
-        private FingerImage fingerImage;
-
+        
         private FingerDetector fingerDetector;
         private PalmDetector palmDetector;
         private TouchDetector touchDetector;
@@ -36,6 +36,9 @@ namespace bbiwarg
         private FingerTracker fingerTracker;
         private TouchTracker touchTracker;
 
+        private OutputImage edgeFingerOutputImage;
+        private OutputImage depthPalmTouchOutputImage;
+
         public VideoHandle(IInputProvider inputProvider)
         {
             this.inputProvider = inputProvider;
@@ -97,36 +100,6 @@ namespace bbiwarg
             }
         }
 
-        public Int16 getDepthAt(int x, int y)
-        {
-            return depthImage.getDepthAt(x, y);
-        }
-
-        public float getRelativeDepth(int x, int y)
-        {
-            return depthImage.getRelativeDepthAt(x, y);
-        }
-
-        public bool isEdgeAt(int x, int y)
-        {
-            return edgeImage.isEdgeAt(x, y);
-        }
-
-        public FingerImageState getFingerImageStateAt(int x, int y)
-        {
-            return fingerImage.getStateAt(x, y);
-        }
-
-        public PalmImageState getPalmImageStateAt(int x, int y)
-        {
-            return palmImage.getStateAt(x, y);
-        }
-
-        public TouchImageState getTouchImageStateAt(int x, int y)
-        {
-            return touchImage.getStateAt(x, y);
-        }
-
         public List<PalmTouchEvent> getPalmTouchEvents()
         {
             return palmTouchDetector.PalmTouchEvents;
@@ -143,47 +116,52 @@ namespace bbiwarg
             Height = inputFrame.Height;
             Timer.stop("readInputData");
 
+            //create output images
+            Timer.start("createOtherImages");
+            edgeFingerOutputImage = new OutputImage(Width, Height);
+            depthPalmTouchOutputImage = new OutputImage(Width, Height);
+            Timer.stop("createOtherImages");
+
             //create depthImage
             Timer.start("createDepthImage");
             Image<Gray, Int16> image = new Image<Gray, Int16>(Width, Height, Width * 2, inputFrame.RawDepthData);
-            depthImage = new DepthImage(image);
+            depthImage = new DepthImage(image, depthPalmTouchOutputImage);
             Timer.stop("createDepthImage");
 
-            //create images
-            Timer.start("createOtherImages");
-            edgeImage = new EdgeImage(depthImage);
-            touchImage = new TouchImage(Width, Height);
-            fingerImage = new FingerImage(Width, Height);
-            palmImage = new PalmImage(Width, Height);
-            Timer.stop("createOtherImages");
+            // create edge image
+            Timer.start("createEdgeImage");
+            edgeImage = new EdgeImage(depthImage, edgeFingerOutputImage);
+            Timer.stop("createEdgeImage");
 
             //detect fingers
             Timer.start("fingerDetection");
-            fingerDetector = new FingerDetector(depthImage, edgeImage, fingerImage);
+            fingerDetector = new FingerDetector(depthImage, edgeImage, edgeFingerOutputImage);
             Timer.stop("fingerDetection");
 
             //track fingers
             Timer.start("fingerTracking");
-            fingerTracker.setDetectedTouchEventsThisFrame(fingerDetector.Fingers, fingerImage);
+            fingerTracker.setDetectedTouchEventsThisFrame(fingerDetector.Fingers, edgeFingerOutputImage);
             Timer.stop("fingerTracking");
 
             //detect palm
             Timer.start("palmDetection");
-            palmDetector = new PalmDetector(depthImage, edgeImage, fingerDetector.Fingers, palmImage);
+            palmDetector = new PalmDetector(depthImage, edgeImage, fingerDetector.Fingers, depthPalmTouchOutputImage);
             Timer.stop("palmDetection");
 
             //detect touchEvents
             Timer.start("touchDetection");
-            touchDetector = new TouchDetector(fingerTracker.TrackedFingers, depthImage, touchImage);
+            touchDetector = new TouchDetector(fingerTracker.TrackedFingers, depthImage, depthPalmTouchOutputImage);
             if (palmDetector.PalmQuad != null)
                 palmTouchDetector = new PalmTouchDetector(touchDetector.TouchEvents, palmDetector.PalmQuad);
             Timer.stop("touchDetection");
 
             //track touchEvents
             Timer.start("touchTracking");
-            touchTracker.setDetectedTouchEventsThisFrame(touchDetector.TouchEvents, touchImage);
+            touchTracker.setDetectedTouchEventsThisFrame(touchDetector.TouchEvents, depthPalmTouchOutputImage);
             Timer.stop("touchTracking");
 
+            OutputImages = new OutputImage[] { edgeFingerOutputImage, depthPalmTouchOutputImage };
+
             Timer.stop("processFrameUpdate");
         }
     }

+ 1 - 3
bbiwarg/bbiwarg.csproj

@@ -79,11 +79,9 @@
     <Compile Include="Detectors\Touch\TouchTracker.cs" />
     <Compile Include="Graphics\OutputWindow.cs" />
     <Compile Include="Graphics\KalmanDemo.cs" />
-    <Compile Include="Images\FingerImage.cs" />
     <Compile Include="Images\DepthImage.cs" />
     <Compile Include="Images\EdgeImage.cs" />
-    <Compile Include="Images\PalmImage.cs" />
-    <Compile Include="Images\TouchImage.cs" />
+    <Compile Include="Graphics\OutputImage.cs" />
     <Compile Include="InputProvider\InputFrame.cs" />
     <Compile Include="InputProvider\IInputProvider.cs" />
     <Compile Include="InputProvider\IisuInputProvider.cs" />