Explorar o código

-implemented multithreading (debugWindow and inputHandle/inputProvider are working in different threads now)
-large refactoring+cleanup

Alexander Hendrich %!s(int64=10) %!d(string=hai) anos
pai
achega
412b4ecccf
Modificáronse 56 ficheiros con 1319 adicións e 1100 borrados
  1. 127 0
      bbiwarg/BBWIWARG.cs
  2. 0 158
      bbiwarg/Graphics/TouchEventVisualizer.cs
  3. 4 4
      bbiwarg/Images/ConfidenceImage.cs
  4. 15 8
      bbiwarg/Images/DepthImage.cs
  5. 5 13
      bbiwarg/Images/EdgeImage.cs
  6. 41 0
      bbiwarg/Input/InputHandling/FrameData.cs
  7. 132 0
      bbiwarg/Input/InputHandling/InputHandler.cs
  8. 126 0
      bbiwarg/Input/InputProviding/InputProvider.cs
  9. 19 25
      bbiwarg/Input/InputProviding/VideoInputProvider.cs
  10. 0 299
      bbiwarg/InputHandler.cs
  11. 0 26
      bbiwarg/InputProviders/InputFrame.cs
  12. 0 71
      bbiwarg/InputProviders/InputProvider.cs
  13. 0 75
      bbiwarg/MainBBWIWARG.cs
  14. 159 0
      bbiwarg/Output/DebugOutput/DebugImages.cs
  15. 67 44
      bbiwarg/Output/DebugOutput/DebugWindow.cs
  16. 157 0
      bbiwarg/Output/DebugOutput/TouchEventVisualizer.cs
  17. 21 1
      bbiwarg/Output/OutputImage.cs
  18. 67 35
      bbiwarg/Parameters.cs
  19. 3 3
      bbiwarg/Recognition/FingerRecognition/Finger.cs
  20. 10 14
      bbiwarg/Recognition/FingerRecognition/FingerDetector.cs
  21. 1 1
      bbiwarg/Recognition/FingerRecognition/FingerSlice.cs
  22. 1 1
      bbiwarg/Recognition/FingerRecognition/FingerSliceTrail.cs
  23. 5 2
      bbiwarg/Recognition/FingerRecognition/FingerTracker.cs
  24. 2 2
      bbiwarg/Recognition/FingerRecognition/TrackedFinger.cs
  25. 1 1
      bbiwarg/Recognition/HandRecognition/Hand.cs
  26. 15 22
      bbiwarg/Recognition/HandRecognition/HandDetector.cs
  27. 6 1
      bbiwarg/Recognition/HandRecognition/HandTracker.cs
  28. 1 1
      bbiwarg/Recognition/HandRecognition/TrackedHand.cs
  29. 1 2
      bbiwarg/Recognition/PalmRecognition/Palm.cs
  30. 9 7
      bbiwarg/Recognition/PalmRecognition/PalmDetector.cs
  31. 5 2
      bbiwarg/Recognition/PalmRecognition/PalmTracker.cs
  32. 4 4
      bbiwarg/Recognition/PalmRecognition/TrackedPalm.cs
  33. 3 12
      bbiwarg/Recognition/TouchRecognition/Touch.cs
  34. 12 10
      bbiwarg/Recognition/TouchRecognition/TouchDetector.cs
  35. 40 12
      bbiwarg/Recognition/TouchRecognition/TouchTracker.cs
  36. 132 0
      bbiwarg/Recognition/TouchRecognition/TrackedTouch.cs
  37. 0 127
      bbiwarg/Recognition/TouchRecognition/TrackedTouchEvent.cs
  38. 2 2
      bbiwarg/Recognition/Tracking/TrackedObject.cs
  39. 31 24
      bbiwarg/Recognition/Tracking/Tracker.cs
  40. 0 0
      bbiwarg/TUIO/OSC.NET/OSCBundle.cs
  41. 0 0
      bbiwarg/TUIO/OSC.NET/OSCMessage.cs
  42. 0 0
      bbiwarg/TUIO/OSC.NET/OSCPacket.cs
  43. 0 0
      bbiwarg/TUIO/OSC.NET/OSCTransmitter.cs
  44. 0 0
      bbiwarg/TUIO/TUIO/TuioContainer.cs
  45. 0 0
      bbiwarg/TUIO/TUIO/TuioCursor.cs
  46. 0 0
      bbiwarg/TUIO/TUIO/TuioPoint.cs
  47. 0 3
      bbiwarg/TUIO/TUIO/TuioServer.cs
  48. 0 0
      bbiwarg/TUIO/TUIO/TuioTime.cs
  49. 23 24
      bbiwarg/TUIO/TuioCommunicator.cs
  50. 1 1
      bbiwarg/Utility/ConvexityDefect.cs
  51. 1 1
      bbiwarg/Utility/Line2D.cs
  52. 1 1
      bbiwarg/Utility/LineSegment2D.cs
  53. 6 12
      bbiwarg/Utility/Logger.cs
  54. 1 1
      bbiwarg/Utility/Quadrangle.cs
  55. 40 27
      bbiwarg/Utility/Timer.cs
  56. 22 21
      bbiwarg/bbiwarg.csproj

+ 127 - 0
bbiwarg/BBWIWARG.cs

@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using System.Linq;
+using System.Text;
+using System.Net;
+using bbiwarg.Output.DebugOutput;
+using bbiwarg.Input.InputProviding;
+using bbiwarg.Input.InputHandling;
+using bbiwarg.TUIO;
+
+namespace bbiwarg
+{
+    class BBIWARG
+    {
+        InputProvider inputProvider;
+        InputHandler inputHandler;
+        TuioCommunicator tuioCommunicator;
+        DebugWindow debugWindow;
+
+        Thread debugOutputThread;
+
+        static void Main(string[] args)
+        {
+            Console.SetWindowSize(Parameters.ConsoleWidth, Parameters.ConsoleHeight);
+            handleArgs(args);
+
+            BBIWARG program = new BBIWARG();
+            program.run();
+        }
+
+        public BBIWARG()
+        {
+            // inputProvider
+            createInputProvider();
+            inputProvider.DeviceStartedEvent += handleDeviceStartedEvent;
+
+            // inputHandler
+            inputHandler = new InputHandler();
+            inputProvider.NewFrameEvent += inputHandler.handleNewFrame;
+
+            // tuioCommunicator
+            if (Parameters.TuioEnabled)
+            {
+                tuioCommunicator = new TuioCommunicator(Parameters.TuioIP.ToString(), Parameters.TuioPort);
+                inputHandler.NewProcessedFrameEvent += tuioCommunicator.handleNewFrameData;
+            }
+
+            // debug output
+            if (Parameters.DebugOutputEnabled)
+            {
+                debugOutputThread = new Thread(new ThreadStart(debugOutputThreadStart));
+            }
+
+        }
+
+        public void run()
+        {
+            inputProvider.start();
+        }
+
+        private void createInputProvider()
+        {
+            if (Parameters.InputSource == InputType.Movie)
+                inputProvider = new VideoInputProvider(Parameters.InputMoviePath);
+            else
+                inputProvider = new InputProvider();
+        }
+
+        private void debugOutputThreadStart()
+        {
+            debugWindow = new DebugWindow(inputProvider, inputHandler);
+            debugWindow.Run(Parameters.DebugOutputUpdateRate, Parameters.DebugOutputRenderRate);
+        }
+
+        private void handleDeviceStartedEvent(object sender, EventArgs e)
+        {
+            startOutputThreads();
+        }
+
+        private void startOutputThreads()
+        {
+            if (Parameters.DebugOutputEnabled)
+                debugOutputThread.Start();
+        }
+
+        private static void handleArgs(String[] args)
+        {
+            if (args.Length > 0)
+            {
+                IPAddress ipAddress;
+                Int16 port;
+                String ipString = null;
+                String portString = null;
+                if (args.Length == 2)
+                {
+                    ipString = args[0];
+                    portString = args[1];
+                }
+                else if (args.Length == 1)
+                {
+                    String[] parts = args[0].Split(':');
+                    ipString = parts[0];
+                    if (parts.Length == 2)
+                        portString = parts[1];
+                }
+
+                while (!TuioCommunicator.tryParseIPAddress(ipString, out ipAddress))
+                {
+                    Console.WriteLine("Please insert the TUIO-Client's IP (Default is 127.0.0.1):");
+                    ipString = Console.ReadLine();
+                }
+                Console.WriteLine("TUIO-IP is set to:" + Parameters.TuioIP.ToString());
+
+                while (!TuioCommunicator.tryParsePort(portString, out port))
+                {
+                    Console.WriteLine("Please insert the TUIO-Client's Port (Default is 3333):");
+                    portString = Console.ReadLine();
+                }
+                Console.WriteLine("TUIO-PORT is set to:" + Parameters.TuioPort);
+
+                Parameters.setTuioParameters(true, ipAddress, port);
+            }
+        }
+    }
+}

+ 0 - 158
bbiwarg/Graphics/TouchEventVisualizer.cs

@@ -1,158 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.TouchRecognition;
-using bbiwarg.Utility;
-
-namespace bbiwarg.Graphics
-{
-    class TouchEventVisualizer
-    {
-        public OutputImage OutputImage { get; private set; }
-
-        private int width, height;
-        private Stopwatch timer;
-
-        private Dictionary<int, int> idTranslations;
-        private Dictionary<int, List<Vector2D>> positions;
-        private Dictionary<int, long> lastUpdates;
-        private int nextFreeID;
-        private int lastUpdated;
-        private bool active;
-
-        public TouchEventVisualizer(int width, int height)
-        {
-            this.width = width;
-            this.height = height;
-            reset();
-
-        }
-
-        public void reset()
-        {
-            timer = new Stopwatch();
-            timer.Start();
-
-            nextFreeID = 1;
-            lastUpdated = 0;
-            active = false;
-            idTranslations = new Dictionary<int, int>();
-            positions = new Dictionary<int, List<Vector2D>>();
-            lastUpdates = new Dictionary<int, long>();
-
-        }
-
-        public void touchDown(object sender, TouchEventArgs tea)
-        {
-            int id = nextFreeID;
-            nextFreeID++;
-
-            idTranslations.Add(tea.TrackID, id);
-            positions.Add(id, new List<Vector2D>());
-            positions[id].Add(tea.RelativePosition);
-            lastUpdates.Add(id, timer.ElapsedMilliseconds);
-            lastUpdated = id;
-            active = true;
-        }
-
-
-        public void touchMove(object sender, TouchEventArgs tea)
-        {
-            int id = idTranslations[tea.TrackID];
-            positions[id].Add(tea.RelativePosition);
-            lastUpdates[id] = timer.ElapsedMilliseconds;
-            lastUpdated = id;
-        }
-
-        public void touchUp(object sender, TouchEventArgs tea)
-        {
-            int id = idTranslations[tea.TrackID];
-            positions[id].Add(tea.RelativePosition);
-            lastUpdates[id] = timer.ElapsedMilliseconds;
-            lastUpdated = id;
-
-            idTranslations.Remove(tea.TrackID);
-        }
-
-        public void updateImage()
-        {
-            //remove old positions
-            long currentTime = timer.ElapsedMilliseconds;
-
-            List<int> ids = new List<int>(lastUpdates.Keys);
-            for (int i = ids.Count - 1; i >= 0; i--) {
-                int id = ids[i];
-                if (currentTime - lastUpdates[id] > Parameters.TouchEventVisualizerFadeOutTime) {
-                    positions.Remove(id);
-                    lastUpdates.Remove(id);
-                    if (id == lastUpdated)
-                        active = false;
-                }
-            }
-
-            OutputImage = new OutputImage(width, height);
-
-            //border
-            OutputImage.drawRectangle(0, 0, width - 1, height - 1, Parameters.TouchEventVisualizerGridColor);
-
-            //draw grid
-            int numRows = Parameters.PalmGridNumRows;
-            int numColumns = Parameters.PalmGridNumColumns;
-            int widthPerColumn = width / numColumns;
-            int heightPerRow = height / numRows;
-
-            int activeRow = -1;
-            int activeCol = -1;
-            if (active && numRows*numColumns > 1) {
-                Vector2D position = positions[lastUpdated][positions[lastUpdated].Count-1];
-                activeRow = (int)Math.Floor(position.Y * Parameters.PalmGridNumRows);
-                activeCol = (int)Math.Floor(position.X * Parameters.PalmGridNumColumns);
-            }
-
-
-            for (int i = 0; i <= numColumns; i++)
-            {
-                OutputImage.drawLineSegment(new LineSegment2D(new Vector2D(i * widthPerColumn, 0), new Vector2D(i * widthPerColumn, height - 1)), Parameters.TouchEventVisualizerGridColor);
-            }
-
-            for (int i = 0; i <= numRows; i++)
-            {
-                OutputImage.drawLineSegment(new LineSegment2D(new Vector2D(0, i * heightPerRow), new Vector2D(width - 1, i * heightPerRow)), Parameters.TouchEventVisualizerGridColor);
-            }
-                        
-            for (int row = 0; row < numRows; row++) {
-                for (int col = 0; col < numColumns; col++) {
-                    if(row == activeRow && col == activeCol) 
-                        OutputImage.fillRectangle(col*widthPerColumn, row*heightPerRow, widthPerColumn, heightPerRow, Parameters.TouchEventVisualizerActiveBlockColor);
-                    
-                    int x = (int)((col+0.5f)*widthPerColumn)-5;
-                    int y = (int)((row+0.5f)*heightPerRow)+5;
-                    OutputImage.drawText(x,y,(1+row*numColumns+col).ToString(),Parameters.TouchEventVisualizerTextColor);
-                }
-            }
-
-            foreach (int id in positions.Keys)
-                drawTouchGesture(positions[id], 1 - ((currentTime - lastUpdates[id]) / (float)Parameters.TouchEventVisualizerFadeOutTime));
-        }
-
-        public void drawTouchGesture(List<Vector2D> positions, float opacity)
-        {
-            Vector2D maxPixel = new Vector2D(width - 1, height - 1);
-            int numPositions = positions.Count;
-            Color lineColor = Parameters.TouchEventVisualizerLineColor;
-            Color pointColor = Parameters.TouchEventVisualizerPointColor;
-            Color lineColorFaded = Color.FromArgb((int)(opacity * lineColor.R), (int)(opacity * lineColor.G), (int)(opacity * lineColor.B));
-            Color pointColorFaded = Color.FromArgb((int)(opacity * pointColor.R), (int)(opacity * pointColor.G), (int)(opacity * pointColor.B));
-            for (int i = 1; i < numPositions; i++)
-            {
-                OutputImage.drawLineSegment(new LineSegment2D(positions[i - 1].scale(maxPixel), positions[i].scale(maxPixel)), lineColorFaded);
-            }
-            Vector2D lastPos = positions[numPositions - 1].scale(maxPixel);
-            OutputImage.fillCircle(lastPos.IntX, lastPos.IntY, 3, pointColorFaded);
-        }
-    }
-}

+ 4 - 4
bbiwarg/Images/ConfidenceImage.cs

@@ -4,20 +4,20 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using bbiwarg.Images;
-using bbiwarg.Graphics;
+using bbiwarg.Output;
 using Emgu.CV;
 using Emgu.CV.Structure;
 
 namespace bbiwarg.Images
 {
-    class ConfidenceImage
+    public class ConfidenceImage
     {
         public Image<Gray, Int16> Image { get; private set; }
         public Image<Gray, byte> Mask { get; private set; }
 
-        public ConfidenceImage(Image<Gray, Int16> image)
+        public ConfidenceImage(IntPtr rawConfidenceData, int width, int height)
         {
-            Image = image;
+            Image = new Image<Gray, Int16>(width, height, width * 2, rawConfidenceData);
 
             Mask = (Image.ThresholdBinary(new Gray(Parameters.ConfidenceImageMinThreshold), new Gray(1))).Convert<Gray, byte>();
         }

+ 15 - 8
bbiwarg/Images/DepthImage.cs

@@ -7,31 +7,38 @@ using System.Threading.Tasks;
 using System.Runtime.InteropServices;
 using Emgu.CV;
 using Emgu.CV.Structure;
-using bbiwarg.Graphics;
+using bbiwarg.Output;
 using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.HandRecognition;
 using bbiwarg.Utility;
 
 namespace bbiwarg.Images
 {
-    class DepthImage
+    public class DepthImage
     {
         public Image<Gray, byte> Image { get; private set; }
         public Image<Gray, byte> BackgroundMask { get; private set; }
         public Int16 MinDepth { get; private set; }
         public Int16 MaxDepth { get; private set; }
 
-        public DepthImage(Image<Gray, Int16> image)
+        public DepthImage(IntPtr rawDepthData, int width, int height, ConfidenceImage confidenceImage)
         {
-            image = image.SmoothMedian(Parameters.DepthImageMedianSize);
+            Image<Gray, Int16> rawDepthImage = new Image<Gray, Int16>(width, height, width * 2, rawDepthData);
+
+            // filter with confidenceImage mask
+            rawDepthImage = rawDepthImage.Or((1 - confidenceImage.Mask).Convert<Gray, Int16>().Mul(Int16.MaxValue));
+
+            // smooth with median filter
+            rawDepthImage = rawDepthImage.SmoothMedian(Parameters.DepthImageMedianSize);
             
-            //threshold min&maxDepth
-            MinDepth = findMinDepth(image);
+            // threshold min&maxDepth
+            MinDepth = findMinDepth(rawDepthImage);
             MaxDepth = (Int16)(MinDepth + Parameters.DepthImageDepthRange);
 
-            //smooth+threshold (dst = (src > (MaxDepth - MinDepth)) ? MaxDepth - MinDepth : src)
-            Image = (image - MinDepth).ThresholdTrunc(new Gray(MaxDepth - MinDepth)).Convert<Gray, byte>();
+            // threshold (dst = (src > (MaxDepth - MinDepth)) ? MaxDepth - MinDepth : src)
+            Image = (rawDepthImage - MinDepth).ThresholdTrunc(new Gray(MaxDepth - MinDepth)).Convert<Gray, byte>();
             
+            // smooth with median filter
             Image = Image.SmoothMedian(Parameters.DepthImageMedianSize);
         }
 

+ 5 - 13
bbiwarg/Images/EdgeImage.cs

@@ -1,20 +1,12 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using bbiwarg.Utility;
 using Emgu.CV;
 using Emgu.CV.Structure;
-using bbiwarg.Recognition.FingerRecognition;
-
-using System.Diagnostics;
-using bbiwarg.Utility;
-using bbiwarg.Graphics;
+using System;
+using System.Drawing;
 
 namespace bbiwarg.Images
 {
-    class EdgeImage
+    public class EdgeImage
     {
         public Image<Gray, Byte> Image { get; private set; }
         public Image<Gray, byte> RoughImage { get; private set; }
@@ -100,4 +92,4 @@ namespace bbiwarg.Images
             return new EdgeImage(Image.Copy(), RoughImage.Copy());
         }
     }
-}
+}

+ 41 - 0
bbiwarg/Input/InputHandling/FrameData.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using bbiwarg.Images;
+using bbiwarg.Recognition.FingerRecognition;
+using bbiwarg.Recognition.HandRecognition;
+using bbiwarg.Recognition.PalmRecognition;
+using bbiwarg.Recognition.TouchRecognition;
+
+namespace bbiwarg.Input.InputHandling
+{
+    public class FrameData
+    {
+        public int FrameID { get; set; }
+
+        // images
+        public DepthImage DepthImage { get; set; }
+        public EdgeImage EdgeImage { get; set; }
+        public ConfidenceImage ConfidenceImage { get; set; }
+
+        // fingers
+        public List<Finger> DetectedFingers { get; set; }
+        public List<Finger> TrackedFingers { get; set; }
+
+        // hands
+        public List<Hand> DetectedHands { get; set; }
+        public List<Hand> TrackedHands { get; set; }
+
+        // palms
+        public List<Palm> DetectedPalms { get; set; }
+        public List<Palm> TrackedPalms { get; set; }
+
+        // touch
+        public List<Touch> DetectedTouches { get; set; }
+        public List<Touch> TrackedTouches { get; set; }
+        public List<TouchEventArgs> TouchEvents { get; set; }
+
+    }
+}

+ 132 - 0
bbiwarg/Input/InputHandling/InputHandler.cs

@@ -0,0 +1,132 @@
+using bbiwarg.Images;
+using bbiwarg.Input.InputProviding;
+using bbiwarg.Recognition.FingerRecognition;
+using bbiwarg.Recognition.HandRecognition;
+using bbiwarg.Recognition.PalmRecognition;
+using bbiwarg.Recognition.TouchRecognition;
+using bbiwarg.Utility;
+using System;
+
+namespace bbiwarg.Input.InputHandling
+{
+    public delegate void NewProcessedFrameEventHandler(InputHandler sender, EventArgs e);
+
+    public class InputHandler
+    {
+        private FingerDetector fingerDetector;
+        private HandDetector handDetector;
+        private PalmDetector palmDetector;
+        private TouchDetector touchDetector;
+
+        private FingerTracker fingerTracker;
+        private HandTracker handTracker;
+        private PalmTracker palmTracker;
+        private TouchTracker touchTracker;
+
+        public FrameData FrameData { get; private set; }
+
+        public event NewProcessedFrameEventHandler NewProcessedFrameEvent;
+
+        public InputHandler()
+        {
+            initialize();
+        }
+
+        private void initialize()
+        {
+            fingerDetector = new FingerDetector();
+            handDetector = new HandDetector();
+            palmDetector = new PalmDetector();
+            touchDetector = new TouchDetector();
+
+            fingerTracker = new FingerTracker();
+            handTracker = new HandTracker();
+            palmTracker = new PalmTracker();
+            touchTracker = new TouchTracker();
+        }
+
+        public void reset()
+        {
+            touchTracker.reset();
+            handTracker.reset();
+            palmTracker.reset();
+            fingerTracker.reset();
+        }
+
+        public void handleNewFrame(object sender, NewFrameEventArgs e)
+        {
+            Timer.start("InputHandler.handleNewFrame");
+
+            FrameData frameData = new FrameData();
+
+            frameData.FrameID = e.FrameID;
+
+            // confidence image
+            Timer.start("InputHandler.handleNewFrame::createConfidenceImage");
+            frameData.ConfidenceImage = new ConfidenceImage(e.RawConfidenceData, e.Width, e.Height);
+            Timer.stop("InputHandler.handleNewFrame::createConfidenceImage");
+
+            // depth image
+            Timer.start("InputHandler.handleNewFrame::createDepthImage");
+            frameData.DepthImage = new DepthImage(e.RawDepthData, e.Width, e.Height, frameData.ConfidenceImage);
+            Timer.stop("InputHandler.handleNewFrame::createDepthImage");
+
+            // edge image
+            Timer.start("InputHandler.handleNewFrame::createEdgeImage");
+            frameData.EdgeImage = new EdgeImage(frameData.DepthImage);
+            Timer.stop("InputHandler.handleNewFrame::createEdgeImage");
+
+            // detect fingers
+            Timer.start("InputHandler.handleNewFrame::detectFingers");
+            fingerDetector.detectFingers(frameData);
+            Timer.stop("InputHandler.handleNewFrame::detectFingers");
+
+            // track fingers
+            Timer.start("InputHandler.handleNewFrame::trackFingers");
+            fingerTracker.trackFingers(frameData);
+            Timer.stop("InputHandler.handleNewFrame::trackFingers");
+
+            // detect hands
+            Timer.start("InputHandler.handleNewFrame::detectHands");
+            handDetector.detectHands(frameData);
+            Timer.stop("InputHandler.handleNewFrame::detectHands");
+
+            // track hands
+            Timer.start("InputHandler.handleNewFrame::trackHands");
+            handTracker.trackHands(frameData);
+            Timer.stop("InputHandler.handleNewFrame::trackHands");
+
+            // detect palms
+            Timer.start("InputHandler.handleNewFrame::detectPalms");
+            palmDetector.detectPalms(frameData);
+            Timer.stop("InputHandler.handleNewFrame::detectPalms");
+
+            // track palms
+            Timer.start("InputHandler.handleNewFrame::trackPalms");
+            palmTracker.trackPalms(frameData);
+            Timer.stop("InputHandler.handleNewFrame::trackPalms");
+
+            // detect touches
+            Timer.start("InputHandler.handleNewFrame::detectTouches");
+            touchDetector.detectTouches(frameData);
+            Timer.stop("InputHandler.handleNewFrame::detectTouches");
+
+            //track touches
+            Timer.start("InputHandler.handleNewFrame::trackTouches");
+            touchTracker.trackTouches(frameData);
+            Timer.stop("InputHandler.handleNewFrame::trackTouches");
+
+
+            Timer.start("InputHandler.handleNewFrame::exportResults");
+            FrameData = frameData;
+            if (NewProcessedFrameEvent != null)
+                NewProcessedFrameEvent(this, new EventArgs());
+            Timer.stop("InputHandler.handleNewFrame::exportResults");
+
+
+            Timer.stop("InputHandler.handleNewFrame");
+
+            Timer.outputAll();
+        }
+    }
+}

+ 126 - 0
bbiwarg/Input/InputProviding/InputProvider.cs

@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Diagnostics;
+using Iisu;
+
+namespace bbiwarg.Input.InputProviding
+{
+    public delegate void DeviceStartedEventHandler(object sender, EventArgs e);
+    public delegate void NewFrameEventHandler(object sender, NewFrameEventArgs e);
+
+    public class NewFrameEventArgs : EventArgs
+    {
+        public int FrameID { get; private set; }
+        public int Width { get; private set; }
+        public int Height { get; private set; }
+        public IntPtr RawDepthData { get; private set; }
+        public IntPtr RawConfidenceData { get; private set; }
+
+        public NewFrameEventArgs(int frameID, int width, int height, IntPtr rawDepthData, IntPtr rawConfidenceData)
+        {
+            FrameID = frameID;
+            Width = width;
+            Height = height;
+            RawDepthData = rawDepthData;
+            RawConfidenceData = rawConfidenceData;
+        }
+    }
+
+    class InputProvider
+    {
+        protected IHandle handle;
+        protected IDevice device;
+
+        protected IParameterHandle<float> frameRate;
+        protected IParameterHandle<int> imageWidth;
+        protected IParameterHandle<int> imageHeight;
+        protected IDataHandle<Iisu.Data.IImageData> depthImage;
+        protected IDataHandle<Iisu.Data.IImageData> confidenceImage;
+
+        protected int lastFrameID;
+
+        public bool IsActive { get; private set; }
+        public virtual int CurrentFrameID { get { return device.FrameId; } }
+
+        public event DeviceStartedEventHandler DeviceStartedEvent;
+        public event NewFrameEventHandler NewFrameEvent;
+
+        public InputProvider()
+        {
+            IsActive = false;
+            lastFrameID = -1;
+        }
+
+        public void start()
+        {
+            createDevice();
+            registerHandles();
+
+            device.Start();
+            IsActive = true;
+
+            if (DeviceStartedEvent != null)
+                DeviceStartedEvent(this, new EventArgs());
+
+            run();
+        }
+
+        public void stop()
+        {
+            IsActive = false;
+            device.Stop(true);
+        }
+
+        protected void createDevice()
+        {
+            handle = Iisu.Iisu.Context.CreateHandle();
+            IDeviceConfiguration conf = createDeviceConfiguration();
+            device = handle.InitializeDevice(conf);
+        }
+
+        protected virtual IDeviceConfiguration createDeviceConfiguration()
+        {
+            IDeviceConfiguration conf =  handle.CreateDeviceConfiguration();
+            conf.IsAsynchronous = false;
+            return conf;
+        }
+
+        protected virtual void registerHandles()
+        {
+            imageWidth = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Width");
+            imageHeight = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Height");
+            frameRate = device.RegisterParameterHandle<float>("SOURCE.FrameRate");
+            Parameters.setImageParameters(imageWidth.Value, imageHeight.Value);
+
+            depthImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.DEPTH.Image");
+            confidenceImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.CONFIDENCE.Image");
+        }
+
+        protected virtual void run()
+        {
+            while (IsActive)
+                nextFrame();
+        }
+
+        protected void nextFrame()
+        {
+            device.UpdateFrame(true);
+            provideNewFrame();
+            device.ReleaseFrame();
+        }
+
+        protected void provideNewFrame()
+        {
+            if (CurrentFrameID != lastFrameID)
+            {
+                if (NewFrameEvent != null)
+                    NewFrameEvent(this, new NewFrameEventArgs(CurrentFrameID, imageWidth.Value, imageHeight.Value, depthImage.Value.Raw, confidenceImage.Value.Raw));
+
+                lastFrameID = CurrentFrameID;
+            }
+        }
+    }
+}

+ 19 - 25
bbiwarg/InputProviders/VideoInputProvider.cs → bbiwarg/Input/InputProviding/VideoInputProvider.cs

@@ -2,17 +2,18 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
-using System.Threading.Tasks;
+using System.Threading;
 using Iisu;
 using bbiwarg.Utility;
 
-namespace bbiwarg.InputProviders
+namespace bbiwarg.Input.InputProviding
 {
     class VideoInputProvider : InputProvider
     {
+
         public override int CurrentFrameID { get { return currentMovieFrame.Value; } }
         public String MoviePath { get; private set; }
-        public bool IsPaused { get { return (playStep.Value == 0); } }
+        public bool IsPaused { get; private set; }
 
         private IParameterHandle<int> currentMovieFrame;
         private IParameterHandle<int> frameCount;
@@ -42,40 +43,33 @@ namespace bbiwarg.InputProviders
 
         public void pause()
         {
-            playStep.Value = 0;
-            Logger.log("Video pause", LogSubject.VideoControls);
+            IsPaused = true;
         }
 
         public void play()
         {
-            playStep.Value = 1;
-            Logger.log("Video play", LogSubject.VideoControls);
+            IsPaused = false;
         }
 
-        public void nextFrame()
+        public void goToNextFrame()
         {
-            playStep.Value = 1;
-            int nextFrame = Math.Min((currentMovieFrame.Value + 1), frameCount.Value - 1);
-            while (currentMovieFrame.Value != nextFrame)
-            {
-                device.UpdateFrame(true);
-                device.ReleaseFrame();
-            }
-            playStep.Value = 0;
-            Logger.log("Video nextFrame", LogSubject.VideoControls);
+            nextFrame();
         }
 
-        public void previousFrame()
+        public void goToPreviousFrame()
         {
             playStep.Value = -1;
-            int previousFrame = Math.Max((currentMovieFrame.Value - 1), 0);
-            while (currentMovieFrame.Value != previousFrame)
-            {
-                device.UpdateFrame(true);
-                device.ReleaseFrame();
+            nextFrame();
+            playStep.Value = 1;
+        }
+
+        protected override void run() {
+            while (IsActive) {
+                if (!IsPaused)
+                    nextFrame();
+                else
+                    Thread.Sleep(30);
             }
-            playStep.Value = 0;
-            Logger.log("Video previousFrame", LogSubject.VideoControls);
         }
     }
 }

+ 0 - 299
bbiwarg/InputHandler.cs

@@ -1,299 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.InputProviders;
-using bbiwarg.Images;
-using bbiwarg.Recognition.FingerRecognition;
-using bbiwarg.Recognition.HandRecognition;
-using bbiwarg.Recognition.PalmRecognition;
-using bbiwarg.Recognition.TouchRecognition;
-using bbiwarg.Recognition.Tracking;
-using bbiwarg.Server;
-using bbiwarg.Graphics;
-using bbiwarg.Utility;
-using Emgu.CV;
-using Emgu.CV.Structure;
-
-namespace bbiwarg
-{
-    class InputHandler
-    {
-        private InputProvider inputProvider;
-        private InputFrame currentInputFrame;
-
-        private DepthImage depthImage;
-        private EdgeImage edgeImage;
-        private ConfidenceImage confidenceImage;
-
-        private FingerDetector fingerDetector;
-        private HandDetector handDetector;
-        private PalmDetector palmDetector;
-        private TouchDetector touchDetector;
-
-        private FingerTracker fingerTracker;
-        private HandTracker handTracker;
-        private PalmTracker palmTracker;
-        private TouchTracker touchTracker;
-
-        private TouchEventVisualizer touchEventVisualizer;
-        private TuioCommunicator tuioCommunicator;
-
-        public OutputImage[] OutputImages { get; private set; }
-        public int CurrentFrameID { get; private set; }
-
-        public InputHandler(InputProvider inputProvider)
-        {
-            this.inputProvider = inputProvider;
-            this.CurrentFrameID = inputProvider.CurrentFrameID;
-
-            initializeConsistentObjects();
-        }
-
-        private void initializeConsistentObjects()
-        {
-            fingerTracker = new FingerTracker();
-            handTracker = new HandTracker();
-            palmTracker = new PalmTracker();
-            touchTracker = new TouchTracker();
-
-            touchEventVisualizer = new TouchEventVisualizer(Parameters.ImageWidth, Parameters.ImageHeight);
-            touchTracker.TouchDown += touchEventVisualizer.touchDown;
-            touchTracker.TouchMove += touchEventVisualizer.touchMove;
-            touchTracker.TouchUp += touchEventVisualizer.touchUp;
-
-            if (Parameters.TuioEnabled)
-            {
-                tuioCommunicator = new TuioCommunicator(Parameters.TuioIP.ToString(), Parameters.TuioPort);
-                touchTracker.TouchDown += tuioCommunicator.touchDown;
-                touchTracker.TouchMove += tuioCommunicator.touchMove;
-                touchTracker.TouchUp += tuioCommunicator.touchUp;
-            }
-        }
-
-        public void resetConsistentObjects()
-        {
-            touchTracker.reset();
-            handTracker.reset();
-            palmTracker.reset();
-            fingerTracker.reset();
-
-            touchEventVisualizer.reset();
-
-            if (Parameters.TuioEnabled)
-                tuioCommunicator.reset();
-        }
-
-        public void updateFrame()
-        {
-            Timer.start("updateFrame");
-            beforeUpdateFrame();
-
-            createConfidenceImage();
-            createDepthImage();
-            createEdgeImage();
-
-            detectFingers();
-            trackFingers();
-
-            detectHands();
-            trackHands();
-
-            detectPalm();
-            trackPalm();
-
-            detectTouchEvents();
-            trackTouchEvents();
-
-            afterUpdateFrame();
-            Timer.stop("updateFrame");
-        }
-
-        private void beforeUpdateFrame()
-        {
-            Timer.start("beforeUpdateFrame");
-
-            currentInputFrame = inputProvider.CurrentFrame;
-
-            CurrentFrameID = currentInputFrame.FrameID;
-            Logger.CurrentFrame = CurrentFrameID;
-
-            if (Parameters.TuioEnabled)
-                tuioCommunicator.initFrame();
-
-            Timer.stop("beforeUpdateFrame");
-        }
-
-        private void afterUpdateFrame()
-        {
-            Timer.start("afterUpdateFrame");
-
-            if (Parameters.TuioEnabled)
-                tuioCommunicator.commitFrame();
-
-            createOutputImages();
-
-            Timer.stop("afterUpdateFrame");
-        }
-
-        private void createConfidenceImage()
-        {
-            Timer.start("createCnfdncImg");
-            Image<Gray, Int16> rawConfidenceImage = new Image<Gray, Int16>(Parameters.ImageWidth, Parameters.ImageHeight, Parameters.ImageWidth * 2, currentInputFrame.RawConfidenceData);
-            confidenceImage = new ConfidenceImage(rawConfidenceImage);
-            Timer.stop("createCnfdncImg");
-        }
-
-        private void createDepthImage()
-        {
-            Timer.start("createDepthImage");
-            Image<Gray, Int16> rawDepthImage = new Image<Gray, Int16>(Parameters.ImageWidth, Parameters.ImageHeight, Parameters.ImageWidth * 2, currentInputFrame.RawDepthData);
-            rawDepthImage = rawDepthImage.Or((1 - confidenceImage.Mask).Convert<Gray, Int16>().Mul(Int16.MaxValue));
-            depthImage = new DepthImage(rawDepthImage);
-            Timer.stop("createDepthImage");
-        }
-
-        private void createEdgeImage()
-        {
-            Timer.start("createEdgeImage");
-            edgeImage = new EdgeImage(depthImage);
-            Timer.stop("createEdgeImage");
-        }
-
-        private void detectFingers()
-        {
-            Timer.start("detectFingers");
-            fingerDetector = new FingerDetector(depthImage, edgeImage);
-            Timer.stop("detectFingers");
-        }
-
-        private void trackFingers()
-        {
-            Timer.start("trackFingers");
-            fingerTracker.updateFrame(fingerDetector.Fingers);
-            Timer.stop("trackFingers");
-        }
-
-        private void detectHands()
-        {
-            Timer.start("detectHands");
-            handDetector = new HandDetector(depthImage, fingerTracker.Fingers);
-            Timer.stop("detectHands");
-        }
-
-        private void trackHands()
-        {
-            Timer.start("trackHands\t");
-            handTracker.updateFrame(handDetector.Hands);
-            Timer.stop("trackHands\t");
-        }
-
-        private void detectPalm()
-        {
-            Timer.start("detectPalm\t");
-            palmDetector = new PalmDetector(depthImage, handTracker.Hands);
-            Timer.stop("detectPalm\t");
-        }
-
-        private void trackPalm()
-        {
-            Timer.start("trackPalm\t");
-            palmTracker.updateFrame(palmDetector.Palms);
-            Timer.stop("trackPalm\t");
-        }
-
-        private void detectTouchEvents()
-        {
-            Timer.start("detectTouchEvents");
-            touchDetector = new TouchDetector(depthImage, fingerTracker.Fingers, palmTracker.OptimizedPalms);
-            Timer.stop("detectTouchEvents");
-        }
-
-        private void trackTouchEvents()
-        {
-            Timer.start("trackTouchEvents");
-            touchTracker.updateFrame(touchDetector.TouchEvents);
-            Timer.stop("trackTouchEvents");
-        }
-
-        private void createOutputImages()
-        {
-            Timer.start("createOutputImages");
-            int numImages = Parameters.OutputNumImages;
-            OutputImages = new OutputImage[numImages];
-            for (int i = 0; i < numImages; i++)
-            {
-                OutputImages[i] = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);
-            }
-
-            //image0
-            OutputImages[0].drawImage((depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image, Parameters.DepthImageColor);
-            foreach (Finger f in fingerTracker.Fingers)
-            {
-                Color color = (f.TouchEvent != null) ? Parameters.TouchEventDetectedColor : Parameters.FingerTipColor;
-                OutputImages[0].fillCircle(f.TipPoint.IntX, f.TipPoint.IntY, 5, color);
-            }
-
-            foreach (TrackedFinger tf in fingerTracker.TrackedObjects)
-            {
-                if (tf.CurrentState == TrackingState.Tracked)
-                {
-                    OutputImages[0].fillCircle(tf.TipPointPrediction.IntX, tf.TipPointPrediction.IntY, 3, Parameters.FingerPointsPredictionColor);
-                    OutputImages[0].fillCircle(tf.HandPointPrediction.IntX, tf.HandPointPrediction.IntY, 3, Parameters.FingerPointsPredictionColor);
-                    Vector2D mid = (tf.TipPointPrediction + tf.HandPointPrediction) / 2;
-                    OutputImages[0].drawLineSegment(new Utility.LineSegment2D(mid, mid + Parameters.FingerTrackerNumDirectionsForMeanDirection * tf.MeanDirection), Parameters.FingerMeanDirectionColor);
-                }
-            }
-
-            //image1
-            OutputImages[1].drawImage(edgeImage.Image.ThresholdBinary(new Gray(0), new Gray(255)), Parameters.EdgeImageColor);
-            foreach (Finger f in fingerTracker.Fingers)
-            {
-                for (int i = 0; i < f.SliceTrail.NumSlices; i++)
-                    OutputImages[1].drawLineSegment(f.SliceTrail[i].LineSegment, Parameters.FingerSliceColor);
-                OutputImages[1].drawContour(f.getContour(Parameters.FingerContourMargin), Parameters.FingerContourColor);
-                OutputImages[1].drawLineSegment(f.LineSegment, Parameters.FingerTrackedColor);
-                OutputImages[1].drawText(f.MidPoint.IntX, f.MidPoint.IntY, f.TrackID.ToString(), Parameters.FingerIDColor);
-            }
-
-            //image2
-            foreach (Hand h in handTracker.Hands)
-            {
-                OutputImages[2].drawImage(h.Mask.ThresholdBinary(new Gray(0), new Gray(255)), Parameters.HandColor[h.TrackID % Parameters.HandNumColors]);
-                OutputImages[2].fillCircle(h.Centroid.IntX, h.Centroid.IntY, 5, Parameters.HandCentroidColor);
-                OutputImages[2].drawText(h.Centroid.IntX, h.Centroid.IntY, h.TrackID.ToString(), Parameters.HandIDColor);
-
-                if (h.Palm != null)
-                    OutputImages[2].drawDefect(h.Palm.ThumbDefect, Parameters.HandThumbDefectPointColor, Parameters.HandThumbDefectLineColor);
-            }
-
-            //image3
-            OutputImages[3].drawImage((depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image.Or(255 - handDetector.HandMask.ThresholdBinary(new Gray(0), new Gray(255))), Parameters.DepthImageColor);
-            foreach (TrackedTouchEvent tte in touchTracker.TrackedObjects)
-            {
-                Vector2D position = tte.AbsolutePositionPrediction;
-                OutputImages[3].fillCircle(position.IntX, position.IntY, 5, Parameters.TouchEventTrackedColor);
-            }
-            foreach (Palm p in palmTracker.OptimizedPalms)
-            {
-                OutputImages[3].drawQuadrangleGrid(p.Quad, Parameters.PalmQuadColor, Parameters.PalmGridColor, Parameters.PalmGridNumRows, Parameters.PalmGridNumColumns);
-            }
-
-            //image4
-            touchEventVisualizer.updateImage();
-            OutputImages[4] = touchEventVisualizer.OutputImage;
-
-
-            //borders
-            for (int i = 0; i < numImages; i++)
-            {
-                OutputImages[i].drawRectangle(0, 0, Parameters.ImageWidth - 1, Parameters.ImageHeight - 1, Parameters.OutputImageBorderColor);
-            }
-
-            Timer.stop("createOutputImages");
-        }
-
-    }
-}

+ 0 - 26
bbiwarg/InputProviders/InputFrame.cs

@@ -1,26 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bbiwarg.InputProviders
-{
-    class InputFrame
-    {
-        public int FrameID { get; private set; }
-        public int Width { get; private set; }
-        public int Height { get; private set; }
-        public IntPtr RawDepthData { get; private set; }
-        public IntPtr RawConfidenceData { get; private set; }
-
-        public InputFrame(int frameID, int width, int height, IntPtr rawDepthData, IntPtr rawConfidenceData)
-        {
-            FrameID = frameID;
-            Width = width;
-            Height = height;
-            RawDepthData = rawDepthData;
-            RawConfidenceData = rawConfidenceData;
-        }
-    }
-}

+ 0 - 71
bbiwarg/InputProviders/InputProvider.cs

@@ -1,71 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Iisu;
-
-namespace bbiwarg.InputProviders
-{
-    class InputProvider
-    {
-        public int ImageWidth { get; private set; }
-        public int ImageHeight { get; private set; }
-        public virtual int CurrentFrameID { get { return device.FrameId; } }
-        public InputFrame CurrentFrame { get; private set; }
-
-        protected IHandle handle;
-        protected IDevice device;
-
-        protected IDataHandle<Iisu.Data.IImageData> depthImage;
-        protected IDataHandle<Iisu.Data.IImageData> confidenceImage;
-
-
-        public void start()
-        {
-            createDevice();
-            registerHandles();
-
-            device.Start();
-        }
-
-        public void stop()
-        {
-            device.Stop(true);
-        }
-
-        protected void createDevice()
-        {
-            handle = Iisu.Iisu.Context.CreateHandle();
-            IDeviceConfiguration conf = createDeviceConfiguration();
-            device = handle.InitializeDevice(conf);
-        }
-
-        protected virtual IDeviceConfiguration createDeviceConfiguration()
-        {
-            return handle.CreateDeviceConfiguration();
-        }
-
-        protected virtual void registerHandles()
-        {
-            ImageWidth = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Width").Value;
-            ImageHeight = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Height").Value;
-
-            depthImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.DEPTH.Image");
-            confidenceImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.CONFIDENCE.Image");
-            device.EventManager.RegisterEventListener("DEVICE.DataFrame", new onNewFrameDelegate(onNewFrame));
-        }
-
-        private delegate void onNewFrameDelegate(String name, uint frameID);
-
-        private void onNewFrame(String name, uint frameID)
-        {
-            device.UpdateFrame(false);
-            IntPtr rawDepthData = depthImage.Value.Raw;
-            IntPtr rawConfidenceData = confidenceImage.Value.Raw;
-            device.ReleaseFrame();
-
-            CurrentFrame = new InputFrame(CurrentFrameID, ImageWidth, ImageHeight, rawDepthData, rawConfidenceData);
-        }
-    }
-}

+ 0 - 75
bbiwarg/MainBBWIWARG.cs

@@ -1,75 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Net;
-using bbiwarg.Graphics;
-using bbiwarg.InputProviders;
-using bbiwarg.Server;
-
-namespace bbiwarg
-{
-    class MainBBIWARG
-    {
-        static void Main(string[] args)
-        {
-            Console.SetWindowSize(Parameters.ConsoleWidth, Parameters.ConsoleHeight);
-            if (args.Length > 0)
-            {
-                handleArgs(args);     
-            }
-
-            InputProvider inputProvider;
-            if (Parameters.InputSource == InputType.Movie)
-                inputProvider = new VideoInputProvider(Parameters.InputMoviePath);
-            else
-                inputProvider = new InputProvider();
-
-            inputProvider.start();
-
-            InputHandler inputHandler = new InputHandler(inputProvider);
-
-            OutputWindow outputWindow = new OutputWindow(inputProvider, inputHandler);
-            outputWindow.Run(Parameters.OutputUpdateRate, Parameters.OutputRenderRate);
-
-            inputProvider.stop();
-        }
-
-        private static void handleArgs(String[] args)
-        {
-            String ipString = null;
-            String portString = null;
-            if (args.Length == 2)
-            {
-                ipString = args[0];
-                portString = args[1];
-            }
-            else if (args.Length == 1)
-            {
-                String[] parts = args[0].Split(':');
-                ipString = parts[0];
-                if(parts.Length == 2)
-                    portString = parts[1];
-            }
-
-            while (!TuioCommunicator.tryParseIPAddress(ipString, out Parameters.TuioIP))
-            {
-                Console.WriteLine("Please insert the TUIO-Client's IP (Default is 127.0.0.1):");
-                ipString = Console.ReadLine();
-            }
-            Console.WriteLine("TUIO-IP is set to:" + Parameters.TuioIP.ToString());
-
-            while (!TuioCommunicator.tryParsePort(portString, out Parameters.TuioPort))
-            {
-                Console.WriteLine("Please insert the TUIO-Client's Port (Default is 3333):");
-                portString = Console.ReadLine();
-            }
-            Console.WriteLine("TUIO-PORT is set to:" + Parameters.TuioPort);
-
-            Parameters.TuioEnabled = true;
-        }
-    }
-}

+ 159 - 0
bbiwarg/Output/DebugOutput/DebugImages.cs

@@ -0,0 +1,159 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Drawing;
+using System.Text;
+using System.Threading.Tasks;
+using bbiwarg.Input.InputHandling;
+using bbiwarg.Recognition.FingerRecognition;
+using bbiwarg.Recognition.HandRecognition;
+using bbiwarg.Recognition.PalmRecognition;
+using bbiwarg.Recognition.TouchRecognition;
+using Emgu.CV.Structure;
+using Emgu.CV;
+
+namespace bbiwarg.Output.DebugOutput
+{
+    class DebugImages
+    {
+        private TouchEventVisualizer touchEventVisualizer;
+
+        public List<OutputImage> Images { get; private set; }
+
+        public DebugImages(TouchEventVisualizer touchEventVisualizer)
+        {
+            Images = new List<OutputImage>();
+            this.touchEventVisualizer = touchEventVisualizer;
+        }
+
+        public void updateImages(FrameData frameData)
+        {
+            Images.Clear();
+
+            Images.Add(getDepthImage(frameData));
+            Images.Add(getFingerImage(frameData));
+            Images.Add(getHandImage(frameData));
+            Images.Add(getPalmImage(frameData));
+            Images.Add(touchEventVisualizer.getOutputImage());
+        }
+
+        private OutputImage getDepthImage(FrameData frameData)
+        {
+            OutputImage depthImage = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);
+
+            // background (depth image)
+            depthImage.drawImage((frameData.DepthImage.MaxDepth - frameData.DepthImage.MinDepth) - frameData.DepthImage.Image, Parameters.DepthImageColor);
+
+            // finger tips
+            foreach (Finger f in frameData.TrackedFingers)
+            {
+                Color tipColor = (f.Touch != null) ? Parameters.TouchEventDetectedColor : Parameters.FingerTipColor;
+                Color handColor = Parameters.FingerHandColor;
+                depthImage.fillCircle(f.TipPoint.IntX, f.TipPoint.IntY, 5, tipColor);
+                depthImage.fillCircle(f.HandPoint.IntX, f.HandPoint.IntY, 5, handColor);
+            }
+
+            // border
+            depthImage.drawBorder(Parameters.OutputImageBorderColor);
+
+            return depthImage;
+        }
+
+        private OutputImage getFingerImage(FrameData frameData)
+        {
+            OutputImage fingerImage = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);
+
+            // background (edge image)
+            fingerImage.drawImage(frameData.EdgeImage.Image.ThresholdBinary(new Gray(0), new Gray(255)), Parameters.EdgeImageColor);
+
+            // draw fingers
+            foreach (Finger f in frameData.TrackedFingers)
+            {
+                foreach (FingerSlice slice in f.SliceTrail.Slices)
+                    fingerImage.drawLineSegment(slice.LineSegment, Parameters.FingerSliceColor);
+                fingerImage.drawContour(f.getContour(Parameters.FingerContourMargin), Parameters.FingerContourColor);
+                fingerImage.drawLineSegment(f.LineSegment, Parameters.FingerTrackedColor);
+                fingerImage.drawText(f.MidPoint.IntX, f.MidPoint.IntY, f.TrackID.ToString(), Parameters.FingerIDColor);
+            }
+
+            //border
+            fingerImage.drawBorder(Parameters.OutputImageBorderColor);
+
+            return fingerImage;
+        }
+
+        private OutputImage getHandImage(FrameData frameData)
+        {
+            OutputImage handImage = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);
+
+            foreach (Hand h in frameData.TrackedHands)
+            {
+
+                handImage.drawImage(h.Mask.ThresholdBinary(new Gray(0), new Gray(255)), Parameters.HandColors[h.TrackID % Parameters.HandNumColors]);
+                handImage.fillCircle(h.Centroid.IntX, h.Centroid.IntY, 5, Parameters.HandCentroidColor);
+                handImage.drawText(h.Centroid.IntX, h.Centroid.IntY, h.TrackID.ToString(), Parameters.HandIDColor);
+
+                if (h.Palm != null)
+                    handImage.drawDefect(h.Palm.ThumbDefect, Parameters.HandThumbDefectPointColor, Parameters.HandThumbDefectLineColor);
+            }
+
+            // border
+            handImage.drawBorder(Parameters.OutputImageBorderColor);
+
+            return handImage;
+        }
+
+        private OutputImage getPalmImage(FrameData frameData)
+        {
+            OutputImage palmImage = new OutputImage(Parameters.ImageWidth, Parameters.ImageHeight);
+
+            // handMask
+            Image<Gray, byte> handMask = new Image<Gray, byte>(Parameters.ImageWidth, Parameters.ImageHeight);
+            foreach (Hand h in frameData.TrackedHands)
+                handMask = handMask.Or(h.Mask);
+
+            // background
+            palmImage.drawImage((frameData.DepthImage.MaxDepth - frameData.DepthImage.MinDepth) - frameData.DepthImage.Image.Or(255 - handMask.ThresholdBinary(new Gray(0), new Gray(255))), Parameters.DepthImageColor);
+            foreach (Touch t in frameData.TrackedTouches)
+                palmImage.fillCircle(t.AbsolutePosition.IntX, t.AbsolutePosition.IntY, 5, Parameters.TouchEventTrackedColor);
+
+            foreach (Palm p in frameData.TrackedPalms)
+                palmImage.drawQuadrangleGrid(p.Quad, Parameters.PalmQuadColor, Parameters.PalmGridColor, Parameters.PalmGridNumRows, Parameters.PalmGridNumColumns);
+            
+            // border
+            palmImage.drawBorder(Parameters.OutputImageBorderColor);
+
+            return palmImage;
+        }
+    }
+}
+
+/*
+            
+//image3
+OutputImages[3].drawImage((depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image.Or(255 - handDetector.HandMask.ThresholdBinary(new Gray(0), new Gray(255))), Parameters.DepthImageColor);
+foreach (TrackedTouch tte in touchTracker.TrackedObjects)
+{
+    Vector2D position = tte.AbsolutePositionPrediction;
+    OutputImages[3].fillCircle(position.IntX, position.IntY, 5, Parameters.TouchEventTrackedColor);
+}
+foreach (Palm p in palmTracker.OptimizedPalms)
+{
+    OutputImages[3].drawQuadrangleGrid(p.Quad, Parameters.PalmQuadColor, Parameters.PalmGridColor, Parameters.PalmGridNumRows, Parameters.PalmGridNumColumns);
+}
+
+//image4
+touchEventVisualizer.updateImage();
+OutputImages[4] = touchEventVisualizer.OutputImage;
+
+//borders
+for (int i = 0; i < numImages; i++)
+{
+    OutputImages[i].drawRectangle(0, 0, Parameters.ImageWidth - 1, Parameters.ImageHeight - 1, Parameters.OutputImageBorderColor);
+}
+
+}
+
+}
+}
+*/

+ 67 - 44
bbiwarg/Graphics/OutputWindow.cs → bbiwarg/Output/DebugOutput/DebugWindow.cs

@@ -7,17 +7,20 @@ using System.Threading.Tasks;
 using OpenTK;
 using OpenTK.Input;
 using OpenTK.Graphics.OpenGL;
-using bbiwarg.InputProviders;
+using OpenTK.Graphics;
+using bbiwarg.Input.InputHandling;
+using bbiwarg.Input.InputProviding;
 using bbiwarg.Utility;
 
-namespace bbiwarg.Graphics
+namespace bbiwarg.Output.DebugOutput
 {
-    public enum PalmGridControlFocus {
+    public enum PalmGridControlFocus
+    {
         Rows,
         Columns
     }
 
-    class OutputWindow : GameWindow
+    class DebugWindow : GameWindow
     {
         private InputHandler inputHandler;
         private InputProvider inputProvider;
@@ -25,18 +28,25 @@ namespace bbiwarg.Graphics
 
         private uint textureID;
 
-        public OutputWindow(InputProvider inputProvider, InputHandler inputHandler)
-            : base((int)(Parameters.OutputScaleFactor * Math.Max(1, Math.Min(Parameters.OutputNumImagesPerRow, Parameters.OutputNumImages)) * Parameters.ImageWidth),
-                   (int)(Parameters.OutputScaleFactor * (1 + (Parameters.OutputNumImages - 1) / Parameters.OutputNumImagesPerRow) * Parameters.ImageHeight))
+        private int currentFrameID;
+        private DebugImages debugImages;
+
+        public DebugWindow(InputProvider inputProvider, InputHandler inputHandler)
+            : base((int)(Parameters.DebugOutputScaleFactor * Math.Max(1, Math.Min(Parameters.DebugOutputNumImagesPerRow, Parameters.DebugOutputNumImages)) * Parameters.ImageWidth),
+                   (int)(Parameters.DebugOutputScaleFactor * (1 + (Parameters.DebugOutputNumImages - 1) / Parameters.DebugOutputNumImagesPerRow) * Parameters.ImageHeight))
         {
             this.inputProvider = inputProvider;
             this.inputHandler = inputHandler;
+
+            TouchEventVisualizer touchEventVisualizer = new TouchEventVisualizer();
+            inputHandler.NewProcessedFrameEvent += touchEventVisualizer.handleNewFrameData;
+            debugImages = new DebugImages(touchEventVisualizer);
         }
 
         protected override void OnLoad(EventArgs e)
         {
             base.OnLoad(e);
-            Title = Parameters.OutputTitle;
+            Title = Parameters.DebugOutputTitle;
             GL.ClearColor(Color.Black);
 
             // transparency
@@ -57,7 +67,13 @@ namespace bbiwarg.Graphics
             Keyboard.KeyDown += HandleKeyDownPalmGridControls;
             if (inputProvider is VideoInputProvider)
                 Keyboard.KeyDown += HandleKeyDownVideoControls;
+        }
 
+        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
+        {
+            base.OnClosing(e);
+
+            inputProvider.stop();
         }
 
         protected override void OnResize(EventArgs e)
@@ -67,8 +83,8 @@ namespace bbiwarg.Graphics
             int screenWidth = ClientRectangle.Width;
             int screenHeight = ClientRectangle.Height;
 
-            int numRows = 1 + (Parameters.OutputNumImages - 1) / Parameters.OutputNumImagesPerRow;
-            int numCols = Math.Min(Parameters.OutputNumImages, Parameters.OutputNumImagesPerRow);
+            int numRows = 1 + (Parameters.DebugOutputNumImages - 1) / Parameters.DebugOutputNumImagesPerRow;
+            int numCols = Math.Min(Parameters.DebugOutputNumImages, Parameters.DebugOutputNumImagesPerRow);
             int heightForWidth = (int)((float)screenWidth / ((float)numCols * Parameters.ImageAspectRatio) * (float)numRows);
 
             GL.Viewport(0, (screenHeight - heightForWidth) / 2, screenWidth, heightForWidth);
@@ -81,57 +97,65 @@ namespace bbiwarg.Graphics
 
         protected override void OnUpdateFrame(FrameEventArgs e)
         {
+            Timer.start("DebugWindow.OnUpdateFrame");
             base.OnUpdateFrame(e);
 
-            if (inputHandler.CurrentFrameID - inputProvider.CurrentFrameID > 20)
-                inputHandler.resetConsistentObjects();
+            FrameData frameData = inputHandler.FrameData;
+            if (frameData != null)
+            {
+                lock (frameData)
+                {
+                    if (currentFrameID != frameData.FrameID)
+                    {
+                        currentFrameID = frameData.FrameID;
 
-            if (inputProvider.CurrentFrameID != inputHandler.CurrentFrameID)
-                inputHandler.updateFrame();
+                        Timer.start("DebugWindow.OnUpdateFrame::updateImages");
+                        debugImages.updateImages(frameData);
+                        Timer.stop("DebugWindow.OnUpdateFrame::updateImages");
+                    }
+                }
+            }
+
+            Timer.stop("DebugWindow.OnUpdateFrame");
         }
 
         protected override void OnRenderFrame(FrameEventArgs e)
         {
-            Timer.start("onRenderFrame");
-
+            Timer.start("DebugWindow.OnRenderFrame");
             base.OnRenderFrame(e);
             GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
             Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, -Vector3.UnitZ, Vector3.UnitY);
             GL.MatrixMode(MatrixMode.Modelview);
             GL.LoadMatrix(ref modelview);
-            
-            Title = Parameters.OutputTitle + " (Frame: " + inputProvider.CurrentFrameID + ")";
 
-            Timer.start("buildTextures");
+            Title = Parameters.DebugOutputTitle + " (Frame: " + currentFrameID + ")";
+
             GL.Enable(EnableCap.Texture2D);
 
+            Timer.start("DebugWindow.OnRenderFrame::drawImages");
             int imageIndex = 0;
-            foreach (OutputImage image in inputHandler.OutputImages)
+            foreach (OutputImage image in debugImages.Images)
             {
-                int x = imageIndex % Parameters.OutputNumImagesPerRow;
-                int y = imageIndex / Parameters.OutputNumImagesPerRow;
+                int column = imageIndex % Parameters.DebugOutputNumImagesPerRow;
+                int row = imageIndex / Parameters.DebugOutputNumImagesPerRow;
                 GL.BindTexture(TextureTarget.Texture2D, textureID);
                 GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Parameters.ImageWidth, Parameters.ImageHeight, 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 + x, 0 + y, -1);
-                GL.TexCoord2(1, 0); GL.Vertex3(1 + x, 0 + y, -1);
-                GL.TexCoord2(1, 1); GL.Vertex3(1 + x, 1 + y, -1);
-                GL.TexCoord2(0, 1); GL.Vertex3(0 + x, 1 + y, -1);
+                GL.TexCoord2(0, 0); GL.Vertex3(0 + column, 0 + row, -1);
+                GL.TexCoord2(1, 0); GL.Vertex3(1 + column, 0 + row, -1);
+                GL.TexCoord2(1, 1); GL.Vertex3(1 + column, 1 + row, -1);
+                GL.TexCoord2(0, 1); GL.Vertex3(0 + column, 1 + row, -1);
                 GL.End();
-                ++imageIndex;
+                imageIndex++;
             }
+            Timer.stop("DebugWindow.OnRenderFrame::drawImages");
 
-            Timer.stop("buildTextures");
-
-            Timer.start("swapBuffers");
+            Timer.start("DebugWindow.OnRenderFrame::SwapBuffers");
             SwapBuffers();
-            Timer.stop("swapBuffers");
-
-            Timer.stop("buildTextures");
-            Timer.stop("onRenderFrame");
+            Timer.stop("DebugWindow.OnRenderFrame::SwapBuffers");
 
-            Timer.outputAll();
+            Timer.stop("DebugWindow.OnRenderFrame");
         }
 
         private void HandleKeyDownVideoControls(object sender, KeyboardKeyEventArgs e)
@@ -148,15 +172,13 @@ namespace bbiwarg.Graphics
                 case Key.Right:
                     if (vip.IsPaused)
                     {
-                        vip.nextFrame();
-                        inputHandler.updateFrame();
+                        vip.goToNextFrame();
                     }
                     break;
                 case Key.Left:
                     if (vip.IsPaused)
                     {
-                        vip.previousFrame();
-                        inputHandler.updateFrame();
+                        vip.goToPreviousFrame();
                     }
                     break;
             }
@@ -165,7 +187,8 @@ namespace bbiwarg.Graphics
 
         private void HandleKeyDownPalmGridControls(object sender, KeyboardKeyEventArgs e)
         {
-            switch (e.Key) {
+            switch (e.Key)
+            {
                 case Key.R:
                     palmGridControlFocus = PalmGridControlFocus.Rows;
                     break;
@@ -176,17 +199,17 @@ namespace bbiwarg.Graphics
                 case Key.KeypadPlus:
                 case Key.BracketRight: //fix
                     if (palmGridControlFocus == PalmGridControlFocus.Rows)
-                        Parameters.PalmGridNumRows++;
+                        Parameters.setPalmGridParameters(Parameters.PalmGridNumRows + 1, Parameters.PalmGridNumColumns);
                     else
-                        Parameters.PalmGridNumColumns++;
+                        Parameters.setPalmGridParameters(Parameters.PalmGridNumRows, Parameters.PalmGridNumColumns + 1);
                     break;
                 case Key.Minus:
                 case Key.KeypadMinus:
                 case Key.Slash: //fix
                     if (palmGridControlFocus == PalmGridControlFocus.Rows)
-                        Parameters.PalmGridNumRows = Math.Max(1, Parameters.PalmGridNumRows - 1);
+                        Parameters.setPalmGridParameters(Math.Max(1, Parameters.PalmGridNumRows - 1), Parameters.PalmGridNumColumns);
                     else
-                        Parameters.PalmGridNumColumns = Math.Max(1, Parameters.PalmGridNumColumns-1);
+                        Parameters.setPalmGridParameters(Parameters.PalmGridNumRows, Math.Max(1, Parameters.PalmGridNumColumns - 1));
                     break;
             }
         }

+ 157 - 0
bbiwarg/Output/DebugOutput/TouchEventVisualizer.cs

@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using bbiwarg.Recognition.TouchRecognition;
+using bbiwarg.Utility;
+using bbiwarg.Input.InputHandling;
+
+namespace bbiwarg.Output.DebugOutput
+{
+    class TouchEventVisualizer
+    {
+        private Stopwatch timer;
+
+        private Dictionary<int, List<Vector2D>> activeTouches;
+        private Dictionary<int, List<Vector2D>> oldTouches;
+        private Dictionary<int, long> lastUpdates;
+        private int nextFreeID;
+        private int lastUpdated;
+        private bool active;
+
+        public TouchEventVisualizer()
+        {
+            reset();
+
+        }
+
+        public void reset()
+        {
+            timer = new Stopwatch();
+            timer.Start();
+
+            nextFreeID = 1;
+            lastUpdated = 0;
+            activeTouches = new Dictionary<int,List<Vector2D>>();
+            oldTouches = new Dictionary<int,List<Vector2D>>();
+            lastUpdates = new Dictionary<int,long>();
+
+        }
+
+        public void handleNewFrameData(InputHandler sender, EventArgs e)
+        {
+            FrameData frameData = sender.FrameData;
+            lock (frameData)
+            {
+                foreach (TouchEventArgs te in frameData.TouchEvents)
+                {
+                    switch (te.Type)
+                    {
+                        case TouchEventType.Down:
+                            activeTouches.Add(te.TrackID, new List<Vector2D>());
+                            activeTouches[te.TrackID].Add(te.Touch.RelativePosition);
+                            break;
+                        case TouchEventType.Move:
+                            activeTouches[te.TrackID].Add(te.Touch.RelativePosition);
+                            break;
+                        case TouchEventType.Up:
+                            activeTouches[te.TrackID].Add(te.Touch.RelativePosition);
+
+                            oldTouches.Add(nextFreeID, activeTouches[te.TrackID]);
+                            lastUpdates.Add(nextFreeID, timer.ElapsedMilliseconds);
+
+                            activeTouches.Remove(te.TrackID);
+                            nextFreeID++;
+                            break;
+                    }
+                }
+            }
+
+        }
+        
+        public OutputImage getOutputImage()
+        {
+            long currentTime = timer.ElapsedMilliseconds;
+            removeOldPositions(currentTime - Parameters.TouchEventVisualizerFadeOutTime);
+
+            int width = Parameters.ImageWidth;
+            int height = Parameters.ImageHeight;
+            OutputImage outputImage = new OutputImage(width, height);
+
+            // border
+            outputImage.drawRectangle(0, 0, width - 1, height - 1, Parameters.TouchEventVisualizerGridColor);
+
+            // draw grid
+            int numRows = Parameters.PalmGridNumRows;
+            int numColumns = Parameters.PalmGridNumColumns;
+            int widthPerColumn = width / numColumns;
+            int heightPerRow = height / numRows;
+
+            // find active blocks
+            bool[,] activeBlocks = new bool[numRows, numColumns];
+            if (numRows * numColumns > 1)
+            {
+                foreach (List<Vector2D> positions in activeTouches.Values)
+                {
+                    Vector2D lastPosition = positions.Last();
+                    int activeRow = (int)Math.Floor(lastPosition.Y * Parameters.PalmGridNumRows);
+                    int activeCol = (int)Math.Floor(lastPosition.X * Parameters.PalmGridNumColumns);
+                    activeBlocks[activeRow, activeCol] = true;
+                }
+            }
+
+            // draw blocks
+            for (int row = 0; row < numRows; row++)
+            {
+                for (int col = 0; col < numColumns; col++)
+                {
+                    if (activeBlocks[row, col])
+                        outputImage.fillRectangle(col * widthPerColumn, row * heightPerRow, widthPerColumn, heightPerRow, Parameters.TouchEventVisualizerActiveBlockColor);
+
+                    int x = (int)((col + 0.5f) * widthPerColumn) - 5;
+                    int y = (int)((row + 0.5f) * heightPerRow) + 5;
+                    outputImage.drawText(x, y, (1 + row * numColumns + col).ToString(), Parameters.TouchEventVisualizerTextColor);
+                }
+            }
+
+            // draw grid
+            for (int i = 0; i <= numColumns; i++)
+                outputImage.drawLineSegment(new LineSegment2D(new Vector2D(i * widthPerColumn, 0), new Vector2D(i * widthPerColumn, height - 1)), Parameters.TouchEventVisualizerGridColor);
+            for (int i = 0; i <= numRows; i++)
+                outputImage.drawLineSegment(new LineSegment2D(new Vector2D(0, i * heightPerRow), new Vector2D(width - 1, i * heightPerRow)), Parameters.TouchEventVisualizerGridColor);
+
+            // draw active touches
+            foreach (List<Vector2D> positions in activeTouches.Values)
+                outputImage.drawTouchGesture(positions);
+
+            // draw old touches (fade out)
+            foreach (int id in oldTouches.Keys) {
+                List<Vector2D> positions = oldTouches[id];
+                long lastUpdate = lastUpdates[id];
+                float opacity = 1 - ((currentTime - lastUpdate) / (float)Parameters.TouchEventVisualizerFadeOutTime);
+                outputImage.drawTouchGesture(positions, opacity);
+            }
+
+            return outputImage;
+        }
+
+        private void removeOldPositions(long breakTime)
+        {
+            long currentTime = timer.ElapsedMilliseconds;
+
+            List<int> ids = new List<int>(lastUpdates.Keys);
+            for (int i = ids.Count - 1; i >= 0; i--)
+            {
+                int id = ids[i];
+                if (breakTime > lastUpdates[id])
+                {
+                    oldTouches.Remove(id);
+                    lastUpdates.Remove(id);
+                }
+            }
+        }
+    }
+}

+ 21 - 1
bbiwarg/Graphics/OutputImage.cs → bbiwarg/Output/OutputImage.cs

@@ -9,7 +9,7 @@ using bbiwarg.Utility;
 using Emgu.CV;
 using Emgu.CV.Structure;
 
-namespace bbiwarg.Graphics
+namespace bbiwarg.Output
 {
     class OutputImage
     {
@@ -135,5 +135,25 @@ namespace bbiwarg.Graphics
             drawLineSegment(new bbiwarg.Utility.LineSegment2D(c, d), borderColor);
             drawLineSegment(new bbiwarg.Utility.LineSegment2D(d, a), borderColor);
         }
+
+        public void drawBorder(Color color) {
+            drawRectangle(0, 0, Image.Width-1, Image.Height-1, color);
+        }
+
+        public void drawTouchGesture(List<Vector2D> positions, float opacity=1)
+        {
+            Vector2D maxPixel = Parameters.ImageMaxPixel;
+            int numPositions = positions.Count;
+            Color lineColor = Parameters.TouchEventVisualizerLineColor;
+            Color pointColor = Parameters.TouchEventVisualizerPointColor;
+            Color lineColorFaded = Color.FromArgb((int)(opacity * lineColor.R), (int)(opacity * lineColor.G), (int)(opacity * lineColor.B));
+            Color pointColorFaded = Color.FromArgb((int)(opacity * pointColor.R), (int)(opacity * pointColor.G), (int)(opacity * pointColor.B));
+            for (int i = 1; i < numPositions; i++)
+            {
+                drawLineSegment(new Utility.LineSegment2D(positions[i - 1].scale(maxPixel), positions[i].scale(maxPixel)), lineColorFaded);
+            }
+            Vector2D lastPos = positions[numPositions - 1].scale(maxPixel);
+            fillCircle(lastPos.IntX, lastPos.IntY, 3, pointColorFaded);
+        }
     }
 }

+ 67 - 35
bbiwarg/Parameters.cs

@@ -12,41 +12,42 @@ namespace bbiwarg
 {
     public enum InputType
     {
-        Camera = 0,
-        Movie = 1
+        Camera,
+        Movie
     }
 
     class Parameters
     {
         // input
-        public static readonly InputType InputSource = InputType.Camera;
+        public static readonly InputType InputSource = InputType.Movie;
         public static readonly String InputMoviePath = "..\\..\\videos\\touch\\4.skv";
 
         // Logger
-        public static readonly LogSubject LogLevel = LogSubject.None;
+        public static readonly LogSubject EnabledLogSubjects = LogSubject.None;
         public static readonly int ConsoleWidth = 90;
         public static readonly int ConsoleHeight = 30;
 
-        // Output
-        public static readonly int OutputUpdateRate = 30;
-        public static readonly int OutputRenderRate = 30;
-        public static readonly int OutputNumImages = 5;
-        public static readonly int OutputNumImagesPerRow = 3;
-        public static readonly float OutputScaleFactor = 1f; // output window size is scaled by this factor (from necessary size for images)
-        public static readonly String OutputTitle = "BBIWARG - Output";
+        // Debug-Output
+        public static readonly bool DebugOutputEnabled = true;
+        public static readonly int DebugOutputUpdateRate = 30;
+        public static readonly int DebugOutputRenderRate = 30;
+        public static readonly int DebugOutputNumImages = 5;
+        public static readonly int DebugOutputNumImagesPerRow = 3;
+        public static readonly float DebugOutputScaleFactor = 1f; // output window size is scaled by this factor (from necessary size for images)
+        public static readonly String DebugOutputTitle = "BBIWARG - DebugOutput";
 
         // TUIO
-        public static bool TuioEnabled = true;
-        public static IPAddress TuioIP = new IPAddress(new byte[4] { 127, 0, 0, 1 });
-        public static Int16 TuioPort = 3333;
+        public static bool TuioEnabled { get; private set; }
+        public static IPAddress TuioIP { get; private set; }
+        public static Int16 TuioPort { get; private set; }
 
         // image
-        public static readonly int ImageWidth = 320;
-        public static readonly int ImageHeight = 240;
-        public static readonly int ImageNumPixels = ImageWidth * ImageHeight;
-        public static readonly Vector2D ImageMaxPixel = new Vector2D(ImageWidth - 1, ImageHeight - 1);
-        public static readonly float ImageDiagonalLength = ImageMaxPixel.Length;
-        public static readonly float ImageAspectRatio = (float)ImageWidth / (float)ImageHeight;
+        public static int ImageWidth { get; private set; }
+        public static int ImageHeight { get; private set; }
+        public static int ImageNumPixels { get; private set; }
+        public static Vector2D ImageMaxPixel { get; private set; }
+        public static float ImageDiagonalLength { get; private set; }
+        public static float ImageAspectRatio { get; private set; }
 
         // confidence image
         public static readonly int ConfidenceImageMinThreshold = 500;
@@ -61,6 +62,9 @@ namespace bbiwarg
         public static readonly int EdgeImageCannySize = 3;
         public static readonly int EdgeImageRoughNumDilationIterations = 1;
 
+        // general tracking
+        public static readonly float TrackerMaxRelativeMove = 0.25f;
+
         // finger detection
         public static readonly int FingerStepSize = 1;
         public static readonly int FingerMaxGapCounter = 3;
@@ -77,12 +81,12 @@ namespace bbiwarg
         // finger tracking
         public static readonly int FingerTrackerNumFramesDetectedUntilTracked = 5;
         public static readonly int FingerTrackerNumFramesLostUntilDeleted = 10;
-        public static readonly float FingerTrackerMaxTipPointMove = 0.25f * ImageDiagonalLength;
-        public static readonly float FingerTrackerMaxHandPointMove = 0.25f * ImageDiagonalLength;
         public static readonly float FingermXX = 0.000005f;
         public static readonly float FingermXY = 0.0f;
         public static readonly float FingermYY = 0.000005f;
         public static readonly int FingerTrackerNumDirectionsForMeanDirection = 10;
+        public static readonly float FingerTrackerMaxTipPointRelativeMove = TrackerMaxRelativeMove;
+        public static readonly float FingerTrackerMaxHandPointRelativeMove = TrackerMaxRelativeMove;
 
         // hand detection
         public static readonly int HandNumColors = 3;
@@ -101,7 +105,7 @@ namespace bbiwarg
         // hand tracker
         public static readonly int HandTrackerNumFramesDetectedUntilTracked = 5;
         public static readonly int HandTrackerNumFramesLostUntilDeleted = 5;
-        public static readonly float HandTrackerMaxCentroidMove = 0.25f * ImageDiagonalLength;
+        public static readonly float HandTrackerMaxCentroidRelativeMove = TrackerMaxRelativeMove;
         public static readonly float HandmXX = 0.0005f;
         public static readonly float HandmXY = 0.0f;
         public static readonly float HandmYY = 0.0005f;
@@ -113,17 +117,17 @@ namespace bbiwarg
         // palm tracker
         public static readonly int PalmTrackerNumFramesDetectedUntilTracked = 5;
         public static readonly int PalmTrackerNumFramesLostUntilDeleted = 5;
-        public static readonly float PalmTrackerMaxWristUpperMove = 0.25f * ImageDiagonalLength;
-        public static readonly float PalmTrackerMaxWristLowerMove = 0.25f * ImageDiagonalLength;
-        public static readonly float PalmTrackerMaxFingersUpperMove = 0.25f * ImageDiagonalLength;
-        public static readonly float PalmTrackerMaxFingersLowerMove = 0.25f * ImageDiagonalLength;
+        public static readonly float PalmTrackerMaxWristUpperRelativeMove = TrackerMaxRelativeMove;
+        public static readonly float PalmTrackerMaxWristLowerRelativeMove = TrackerMaxRelativeMove;
+        public static readonly float PalmTrackerMaxFingersUpperRelativeMove = TrackerMaxRelativeMove;
+        public static readonly float PalmTrackerMaxFingersLowerRelativeMove = TrackerMaxRelativeMove;
         public static readonly float PalmmXX = 0.00005f;
         public static readonly float PalmmXY = 0.0f;
         public static readonly float PalmmYY = 0.00005f;
 
         //palm Grid
-        public static int PalmGridNumRows = 3;
-        public static int PalmGridNumColumns = 4;
+        public static int PalmGridNumRows { get; private set; }
+        public static int PalmGridNumColumns { get; private set; }
 
         // touch detection
         public static readonly float TouchMinTouchValue = 0.3f;
@@ -136,8 +140,7 @@ namespace bbiwarg
         // touch tracking
         public static readonly int TouchTrackerNumFramesDetectedUntilTracked = 1;
         public static readonly int TouchTrackerNumFramesLostUntilDeleted = 5;
-        public static readonly float TouchTrackerMaxAbsolutePositionMove = 0.25f * ImageDiagonalLength;
-        public static readonly float TouchTrackerMaxRelativePositionMove = 1f;
+        public static readonly float TouchTrackerMaxAbsolutePositionRelativeMove = TrackerMaxRelativeMove;
         public static readonly float TouchmXX = 0.003f;
         public static readonly float TouchmXY = 0.0f;
         public static readonly float TouchmYY = 0.00165f;
@@ -158,10 +161,9 @@ namespace bbiwarg
         public static readonly Color FingerDetectedColor = ColorDetected;
         public static readonly Color FingerTrackedColor = ColorTracked;
         public static readonly Color FingerTipColor = Color.Blue;
+        public static readonly Color FingerHandColor = Color.Yellow;
         public static readonly Color FingerContourColor = Color.Red;
         public static readonly Color FingerIDColor = Color.White;
-        public static readonly Color FingerPointsPredictionColor = Color.Yellow;
-        public static readonly Color FingerMeanDirectionColor = Color.Red;
 
         public static readonly Color TouchEventDetectedColor = ColorDetected;
         public static readonly Color TouchEventTrackedColor = ColorTracked;
@@ -173,15 +175,45 @@ namespace bbiwarg
         public static readonly Color TouchEventVisualizerPointColor = Color.Red;
         public static readonly Color TouchEventVisualizerGridColor = Color.White;
         public static readonly Color TouchEventVisualizerTextColor = Color.White;
-        public static readonly Color TouchEventVisualizerActiveBlockColor = Color.DarkSlateGray; 
+        public static readonly Color TouchEventVisualizerActiveBlockColor = Color.DarkSlateGray;
 
         public static readonly Color PalmQuadColor = Color.Blue;
         public static readonly Color PalmGridColor = Color.CornflowerBlue;
 
-        public static readonly Color[] HandColor = new Color[3] { Color.Red, Color.Blue, Color.Green };
+        public static readonly Color[] HandColors = new Color[3] { Color.Red, Color.Blue, Color.Green };
         public static readonly Color HandCentroidColor = Color.Yellow;
         public static readonly Color HandIDColor = Color.White;
         public static readonly Color HandThumbDefectPointColor = Color.Lime;
         public static readonly Color HandThumbDefectLineColor = Color.CornflowerBlue;
+
+        static Parameters()
+        {
+            setImageParameters(320, 240);
+            setTuioParameters(true, new IPAddress(new byte[4] { 127, 0, 0, 1 }), 3333);
+            setPalmGridParameters(3, 4);
+        }
+
+        public static void setImageParameters(int width, int height)
+        {
+            ImageWidth = width;
+            ImageHeight = height;
+            ImageNumPixels = ImageWidth * ImageHeight;
+            ImageMaxPixel = new Vector2D(ImageWidth - 1, ImageHeight - 1);
+            ImageDiagonalLength = ImageMaxPixel.Length;
+            ImageAspectRatio = (float)ImageWidth / (float)ImageHeight;
+        }
+
+        public static void setTuioParameters(bool enabled, IPAddress ipAddress, Int16 port)
+        {
+            TuioEnabled = enabled;
+            TuioIP = ipAddress;
+            TuioPort = port;
+        }
+
+        public static void setPalmGridParameters(int numRows, int numColumns)
+        {
+            PalmGridNumRows = numRows;
+            PalmGridNumColumns = numColumns;
+        }
     }
 }

+ 3 - 3
bbiwarg/Recognition/FingerRecognition/Finger.cs

@@ -6,7 +6,7 @@ using System.Text;
 using System.Threading.Tasks;
 using bbiwarg.Images;
 using bbiwarg.Utility;
-using bbiwarg.Graphics;
+using bbiwarg.Output;
 using bbiwarg.Recognition.HandRecognition;
 using bbiwarg.Recognition.TouchRecognition;
 using bbiwarg.Recognition.Tracking;
@@ -14,7 +14,7 @@ using Emgu.CV;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
-    class Finger : TrackableObject
+    public class Finger : TrackableObject
     {
         public Vector2D TipPoint { get { return SliceTrail.StartSlice.Mid; } }
         public Vector2D HandPoint { get { return SliceTrail.EndSlice.Mid; } }
@@ -23,7 +23,7 @@ namespace bbiwarg.Recognition.FingerRecognition
         public LineSegment2D LineSegment { get { return SliceTrail.LineSegment; } }
         public FingerSliceTrail SliceTrail { get; private set; }
         public Hand Hand { get; set; }
-        public TouchEvent TouchEvent { get; set; }
+        public Touch Touch { get; set; }
 
         public Finger(FingerSliceTrail sliceTrail)
             : base()

+ 10 - 14
bbiwarg/Recognition/FingerRecognition/FingerDetector.cs

@@ -6,10 +6,10 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using bbiwarg.Images;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Utility;
 using Emgu.CV.Structure;
 using Emgu.CV;
-using bbiwarg.Graphics;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
@@ -18,25 +18,19 @@ namespace bbiwarg.Recognition.FingerRecognition
         private DepthImage depthImage;
         private EdgeImage edgeImageOriginal;
         private EdgeImage edgeImageAdapted;
-        public List<Finger> Fingers { get; private set; }
+        private List<Finger> fingers;
 
-        public FingerDetector(DepthImage depthImage, EdgeImage edgeImage)
+        public void detectFingers(FrameData frameData)
         {
-            this.depthImage = depthImage;
-            this.edgeImageOriginal = edgeImage;
-            this.edgeImageAdapted = edgeImage.copy();
+            depthImage = frameData.DepthImage;
+            edgeImageOriginal = frameData.EdgeImage;
+            edgeImageAdapted = frameData.EdgeImage.copy();
+            fingers = new List<Finger>();
 
-            detectFingers();
-        }
-
-        private void detectFingers()
-        {
             Vector2D maxPixel = Parameters.ImageMaxPixel;
             int maxX = maxPixel.IntX;
             int maxY = maxPixel.IntY;
 
-            Fingers = new List<Finger>();
-
             for (int y = 1; y < maxY; y += 4)
             {
                 for (int x = 1; x < maxX; x += 2)
@@ -64,6 +58,8 @@ namespace bbiwarg.Recognition.FingerRecognition
                     }
                 }
             }
+
+            frameData.DetectedFingers = fingers;
         }
 
         private Vector2D getEdgeDirection(Vector2D edgePoint)
@@ -199,7 +195,7 @@ namespace bbiwarg.Recognition.FingerRecognition
 
             //add finger
             if (!isCrippleFinger(finger))
-                Fingers.Add(finger);
+                fingers.Add(finger);
 
             //remove edges around detected finger to improve performance
             edgeImageAdapted.removeEdgesInsidePolygon(finger.getContour(Parameters.FingerContourMargin).ToArray());

+ 1 - 1
bbiwarg/Recognition/FingerRecognition/FingerSlice.cs

@@ -7,7 +7,7 @@ using bbiwarg.Utility;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
-    class FingerSlice
+    public class FingerSlice
     {
         public Vector2D Mid { get; private set; }
         public Vector2D Start { get; private set; }

+ 1 - 1
bbiwarg/Recognition/FingerRecognition/FingerSliceTrail.cs

@@ -9,7 +9,7 @@ using Emgu.CV;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
-    class FingerSliceTrail
+    public class FingerSliceTrail
     {
         private LineSegment2D lineSegment;
         private Vector2D fittedDirection;

+ 5 - 2
bbiwarg/Recognition/FingerRecognition/FingerTracker.cs

@@ -5,14 +5,17 @@ using System.Text;
 using System.Threading.Tasks;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
+using bbiwarg.Input.InputHandling;
 
 namespace bbiwarg.Recognition.FingerRecognition
 {
 
     class FingerTracker : Tracker<Finger, TrackedFinger>
     {
-
-        public List<Finger> Fingers { get { return getCurrentObjectsWithState(TrackingState.Tracked); } }
+        public void trackFingers(FrameData frameData) {
+            trackObjects(frameData.DetectedFingers);
+            frameData.TrackedFingers = getCurrentObjectsWithState(TrackingState.Tracked);
+        }
 
         protected override TrackedFinger createTrackedObject(Finger detectedObject)
         {

+ 2 - 2
bbiwarg/Recognition/FingerRecognition/TrackedFinger.cs

@@ -65,8 +65,8 @@ namespace bbiwarg.Recognition.FingerRecognition
                 hand = detectedFinger.HandPoint;
             }
 
-            float tipPointSimilarity = getPositionSimilarity(TipPointPrediction, tip, Parameters.FingerTrackerMaxTipPointMove);
-            float handPointSimilarity = getPositionSimilarity(HandPointPrediction, hand, Parameters.FingerTrackerMaxHandPointMove);
+            float tipPointSimilarity = getPositionSimilarity(TipPointPrediction, tip, Parameters.FingerTrackerMaxTipPointRelativeMove);
+            float handPointSimilarity = getPositionSimilarity(HandPointPrediction, hand, Parameters.FingerTrackerMaxHandPointRelativeMove);
 
             return tipPointSimilarity * handPointSimilarity;
         }

+ 1 - 1
bbiwarg/Recognition/HandRecognition/Hand.cs

@@ -13,7 +13,7 @@ using bbiwarg.Recognition.PalmRecognition;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
-    class Hand : TrackableObject
+    public class Hand : TrackableObject
     {
         public Vector2D Centroid { get; private set; }
         public Image<Gray, byte> Mask { get; private set; }

+ 15 - 22
bbiwarg/Recognition/HandRecognition/HandDetector.cs

@@ -6,8 +6,9 @@ using System.Text;
 using System.Threading.Tasks;
 using bbiwarg.Images;
 using bbiwarg.Recognition.FingerRecognition;
-using bbiwarg.Graphics;
+using bbiwarg.Output;
 using bbiwarg.Utility;
+using bbiwarg.Input.InputHandling;
 using Emgu.CV;
 using Emgu.CV.Structure;
 
@@ -21,20 +22,19 @@ namespace bbiwarg.Recognition.HandRecognition
         private Image<Gray, byte> modifiedHandDepthImage;
         private List<Finger> fingers;
         private Dictionary<Hand, List<Finger>> otherHandsFingers;
+        private List<Hand> hands;
 
-        public List<Hand> Hands { get; private set; }
-        public Image<Gray, byte> HandMask { get; private set; }
-
-        public HandDetector(DepthImage depthImage, List<Finger> fingers)
+        public void detectHands(FrameData frameData)
         {
-            this.depthImage = depthImage;
-            this.fingers = fingers;
+            depthImage = frameData.DepthImage;
+            fingers = frameData.TrackedFingers;
 
             createModifiedHandEdgeImage();
             findHands();
             fixOverlappingFingers();
             findCentroids();
-            createHandMask();
+
+            frameData.DetectedHands = hands;
         }
 
         private void createModifiedHandEdgeImage()
@@ -51,7 +51,7 @@ namespace bbiwarg.Recognition.HandRecognition
 
         private void findHands()
         {
-            Hands = new List<Hand>();
+            hands = new List<Hand>();
             otherHandsFingers = new Dictionary<Hand,List<Finger>>();
             List<Finger> assignedFingers = new List<Finger>();
 
@@ -75,7 +75,7 @@ namespace bbiwarg.Recognition.HandRecognition
 
                     Hand hand = new Hand(handMask, fingersOnHand);
                     otherHandsFingers.Add(hand, fingersOnOtherHand);
-                    Hands.Add(hand);
+                    hands.Add(hand);
                 }
             }
         }
@@ -98,7 +98,7 @@ namespace bbiwarg.Recognition.HandRecognition
         {
             List<Hand> mergedHands = new List<Hand>();
 
-            foreach (Hand hand in Hands)
+            foreach (Hand hand in hands)
             {
                 if (!mergedHands.Contains(hand))
                 {
@@ -130,7 +130,7 @@ namespace bbiwarg.Recognition.HandRecognition
 
                             //check if pHandExtension is in other hand (if so -> merge with hand)
                             bool merge = false;
-                            foreach (Hand mergeHand in Hands)
+                            foreach (Hand mergeHand in hands)
                             {
                                 if (mergeHand.isInside(pHandExtension) && !mergedHands.Contains(mergeHand))
                                 {
@@ -153,7 +153,7 @@ namespace bbiwarg.Recognition.HandRecognition
                 }
             }
             foreach (Hand mergedHand in mergedHands)
-                Hands.Remove(mergedHand);
+                hands.Remove(mergedHand);
         }
 
         private void mergeToHand(Hand hand, Hand mergeHand)
@@ -175,22 +175,15 @@ namespace bbiwarg.Recognition.HandRecognition
 
         private void fillOverlappingFingers()
         {
-            foreach (Hand hand in Hands)
+            foreach (Hand hand in hands)
             {
                 hand.fillOverlappingFingers(otherHandsFingers[hand]);
             }
         }
 
         private void findCentroids() {
-            foreach (Hand hand in Hands)
+            foreach (Hand hand in hands)
                 hand.findCentroid();
         }
-
-        private void createHandMask()
-        {
-            HandMask = new Image<Gray, byte>(Parameters.ImageWidth, Parameters.ImageHeight);
-            foreach (Hand hand in Hands)
-                HandMask = HandMask.Or(hand.Mask);
-        }
     }
 }

+ 6 - 1
bbiwarg/Recognition/HandRecognition/HandTracker.cs

@@ -4,12 +4,17 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using bbiwarg.Recognition.Tracking;
+using bbiwarg.Input.InputHandling;
 
 namespace bbiwarg.Recognition.HandRecognition
 {
     class HandTracker : Tracker<Hand, TrackedHand>
     {
-        public List<Hand> Hands { get { return getCurrentObjectsWithState(TrackingState.Tracked); } }
+        public void trackHands(FrameData frameData)
+        {
+            trackObjects(frameData.DetectedHands);
+            frameData.TrackedHands = getCurrentObjectsWithState(TrackingState.Tracked);
+        }
 
         protected override TrackedHand createTrackedObject(Hand detectedObject)
         {

+ 1 - 1
bbiwarg/Recognition/HandRecognition/TrackedHand.cs

@@ -36,7 +36,7 @@ namespace bbiwarg.Recognition.HandRecognition
 
         public override float calculateSimilarity(Hand detectedHand)
         {
-            float centroidSimilarity = getPositionSimilarity(CentroidPrediction, detectedHand.Centroid, Parameters.HandTrackerMaxCentroidMove);
+            float centroidSimilarity = getPositionSimilarity(CentroidPrediction, detectedHand.Centroid, Parameters.HandTrackerMaxCentroidRelativeMove);
 
             return centroidSimilarity;
         }

+ 1 - 2
bbiwarg/Recognition/PalmRecognition/Palm.cs

@@ -16,7 +16,7 @@ namespace bbiwarg.Recognition.PalmRecognition
         Left = 2
     }
 
-    class Palm : TrackableObject
+    public class Palm : TrackableObject
     {
         public Hand Hand { get; private set; }
         public ConvexityDefect ThumbDefect { get; private set; }
@@ -47,7 +47,6 @@ namespace bbiwarg.Recognition.PalmRecognition
             Vector2D relativePosition = Quad.getRelativePosition(absolutePosition);
             float x = Math.Max(0, Math.Min(1, relativePosition.X));
             float y = Math.Max(0, Math.Min(1, relativePosition.Y));
-            Console.WriteLine(x + "\t" + y);
 
             return new Vector2D(x, y);
         }

+ 9 - 7
bbiwarg/Recognition/PalmRecognition/PalmDetector.cs

@@ -8,6 +8,7 @@ using bbiwarg.Images;
 using bbiwarg.Utility;
 using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.HandRecognition;
+using bbiwarg.Input.InputHandling;
 using Emgu.CV;
 using Emgu.CV.Structure;
 
@@ -17,20 +18,21 @@ namespace bbiwarg.Recognition.PalmRecognition
     {
         private DepthImage depthImage;
         private List<Hand> hands;
+        private List<Palm> palms;
 
-        public List<Palm> Palms;
-
-        public PalmDetector(DepthImage depthImage, List<Hand> hands)
+        public void detectPalms(FrameData frameData)
         {
-            this.depthImage = depthImage;
-            this.hands = hands;
+            depthImage = frameData.DepthImage;
+            hands = frameData.TrackedHands;
 
             findPalms();
+
+            frameData.DetectedPalms = palms;
         }
 
         private void findPalms()
         {
-            Palms = new List<Palm>();
+            palms = new List<Palm>();
             foreach (Hand hand in hands)
             {
                 if (hand.Fingers.Count == 1)
@@ -40,7 +42,7 @@ namespace bbiwarg.Recognition.PalmRecognition
                     if (thumbDefect != null)
                     {
                         Palm palm = createPalm(hand, thumbDefect);
-                        Palms.Add(palm);
+                        palms.Add(palm);
                     }
                 }
             }

+ 5 - 2
bbiwarg/Recognition/PalmRecognition/PalmTracker.cs

@@ -4,13 +4,16 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using bbiwarg.Recognition.Tracking;
+using bbiwarg.Input.InputHandling;
 
 namespace bbiwarg.Recognition.PalmRecognition
 {
     class PalmTracker : Tracker<Palm, TrackedPalm>
     {
-        public List<Palm> Palms { get { return getCurrentObjectsWithState(TrackingState.Tracked); } }
-        public List<Palm> OptimizedPalms { get { return getOptimizedPalms(); } }
+        public void trackPalms(FrameData frameData) {
+            trackObjects(frameData.DetectedPalms);
+            frameData.TrackedPalms = getOptimizedPalms();
+        }
 
         protected override TrackedPalm createTrackedObject(Palm detectedPalm)
         {

+ 4 - 4
bbiwarg/Recognition/PalmRecognition/TrackedPalm.cs

@@ -64,10 +64,10 @@ namespace bbiwarg.Recognition.PalmRecognition
         public override float calculateSimilarity(Palm detectedPalm)
         {
             float handSimilarity = (detectedPalm.Hand.TrackID == LastObject.Hand.TrackID) ? 1 : 0;
-            float wristUpperSimilarity = getPositionSimilarity(WristUpperPrediction, detectedPalm.WristUpper, Parameters.PalmTrackerMaxWristUpperMove);
-            float wristLowerSimilarity = getPositionSimilarity(WristLowerPrediction, detectedPalm.WristLower, Parameters.PalmTrackerMaxWristLowerMove);
-            float fingersUpperSimilarity = getPositionSimilarity(FingersUpperPrediction, detectedPalm.FingersUpper, Parameters.PalmTrackerMaxFingersUpperMove);
-            float fingersLowerSimilarity = getPositionSimilarity(FingersLowerPrediction, detectedPalm.FingersLower, Parameters.PalmTrackerMaxFingersLowerMove);
+            float wristUpperSimilarity = getPositionSimilarity(WristUpperPrediction, detectedPalm.WristUpper, Parameters.PalmTrackerMaxWristUpperRelativeMove);
+            float wristLowerSimilarity = getPositionSimilarity(WristLowerPrediction, detectedPalm.WristLower, Parameters.PalmTrackerMaxWristLowerRelativeMove);
+            float fingersUpperSimilarity = getPositionSimilarity(FingersUpperPrediction, detectedPalm.FingersUpper, Parameters.PalmTrackerMaxFingersUpperRelativeMove);
+            float fingersLowerSimilarity = getPositionSimilarity(FingersLowerPrediction, detectedPalm.FingersLower, Parameters.PalmTrackerMaxFingersLowerRelativeMove);
 
             float similarity = handSimilarity * wristUpperSimilarity * wristLowerSimilarity * fingersUpperSimilarity * fingersLowerSimilarity;
 

+ 3 - 12
bbiwarg/Recognition/TouchRecognition/TouchEvent.cs → bbiwarg/Recognition/TouchRecognition/Touch.cs

@@ -12,32 +12,23 @@ using Emgu.CV.Structure;
 
 namespace bbiwarg.Recognition.TouchRecognition
 {
-    class TouchEvent : TrackableObject
+    public class Touch : TrackableObject
     {
         public Vector2D AbsolutePosition { get; private set; }
         public Vector2D RelativePosition { get; private set; }
-        public Image<Gray, byte> TouchMask { get; private set; }
         public Finger Finger { get; private set; }
         public Palm Palm { get; private set; }
 
 
-        public TouchEvent(Vector2D absolutePosition, Image<Gray, byte> touchMask, Finger finger, Palm palm)
+        public Touch(Vector2D absolutePosition, Finger finger, Palm palm)
         {
             AbsolutePosition = absolutePosition;
             RelativePosition = palm.getRelativePosition(absolutePosition);
-            TouchMask = touchMask;
             Finger = finger;
             Palm = palm;
 
-            finger.TouchEvent = this;
+            finger.Touch = this;
         }
 
-        public float getTouchValue()
-        {
-            int touchPixels = TouchMask.CountNonzero()[0];
-            int numPixels = TouchMask.Width * TouchMask.Height;
-            float touchValue = touchPixels / (float)numPixels;
-            return touchValue;
-        }
     }
 }

+ 12 - 10
bbiwarg/Recognition/TouchRecognition/TouchDetector.cs

@@ -10,7 +10,8 @@ using bbiwarg.Images;
 using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.PalmRecognition;
 using bbiwarg.Utility;
-using bbiwarg.Graphics;
+using bbiwarg.Output;
+using bbiwarg.Input.InputHandling;
 
 namespace bbiwarg.Recognition.TouchRecognition
 {
@@ -19,18 +20,19 @@ namespace bbiwarg.Recognition.TouchRecognition
         private DepthImage depthImage;
         private List<Finger> fingers;
         private List<Palm> palms;
+        private List<Touch> touches;
 
-        public List<TouchEvent> TouchEvents { get; private set; }
-
-        public TouchDetector(DepthImage depthImage, List<Finger> fingers, List<Palm> palms)
+        public void detectTouches(FrameData frameData)
         {
-            this.depthImage = depthImage;
-            this.fingers = fingers;
-            this.palms = palms;
-            TouchEvents = new List<TouchEvent>();
+            depthImage = frameData.DepthImage;
+            fingers = frameData.TrackedFingers;
+            palms = frameData.TrackedPalms;
+            touches = new List<Touch>();
 
             if (palms.Count > 0)
                 detectTouch();
+
+            frameData.DetectedTouches = touches;
         }
 
         private void detectTouch()
@@ -54,8 +56,8 @@ namespace bbiwarg.Recognition.TouchRecognition
 
                         if (touchValue > Parameters.TouchMinTouchValue)
                         {
-                            TouchEvent touchEvent = new TouchEvent(tipPointOutside, touchMask, finger, palm);
-                            TouchEvents.Add(touchEvent);
+                            Touch touchEvent = new Touch(tipPointOutside, finger, palm);
+                            touches.Add(touchEvent);
                         }
                     }
                 }

+ 40 - 12
bbiwarg/Recognition/TouchRecognition/TouchTracker.cs

@@ -5,27 +5,55 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using bbiwarg.Images;
-using bbiwarg.Graphics;
+using bbiwarg.Output;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
+using bbiwarg.Input.InputHandling;
 
 namespace bbiwarg.Recognition.TouchRecognition
 {
-    class TouchTracker : Tracker<TouchEvent, TrackedTouchEvent>
+    class TouchTracker : Tracker<Touch, TrackedTouch>
     {
-        public List<TouchEvent> TouchEvents { get { return getCurrentObjectsWithState(TrackingState.Tracked); } }
+        private List<TouchEventArgs> touchEvents;
+        
+        public TouchTracker() {
+            touchEvents = new List<TouchEventArgs>();
+        }
+
+        public void trackTouches(FrameData frameData) {
+            trackObjects(frameData.DetectedTouches);
+            frameData.TrackedTouches = getOptimizedTouches();
+            frameData.TouchEvents = flushTouchEvents();
+        }
 
-        public event TouchEventHandler TouchDown;
-        public event TouchEventHandler TouchMove;
-        public event TouchEventHandler TouchUp;
+        protected override TrackedTouch createTrackedObject(Touch detectedObject)
+        {
+            TrackedTouch tt = new TrackedTouch(idPool.getNextUnusedID(), detectedObject, Parameters.TouchTrackerNumFramesDetectedUntilTracked, Parameters.TouchTrackerNumFramesLostUntilDeleted);
+            tt.TouchEvent += touchEvent;
+            return tt;
+        }
 
-        protected override TrackedTouchEvent createTrackedObject(TouchEvent detectedObject)
+        private List<Touch> getOptimizedTouches()
         {
-            TrackedTouchEvent tte = new TrackedTouchEvent(idPool.getNextUnusedID(), detectedObject, Parameters.TouchTrackerNumFramesDetectedUntilTracked, Parameters.TouchTrackerNumFramesLostUntilDeleted);
-            tte.TouchDown += TouchDown;
-            tte.TouchMove += TouchMove;
-            tte.TouchUp += TouchUp;
-            return tte;
+            List<Touch> optimizedTouchs = new List<Touch>();
+            foreach (TrackedTouch tp in TrackedObjects)
+            {
+                if (tp.IsTouchActive)
+                    optimizedTouchs.Add(tp.OptimizedTouch);
+            }
+            return optimizedTouchs;
         }
+
+        private void touchEvent(TrackedTouch sender, TouchEventArgs e)
+        {
+            touchEvents.Add(e);
+        }
+
+        public List<TouchEventArgs> flushTouchEvents() {
+            List<TouchEventArgs> flushedTouchEvents = touchEvents;
+            touchEvents = new List<TouchEventArgs>();
+            return flushedTouchEvents;
+        }
+
     }
 }

+ 132 - 0
bbiwarg/Recognition/TouchRecognition/TrackedTouch.cs

@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using bbiwarg.Recognition.Tracking;
+using bbiwarg.Utility;
+
+namespace bbiwarg.Recognition.TouchRecognition
+{
+    public enum TouchEventType
+    {
+        Down,
+        Move,
+        Up
+    }
+
+    public delegate void TouchEventHandler(TrackedTouch sender, TouchEventArgs e);
+    
+    public class TouchEventArgs
+    {
+        public int TrackID { get; private set; }
+        public TouchEventType Type { get; private set; }
+        public Touch Touch { get; private set; }
+
+        public TouchEventArgs(int trackID, TouchEventType type, Touch touch)
+        {
+            TrackID = trackID;
+            Type = type;
+            Touch = touch;
+        }
+    }
+
+    public class TrackedTouch : TrackedObject<Touch>
+    {
+        private Kalman2DPositionFilter absolutePositionKalman;
+        private int fingerID;
+
+        public Vector2D AbsolutePositionPrediction { get { return absolutePositionKalman.getPrediction(); } }
+        public Touch OptimizedTouch { get; private set; }
+        public bool IsTouchActive { get; private set; }
+
+        public event TouchEventHandler TouchEvent;
+
+        public TrackedTouch(int id, Touch detectedTouch, int numFramesDetectedUntilTracked, int numFramesLostUntilDeleted)
+            : base(id, detectedTouch, numFramesDetectedUntilTracked, numFramesLostUntilDeleted)
+        {
+            absolutePositionKalman = new Kalman2DPositionFilter(Parameters.TouchmXX, Parameters.TouchmXY, Parameters.TouchmYY);
+            absolutePositionKalman.setInitialPosition(detectedTouch.AbsolutePosition);
+
+            fingerID = detectedTouch.Finger.TrackID;
+            IsTouchActive = false;
+
+            logStateChange();
+        }
+
+        public override void updateFrame(Touch detectedTouch)
+        {
+            base.updateFrame(detectedTouch);
+
+            if (NumFramesInCurrentState == 1)
+                logStateChange();
+
+            if (detectedTouch != null)
+            {
+                absolutePositionKalman.getCorrectedPosition(detectedTouch.AbsolutePosition);
+
+                updateOptimizedTouch(detectedTouch);
+
+                if (CurrentState == TrackingState.Tracked)
+                {
+                    if (!IsTouchActive)
+                        TriggerTouchDown();
+                    else
+                        TriggerTouchMove();
+                }
+            }
+            else if (IsTouchActive && CurrentState == TrackingState.Deleted)
+                TriggerTouchUp();
+
+        }
+
+        private void updateOptimizedTouch(Touch detectedTouch)
+        {
+            OptimizedTouch = new Touch(AbsolutePositionPrediction, detectedTouch.Finger, detectedTouch.Palm);
+        }
+
+        public override float calculateSimilarity(Touch detectedTouchEvent)
+        {
+            float fingerSimilarity = (fingerID == detectedTouchEvent.Finger.TrackID) ? 1 : 0;
+            //float absolutePositionSimilarity = getPositionSimilarity(AbsolutePositionPrediction, detectedTouchEvent.AbsolutePosition, Parameters.TouchTrackerMaxAbsolutePositionMove);
+            //float relativePositionSimilarity = getPositionSimilarity(RelativePositionPrediction, detectedTouchEvent.RelativePosition, Parameters.TouchTrackerMaxRelativePositionMove); 
+
+            float similarity = fingerSimilarity;// *absolutePositionSimilarity * relativePositionSimilarity;
+
+            return similarity;
+        }
+
+        private void logStateChange()
+        {
+            String stateAsString = CurrentState.ToString().ToLower();
+            Logger.log(String.Format("TouchEvent #{0} {1}", this.ID, stateAsString), LogSubject.TouchTracker);
+        }
+
+        private void TriggerTouchDown()
+        {
+            if (TouchEvent != null)
+            {
+                IsTouchActive = true;
+                TouchEvent(this, new TouchEventArgs(ID, TouchEventType.Down, OptimizedTouch));
+            }
+        }
+
+        private void TriggerTouchMove()
+        {
+            if (TouchEvent != null)
+            {
+                TouchEvent(this, new TouchEventArgs(ID, TouchEventType.Move, OptimizedTouch));
+            }
+        }
+
+        private void TriggerTouchUp()
+        {
+            if (TouchEvent != null)
+            {
+                IsTouchActive = false;
+                TouchEvent(this, new TouchEventArgs(ID, TouchEventType.Up, OptimizedTouch));
+            }
+        }
+
+    }
+}

+ 0 - 127
bbiwarg/Recognition/TouchRecognition/TrackedTouchEvent.cs

@@ -1,127 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using bbiwarg.Recognition.Tracking;
-using bbiwarg.Utility;
-
-namespace bbiwarg.Recognition.TouchRecognition
-{
-    public delegate void TouchEventHandler(object sender, TouchEventArgs e);
-    public class TouchEventArgs : EventArgs
-    {
-        public int TrackID { get; private set; }
-        public Vector2D AbsolutePosition { get; private set; }
-        public Vector2D RelativePosition { get; private set; }
-
-        public TouchEventArgs(int trackID, Vector2D absolutePosition, Vector2D relativePosition)
-        {
-            TrackID = trackID;
-            AbsolutePosition = absolutePosition;
-            RelativePosition = relativePosition;
-        }
-    }
-
-    class TrackedTouchEvent : TrackedObject<TouchEvent>
-    {
-        private Kalman2DPositionFilter absolutePositionKalman;
-        private Kalman2DPositionFilter relativePositionKalman;
-        private int fingerID;
-        private bool isTouchActive;
-
-        public Vector2D AbsolutePositionPrediction { get { return absolutePositionKalman.getPrediction(); } }
-        public Vector2D RelativePositionPrediction { get { return relativePositionKalman.getPrediction(); } }
-
-        public event TouchEventHandler TouchDown;
-        public event TouchEventHandler TouchMove;
-        public event TouchEventHandler TouchUp;
-
-        public TrackedTouchEvent(int id, TouchEvent detectedTouchEvent, int numFramesDetectedUntilTracked, int numFramesLostUntilDeleted)
-            : base(id, detectedTouchEvent, numFramesDetectedUntilTracked, numFramesLostUntilDeleted)
-        {
-            absolutePositionKalman = new Kalman2DPositionFilter(Parameters.TouchmXX, Parameters.TouchmXY, Parameters.TouchmYY);
-            absolutePositionKalman.setInitialPosition(detectedTouchEvent.AbsolutePosition);
-
-            relativePositionKalman = new Kalman2DPositionFilter(Parameters.TouchmXX, Parameters.TouchmXY, Parameters.TouchmYY);
-            relativePositionKalman.setInitialPosition(detectedTouchEvent.RelativePosition);
-
-            fingerID = detectedTouchEvent.Finger.TrackID;
-            isTouchActive = false;
-
-            logStateChange();
-        }
-
-        public override void updateFrame(TouchEvent detectedTouchEvent)
-        {
-            base.updateFrame(detectedTouchEvent);
-
-            if (NumFramesInCurrentState == 1)
-                logStateChange();
-
-            if (detectedTouchEvent != null)
-            {
-                absolutePositionKalman.getCorrectedPosition(detectedTouchEvent.AbsolutePosition);
-                relativePositionKalman.getCorrectedPosition(detectedTouchEvent.RelativePosition);
-
-                if (CurrentState == TrackingState.Tracked)
-                {
-                    if (!isTouchActive)
-                        TriggerTouchDown(new TouchEventArgs(ID, AbsolutePositionPrediction, RelativePositionPrediction));
-                    else
-                        TriggerTouchMove(new TouchEventArgs(ID, AbsolutePositionPrediction, RelativePositionPrediction));
-                }
-            }
-            else if (isTouchActive && CurrentState == TrackingState.Deleted)
-                TriggerTouchUp(new TouchEventArgs(ID, AbsolutePositionPrediction, RelativePositionPrediction));
-
-        }
-
-        public override float calculateSimilarity(TouchEvent detectedTouchEvent)
-        {
-            float fingerSimilarity = (fingerID == detectedTouchEvent.Finger.TrackID) ? 1 : 0;
-            //float absolutePositionSimilarity = getPositionSimilarity(AbsolutePositionPrediction, detectedTouchEvent.AbsolutePosition, Parameters.TouchTrackerMaxAbsolutePositionMove);
-            //float relativePositionSimilarity = getPositionSimilarity(RelativePositionPrediction, detectedTouchEvent.RelativePosition, Parameters.TouchTrackerMaxRelativePositionMove); 
-
-            float similarity = fingerSimilarity;// *absolutePositionSimilarity * relativePositionSimilarity;
-
-            return similarity;
-        }
-
-        private void logStateChange()
-        {
-            String stateAsString = CurrentState.ToString().ToLower();
-            Logger.log(String.Format("TouchEvent #{0} {1}", this.ID, stateAsString), LogSubject.TouchTracker);
-        }
-
-        private void TriggerTouchDown(TouchEventArgs e)
-        {
-            if (TouchDown != null)
-            {
-                isTouchActive = true;
-                TouchDown(this, e);
-                Logger.log(String.Format("TouchEvent #{0} TouchDown at {1}", this.ID, e.RelativePosition), LogSubject.TouchEvents);
-            }
-        }
-
-        private void TriggerTouchMove(TouchEventArgs e)
-        {
-            if (TouchMove != null)
-            {
-                TouchMove(this, e);
-                Logger.log(String.Format("TouchEvent #{0} TouchMove at {1}", this.ID, e.RelativePosition), LogSubject.TouchEvents);
-            }
-        }
-
-        private void TriggerTouchUp(TouchEventArgs e)
-        {
-            if (TouchUp != null)
-            {
-                isTouchActive = false;
-                TouchUp(this, e);
-                Logger.log(String.Format("TouchEvent #{0} TouchUp at {1}", this.ID, e.RelativePosition), LogSubject.TouchEvents);
-            }
-        }
-
-    }
-}

+ 2 - 2
bbiwarg/Recognition/Tracking/TrackedObject.cs

@@ -101,10 +101,10 @@ namespace bbiwarg.Recognition.Tracking
             return newState;
         }
 
-        protected float getPositionSimilarity(Vector2D p1, Vector2D p2, float maxDistance)
+        protected float getPositionSimilarity(Vector2D p1, Vector2D p2, float maxRelativeDistance)
         {
             float distance = p1.getDistanceTo(p2);
-            float similarity = Math.Max(1 - distance / maxDistance, 0);
+            float similarity = Math.Max(1 - distance / (maxRelativeDistance * Parameters.ImageDiagonalLength), 0);
             return similarity;
         }
     }

+ 31 - 24
bbiwarg/Recognition/Tracking/Tracker.cs

@@ -1,12 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
 
 namespace bbiwarg.Recognition.Tracking
 {
-    abstract class Tracker<T, TrackedT>
+    internal abstract class Tracker<T, TrackedT>
         where T : TrackableObject
         where TrackedT : TrackedObject<T>
     {
@@ -16,7 +12,6 @@ namespace bbiwarg.Recognition.Tracking
 
         public List<TrackedT> TrackedObjects;
 
-
         public Tracker()
         {
             reset();
@@ -28,7 +23,7 @@ namespace bbiwarg.Recognition.Tracking
             TrackedObjects = new List<TrackedT>();
         }
 
-        public void updateFrame(List<T> detectedObjects)
+        protected void trackObjects(List<T> detectedObjects)
         {
             if (TrackedObjects.Count == 0)
             {
@@ -41,13 +36,14 @@ namespace bbiwarg.Recognition.Tracking
             }
         }
 
-        public void updateTrackedObjects(List<T> detectedObjects)
+        protected void updateTrackedObjects(List<T> detectedObjects)
         {
             List<TrackedT> unassignedTrackedObjects = new List<TrackedT>(TrackedObjects);
             List<T> unassignedDetectedObjects = new List<T>(detectedObjects);
 
             createSimilarities(detectedObjects);
-            while (similarities.Count > 0) {
+            while (similarities.Count > 0)
+            {
                 Similarity<T, TrackedT> maxSimilarity = similarities[0];
                 maxSimilarity.TrackedObject.updateFrame(maxSimilarity.DetectedObject);
 
@@ -58,7 +54,8 @@ namespace bbiwarg.Recognition.Tracking
 
             addNewTrackedObjects(unassignedDetectedObjects);
 
-            foreach (TrackedT trackedObject in unassignedTrackedObjects) {
+            foreach (TrackedT trackedObject in unassignedTrackedObjects)
+            {
                 trackedObject.updateFrame(null);
             }
         }
@@ -72,13 +69,16 @@ namespace bbiwarg.Recognition.Tracking
             }
         }
 
-        private void createSimilarities(List<T> detectedObjects) {
+        private void createSimilarities(List<T> detectedObjects)
+        {
             similarities = new List<Similarity<T, TrackedT>>();
 
-            foreach (TrackedT trackedObject in TrackedObjects) {
-                foreach (T detectedObject in detectedObjects) {
+            foreach (TrackedT trackedObject in TrackedObjects)
+            {
+                foreach (T detectedObject in detectedObjects)
+                {
                     float similarityValue = trackedObject.calculateSimilarity(detectedObject);
-                    Similarity<T, TrackedT> similarity = new Similarity<T,TrackedT>(trackedObject, detectedObject, similarityValue);
+                    Similarity<T, TrackedT> similarity = new Similarity<T, TrackedT>(trackedObject, detectedObject, similarityValue);
                     if (similarity.Value > 0)
                         similarities.Add(similarity);
                 }
@@ -88,33 +88,40 @@ namespace bbiwarg.Recognition.Tracking
             similarities.Sort((s1, s2) => s2.Value.CompareTo(s1.Value));
         }
 
-        private void removeConcurringSimilarities(Similarity<T, TrackedT> similarity) {
-            for (int i = similarities.Count - 1; i >= 0; i--) {
+        private void removeConcurringSimilarities(Similarity<T, TrackedT> similarity)
+        {
+            for (int i = similarities.Count - 1; i >= 0; i--)
+            {
                 Similarity<T, TrackedT> s = similarities[i];
                 if (s.TrackedObject == similarity.TrackedObject || s.DetectedObject == similarity.DetectedObject)
                     similarities.RemoveAt(i);
             }
         }
 
-        private void removeDeletableTrackedObjects() {
-            for (int i = TrackedObjects.Count - 1; i >= 0; i--) {
+        private void removeDeletableTrackedObjects()
+        {
+            for (int i = TrackedObjects.Count - 1; i >= 0; i--)
+            {
                 TrackedT trackedObject = TrackedObjects[i];
-                if (trackedObject.CurrentState == TrackingState.Deleted) {
+                if (trackedObject.CurrentState == TrackingState.Deleted)
+                {
                     idPool.setIDUnused(trackedObject.ID);
                     TrackedObjects.RemoveAt(i);
                 }
             }
         }
 
-        protected List<T> getCurrentObjectsWithState(TrackingState state) {
+        protected List<T> getCurrentObjectsWithState(TrackingState state)
+        {
             List<T> objects = new List<T>();
-            foreach (TrackedT trackedObject in TrackedObjects) {
+            foreach (TrackedT trackedObject in TrackedObjects)
+            {
                 if (trackedObject.CurrentState == state)
                     objects.Add(trackedObject.CurrentObject);
             }
             return objects;
-        } 
+        }
 
         protected abstract TrackedT createTrackedObject(T detectedObject);
     }
-}
+}

+ 0 - 0
bbiwarg/Server/OSC.NET/OSCBundle.cs → bbiwarg/TUIO/OSC.NET/OSCBundle.cs


+ 0 - 0
bbiwarg/Server/OSC.NET/OSCMessage.cs → bbiwarg/TUIO/OSC.NET/OSCMessage.cs


+ 0 - 0
bbiwarg/Server/OSC.NET/OSCPacket.cs → bbiwarg/TUIO/OSC.NET/OSCPacket.cs


+ 0 - 0
bbiwarg/Server/OSC.NET/OSCTransmitter.cs → bbiwarg/TUIO/OSC.NET/OSCTransmitter.cs


+ 0 - 0
bbiwarg/Server/TUIO/TuioContainer.cs → bbiwarg/TUIO/TUIO/TuioContainer.cs


+ 0 - 0
bbiwarg/Server/TUIO/TuioCursor.cs → bbiwarg/TUIO/TUIO/TuioCursor.cs


+ 0 - 0
bbiwarg/Server/TUIO/TuioPoint.cs → bbiwarg/TUIO/TUIO/TuioPoint.cs


+ 0 - 3
bbiwarg/Server/TUIO/TuioServer.cs → bbiwarg/TUIO/TUIO/TuioServer.cs

@@ -133,9 +133,6 @@ namespace TUIO
                     addAliveMessagesToBundle(packet);
                 }*/
                 packet.Append(currentMessage);
-
-                Logger.log("Send Cursor " + cursor.getSessionID() + " at time " + TuioTime.getSystemTime().ToString(), LogSubject.TUIOServer);
-
             }
             currentMessage = new OSCMessage("/tuio/2Dcur");
             currentMessage.Append("fseq");

+ 0 - 0
bbiwarg/Server/TUIO/TuioTime.cs → bbiwarg/TUIO/TUIO/TuioTime.cs


+ 23 - 24
bbiwarg/Server/TuioCommunicator.cs → bbiwarg/TUIO/TuioCommunicator.cs

@@ -7,9 +7,10 @@ using System.Net;
 using System.Net.Sockets;
 using bbiwarg.Recognition.TouchRecognition;
 using bbiwarg.Utility;
+using bbiwarg.Input.InputHandling;
 using TUIO;
 
-namespace bbiwarg.Server
+namespace bbiwarg.TUIO
 {
     class TuioCommunicator
     {
@@ -22,21 +23,29 @@ namespace bbiwarg.Server
             cursors = new Dictionary<int, TuioCursor>();
         }
 
-        public void touchDown(object sender, TouchEventArgs tea)
+        public void handleNewFrameData(InputHandler sender, EventArgs e)
         {
-            TuioCursor cursor = server.addTuioCursor(tea.RelativePosition.X, tea.RelativePosition.Y);
-            cursors.Add(tea.TrackID, cursor);
-        }
-
-        public void touchMove(object sender, TouchEventArgs tea)
-        {
-            server.updateTuioCursor(cursors[tea.TrackID], tea.RelativePosition.X, tea.RelativePosition.Y);
-        }
+            server.initFrame();
+            FrameData frameData = sender.FrameData;
+            lock (frameData) {
+                foreach (TouchEventArgs te in frameData.TouchEvents) {
+                    switch (te.Type) {
+                        case TouchEventType.Down:
+                            TuioCursor cursor = server.addTuioCursor(te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
+                            cursors.Add(te.TrackID, cursor);
+                            break;
+                        case TouchEventType.Move:
+                            server.updateTuioCursor(cursors[te.TrackID], te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
+                            break;
+                        case TouchEventType.Up:
+                            server.removeTuioCursor(cursors[te.TrackID]);
+                            cursors.Remove(te.TrackID);
+                            break;
+                    }
+                }
+            }
 
-        public void touchUp(object sender, TouchEventArgs tea)
-        {
-            server.removeTuioCursor(cursors[tea.TrackID]);
-            cursors.Remove(tea.TrackID);
+            server.commitFrame();
         }
 
         public void close()
@@ -44,16 +53,6 @@ namespace bbiwarg.Server
             server.close();
         }
 
-        public void initFrame()
-        {
-            server.initFrame();
-        }
-
-        public void commitFrame()
-        {
-            server.commitFrame();
-        }
-
         public void reset()
         {
             foreach (int id in cursors.Keys)

+ 1 - 1
bbiwarg/Utility/ConvexityDefect.cs

@@ -8,7 +8,7 @@ using Emgu.CV.Structure;
 
 namespace bbiwarg.Utility
 {
-    class ConvexityDefect
+    public class ConvexityDefect
     {
         public Vector2D OuterShort { get; private set; }
         public Vector2D OuterLong { get; private set; }

+ 1 - 1
bbiwarg/Utility/Line2D.cs

@@ -13,7 +13,7 @@ namespace bbiwarg.Utility
         below = 2
     }
 
-    class Line2D
+    public class Line2D
     {
         public Vector2D PointOnLine { get; private set; }
         public Vector2D Direction { get; private set; }

+ 1 - 1
bbiwarg/Utility/LineSegment2D.cs

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
 namespace bbiwarg.Utility
 {
 
-    class LineSegment2D
+    public class LineSegment2D
     {
         public Vector2D P1 { get; private set; }
         public Vector2D P2 { get; private set; }

+ 6 - 12
bbiwarg/Utility/Logger.cs

@@ -16,26 +16,20 @@ namespace bbiwarg.Utility
         TouchDetector = 16,
         TouchTracker = 32,
         TUIOServer = 64,
-        Timer = 128,
-        TouchEvents = 256,
-        VideoControls = 512,
-        HandTracker = 1024,
-        PalmTracker = 2048
+        TouchEvents = 128,
+        VideoControls = 256,
+        HandTracker = 512,
+        PalmTracker = 1024
     }
+
     static class Logger
     {
         public static int CurrentFrame { get; set; }
 
         public static void log(string message, LogSubject subject)
         {
-            if (Parameters.LogLevel.HasFlag(subject))
+            if (Parameters.EnabledLogSubjects.HasFlag(subject))
                 Console.WriteLine("Frame: " + CurrentFrame + "\t" + message);
         }
-
-        public static void clear(LogSubject subject)
-        {
-            if (Parameters.LogLevel.HasFlag(subject))
-                Console.Clear();
-        }
     }
 }

+ 1 - 1
bbiwarg/Utility/Quadrangle.cs

@@ -13,7 +13,7 @@ using Emgu.CV.Structure;
 
 namespace bbiwarg.Utility
 {
-    class Quadrangle
+    public class Quadrangle
     {
         public Vector2D TopLeft { get; private set; }
         public Vector2D TopRight { get; private set; }

+ 40 - 27
bbiwarg/Utility/Timer.cs

@@ -9,53 +9,66 @@ namespace bbiwarg.Utility
 {
     class Timer
     {
+        private static Object sync = new object();
         private static Dictionary<String, Stopwatch> stopwatches = new Dictionary<string, Stopwatch>();
         private static Dictionary<String, double> currentTimes = new Dictionary<string, double>();
         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>();
+        private static int maxNameLength = 1;
 
         public static void start(String name)
         {
-            if (!stopwatches.ContainsKey(name))
+            lock (sync)
             {
-                stopwatches.Add(name, new Stopwatch());
-                minTimes.Add(name, int.MaxValue);
-                maxTimes.Add(name, 0);
-                sumTimes.Add(name, 0);
-                numTimes.Add(name, 0);
-                currentTimes.Add(name, 0);
+                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);
+                    currentTimes.Add(name, 0);
+                    maxNameLength = Math.Max(maxNameLength, name.Length);
+                }
+                stopwatches[name].Restart();
             }
-            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]++;
-            currentTimes[name] = time;
-        }
-
-        public static void output(String name)
-        {
-            Logger.log(String.Format("name:{0}\tavg:{1:00.00}\tcurrent:{2:00.00}",
-                name, sumTimes[name] / Math.Max(numTimes[name], 1), currentTimes[name]), LogSubject.Timer);
+            lock (sync)
+            {
+                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]++;
+                currentTimes[name] = time;
+            }
         }
-
         public static void outputAll()
         {
-            Logger.clear(LogSubject.Timer);
-            Logger.log("---TIMERS-START---", LogSubject.Timer);
-            foreach (String name in stopwatches.Keys)
+            lock (sync)
             {
-                output(name);
+                StringBuilder divider = new StringBuilder();
+                divider.Append("├-");
+                divider.Append(new String('-', maxNameLength));
+                divider.Append("-┼-------┼-------┤");
+
+                Console.Clear();
+                Console.WriteLine(String.Format("| {0,-" + maxNameLength + "} | {1,-5} | {2,-5} |", "NAME", "AVG.", "CUR."));
+                Console.WriteLine(divider.ToString());
+                foreach (String name in stopwatches.Keys)
+                {
+                    double average = sumTimes[name] / Math.Max(numTimes[name], 1);
+                    double current = currentTimes[name];
+
+                    Console.WriteLine(String.Format("| {0,-" + maxNameLength + "} | {1:00.00} | {2:00.00} |", name, average, current));
+                }
             }
-            Logger.log("---TIMERS-END---", LogSubject.Timer);
         }
 
     }

+ 22 - 21
bbiwarg/bbiwarg.csproj

@@ -49,7 +49,7 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup>
-    <StartupObject>bbiwarg.MainBBIWARG</StartupObject>
+    <StartupObject>bbiwarg.BBIWARG</StartupObject>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="Emgu.CV, Version=2.4.2.1777, Culture=neutral, PublicKeyToken=7281126722ab4438, processorArchitecture=MSIL">
@@ -81,12 +81,13 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Input\InputHandling\FrameData.cs" />
+    <Compile Include="Output\DebugOutput\DebugImages.cs" />
     <Compile Include="Parameters.cs" />
-    <Compile Include="Graphics\OutputWindow.cs" />
-    <Compile Include="InputHandler.cs" />
-    <Compile Include="InputProviders\InputFrame.cs" />
-    <Compile Include="InputProviders\InputProvider.cs" />
-    <Compile Include="InputProviders\VideoInputProvider.cs" />
+    <Compile Include="Output\DebugOutput\DebugWindow.cs" />
+    <Compile Include="Input\InputHandling\InputHandler.cs" />
+    <Compile Include="Input\InputProviding\InputProvider.cs" />
+    <Compile Include="Input\InputProviding\VideoInputProvider.cs" />
     <Compile Include="Recognition\FingerRecognition\Finger.cs" />
     <Compile Include="Recognition\FingerRecognition\FingerDetector.cs" />
     <Compile Include="Recognition\FingerRecognition\FingerSliceTrail.cs" />
@@ -102,31 +103,31 @@
     <Compile Include="Recognition\PalmRecognition\PalmTracker.cs" />
     <Compile Include="Recognition\PalmRecognition\TrackedPalm.cs" />
     <Compile Include="Recognition\TouchRecognition\TouchDetector.cs" />
-    <Compile Include="Recognition\TouchRecognition\TouchEvent.cs" />
+    <Compile Include="Recognition\TouchRecognition\Touch.cs" />
     <Compile Include="Recognition\TouchRecognition\TouchTracker.cs" />
-    <Compile Include="Graphics\TouchEventVisualizer.cs" />
+    <Compile Include="Output\DebugOutput\TouchEventVisualizer.cs" />
     <Compile Include="Images\ConfidenceImage.cs" />
     <Compile Include="Images\DepthImage.cs" />
     <Compile Include="Images\EdgeImage.cs" />
-    <Compile Include="Graphics\OutputImage.cs" />
-    <Compile Include="MainBBWIWARG.cs" />
+    <Compile Include="Output\OutputImage.cs" />
+    <Compile Include="BBWIWARG.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Recognition\TouchRecognition\TrackedTouchEvent.cs" />
+    <Compile Include="Recognition\TouchRecognition\TrackedTouch.cs" />
     <Compile Include="Recognition\Tracking\Similarity.cs" />
     <Compile Include="Recognition\Tracking\TrackableObject.cs" />
     <Compile Include="Recognition\Tracking\TrackedObject.cs" />
     <Compile Include="Recognition\Tracking\Tracker.cs" />
     <Compile Include="Recognition\Tracking\TrackIDPool.cs" />
-    <Compile Include="Server\OSC.NET\OSCBundle.cs" />
-    <Compile Include="Server\OSC.NET\OSCMessage.cs" />
-    <Compile Include="Server\OSC.NET\OSCPacket.cs" />
-    <Compile Include="Server\OSC.NET\OSCTransmitter.cs" />
-    <Compile Include="Server\TuioCommunicator.cs" />
-    <Compile Include="Server\TUIO\TuioContainer.cs" />
-    <Compile Include="Server\TUIO\TuioCursor.cs" />
-    <Compile Include="Server\TUIO\TuioPoint.cs" />
-    <Compile Include="Server\TUIO\TuioServer.cs" />
-    <Compile Include="Server\TUIO\TuioTime.cs" />
+    <Compile Include="TUIO\OSC.NET\OSCBundle.cs" />
+    <Compile Include="TUIO\OSC.NET\OSCMessage.cs" />
+    <Compile Include="TUIO\OSC.NET\OSCPacket.cs" />
+    <Compile Include="TUIO\OSC.NET\OSCTransmitter.cs" />
+    <Compile Include="TUIO\TuioCommunicator.cs" />
+    <Compile Include="TUIO\TUIO\TuioContainer.cs" />
+    <Compile Include="TUIO\TUIO\TuioCursor.cs" />
+    <Compile Include="TUIO\TUIO\TuioPoint.cs" />
+    <Compile Include="TUIO\TUIO\TuioServer.cs" />
+    <Compile Include="TUIO\TUIO\TuioTime.cs" />
     <Compile Include="Utility\ConvexityDefect.cs" />
     <Compile Include="Utility\Kalman2DPositionFilter.cs" />
     <Compile Include="Utility\Line2D.cs" />