Browse Source

-replaced openTK with windows forms
-implemented video+grid controls in debugWindow
-added moveRestartEvent to videoInputProvider (inputhandler needs reset on restart)
-moved calculate similarity to trackers instead of trackedObjects
-removed image-parameters (values are read from inputprovider an passed along) same with palmGrid and tuio ip&port

Alexander Hendrich 11 years ago
parent
commit
992fd14c4f
42 changed files with 1530 additions and 837 deletions
  1. 46 44
      bbiwarg/BBWIWARG.cs
  2. 5 2
      bbiwarg/Images/ConfidenceImage.cs
  3. 4 2
      bbiwarg/Images/DepthImage.cs
  4. 6 3
      bbiwarg/Images/EdgeImage.cs
  5. 4 1
      bbiwarg/Input/InputHandling/FrameData.cs
  6. 45 11
      bbiwarg/Input/InputHandling/InputHandler.cs
  7. 11 12
      bbiwarg/Input/InputProviding/InputProvider.cs
  8. 16 4
      bbiwarg/Input/InputProviding/VideoInputProvider.cs
  9. 141 0
      bbiwarg/Output/DebugOutput/DebugImageCreator.cs
  10. 0 162
      bbiwarg/Output/DebugOutput/DebugImages.cs
  11. 302 0
      bbiwarg/Output/DebugOutput/DebugWindow.Designer.cs
  12. 100 151
      bbiwarg/Output/DebugOutput/DebugWindow.cs
  13. 120 0
      bbiwarg/Output/DebugOutput/DebugWindow.resx
  14. 87 83
      bbiwarg/Output/DebugOutput/TouchEventVisualizer.cs
  15. 68 0
      bbiwarg/Output/GlassesOutput/GlassesWindow.Designer.cs
  16. 114 105
      bbiwarg/Output/GlassesOutput/GlassesWindow.cs
  17. 120 0
      bbiwarg/Output/GlassesOutput/GlassesWindow.resx
  18. 30 24
      bbiwarg/Output/OutputImage.cs
  19. 16 56
      bbiwarg/Parameters.cs
  20. 7 7
      bbiwarg/Recognition/FingerRecognition/FingerDetector.cs
  21. 5 4
      bbiwarg/Recognition/FingerRecognition/FingerSliceTrail.cs
  22. 25 1
      bbiwarg/Recognition/FingerRecognition/FingerTracker.cs
  23. 1 21
      bbiwarg/Recognition/FingerRecognition/TrackedFinger.cs
  24. 4 3
      bbiwarg/Recognition/HandRecognition/Hand.cs
  25. 6 6
      bbiwarg/Recognition/HandRecognition/HandDetector.cs
  26. 11 0
      bbiwarg/Recognition/HandRecognition/HandTracker.cs
  27. 0 7
      bbiwarg/Recognition/HandRecognition/TrackedHand.cs
  28. 13 13
      bbiwarg/Recognition/PalmRecognition/PalmDetector.cs
  29. 19 1
      bbiwarg/Recognition/PalmRecognition/PalmTracker.cs
  30. 0 13
      bbiwarg/Recognition/PalmRecognition/TrackedPalm.cs
  31. 4 5
      bbiwarg/Recognition/TouchRecognition/TouchDetector.cs
  32. 27 0
      bbiwarg/Recognition/TouchRecognition/TouchEvent.cs
  33. 18 9
      bbiwarg/Recognition/TouchRecognition/TouchTracker.cs
  34. 7 39
      bbiwarg/Recognition/TouchRecognition/TrackedTouch.cs
  35. 0 9
      bbiwarg/Recognition/Tracking/TrackedObject.cs
  36. 17 3
      bbiwarg/Recognition/Tracking/Tracker.cs
  37. 27 14
      bbiwarg/TUIO/TuioCommunicator.cs
  38. 27 0
      bbiwarg/Utility/ImageSize.cs
  39. 1 1
      bbiwarg/Utility/Logger.cs
  40. 40 11
      bbiwarg/Utility/Projection2DTo2D.cs
  41. 7 7
      bbiwarg/Utility/Vector2D.cs
  42. 29 3
      bbiwarg/bbiwarg.csproj

+ 46 - 44
bbiwarg/BBWIWARG.cs

@@ -5,6 +5,8 @@ using System.Threading;
 using System.Linq;
 using System.Linq;
 using System.Text;
 using System.Text;
 using System.Net;
 using System.Net;
+using System.Windows;
+using System.Windows.Forms;
 using bbiwarg.Output.DebugOutput;
 using bbiwarg.Output.DebugOutput;
 using bbiwarg.Output.GlassesOutput;
 using bbiwarg.Output.GlassesOutput;
 using bbiwarg.Input.InputProviding;
 using bbiwarg.Input.InputProviding;
@@ -15,52 +17,54 @@ namespace bbiwarg
 {
 {
     class BBIWARG
     class BBIWARG
     {
     {
-        InputProvider inputProvider;
-        InputHandler inputHandler;
-        TuioCommunicator tuioCommunicator;
-        DebugWindow debugWindow;
-        GlassesWindow glassesWindow;
+        private InputProvider inputProvider;
+        private InputHandler inputHandler;
 
 
-        Thread debugOutputThread;
-        Thread glassesOutputThread;
+        private bool tuioEnabled;
+        private String tuioIP;
+        private Int16 tuioPort;
+        private TuioCommunicator tuioCommunicator;
+
+        private DebugWindow debugWindow;
+        private GlassesWindow glassesWindow;
+
+        private Thread debugWindowThread;
+        private Thread glassesWindowThread;
 
 
         static void Main(string[] args)
         static void Main(string[] args)
         {
         {
             Console.SetWindowSize(Parameters.ConsoleWidth, Parameters.ConsoleHeight);
             Console.SetWindowSize(Parameters.ConsoleWidth, Parameters.ConsoleHeight);
-            handleArgs(args);
 
 
-            BBIWARG program = new BBIWARG();
+            BBIWARG program = new BBIWARG(args);
             program.run();
             program.run();
         }
         }
 
 
-        public BBIWARG()
+        public BBIWARG(string[] args)
         {
         {
+            handleArgs(args);
+
             // inputProvider
             // inputProvider
             createInputProvider();
             createInputProvider();
+            inputProvider.initialize();
             inputProvider.DeviceStartedEvent += handleDeviceStartedEvent;
             inputProvider.DeviceStartedEvent += handleDeviceStartedEvent;
 
 
             // inputHandler
             // inputHandler
-            inputHandler = new InputHandler();
-            inputProvider.NewFrameEvent += inputHandler.handleNewFrame;
+            inputHandler = new InputHandler(inputProvider);
 
 
             // tuioCommunicator
             // tuioCommunicator
-            if (Parameters.TuioEnabled)
+            if (tuioEnabled)
             {
             {
-                tuioCommunicator = new TuioCommunicator(Parameters.TuioIP.ToString(), Parameters.TuioPort);
+                tuioCommunicator = new TuioCommunicator(tuioIP, tuioPort);
                 inputHandler.NewProcessedFrameEvent += tuioCommunicator.handleNewFrameData;
                 inputHandler.NewProcessedFrameEvent += tuioCommunicator.handleNewFrameData;
             }
             }
 
 
             // debug output
             // debug output
             if (Parameters.DebugWindowEnabled)
             if (Parameters.DebugWindowEnabled)
-            {
-                debugOutputThread = new Thread(new ThreadStart(debugOutputThreadStart));
-            }
+                debugWindowThread = new Thread(new ThreadStart(debugWindowThreadStart));
 
 
             // glasses output
             // glasses output
             if (Parameters.GlassesWindowEnabled)
             if (Parameters.GlassesWindowEnabled)
-            {
-                glassesOutputThread = new Thread(new ThreadStart(glassesOutputThreadStart));
-            }
+                glassesWindowThread = new Thread(new ThreadStart(glassesWindowThreadStart));
 
 
         }
         }
 
 
@@ -77,38 +81,32 @@ namespace bbiwarg
                 inputProvider = new InputProvider();
                 inputProvider = new InputProvider();
         }
         }
 
 
-        private void debugOutputThreadStart()
+        private void debugWindowThreadStart()
         {
         {
-            debugWindow = new DebugWindow(inputProvider, inputHandler);
-            debugWindow.Run(Parameters.DebugWindowUpdateRate, Parameters.DebugWindowRenderRate);
+            debugWindow = new DebugWindow(inputProvider, inputHandler, Parameters.DebugWindowTitle, Parameters.DebugWindowUpdateIntervall);
+            Application.Run(debugWindow);
         }
         }
 
 
-        private void glassesOutputThreadStart()
+        private void glassesWindowThreadStart()
         {
         {
-            glassesWindow = new GlassesWindow(inputProvider, inputHandler);
-            glassesWindow.Run(Parameters.GlassesWindowUpdateRate, Parameters.GlassesWindowRenderRate);
+            glassesWindow = new GlassesWindow(inputProvider, inputHandler, Parameters.GlassesWindowTitle, Parameters.GlassesWindowOutputSize, Parameters.GlassesWindowUpdateInterval);
+            Application.Run(glassesWindow);
         }
         }
 
 
         private void handleDeviceStartedEvent(object sender, EventArgs e)
         private void handleDeviceStartedEvent(object sender, EventArgs e)
-        {
-            startOutputThreads();
-        }
-
-        private void startOutputThreads()
         {
         {
             if (Parameters.DebugWindowEnabled)
             if (Parameters.DebugWindowEnabled)
-                debugOutputThread.Start();
+                debugWindowThread.Start();
 
 
             if (Parameters.GlassesWindowEnabled)
             if (Parameters.GlassesWindowEnabled)
-                glassesOutputThread.Start();
+                glassesWindowThread.Start();
         }
         }
 
 
-        private static void handleArgs(String[] args)
+        private void handleArgs(String[] args)
         {
         {
             if (args.Length > 0)
             if (args.Length > 0)
             {
             {
-                IPAddress ipAddress;
-                Int16 port;
+                tuioEnabled = true;
                 String ipString = null;
                 String ipString = null;
                 String portString = null;
                 String portString = null;
                 if (args.Length == 2)
                 if (args.Length == 2)
@@ -124,21 +122,25 @@ namespace bbiwarg
                         portString = parts[1];
                         portString = parts[1];
                 }
                 }
 
 
-                while (!TuioCommunicator.tryParseIPAddress(ipString, out ipAddress))
+                while (!TuioCommunicator.tryParseIPAddress(ipString, out tuioIP))
                 {
                 {
-                    Console.WriteLine("Please insert the TUIO-Client's IP (Default is 127.0.0.1):");
+                    Console.WriteLine("Please insert the TUIO-Client's IP (Default is " + Parameters.TuioDefaultIP + "):");
                     ipString = Console.ReadLine();
                     ipString = Console.ReadLine();
                 }
                 }
-                Console.WriteLine("TUIO-IP is set to:" + Parameters.TuioIP.ToString());
+                Console.WriteLine("TUIO-IP is set to:" + tuioIP);
 
 
-                while (!TuioCommunicator.tryParsePort(portString, out port))
+                while (!TuioCommunicator.tryParsePort(portString, out tuioPort))
                 {
                 {
-                    Console.WriteLine("Please insert the TUIO-Client's Port (Default is 3333):");
+                    Console.WriteLine("Please insert the TUIO-Client's Port (Default is " + Parameters.TuioDefaultPort + "):");
                     portString = Console.ReadLine();
                     portString = Console.ReadLine();
                 }
                 }
-                Console.WriteLine("TUIO-PORT is set to:" + Parameters.TuioPort);
-
-                Parameters.setTuioParameters(true, ipAddress, port);
+                Console.WriteLine("TUIO-PORT is set to:" + tuioPort);
+            }
+            else
+            {
+                tuioEnabled = Parameters.TuioEnabledByDefault;
+                tuioIP = Parameters.TuioDefaultIP;
+                tuioPort = Parameters.TuioDefaultPort;
             }
             }
         }
         }
     }
     }

+ 5 - 2
bbiwarg/Images/ConfidenceImage.cs

@@ -7,17 +7,20 @@ using bbiwarg.Images;
 using bbiwarg.Output;
 using bbiwarg.Output;
 using Emgu.CV;
 using Emgu.CV;
 using Emgu.CV.Structure;
 using Emgu.CV.Structure;
+using bbiwarg.Utility;
 
 
 namespace bbiwarg.Images
 namespace bbiwarg.Images
 {
 {
     public class ConfidenceImage
     public class ConfidenceImage
     {
     {
+        public ImageSize Size { get; private set; }
         public Image<Gray, Int16> Image { get; private set; }
         public Image<Gray, Int16> Image { get; private set; }
         public Image<Gray, byte> Mask { get; private set; }
         public Image<Gray, byte> Mask { get; private set; }
 
 
-        public ConfidenceImage(IntPtr rawConfidenceData, int width, int height)
+        public ConfidenceImage(IntPtr rawConfidenceData, ImageSize size)
         {
         {
-            Image = new Image<Gray, Int16>(width, height, width * 2, rawConfidenceData);
+            Size = size;
+            Image = new Image<Gray, Int16>(Size.Width, Size.Height, size.Width * 2, rawConfidenceData);
 
 
             Mask = (Image.ThresholdBinary(new Gray(Parameters.ConfidenceImageMinThreshold), new Gray(1))).Convert<Gray, byte>();
             Mask = (Image.ThresholdBinary(new Gray(Parameters.ConfidenceImageMinThreshold), new Gray(1))).Convert<Gray, byte>();
         }
         }

+ 4 - 2
bbiwarg/Images/DepthImage.cs

@@ -16,14 +16,16 @@ namespace bbiwarg.Images
 {
 {
     public class DepthImage
     public class DepthImage
     {
     {
+        public ImageSize Size { get; private set; }
         public Image<Gray, byte> Image { get; private set; }
         public Image<Gray, byte> Image { get; private set; }
         public Image<Gray, byte> BackgroundMask { get; private set; }
         public Image<Gray, byte> BackgroundMask { get; private set; }
         public Int16 MinDepth { get; private set; }
         public Int16 MinDepth { get; private set; }
         public Int16 MaxDepth { get; private set; }
         public Int16 MaxDepth { get; private set; }
 
 
-        public DepthImage(IntPtr rawDepthData, int width, int height, ConfidenceImage confidenceImage)
+        public DepthImage(IntPtr rawDepthData, ImageSize size, ConfidenceImage confidenceImage)
         {
         {
-            Image<Gray, Int16> rawDepthImage = new Image<Gray, Int16>(width, height, width * 2, rawDepthData);
+            Size = size;
+            Image<Gray, Int16> rawDepthImage = new Image<Gray, Int16>(Size.Width, Size.Height, Size.Width * 2, rawDepthData);
 
 
             // filter with confidenceImage mask
             // filter with confidenceImage mask
             rawDepthImage = rawDepthImage.Or((1 - confidenceImage.Mask).Convert<Gray, Int16>().Mul(Int16.MaxValue));
             rawDepthImage = rawDepthImage.Or((1 - confidenceImage.Mask).Convert<Gray, Int16>().Mul(Int16.MaxValue));

+ 6 - 3
bbiwarg/Images/EdgeImage.cs

@@ -8,17 +8,20 @@ namespace bbiwarg.Images
 {
 {
     public class EdgeImage
     public class EdgeImage
     {
     {
+        public ImageSize Size { get; private set; }
         public Image<Gray, Byte> Image { get; private set; }
         public Image<Gray, Byte> Image { get; private set; }
         public Image<Gray, byte> RoughImage { get; private set; }
         public Image<Gray, byte> RoughImage { get; private set; }
 
 
         public EdgeImage(DepthImage depthImage)
         public EdgeImage(DepthImage depthImage)
         {
         {
+            Size = depthImage.Size;
             Image = depthImage.Image.ConvertScale<byte>(255f / (depthImage.MaxDepth - depthImage.MinDepth), 0).Canny(Parameters.EdgeImageCannyStartThreshold, Parameters.EdgeImageCannyLinkingThreshold, Parameters.EdgeImageCannySize).ThresholdBinary(new Gray(0), new Gray(1));
             Image = depthImage.Image.ConvertScale<byte>(255f / (depthImage.MaxDepth - depthImage.MinDepth), 0).Canny(Parameters.EdgeImageCannyStartThreshold, Parameters.EdgeImageCannyLinkingThreshold, Parameters.EdgeImageCannySize).ThresholdBinary(new Gray(0), new Gray(1));
             RoughImage = Image.Dilate(Parameters.EdgeImageRoughNumDilationIterations);
             RoughImage = Image.Dilate(Parameters.EdgeImageRoughNumDilationIterations);
         }
         }
 
 
-        public EdgeImage(Image<Gray, Byte> edgeImage, Image<Gray, Byte> roughEdgeImage)
+        public EdgeImage(Image<Gray, Byte> edgeImage, Image<Gray, Byte> roughEdgeImage, ImageSize size)
         {
         {
+            Size = size;
             Image = edgeImage;
             Image = edgeImage;
             RoughImage = roughEdgeImage;
             RoughImage = roughEdgeImage;
         }
         }
@@ -51,7 +54,7 @@ namespace bbiwarg.Images
 
 
         public Vector2D findNextRoughEdge(Vector2D start, Vector2D direction, int maxSearchSize = 0)
         public Vector2D findNextRoughEdge(Vector2D start, Vector2D direction, int maxSearchSize = 0)
         {
         {
-            Vector2D maxGrow = (Parameters.ImageMaxPixel - start) / direction;
+            Vector2D maxGrow = (Size.MaxPixel - start) / direction;
             Vector2D maxDecline = start / direction.getAbsolute();
             Vector2D maxDecline = start / direction.getAbsolute();
 
 
             int maxStepsX;
             int maxStepsX;
@@ -89,7 +92,7 @@ namespace bbiwarg.Images
 
 
         public EdgeImage copy()
         public EdgeImage copy()
         {
         {
-            return new EdgeImage(Image.Copy(), RoughImage.Copy());
+            return new EdgeImage(Image.Copy(), RoughImage.Copy(), Size);
         }
         }
     }
     }
 }
 }

+ 4 - 1
bbiwarg/Input/InputHandling/FrameData.cs

@@ -8,12 +8,15 @@ using bbiwarg.Recognition.FingerRecognition;
 using bbiwarg.Recognition.HandRecognition;
 using bbiwarg.Recognition.HandRecognition;
 using bbiwarg.Recognition.PalmRecognition;
 using bbiwarg.Recognition.PalmRecognition;
 using bbiwarg.Recognition.TouchRecognition;
 using bbiwarg.Recognition.TouchRecognition;
+using bbiwarg.Utility;
 
 
 namespace bbiwarg.Input.InputHandling
 namespace bbiwarg.Input.InputHandling
 {
 {
     public class FrameData
     public class FrameData
     {
     {
         public int FrameID { get; set; }
         public int FrameID { get; set; }
+        public ImageSize ImageSize { get; set; }
+        public bool ResetFlag { get; set; }
 
 
         // images
         // images
         public DepthImage DepthImage { get; set; }
         public DepthImage DepthImage { get; set; }
@@ -35,7 +38,7 @@ namespace bbiwarg.Input.InputHandling
         // touch
         // touch
         public List<Touch> DetectedTouches { get; set; }
         public List<Touch> DetectedTouches { get; set; }
         public List<Touch> TrackedTouches { get; set; }
         public List<Touch> TrackedTouches { get; set; }
-        public List<TouchEventArgs> TouchEvents { get; set; }
+        public List<TouchEvent> TouchEvents { get; set; }
 
 
     }
     }
 }
 }

+ 45 - 11
bbiwarg/Input/InputHandling/InputHandler.cs

@@ -9,10 +9,23 @@ using System;
 
 
 namespace bbiwarg.Input.InputHandling
 namespace bbiwarg.Input.InputHandling
 {
 {
-    public delegate void NewProcessedFrameEventHandler(InputHandler sender, EventArgs e);
+    public delegate void NewProcessedFrameEventHandler(object sender, NewProcessedFrameEventArgs e);
+
+    public class NewProcessedFrameEventArgs
+    {
+        public FrameData FrameData { get; private set; }
+
+        public NewProcessedFrameEventArgs(FrameData frameData)
+        {
+            FrameData = frameData;
+        }
+    }
 
 
     public class InputHandler
     public class InputHandler
     {
     {
+        private InputProvider inputProvider;
+        private bool resetFlag;
+
         private FingerDetector fingerDetector;
         private FingerDetector fingerDetector;
         private HandDetector handDetector;
         private HandDetector handDetector;
         private PalmDetector palmDetector;
         private PalmDetector palmDetector;
@@ -23,26 +36,36 @@ namespace bbiwarg.Input.InputHandling
         private PalmTracker palmTracker;
         private PalmTracker palmTracker;
         private TouchTracker touchTracker;
         private TouchTracker touchTracker;
 
 
+        public ImageSize ImageSize;
         public FrameData FrameData { get; private set; }
         public FrameData FrameData { get; private set; }
 
 
         public event NewProcessedFrameEventHandler NewProcessedFrameEvent;
         public event NewProcessedFrameEventHandler NewProcessedFrameEvent;
 
 
-        public InputHandler()
+        public InputHandler(InputProvider inputProvider)
         {
         {
+            this.inputProvider = inputProvider;
             initialize();
             initialize();
+
+            inputProvider.NewFrameEvent += handleNewFrame;
+            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
+            if (videoInputProvider != null)
+                videoInputProvider.MovieRestartedEvent += handleMovieRestart;
         }
         }
 
 
         private void initialize()
         private void initialize()
         {
         {
+            ImageSize = new ImageSize(inputProvider.ImageWidth, inputProvider.ImageHeight);
+            resetFlag = false;
+
             fingerDetector = new FingerDetector();
             fingerDetector = new FingerDetector();
             handDetector = new HandDetector();
             handDetector = new HandDetector();
             palmDetector = new PalmDetector();
             palmDetector = new PalmDetector();
             touchDetector = new TouchDetector();
             touchDetector = new TouchDetector();
 
 
-            fingerTracker = new FingerTracker();
-            handTracker = new HandTracker();
-            palmTracker = new PalmTracker();
-            touchTracker = new TouchTracker();
+            fingerTracker = new FingerTracker(ImageSize);
+            handTracker = new HandTracker(ImageSize);
+            palmTracker = new PalmTracker(ImageSize);
+            touchTracker = new TouchTracker(ImageSize);
         }
         }
 
 
         public void reset()
         public void reset()
@@ -60,15 +83,20 @@ namespace bbiwarg.Input.InputHandling
             FrameData frameData = new FrameData();
             FrameData frameData = new FrameData();
 
 
             frameData.FrameID = e.FrameID;
             frameData.FrameID = e.FrameID;
+            frameData.ImageSize = ImageSize;
+
+            // reset flag
+            frameData.ResetFlag = resetFlag;
+            resetFlag = false;
 
 
             // confidence image
             // confidence image
             Timer.start("InputHandler.handleNewFrame::createConfidenceImage");
             Timer.start("InputHandler.handleNewFrame::createConfidenceImage");
-            frameData.ConfidenceImage = new ConfidenceImage(e.RawConfidenceData, e.Width, e.Height);
+            frameData.ConfidenceImage = new ConfidenceImage(e.RawConfidenceData, ImageSize);
             Timer.stop("InputHandler.handleNewFrame::createConfidenceImage");
             Timer.stop("InputHandler.handleNewFrame::createConfidenceImage");
 
 
             // depth image
             // depth image
             Timer.start("InputHandler.handleNewFrame::createDepthImage");
             Timer.start("InputHandler.handleNewFrame::createDepthImage");
-            frameData.DepthImage = new DepthImage(e.RawDepthData, e.Width, e.Height, frameData.ConfidenceImage);
+            frameData.DepthImage = new DepthImage(e.RawDepthData, ImageSize, frameData.ConfidenceImage);
             Timer.stop("InputHandler.handleNewFrame::createDepthImage");
             Timer.stop("InputHandler.handleNewFrame::createDepthImage");
 
 
             // edge image
             // edge image
@@ -120,13 +148,19 @@ namespace bbiwarg.Input.InputHandling
             Timer.start("InputHandler.handleNewFrame::exportResults");
             Timer.start("InputHandler.handleNewFrame::exportResults");
             FrameData = frameData;
             FrameData = frameData;
             if (NewProcessedFrameEvent != null)
             if (NewProcessedFrameEvent != null)
-                NewProcessedFrameEvent(this, new EventArgs());
+                NewProcessedFrameEvent(this, new NewProcessedFrameEventArgs(frameData));
             Timer.stop("InputHandler.handleNewFrame::exportResults");
             Timer.stop("InputHandler.handleNewFrame::exportResults");
 
 
-
             Timer.stop("InputHandler.handleNewFrame");
             Timer.stop("InputHandler.handleNewFrame");
 
 
-            Timer.outputAll();
+            if (Parameters.LoggerTimerOutputEnabled)
+                Timer.outputAll();
+        }
+
+        private void handleMovieRestart(object sender, EventArgs e)
+        {
+            reset();
+            resetFlag = true;
         }
         }
     }
     }
 }
 }

+ 11 - 12
bbiwarg/Input/InputProviding/InputProvider.cs

@@ -29,7 +29,7 @@ namespace bbiwarg.Input.InputProviding
         }
         }
     }
     }
 
 
-    class InputProvider
+    public class InputProvider
     {
     {
         protected IHandle handle;
         protected IHandle handle;
         protected IDevice device;
         protected IDevice device;
@@ -42,6 +42,8 @@ namespace bbiwarg.Input.InputProviding
 
 
         protected int lastFrameID;
         protected int lastFrameID;
 
 
+        public int ImageWidth { get { return imageWidth.Value; } }
+        public int ImageHeight { get { return imageHeight.Value; } }
         public bool IsActive { get; private set; }
         public bool IsActive { get; private set; }
         public virtual int CurrentFrameID { get { return device.FrameId; } }
         public virtual int CurrentFrameID { get { return device.FrameId; } }
 
 
@@ -54,11 +56,14 @@ namespace bbiwarg.Input.InputProviding
             lastFrameID = -1;
             lastFrameID = -1;
         }
         }
 
 
-        public void start()
+        public void initialize()
         {
         {
             createDevice();
             createDevice();
             registerHandles();
             registerHandles();
+        }
 
 
+        public void start()
+        {
             device.Start();
             device.Start();
             IsActive = true;
             IsActive = true;
 
 
@@ -83,7 +88,7 @@ namespace bbiwarg.Input.InputProviding
 
 
         protected virtual IDeviceConfiguration createDeviceConfiguration()
         protected virtual IDeviceConfiguration createDeviceConfiguration()
         {
         {
-            IDeviceConfiguration conf =  handle.CreateDeviceConfiguration();
+            IDeviceConfiguration conf = handle.CreateDeviceConfiguration();
             conf.IsAsynchronous = false;
             conf.IsAsynchronous = false;
             return conf;
             return conf;
         }
         }
@@ -93,7 +98,6 @@ namespace bbiwarg.Input.InputProviding
             imageWidth = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Width");
             imageWidth = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Width");
             imageHeight = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Height");
             imageHeight = device.RegisterParameterHandle<int>("SOURCE.CAMERA.DEPTH.Height");
             frameRate = device.RegisterParameterHandle<float>("SOURCE.FrameRate");
             frameRate = device.RegisterParameterHandle<float>("SOURCE.FrameRate");
-            Parameters.setImageParameters(imageWidth.Value, imageHeight.Value);
 
 
             depthImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.DEPTH.Image");
             depthImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.DEPTH.Image");
             confidenceImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.CONFIDENCE.Image");
             confidenceImage = device.RegisterDataHandle<Iisu.Data.IImageData>("SOURCE.CAMERA.CONFIDENCE.Image");
@@ -105,7 +109,7 @@ namespace bbiwarg.Input.InputProviding
                 nextFrame();
                 nextFrame();
         }
         }
 
 
-        protected void nextFrame()
+        protected virtual void nextFrame()
         {
         {
             device.UpdateFrame(true);
             device.UpdateFrame(true);
             provideNewFrame();
             provideNewFrame();
@@ -114,13 +118,8 @@ namespace bbiwarg.Input.InputProviding
 
 
         protected void provideNewFrame()
         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;
-            }
+            if (NewFrameEvent != null)
+                NewFrameEvent(this, new NewFrameEventArgs(CurrentFrameID, ImageWidth, ImageHeight, depthImage.Value.Raw, confidenceImage.Value.Raw));
         }
         }
     }
     }
 }
 }

+ 16 - 4
bbiwarg/Input/InputProviding/VideoInputProvider.cs

@@ -8,16 +8,19 @@ using bbiwarg.Utility;
 
 
 namespace bbiwarg.Input.InputProviding
 namespace bbiwarg.Input.InputProviding
 {
 {
+    public delegate void MovieRestartedEventHandler(object sender, EventArgs e);
+
     class VideoInputProvider : InputProvider
     class VideoInputProvider : InputProvider
     {
     {
+        private IParameterHandle<int> currentMovieFrame;
+        private IParameterHandle<int> frameCount;
+        private IParameterHandle<int> playStep;
 
 
         public override int CurrentFrameID { get { return currentMovieFrame.Value; } }
         public override int CurrentFrameID { get { return currentMovieFrame.Value; } }
         public String MoviePath { get; private set; }
         public String MoviePath { get; private set; }
         public bool IsPaused { get; private set; }
         public bool IsPaused { get; private set; }
 
 
-        private IParameterHandle<int> currentMovieFrame;
-        private IParameterHandle<int> frameCount;
-        private IParameterHandle<int> playStep;
+        public event MovieRestartedEventHandler MovieRestartedEvent;
 
 
         public VideoInputProvider(String moviePath)
         public VideoInputProvider(String moviePath)
         {
         {
@@ -68,8 +71,17 @@ namespace bbiwarg.Input.InputProviding
                 if (!IsPaused)
                 if (!IsPaused)
                     nextFrame();
                     nextFrame();
                 else
                 else
-                    Thread.Sleep(30);
+                    Thread.Sleep((int)(1000 / frameRate.Value));
             }
             }
         }
         }
+
+        protected override void nextFrame()
+        {
+            base.nextFrame();
+
+            if(CurrentFrameID == 0 && MovieRestartedEvent != null)
+                MovieRestartedEvent(this, new EventArgs());
+
+        }
     }
     }
 }
 }

+ 141 - 0
bbiwarg/Output/DebugOutput/DebugImageCreator.cs

@@ -0,0 +1,141 @@
+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 DebugImageCreator
+    {
+        private TouchEventVisualizer touchEventVisualizer;
+
+        public OutputImage DepthImage { get; private set; }
+        public OutputImage FingerImage { get; private set; }
+        public OutputImage HandImage { get; private set; }
+        public OutputImage PalmImage { get; private set; }
+        public OutputImage TouchImage { get; private set; }
+
+        public DebugImageCreator(TouchEventVisualizer touchEventVisualizer)
+        {
+            this.touchEventVisualizer = touchEventVisualizer;
+        }
+
+        public void updateImages(FrameData frameData, int palmGridNumRows, int palmGridNumColumns)
+        {
+            updateDepthImage(frameData);
+            updateFingerImage(frameData);
+            updateHandImage(frameData);
+            updatePalmImage(frameData, palmGridNumRows, palmGridNumColumns);
+            updateTouchImage(frameData, palmGridNumRows, palmGridNumColumns);
+        }
+
+        private void updateDepthImage(FrameData frameData)
+        {
+            if (DepthImage != null)
+                DepthImage.Dispose();
+
+            DepthImage = new OutputImage(frameData.ImageSize);
+
+            // 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, 5, tipColor);
+                DepthImage.fillCircle(f.HandPoint, 5, handColor);
+            }
+
+            // border
+            DepthImage.drawBorder(Parameters.OutputImageBorderColor);
+        }
+
+        private void updateFingerImage(FrameData frameData)
+        {
+            if (FingerImage != null)
+                FingerImage.Dispose();
+
+            FingerImage = new OutputImage(frameData.ImageSize);
+
+            // 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, f.TrackID.ToString(), Parameters.FingerIDColor);
+            }
+
+            //border
+            FingerImage.drawBorder(Parameters.OutputImageBorderColor);
+        }
+
+        private void updateHandImage(FrameData frameData)
+        {
+            if (HandImage != null)
+                HandImage.Dispose();
+
+            HandImage = new OutputImage(frameData.ImageSize);
+
+            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, 5, Parameters.HandCentroidColor);
+                HandImage.drawText(h.Centroid, h.TrackID.ToString(), Parameters.HandIDColor);
+
+                if (h.Palm != null)
+                    HandImage.drawDefect(h.Palm.ThumbDefect, Parameters.HandThumbDefectPointColor, Parameters.HandThumbDefectLineColor);
+            }
+
+            // border
+            HandImage.drawBorder(Parameters.OutputImageBorderColor);
+        }
+
+        private void updatePalmImage(FrameData frameData, int numRows, int numColumns)
+        {
+            if (PalmImage != null)
+                PalmImage.Dispose();
+
+            PalmImage = new OutputImage(frameData.ImageSize);
+
+            // handMask
+            Image<Gray, byte> handMask = new Image<Gray, byte>(frameData.ImageSize.Width, frameData.ImageSize.Height);
+            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, 5, Parameters.TouchEventTrackedColor);
+
+            foreach (Palm p in frameData.TrackedPalms)
+                PalmImage.drawQuadrangleGrid(p.Quad, Parameters.PalmQuadColor, Parameters.PalmGridColor, numRows, numColumns);
+            
+            // border
+            PalmImage.drawBorder(Parameters.OutputImageBorderColor);
+        }
+
+        private void updateTouchImage(FrameData frameData, int numRows, int numColumns) {
+            if (TouchImage != null)
+                TouchImage.Dispose();
+
+            TouchImage = touchEventVisualizer.getOutputImage(frameData.ImageSize, numRows, numColumns);
+        }
+    }
+}

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

@@ -1,162 +0,0 @@
-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)
-        {
-            foreach (OutputImage image in Images)
-                image.Dispose();
-
-            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);
-}
-
-}
-
-}
-}
-*/

+ 302 - 0
bbiwarg/Output/DebugOutput/DebugWindow.Designer.cs

@@ -0,0 +1,302 @@
+namespace bbiwarg.Output.DebugOutput
+{
+    partial class DebugWindow
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.depthImageBox = new Emgu.CV.UI.ImageBox();
+            this.fingerImageBox = new Emgu.CV.UI.ImageBox();
+            this.handImageBox = new Emgu.CV.UI.ImageBox();
+            this.palmImageBox = new Emgu.CV.UI.ImageBox();
+            this.imageBox6 = new Emgu.CV.UI.ImageBox();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.frameLabel = new System.Windows.Forms.Label();
+            this.palmGridNumColumnsTrackBar = new System.Windows.Forms.TrackBar();
+            this.palmGridNumColumnsLabel = new System.Windows.Forms.Label();
+            this.palmGridNumRowsLabel = new System.Windows.Forms.Label();
+            this.palmGridLabel = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.videoControlLabel = new System.Windows.Forms.Label();
+            this.palmGridNumRowsTrackBar = new System.Windows.Forms.TrackBar();
+            this.previousFrameButton = new System.Windows.Forms.Button();
+            this.nextFrameButton = new System.Windows.Forms.Button();
+            this.playPauseButton = new System.Windows.Forms.Button();
+            this.touchImageBox = new Emgu.CV.UI.ImageBox();
+            ((System.ComponentModel.ISupportInitialize)(this.depthImageBox)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.fingerImageBox)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.handImageBox)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.palmImageBox)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.imageBox6)).BeginInit();
+            this.panel1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.palmGridNumColumnsTrackBar)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.palmGridNumRowsTrackBar)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.touchImageBox)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // depthImageBox
+            // 
+            this.depthImageBox.FunctionalMode = Emgu.CV.UI.ImageBox.FunctionalModeOption.Minimum;
+            this.depthImageBox.Location = new System.Drawing.Point(-4, -3);
+            this.depthImageBox.Margin = new System.Windows.Forms.Padding(0);
+            this.depthImageBox.Name = "depthImageBox";
+            this.depthImageBox.Size = new System.Drawing.Size(320, 240);
+            this.depthImageBox.TabIndex = 2;
+            this.depthImageBox.TabStop = false;
+            // 
+            // fingerImageBox
+            // 
+            this.fingerImageBox.FunctionalMode = Emgu.CV.UI.ImageBox.FunctionalModeOption.Minimum;
+            this.fingerImageBox.Location = new System.Drawing.Point(316, -3);
+            this.fingerImageBox.Margin = new System.Windows.Forms.Padding(0);
+            this.fingerImageBox.Name = "fingerImageBox";
+            this.fingerImageBox.Size = new System.Drawing.Size(320, 240);
+            this.fingerImageBox.TabIndex = 2;
+            this.fingerImageBox.TabStop = false;
+            // 
+            // handImageBox
+            // 
+            this.handImageBox.FunctionalMode = Emgu.CV.UI.ImageBox.FunctionalModeOption.Minimum;
+            this.handImageBox.Location = new System.Drawing.Point(636, -3);
+            this.handImageBox.Margin = new System.Windows.Forms.Padding(0);
+            this.handImageBox.Name = "handImageBox";
+            this.handImageBox.Size = new System.Drawing.Size(320, 240);
+            this.handImageBox.TabIndex = 2;
+            this.handImageBox.TabStop = false;
+            // 
+            // palmImageBox
+            // 
+            this.palmImageBox.FunctionalMode = Emgu.CV.UI.ImageBox.FunctionalModeOption.Minimum;
+            this.palmImageBox.Location = new System.Drawing.Point(-4, 237);
+            this.palmImageBox.Margin = new System.Windows.Forms.Padding(0);
+            this.palmImageBox.Name = "palmImageBox";
+            this.palmImageBox.Size = new System.Drawing.Size(320, 240);
+            this.palmImageBox.TabIndex = 2;
+            this.palmImageBox.TabStop = false;
+            // 
+            // imageBox6
+            // 
+            this.imageBox6.Location = new System.Drawing.Point(574, 229);
+            this.imageBox6.Margin = new System.Windows.Forms.Padding(0);
+            this.imageBox6.Name = "imageBox6";
+            this.imageBox6.Size = new System.Drawing.Size(0, 0);
+            this.imageBox6.TabIndex = 2;
+            this.imageBox6.TabStop = false;
+            // 
+            // panel1
+            // 
+            this.panel1.Controls.Add(this.frameLabel);
+            this.panel1.Controls.Add(this.palmGridNumColumnsTrackBar);
+            this.panel1.Controls.Add(this.palmGridNumColumnsLabel);
+            this.panel1.Controls.Add(this.palmGridNumRowsLabel);
+            this.panel1.Controls.Add(this.palmGridLabel);
+            this.panel1.Controls.Add(this.label2);
+            this.panel1.Controls.Add(this.videoControlLabel);
+            this.panel1.Controls.Add(this.palmGridNumRowsTrackBar);
+            this.panel1.Controls.Add(this.previousFrameButton);
+            this.panel1.Controls.Add(this.nextFrameButton);
+            this.panel1.Controls.Add(this.playPauseButton);
+            this.panel1.Location = new System.Drawing.Point(636, 237);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(320, 240);
+            this.panel1.TabIndex = 3;
+            // 
+            // frameLabel
+            // 
+            this.frameLabel.Location = new System.Drawing.Point(116, 14);
+            this.frameLabel.Name = "frameLabel";
+            this.frameLabel.Size = new System.Drawing.Size(77, 13);
+            this.frameLabel.TabIndex = 12;
+            this.frameLabel.Text = "Frame:";
+            this.frameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // palmGridNumColumnsTrackBar
+            // 
+            this.palmGridNumColumnsTrackBar.Location = new System.Drawing.Point(56, 148);
+            this.palmGridNumColumnsTrackBar.Minimum = 1;
+            this.palmGridNumColumnsTrackBar.Name = "palmGridNumColumnsTrackBar";
+            this.palmGridNumColumnsTrackBar.Size = new System.Drawing.Size(247, 45);
+            this.palmGridNumColumnsTrackBar.TabIndex = 4;
+            this.palmGridNumColumnsTrackBar.Value = 1;
+            this.palmGridNumColumnsTrackBar.Scroll += new System.EventHandler(this.palmGridTrackBar_Scroll);
+            // 
+            // palmGridNumColumnsLabel
+            // 
+            this.palmGridNumColumnsLabel.AutoSize = true;
+            this.palmGridNumColumnsLabel.Location = new System.Drawing.Point(3, 148);
+            this.palmGridNumColumnsLabel.Name = "palmGridNumColumnsLabel";
+            this.palmGridNumColumnsLabel.Size = new System.Drawing.Size(47, 13);
+            this.palmGridNumColumnsLabel.TabIndex = 10;
+            this.palmGridNumColumnsLabel.Text = "Columns";
+            // 
+            // palmGridNumRowsLabel
+            // 
+            this.palmGridNumRowsLabel.AutoSize = true;
+            this.palmGridNumRowsLabel.Location = new System.Drawing.Point(3, 108);
+            this.palmGridNumRowsLabel.Name = "palmGridNumRowsLabel";
+            this.palmGridNumRowsLabel.Size = new System.Drawing.Size(34, 13);
+            this.palmGridNumRowsLabel.TabIndex = 9;
+            this.palmGridNumRowsLabel.Text = "Rows";
+            // 
+            // palmGridLabel
+            // 
+            this.palmGridLabel.AutoSize = true;
+            this.palmGridLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.palmGridLabel.Location = new System.Drawing.Point(3, 83);
+            this.palmGridLabel.Name = "palmGridLabel";
+            this.palmGridLabel.Size = new System.Drawing.Size(61, 13);
+            this.palmGridLabel.TabIndex = 8;
+            this.palmGridLabel.Text = "Palm Grid";
+            // 
+            // label2
+            // 
+            this.label2.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.label2.Location = new System.Drawing.Point(98, 25);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(0, 0);
+            this.label2.TabIndex = 7;
+            // 
+            // videoControlLabel
+            // 
+            this.videoControlLabel.AutoSize = true;
+            this.videoControlLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.videoControlLabel.Location = new System.Drawing.Point(3, 14);
+            this.videoControlLabel.Name = "videoControlLabel";
+            this.videoControlLabel.Size = new System.Drawing.Size(89, 13);
+            this.videoControlLabel.TabIndex = 6;
+            this.videoControlLabel.Text = "Video Controls";
+            // 
+            // palmGridNumRowsTrackBar
+            // 
+            this.palmGridNumRowsTrackBar.Location = new System.Drawing.Point(56, 108);
+            this.palmGridNumRowsTrackBar.Minimum = 1;
+            this.palmGridNumRowsTrackBar.Name = "palmGridNumRowsTrackBar";
+            this.palmGridNumRowsTrackBar.Size = new System.Drawing.Size(247, 45);
+            this.palmGridNumRowsTrackBar.TabIndex = 3;
+            this.palmGridNumRowsTrackBar.Value = 1;
+            this.palmGridNumRowsTrackBar.Scroll += new System.EventHandler(this.palmGridTrackBar_Scroll);
+            // 
+            // previousFrameButton
+            // 
+            this.previousFrameButton.Enabled = false;
+            this.previousFrameButton.Location = new System.Drawing.Point(6, 35);
+            this.previousFrameButton.Name = "previousFrameButton";
+            this.previousFrameButton.Size = new System.Drawing.Size(104, 23);
+            this.previousFrameButton.TabIndex = 0;
+            this.previousFrameButton.Text = "previousFrame";
+            this.previousFrameButton.UseVisualStyleBackColor = true;
+            this.previousFrameButton.Click += new System.EventHandler(this.previousFrameButton_Click);
+            // 
+            // nextFrameButton
+            // 
+            this.nextFrameButton.Enabled = false;
+            this.nextFrameButton.Location = new System.Drawing.Point(199, 35);
+            this.nextFrameButton.Name = "nextFrameButton";
+            this.nextFrameButton.Size = new System.Drawing.Size(104, 23);
+            this.nextFrameButton.TabIndex = 2;
+            this.nextFrameButton.Text = "nextFrame";
+            this.nextFrameButton.UseVisualStyleBackColor = true;
+            this.nextFrameButton.Click += new System.EventHandler(this.nextFrameButton_Click);
+            // 
+            // playPauseButton
+            // 
+            this.playPauseButton.Enabled = false;
+            this.playPauseButton.Location = new System.Drawing.Point(116, 35);
+            this.playPauseButton.Name = "playPauseButton";
+            this.playPauseButton.Size = new System.Drawing.Size(77, 23);
+            this.playPauseButton.TabIndex = 1;
+            this.playPauseButton.Text = "Pause";
+            this.playPauseButton.UseVisualStyleBackColor = true;
+            this.playPauseButton.Click += new System.EventHandler(this.playPauseButton_Click);
+            // 
+            // touchImageBox
+            // 
+            this.touchImageBox.FunctionalMode = Emgu.CV.UI.ImageBox.FunctionalModeOption.Minimum;
+            this.touchImageBox.Location = new System.Drawing.Point(316, 237);
+            this.touchImageBox.Margin = new System.Windows.Forms.Padding(0);
+            this.touchImageBox.Name = "touchImageBox";
+            this.touchImageBox.Size = new System.Drawing.Size(320, 240);
+            this.touchImageBox.TabIndex = 2;
+            this.touchImageBox.TabStop = false;
+            // 
+            // DebugWindow
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.AutoSize = true;
+            this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+            this.ClientSize = new System.Drawing.Size(1108, 578);
+            this.Controls.Add(this.touchImageBox);
+            this.Controls.Add(this.panel1);
+            this.Controls.Add(this.imageBox6);
+            this.Controls.Add(this.palmImageBox);
+            this.Controls.Add(this.handImageBox);
+            this.Controls.Add(this.fingerImageBox);
+            this.Controls.Add(this.depthImageBox);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+            this.MaximizeBox = false;
+            this.Name = "DebugWindow";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "DebugWindow";
+            ((System.ComponentModel.ISupportInitialize)(this.depthImageBox)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.fingerImageBox)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.handImageBox)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.palmImageBox)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.imageBox6)).EndInit();
+            this.panel1.ResumeLayout(false);
+            this.panel1.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.palmGridNumColumnsTrackBar)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.palmGridNumRowsTrackBar)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.touchImageBox)).EndInit();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private Emgu.CV.UI.ImageBox depthImageBox;
+        private Emgu.CV.UI.ImageBox fingerImageBox;
+        private Emgu.CV.UI.ImageBox handImageBox;
+        private Emgu.CV.UI.ImageBox palmImageBox;
+        private Emgu.CV.UI.ImageBox imageBox6;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Button playPauseButton;
+        private System.Windows.Forms.Label videoControlLabel;
+        private System.Windows.Forms.TrackBar palmGridNumRowsTrackBar;
+        private System.Windows.Forms.Button previousFrameButton;
+        private System.Windows.Forms.Button nextFrameButton;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label palmGridLabel;
+        private System.Windows.Forms.Label palmGridNumRowsLabel;
+        private System.Windows.Forms.TrackBar palmGridNumColumnsTrackBar;
+        private System.Windows.Forms.Label palmGridNumColumnsLabel;
+        private System.Windows.Forms.Label frameLabel;
+        private Emgu.CV.UI.ImageBox touchImageBox;
+
+
+    }
+}

+ 100 - 151
bbiwarg/Output/DebugOutput/DebugWindow.cs

@@ -1,213 +1,162 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
 using System.Drawing;
 using System.Drawing;
 using System.Linq;
 using System.Linq;
 using System.Text;
 using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using OpenTK;
-using OpenTK.Input;
-using OpenTK.Graphics.OpenGL;
-using OpenTK.Graphics;
-using bbiwarg.Input.InputHandling;
+using System.Windows.Forms;
+using System.Windows;
 using bbiwarg.Input.InputProviding;
 using bbiwarg.Input.InputProviding;
+using bbiwarg.Input.InputHandling;
 using bbiwarg.Utility;
 using bbiwarg.Utility;
+using Emgu.CV.UI;
 
 
 namespace bbiwarg.Output.DebugOutput
 namespace bbiwarg.Output.DebugOutput
 {
 {
-    public enum PalmGridControlFocus
-    {
-        Rows,
-        Columns
-    }
-
-    class DebugWindow : GameWindow
+    public partial class DebugWindow : Form
     {
     {
         private InputHandler inputHandler;
         private InputHandler inputHandler;
         private InputProvider inputProvider;
         private InputProvider inputProvider;
-        private PalmGridControlFocus palmGridControlFocus;
-
-        private uint textureID;
-
+        private DebugImageCreator debugImageCreator;
+        private System.Windows.Forms.Timer timer;
         private int currentFrameID;
         private int currentFrameID;
-        private DebugImages debugImages;
+        private bool guiUpToDate;
 
 
-        public DebugWindow(InputProvider inputProvider, InputHandler inputHandler)
-            : base((int)(Parameters.DebugWindowScaleFactor * Math.Max(1, Math.Min(Parameters.DebugWindowNumImagesPerRow, Parameters.DebugWindowNumImages)) * Parameters.ImageWidth),
-                   (int)(Parameters.DebugWindowScaleFactor * (1 + (Parameters.DebugWindowNumImages - 1) / Parameters.DebugWindowNumImagesPerRow) * Parameters.ImageHeight))
+        public DebugWindow(InputProvider inputProvider, InputHandler inputHandler, String name, int updateInterval)
         {
         {
+            InitializeComponent();
+
             this.inputProvider = inputProvider;
             this.inputProvider = inputProvider;
             this.inputHandler = inputHandler;
             this.inputHandler = inputHandler;
+            guiUpToDate = false;
+
+            Name = name;
+            Text = name;
 
 
             TouchEventVisualizer touchEventVisualizer = new TouchEventVisualizer();
             TouchEventVisualizer touchEventVisualizer = new TouchEventVisualizer();
             inputHandler.NewProcessedFrameEvent += touchEventVisualizer.handleNewFrameData;
             inputHandler.NewProcessedFrameEvent += touchEventVisualizer.handleNewFrameData;
-            debugImages = new DebugImages(touchEventVisualizer);
-        }
+            debugImageCreator = new DebugImageCreator(touchEventVisualizer);
 
 
-        protected override void OnLoad(EventArgs e)
-        {
-            base.OnLoad(e);
-            Title = Parameters.DebugWindowTitle;
-            GL.ClearColor(Color.Black);
-
-            // Texture
-            GL.Enable(EnableCap.Texture2D);
-            GL.GenTextures(1, out textureID);
-            GL.BindTexture(TextureTarget.Texture2D, textureID);
-            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
-            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
-
-            palmGridControlFocus = PalmGridControlFocus.Rows;
-            Keyboard.KeyDown += HandleKeyDownPalmGridControls;
             if (inputProvider is VideoInputProvider)
             if (inputProvider is VideoInputProvider)
-                Keyboard.KeyDown += HandleKeyDownVideoControls;
-        }
+                playPauseButton.Enabled = true;
 
 
-        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
-        {
-            base.OnClosing(e);
+            palmGridNumRowsTrackBar.Value = Parameters.PalmGridDefaultNumRows;
+            palmGridNumColumnsTrackBar.Value = Parameters.PalmGridDefaultNumColumns;
 
 
-            inputProvider.stop();
+            timer = new System.Windows.Forms.Timer();
+            timer.Interval = updateInterval;
+            timer.Tick += update;
+            timer.Start();
         }
         }
 
 
-        protected override void OnResize(EventArgs e)
+        protected override void OnClosing(CancelEventArgs e)
         {
         {
-            base.OnResize(e);
-
-            int screenWidth = ClientRectangle.Width;
-            int screenHeight = ClientRectangle.Height;
-
-            int numRows = 1 + (Parameters.DebugWindowNumImages - 1) / Parameters.DebugWindowNumImagesPerRow;
-            int numCols = Math.Min(Parameters.DebugWindowNumImages, Parameters.DebugWindowNumImagesPerRow);
-            int heightForWidth = (int)((float)screenWidth / ((float)numCols * Parameters.ImageAspectRatio) * (float)numRows);
-
-            GL.Viewport(0, (screenHeight - heightForWidth) / 2, screenWidth, heightForWidth);
-
-            // top left at (0,0) every image from (i, j) to (i + 1, j + 1)
-            Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, numCols, numRows, 0, 0.001f, 10f);
-            GL.MatrixMode(MatrixMode.Projection);
-            GL.LoadMatrix(ref projection);
+            base.OnClosing(e);
+            inputProvider.stop();
         }
         }
 
 
-        protected override void OnUpdateFrame(FrameEventArgs e)
+        private void update(object sender, EventArgs e)
         {
         {
-            Timer.start("DebugWindow.OnUpdateFrame");
-            base.OnUpdateFrame(e);
+            Utility.Timer.start("DebugWindow.update");
 
 
             if (!inputProvider.IsActive)
             if (!inputProvider.IsActive)
-                Exit();
+                Close();
 
 
             FrameData frameData = inputHandler.FrameData;
             FrameData frameData = inputHandler.FrameData;
-            if (frameData != null)
-            {
-                lock (frameData)
-                {
+            if (frameData != null) {
+                lock (frameData) {
                     if (currentFrameID != frameData.FrameID)
                     if (currentFrameID != frameData.FrameID)
                     {
                     {
                         currentFrameID = frameData.FrameID;
                         currentFrameID = frameData.FrameID;
-
-                        Timer.start("DebugWindow.OnUpdateFrame::updateImages");
-                        debugImages.updateImages(frameData);
-                        Timer.stop("DebugWindow.OnUpdateFrame::updateImages");
+                        Utility.Timer.start("DebugWindow.update::updateImages");
+                        updateImages(frameData);
+                        Utility.Timer.stop("DebugWindow.update::updateImages");
                     }
                     }
                 }
                 }
             }
             }
 
 
-            Timer.stop("DebugWindow.OnUpdateFrame");
+            if (!guiUpToDate)
+            {
+                Utility.Timer.start("DebugWindow.update::updateGUI");
+                updateGUI();
+                Utility.Timer.stop("DebugWindow.update::updateGUI");
+            }
+            
+            Utility.Timer.stop("DebugWindow.update");
         }
         }
 
 
-        protected override void OnRenderFrame(FrameEventArgs e)
-        {
-            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);
+        private void updateImages(FrameData frameData) {
+            guiUpToDate = false;
+
+            int numRows = palmGridNumRowsTrackBar.Value;
+            int numColumns = palmGridNumColumnsTrackBar.Value;
+            debugImageCreator.updateImages(frameData, numRows, numColumns);            
+        }
 
 
-            Title = Parameters.DebugWindowTitle + " (Frame: " + currentFrameID + ")";
+        private void updateGUI() {
+            // update image boxes
+            depthImageBox.Image = debugImageCreator.DepthImage;
+            fingerImageBox.Image = debugImageCreator.FingerImage;
+            handImageBox.Image = debugImageCreator.HandImage;
+            palmImageBox.Image = debugImageCreator.PalmImage;
+            touchImageBox.Image = debugImageCreator.TouchImage;
 
 
-            GL.Enable(EnableCap.Texture2D);
+            // update frame label
+            frameLabel.Text = "Frame: " + currentFrameID;
 
 
-            Timer.start("DebugWindow.OnRenderFrame::drawImages");
-            int imageIndex = 0;
-            foreach (OutputImage image in debugImages.Images)
-            {
-                int column = imageIndex % Parameters.DebugWindowNumImagesPerRow;
-                int row = imageIndex / Parameters.DebugWindowNumImagesPerRow;
-                GL.BindTexture(TextureTarget.Texture2D, textureID);
-                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Parameters.ImageWidth, Parameters.ImageHeight, 0, PixelFormat.Rgb, PixelType.UnsignedByte, image.MIplImage.imageData);
-                GL.Begin(PrimitiveType.Quads);
-                GL.Color3(1.0, 1.0, 1.0);
-                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++;
-            }
-            Timer.stop("DebugWindow.OnRenderFrame::drawImages");
+            guiUpToDate = true;
+        }
 
 
-            Timer.start("DebugWindow.OnRenderFrame::SwapBuffers");
-            SwapBuffers();
-            Timer.stop("DebugWindow.OnRenderFrame::SwapBuffers");
+        private void playPauseButton_Click(object sender, EventArgs e)
+        {
+            handlePlayPause();
+        }
 
 
-            Timer.stop("DebugWindow.OnRenderFrame");
+        private void nextFrameButton_Click(object sender, EventArgs e)
+        {
+            handleGoToNextFrame();
         }
         }
 
 
-        private void HandleKeyDownVideoControls(object sender, KeyboardKeyEventArgs e)
+        private void previousFrameButton_Click(object sender, EventArgs e)
         {
         {
-            VideoInputProvider vip = (VideoInputProvider)inputProvider;
-            switch (e.Key)
+            handleGoToPreviousFrame();
+        }
+
+        private void handlePlayPause() {
+            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
+
+            if (videoInputProvider.IsPaused)
             {
             {
-                case Key.Space:
-                    if (vip.IsPaused)
-                        vip.play();
-                    else
-                        vip.pause();
-                    break;
-                case Key.Right:
-                    if (vip.IsPaused)
-                    {
-                        vip.goToNextFrame();
-                    }
-                    break;
-                case Key.Left:
-                    if (vip.IsPaused)
-                    {
-                        vip.goToPreviousFrame();
-                    }
-                    break;
+                videoInputProvider.play();
+                playPauseButton.Text = "Pause";
+                nextFrameButton.Enabled = false;
+                previousFrameButton.Enabled = false;
+            }
+            else {
+                videoInputProvider.pause();
+                playPauseButton.Text = "Play";
+                nextFrameButton.Enabled = true;
+                previousFrameButton.Enabled = true;
             }
             }
         }
         }
 
 
+        private void handleGoToNextFrame() {
+            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
+            videoInputProvider.goToNextFrame();
+        }
 
 
-        private void HandleKeyDownPalmGridControls(object sender, KeyboardKeyEventArgs e)
+        private void handleGoToPreviousFrame()
         {
         {
-            switch (e.Key)
-            {
-                case Key.R:
-                    palmGridControlFocus = PalmGridControlFocus.Rows;
-                    break;
-                case Key.C:
-                    palmGridControlFocus = PalmGridControlFocus.Columns;
-                    break;
-                case Key.Plus:
-                case Key.KeypadPlus:
-                case Key.BracketRight: //fix
-                    if (palmGridControlFocus == PalmGridControlFocus.Rows)
-                        Parameters.setPalmGridParameters(Parameters.PalmGridNumRows + 1, Parameters.PalmGridNumColumns);
-                    else
-                        Parameters.setPalmGridParameters(Parameters.PalmGridNumRows, Parameters.PalmGridNumColumns + 1);
-                    break;
-                case Key.Minus:
-                case Key.KeypadMinus:
-                case Key.Slash: //fix
-                    if (palmGridControlFocus == PalmGridControlFocus.Rows)
-                        Parameters.setPalmGridParameters(Math.Max(1, Parameters.PalmGridNumRows - 1), Parameters.PalmGridNumColumns);
-                    else
-                        Parameters.setPalmGridParameters(Parameters.PalmGridNumRows, Math.Max(1, Parameters.PalmGridNumColumns - 1));
-                    break;
-            }
+            VideoInputProvider videoInputProvider = inputProvider as VideoInputProvider;
+            videoInputProvider.goToPreviousFrame();
+        }
+
+        private void palmGridTrackBar_Scroll(object sender, EventArgs e)
+        {
+            currentFrameID = -1;
+            update(sender, e);
         }
         }
     }
     }
 }
 }

+ 120 - 0
bbiwarg/Output/DebugOutput/DebugWindow.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 87 - 83
bbiwarg/Output/DebugOutput/TouchEventVisualizer.cs

@@ -13,19 +13,18 @@ namespace bbiwarg.Output.DebugOutput
 {
 {
     class TouchEventVisualizer
     class TouchEventVisualizer
     {
     {
+        private Object sync;
         private Stopwatch timer;
         private Stopwatch timer;
 
 
         private Dictionary<int, List<Vector2D>> activeTouches;
         private Dictionary<int, List<Vector2D>> activeTouches;
         private Dictionary<int, List<Vector2D>> oldTouches;
         private Dictionary<int, List<Vector2D>> oldTouches;
         private Dictionary<int, long> lastUpdates;
         private Dictionary<int, long> lastUpdates;
         private int nextFreeID;
         private int nextFreeID;
-        private int lastUpdated;
-        private bool active;
 
 
         public TouchEventVisualizer()
         public TouchEventVisualizer()
         {
         {
+            sync = new object();
             reset();
             reset();
-
         }
         }
 
 
         public void reset()
         public void reset()
@@ -34,108 +33,113 @@ namespace bbiwarg.Output.DebugOutput
             timer.Start();
             timer.Start();
 
 
             nextFreeID = 1;
             nextFreeID = 1;
-            lastUpdated = 0;
-            activeTouches = new Dictionary<int,List<Vector2D>>();
-            oldTouches = new Dictionary<int,List<Vector2D>>();
-            lastUpdates = new Dictionary<int,long>();
+            activeTouches = new Dictionary<int, List<Vector2D>>();
+            oldTouches = new Dictionary<int, List<Vector2D>>();
+            lastUpdates = new Dictionary<int, long>();
 
 
         }
         }
 
 
-        public void handleNewFrameData(InputHandler sender, EventArgs e)
+        public void handleNewFrameData(object sender, NewProcessedFrameEventArgs e)
         {
         {
-            FrameData frameData = sender.FrameData;
-            lock (frameData)
-            {
-                foreach (TouchEventArgs te in frameData.TouchEvents)
+            FrameData frameData = e.FrameData;
+            lock (frameData) lock (sync) 
                 {
                 {
-                    switch (te.Type)
+                    if (frameData.ResetFlag)
+                        reset();
+
+                    foreach (TouchEvent te in frameData.TouchEvents)
                     {
                     {
-                        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;
+                        switch (te.Type)
+                        {
+                            case TouchEventType.Down:
+                                activeTouches.Add(te.Touch.TrackID, new List<Vector2D>());
+                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
+                                break;
+                            case TouchEventType.Move:
+                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
+                                break;
+                            case TouchEventType.Up:
+                                activeTouches[te.Touch.TrackID].Add(te.Touch.RelativePosition);
+
+                                oldTouches.Add(nextFreeID, activeTouches[te.Touch.TrackID]);
+                                lastUpdates.Add(nextFreeID, timer.ElapsedMilliseconds);
+
+                                activeTouches.Remove(te.Touch.TrackID);
+                                nextFreeID++;
+                                break;
+                        }
                     }
                     }
                 }
                 }
-            }
-
         }
         }
-        
-        public OutputImage getOutputImage()
+
+        public OutputImage getOutputImage(ImageSize imageSize, int numRows, int numColumns)
         {
         {
-            long currentTime = timer.ElapsedMilliseconds;
-            removeOldPositions(currentTime - Parameters.TouchEventVisualizerFadeOutTime);
+            lock (sync)
+            {
+                long currentTime = timer.ElapsedMilliseconds;
+                removeOldPositions(currentTime - Parameters.TouchEventVisualizerFadeOutTime);
 
 
-            int width = Parameters.ImageWidth;
-            int height = Parameters.ImageHeight;
-            OutputImage outputImage = new OutputImage(width, height);
+                OutputImage outputImage = new OutputImage(imageSize);
+                int imageWidth = imageSize.Width;
+                int imageHeight = imageSize.Height;
 
 
-            // border
-            outputImage.drawRectangle(0, 0, width - 1, height - 1, Parameters.TouchEventVisualizerGridColor);
+                // border
+                outputImage.drawBorder(Parameters.TouchEventVisualizerGridColor);
 
 
-            // draw grid
-            int numRows = Parameters.PalmGridNumRows;
-            int numColumns = Parameters.PalmGridNumColumns;
-            int widthPerColumn = width / numColumns;
-            int heightPerRow = height / numRows;
+                // draw grid
+                int widthPerColumn = imageWidth / numColumns;
+                int heightPerRow = imageHeight / numRows;
 
 
-            // find active blocks
-            bool[,] activeBlocks = new bool[numRows, numColumns];
-            if (numRows * numColumns > 1)
-            {
-                foreach (List<Vector2D> positions in activeTouches.Values)
+                // find active blocks
+                bool[,] activeBlocks = new bool[numRows, numColumns];
+                if (numRows * numColumns > 1)
                 {
                 {
-                    Vector2D lastPosition = positions.Last();
-                    int activeRow = (int)Math.Min(lastPosition.Y * Parameters.PalmGridNumRows, numRows-1);
-                    int activeCol = (int)Math.Min(lastPosition.X * Parameters.PalmGridNumColumns, numColumns-1);
-                    activeBlocks[activeRow, activeCol] = true;
+                    foreach (List<Vector2D> positions in activeTouches.Values)
+                    {
+                        Vector2D lastPosition = positions.Last();
+                        int activeRow = (int)Math.Min(lastPosition.Y * numRows, numRows - 1);
+                        int activeCol = (int)Math.Min(lastPosition.X * numColumns, numColumns - 1);
+                        activeBlocks[activeRow, activeCol] = true;
+                    }
                 }
                 }
-            }
 
 
-            // draw blocks
-            for (int row = 0; row < numRows; row++)
-            {
-                for (int col = 0; col < numColumns; col++)
+                // draw blocks
+                int index = 1;
+                for (int row = 0; row < numRows; row++)
                 {
                 {
-                    if (activeBlocks[row, col])
-                        outputImage.fillRectangle(col * widthPerColumn, row * heightPerRow, widthPerColumn, heightPerRow, Parameters.TouchEventVisualizerActiveBlockColor);
+                    for (int col = 0; col < numColumns; col++)
+                    {
+                        if (activeBlocks[row, col])
+                            outputImage.fillRectangle(new Rectangle(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);
+                        int x = (int)((col + 0.5f) * widthPerColumn) - 5;
+                        int y = (int)((row + 0.5f) * heightPerRow) + 5;
+                        outputImage.drawText(new Point(x,y), index.ToString(), Parameters.TouchEventVisualizerTextColor);
+                        index++;
+                    }
                 }
                 }
-            }
 
 
-            // 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);
-            }
+                // draw grid
+                for (int i = 0; i <= numColumns; i++)
+                    outputImage.drawLineSegment(new LineSegment2D(new Vector2D(i * widthPerColumn, 0), new Vector2D(i * widthPerColumn, imageHeight - 1)), Parameters.TouchEventVisualizerGridColor);
+                for (int i = 0; i <= numRows; i++)
+                    outputImage.drawLineSegment(new LineSegment2D(new Vector2D(0, i * heightPerRow), new Vector2D(imageWidth - 1, i * heightPerRow)), Parameters.TouchEventVisualizerGridColor);
 
 
-            return outputImage;
+                // draw active touches
+                foreach (List<Vector2D> positions in activeTouches.Values)
+                    outputImage.drawTouchGesture(positions, imageSize.MaxPixel);
+
+                // 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, imageSize.MaxPixel, opacity);
+                }
+
+                return outputImage;
+            }
         }
         }
 
 
         private void removeOldPositions(long breakTime)
         private void removeOldPositions(long breakTime)

+ 68 - 0
bbiwarg/Output/GlassesOutput/GlassesWindow.Designer.cs

@@ -0,0 +1,68 @@
+namespace bbiwarg.Output.GlassesOutput
+{
+    partial class GlassesWindow
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.imageBox = new Emgu.CV.UI.ImageBox();
+            ((System.ComponentModel.ISupportInitialize)(this.imageBox)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // imageBox
+            // 
+            this.imageBox.FunctionalMode = Emgu.CV.UI.ImageBox.FunctionalModeOption.Minimum;
+            this.imageBox.Location = new System.Drawing.Point(0, 0);
+            this.imageBox.Margin = new System.Windows.Forms.Padding(0);
+            this.imageBox.Name = "imageBox";
+            this.imageBox.Size = new System.Drawing.Size(1280, 720);
+            this.imageBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
+            this.imageBox.TabIndex = 2;
+            this.imageBox.TabStop = false;
+            // 
+            // GlassesWindow
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.AutoSize = true;
+            this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+            this.ClientSize = new System.Drawing.Size(1284, 702);
+            this.Controls.Add(this.imageBox);
+            this.Name = "GlassesWindow";
+            this.Text = "GlassesWindow";
+            this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.GlassesWindow_OnKeyDown);
+            ((System.ComponentModel.ISupportInitialize)(this.imageBox)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private Emgu.CV.UI.ImageBox imageBox;
+    }
+}

+ 114 - 105
bbiwarg/Output/GlassesOutput/GlassesWindow.cs

@@ -1,92 +1,78 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Linq;
+using System.ComponentModel;
+using System.Data;
 using System.Drawing;
 using System.Drawing;
+using System.Linq;
 using System.Text;
 using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using OpenTK;
-using OpenTK.Input;
-using OpenTK.Graphics.OpenGL;
-using OpenTK.Graphics;
+using System.Windows.Forms;
 using bbiwarg.Input.InputHandling;
 using bbiwarg.Input.InputHandling;
 using bbiwarg.Input.InputProviding;
 using bbiwarg.Input.InputProviding;
 using bbiwarg.Utility;
 using bbiwarg.Utility;
+using bbiwarg.Recognition.FingerRecognition;
+using bbiwarg.Recognition.PalmRecognition;
+using Emgu.CV.UI;
 
 
 namespace bbiwarg.Output.GlassesOutput
 namespace bbiwarg.Output.GlassesOutput
 {
 {
-    class GlassesWindow : GameWindow
+    public partial class GlassesWindow : Form
     {
     {
-        private InputHandler inputHandler;
         private InputProvider inputProvider;
         private InputProvider inputProvider;
-        private uint textureID;
+        private InputHandler inputHandler;
+        private System.Windows.Forms.Timer timer;
         private int currentFrameID;
         private int currentFrameID;
+        private bool guiUpToDate;
+        private ImageSize inputSize;
+        private ImageSize outputSize;
         private OutputImage image;
         private OutputImage image;
         private Projection2DTo2D projection;
         private Projection2DTo2D projection;
-        private bool calibrationImageUpToDate;
         private List<Vector2D> calibrationPoints;
         private List<Vector2D> calibrationPoints;
         private int calibrationPointIndex;
         private int calibrationPointIndex;
+        private bool calibrationImageUpToDate;
 
 
-        public GlassesWindow(InputProvider inputProvider, InputHandler inputHandler)
-            : base(Parameters.GlassesWindowWidth, Parameters.GlassesWindowHeight)
+        public GlassesWindow(InputProvider inputProvider, InputHandler inputHandler, String name, ImageSize outputSize, int updateInterval)
         {
         {
+            InitializeComponent();
+
             this.inputProvider = inputProvider;
             this.inputProvider = inputProvider;
             this.inputHandler = inputHandler;
             this.inputHandler = inputHandler;
-
-            projection = new Projection2DTo2D(Parameters.ImageWidth, Parameters.ImageHeight, Parameters.GlassesWindowWidth, Parameters.GlassesWindowHeight);
+            this.inputSize = inputHandler.ImageSize;
+            this.outputSize = outputSize;
+            guiUpToDate = false;
             calibrationImageUpToDate = false;
             calibrationImageUpToDate = false;
+
             calibrationPoints = new List<Vector2D>();
             calibrationPoints = new List<Vector2D>();
-            calibrationPoints.Add(new Vector2D(0.25f * Parameters.GlassesWindowWidth, 0.25f * Parameters.GlassesWindowHeight));
-            calibrationPoints.Add(new Vector2D(0.75f * Parameters.GlassesWindowWidth, 0.25f * Parameters.GlassesWindowHeight));
-            calibrationPoints.Add(new Vector2D(0.75f * Parameters.GlassesWindowWidth, 0.75f * Parameters.GlassesWindowHeight));
-            calibrationPoints.Add(new Vector2D(0.25f * Parameters.GlassesWindowWidth, 0.75f * Parameters.GlassesWindowHeight));
+            calibrationPoints.Add(outputSize.getAbsolutePoint(new Vector2D(0.25f, 0.25f)));
+            calibrationPoints.Add(outputSize.getAbsolutePoint(new Vector2D(0.75f, 0.25f)));
+            calibrationPoints.Add(outputSize.getAbsolutePoint(new Vector2D(0.75f, 0.75f)));
+            calibrationPoints.Add(outputSize.getAbsolutePoint(new Vector2D(0.25f, 0.75f)));
             calibrationPointIndex = 0;
             calibrationPointIndex = 0;
-        }
+            projection = new Projection2DTo2D(inputSize, outputSize, calibrationPoints.Count);
 
 
-        protected override void OnLoad(EventArgs e)
-        {
-            base.OnLoad(e);
-            Title = Parameters.GlassesWindowTitle;
-            GL.ClearColor(Color.Black);
-
-            // Texture
-            GL.Enable(EnableCap.Texture2D);
-            GL.GenTextures(1, out textureID);
-            GL.BindTexture(TextureTarget.Texture2D, textureID);
-            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
-            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
-
-            Keyboard.KeyDown += handleKeyDown;
-        }
+            Name = name;
+            Text = name;
 
 
-        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
-        {
-            base.OnClosing(e);
+            timer = new System.Windows.Forms.Timer();
+            timer.Interval = updateInterval;
+            timer.Tick += update;
+            timer.Start();
 
 
-            inputProvider.stop();
+            KeyPreview = true;
         }
         }
 
 
-        protected override void OnResize(EventArgs e)
+        protected override void OnClosing(CancelEventArgs e)
         {
         {
-            base.OnResize(e);
-
-            int screenWidth = ClientRectangle.Width;
-            int screenHeight = ClientRectangle.Height;
-
-            GL.Viewport(0, 0, screenWidth, screenHeight);
-            
-            //Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, numCols, numRows, 0, 0.001f, 10f);
-            Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, 1, 1, 0, 0.001f, 10f);
-            GL.MatrixMode(MatrixMode.Projection);
-            GL.LoadMatrix(ref projection);
+            base.OnClosing(e);
+            inputProvider.stop();
         }
         }
 
 
-        protected override void OnUpdateFrame(FrameEventArgs e)
+        private void update(object sender, EventArgs e)
         {
         {
-            Timer.start("GlassesWindow.OnUpdateFrame");
-            base.OnUpdateFrame(e);
+            Utility.Timer.start("GlassesWindow.update");
 
 
             if (!inputProvider.IsActive)
             if (!inputProvider.IsActive)
-                Exit();
+                Close();
 
 
             if (projection.IsCalibrated)
             if (projection.IsCalibrated)
             {
             {
@@ -98,80 +84,103 @@ namespace bbiwarg.Output.GlassesOutput
                         if (currentFrameID != frameData.FrameID)
                         if (currentFrameID != frameData.FrameID)
                         {
                         {
                             currentFrameID = frameData.FrameID;
                             currentFrameID = frameData.FrameID;
-
-                            Timer.start("GlassesWindow.OnUpdateFrame::updateImage");
+                            Utility.Timer.start("GlassesWindow.update::updateImage");
                             updateImage(frameData);
                             updateImage(frameData);
-                            Timer.stop("GlassesWindow.OnUpdateFrame::updateImage");
+                            Utility.Timer.stop("GlassesWindow.update::updateImage");
                         }
                         }
                     }
                     }
                 }
                 }
             }
             }
-            else {
-                if (!calibrationImageUpToDate) {
+            else
+            {
+                if (!calibrationImageUpToDate)
                     updateCalibrationImage();
                     updateCalibrationImage();
-                }
             }
             }
-            Timer.stop("GlassesWindow.OnUpdateFrame");
-        }
 
 
+            if (!guiUpToDate)
+            {
+                Utility.Timer.start("GlassesWindow.update::updateGUI");
+                updateGUI();
+                Utility.Timer.stop("GlassesWindow.update::updateGUI");
+            }
 
 
-        protected override void OnRenderFrame(FrameEventArgs e)
-        {
-            Timer.start("GlassesWindow.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.DebugWindowTitle + " (Frame: " + currentFrameID + ")";
-
-            GL.Enable(EnableCap.Texture2D);
-
-            Timer.start("GlassesWindow.OnRenderFrame::drawImage");
-            
-            GL.BindTexture(TextureTarget.Texture2D, textureID);
-            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Parameters.GlassesWindowWidth, Parameters.GlassesWindowHeight, 0, PixelFormat.Rgb, PixelType.UnsignedByte, image.MIplImage.imageData);
-            GL.Begin(PrimitiveType.Quads);
-            GL.Color3(1.0, 1.0, 1.0);
-            GL.TexCoord2(0, 0); GL.Vertex3(0, 0, -1);
-            GL.TexCoord2(1, 0); GL.Vertex3(1, 0, -1);
-            GL.TexCoord2(1, 1); GL.Vertex3(1, 1, -1);
-            GL.TexCoord2(0, 1); GL.Vertex3(0, 1, -1);
-            GL.End();
-
-            Timer.stop("GlassesWindow.OnRenderFrame::drawImage");
-
-            Timer.start("GlassesWindow.OnRenderFrame::SwapBuffers");
-            SwapBuffers();
-            Timer.stop("GlassesWindow.OnRenderFrame::SwapBuffers");
-
-            Timer.stop("GlassesWindow.OnRenderFrame");
+            Utility.Timer.stop("GlassesWindow.update");
         }
         }
 
 
-        private void handleKeyDown(object sender, KeyboardKeyEventArgs e)
+        private void updateImage(FrameData frameData)
         {
         {
+            guiUpToDate = false;
+
+            if (image != null)
+                image.Dispose();
+
+            image = new OutputImage(outputSize);
+            foreach (Palm palm in frameData.TrackedPalms)
+            {
+                Quadrangle quadInput = palm.Quad;
+                Vector2D a = projection.projectPoint(quadInput.TopLeft);
+                Vector2D b = projection.projectPoint(quadInput.TopRight);
+                Vector2D c = projection.projectPoint(quadInput.BottomRight);
+                Vector2D d = projection.projectPoint(quadInput.BottomLeft);
+                Quadrangle quadOutput = new Quadrangle(a, b, c, d);
+                image.drawQuadrangleGrid(quadOutput, Color.Yellow, Color.Orange, 3, 4);
+            }
+
+            foreach (Finger finger in frameData.TrackedFingers)
+            {
+                Vector2D tipProjected = projection.projectPoint(finger.TipPoint);
+                image.fillCircle(tipProjected, 10, Color.Yellow);
+            }
 
 
         }
         }
 
 
-        private void updateImage(FrameData frameData) {
+        private void updateCalibrationImage()
+        {
+            guiUpToDate = false;
+
             if (image != null)
             if (image != null)
                 image.Dispose();
                 image.Dispose();
-            image = new OutputImage(Parameters.GlassesWindowWidth, Parameters.GlassesWindowHeight);
-                            
+
+            image = new OutputImage(outputSize);
+            image.fillCircle(calibrationPoints[calibrationPointIndex], 50, Color.Orange);
         }
         }
 
 
-        private void updateCalibrationImage() {
-            //if (image != null)
-            //    image.Dispose();
+        private void updateGUI()
+        {
+            // update image boxes
+            imageBox.Image = image;
 
 
-            image = new OutputImage(Parameters.GlassesWindowWidth, Parameters.GlassesWindowHeight);
+            guiUpToDate = true;
+        }
+
+        private void GlassesWindow_OnKeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.K)
+            {
+                FrameData frameData = inputHandler.FrameData;
+                if (frameData != null)
+                {
+                    lock (frameData)
+                    {
+                        if (frameData.TrackedFingers.Count == 1)
+                        {
+                            Vector2D pointOutput = calibrationPoints[calibrationPointIndex];
+                            Vector2D pointInput = frameData.TrackedFingers[0].TipPoint;
 
 
-            Vector2D calibrationPoint = calibrationPoints[calibrationPointIndex];
-            image.fillCircle(calibrationPoint.IntX, calibrationPoint.IntY, 10, Parameters.CalibrationPointColor);
+                            projection.addCalibrationPoints(pointInput, pointOutput);
 
 
-            calibrationImageUpToDate = true;
+                            calibrationPointIndex = (calibrationPointIndex + 1) % calibrationPoints.Count;
+                            calibrationImageUpToDate = false;
+                        }
+                    }
+                }
+            }
+            else if (e.KeyCode == Keys.R)
+            {
+                projection.reset();
+                calibrationImageUpToDate = false;
+                calibrationPointIndex = 0;
+            }
         }
         }
-
     }
     }
 }
 }

+ 120 - 0
bbiwarg/Output/GlassesOutput/GlassesWindow.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 30 - 24
bbiwarg/Output/OutputImage.cs

@@ -11,10 +11,15 @@ using Emgu.CV.Structure;
 
 
 namespace bbiwarg.Output
 namespace bbiwarg.Output
 {
 {
-    class OutputImage : Image<Rgb,byte>
+    class OutputImage : Image<Rgb, byte>
     {
     {
         public OutputImage(int width, int height)
         public OutputImage(int width, int height)
-            :base(width,height)
+            : base(width, height)
+        {
+        }
+
+        public OutputImage(ImageSize size)
+            : base(size.Width, size.Height)
         {
         {
         }
         }
 
 
@@ -43,31 +48,32 @@ namespace bbiwarg.Output
             Draw(points, new Rgb(color), thickness);
             Draw(points, new Rgb(color), thickness);
         }
         }
 
 
-        public void drawPixel(int x, int y, Color color)
+        public void drawPixel(Point position, Color color)
         {
         {
-            Data[y, x, 0] = color.R;
-            Data[y, x, 1] = color.G;
-            Data[y, x, 2] = color.B;
+            Data[position.Y, position.X, 0] = color.R;
+            Data[position.Y, position.X, 0] = color.G;
+            Data[position.Y, position.X, 0] = color.B;
         }
         }
 
 
-        public void fillCircle(int x, int y, float radius, Color color)
+        public void fillCircle(Point position, float radius, Color color)
         {
         {
-            Draw(new CircleF(new PointF(x, y), radius), new Rgb(color), 0);
+            Draw(new CircleF(position, radius), new Rgb(color), 0);
         }
         }
 
 
-        public void fillRectangle(int x, int y, int width, int height, Color color) {
-            Draw(new Rectangle(x, y, width, height), new Rgb(color),-1);
+        public void fillRectangle(Rectangle rect, Color color)
+        {
+            Draw(rect, new Rgb(color), -1);
         }
         }
 
 
-        public void drawRectangle(int x, int y, int width, int height, Color color, int thichness = 0)
+        public void drawRectangle(Rectangle rect, Color color, int thichness = 0)
         {
         {
-            Draw(new Rectangle(x, y, width, height), new Rgb(color), thichness);
+            Draw(rect, new Rgb(color), thichness);
         }
         }
 
 
-        public void drawText(int x, int y, String text, Color color)
+        public void drawText(Point position, String text, Color color)
         {
         {
             MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 1, 1);
             MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 1, 1);
-            Draw(text, ref font, new Point(x, y), new Rgb(color));
+            Draw(text, ref font, position, new Rgb(color));
         }
         }
 
 
         public void drawDefect(ConvexityDefect defect, Color pointColor, Color lineColor)
         public void drawDefect(ConvexityDefect defect, Color pointColor, Color lineColor)
@@ -75,9 +81,9 @@ namespace bbiwarg.Output
             drawLineSegment(new Utility.LineSegment2D(defect.OuterShort, defect.Inner), lineColor);
             drawLineSegment(new Utility.LineSegment2D(defect.OuterShort, defect.Inner), lineColor);
             drawLineSegment(new Utility.LineSegment2D(defect.OuterLong, defect.Inner), lineColor);
             drawLineSegment(new Utility.LineSegment2D(defect.OuterLong, defect.Inner), lineColor);
 
 
-            fillCircle(defect.Inner.IntX, defect.Inner.IntY, 2, pointColor);
-            fillCircle(defect.OuterShort.IntX, defect.OuterShort.IntY, 2, pointColor);
-            fillCircle(defect.OuterLong.IntX, defect.OuterLong.IntY, 2, pointColor);
+            fillCircle(defect.Inner, 2, pointColor);
+            fillCircle(defect.OuterShort, 2, pointColor);
+            fillCircle(defect.OuterLong, 2, pointColor);
 
 
         }
         }
 
 
@@ -110,13 +116,13 @@ namespace bbiwarg.Output
             drawLineSegment(new bbiwarg.Utility.LineSegment2D(d, a), borderColor);
             drawLineSegment(new bbiwarg.Utility.LineSegment2D(d, a), borderColor);
         }
         }
 
 
-        public void drawBorder(Color color) {
-            drawRectangle(0, 0, Width-1, Height-1, color);
+        public void drawBorder(Color color)
+        {
+            drawRectangle(new Rectangle(0, 0, Width, Height), color);
         }
         }
 
 
-        public void drawTouchGesture(List<Vector2D> positions, float opacity=1)
+        public void drawTouchGesture(List<Vector2D> positions, Vector2D scale, float opacity = 1)
         {
         {
-            Vector2D maxPixel = Parameters.ImageMaxPixel;
             int numPositions = positions.Count;
             int numPositions = positions.Count;
             Color lineColor = Parameters.TouchEventVisualizerLineColor;
             Color lineColor = Parameters.TouchEventVisualizerLineColor;
             Color pointColor = Parameters.TouchEventVisualizerPointColor;
             Color pointColor = Parameters.TouchEventVisualizerPointColor;
@@ -124,10 +130,10 @@ namespace bbiwarg.Output
             Color pointColorFaded = Color.FromArgb((int)(opacity * pointColor.R), (int)(opacity * pointColor.G), (int)(opacity * pointColor.B));
             Color pointColorFaded = Color.FromArgb((int)(opacity * pointColor.R), (int)(opacity * pointColor.G), (int)(opacity * pointColor.B));
             for (int i = 1; i < numPositions; i++)
             for (int i = 1; i < numPositions; i++)
             {
             {
-                drawLineSegment(new Utility.LineSegment2D(positions[i - 1].scale(maxPixel), positions[i].scale(maxPixel)), lineColorFaded);
+                drawLineSegment(new Utility.LineSegment2D(positions[i - 1].scale(scale), positions[i].scale(scale)), lineColorFaded);
             }
             }
-            Vector2D lastPos = positions[numPositions - 1].scale(maxPixel);
-            fillCircle(lastPos.IntX, lastPos.IntY, 3, pointColorFaded);
+            Vector2D lastPos = positions[numPositions - 1].scale(scale);
+            fillCircle(lastPos, 3, pointColorFaded);
         }
         }
 
 
         public void drawImage(Image<Gray, byte> image, Color color)
         public void drawImage(Image<Gray, byte> image, Color color)

+ 16 - 56
bbiwarg/Parameters.cs

@@ -18,44 +18,34 @@ namespace bbiwarg
 
 
     class Parameters
     class Parameters
     {
     {
+        // console
+        public static readonly int ConsoleWidth = 90;
+        public static readonly int ConsoleHeight = 30;
+
         // input
         // input
-        public static readonly InputType InputSource = InputType.Movie;
+        public static readonly InputType InputSource = InputType.Camera;
         public static readonly String InputMoviePath = "..\\..\\videos\\touch\\4.skv";
         public static readonly String InputMoviePath = "..\\..\\videos\\touch\\4.skv";
 
 
         // Logger
         // Logger
-        public static readonly LogSubject EnabledLogSubjects = LogSubject.None;
-        public static readonly int ConsoleWidth = 90;
-        public static readonly int ConsoleHeight = 30;
+        public static readonly bool LoggerTimerOutputEnabled = false;
+        public static readonly LogSubject LoggerEnabledSubjects = LogSubject.None;
 
 
         // Debug window
         // Debug window
         public static readonly bool DebugWindowEnabled = true;
         public static readonly bool DebugWindowEnabled = true;
-        public static readonly int DebugWindowUpdateRate = 30;
-        public static readonly int DebugWindowRenderRate = 30;
-        public static readonly int DebugWindowNumImages = 5;
-        public static readonly int DebugWindowNumImagesPerRow = 3;
-        public static readonly float DebugWindowScaleFactor = 1f; // output window size is scaled by this factor (from necessary size for images)
+        public static readonly int DebugWindowUpdateIntervall = 1000 / 30; // 30fps
         public static readonly String DebugWindowTitle = "BBIWARG - DebugOutput";
         public static readonly String DebugWindowTitle = "BBIWARG - DebugOutput";
 
 
         // glasses window
         // glasses window
         public static readonly bool GlassesWindowEnabled = true;
         public static readonly bool GlassesWindowEnabled = true;
         public static readonly int GlassesWindowUpdateRate = 30;
         public static readonly int GlassesWindowUpdateRate = 30;
-        public static readonly int GlassesWindowRenderRate = 30;
-        public static readonly int GlassesWindowWidth = 320;//1280;
-        public static readonly int GlassesWindowHeight = 240;//720;
+        public static readonly int GlassesWindowUpdateInterval = 1000 / 30; // 30fps
+        public static readonly ImageSize GlassesWindowOutputSize = new ImageSize(1024, 768);
         public static readonly String GlassesWindowTitle = "BBIWARG - GlassesOutput";
         public static readonly String GlassesWindowTitle = "BBIWARG - GlassesOutput";
 
 
         // TUIO
         // TUIO
-        public static bool TuioEnabled { get; private set; }
-        public static IPAddress TuioIP { get; private set; }
-        public static Int16 TuioPort { get; private set; }
-
-        // image
-        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; }
+        public static readonly bool TuioEnabledByDefault = false;
+        public static readonly String TuioDefaultIP = "127.0.0.1";
+        public static readonly Int16 TuioDefaultPort = 3333;
 
 
         // confidence image
         // confidence image
         public static readonly int ConfidenceImageMinThreshold = 500;
         public static readonly int ConfidenceImageMinThreshold = 500;
@@ -102,7 +92,7 @@ namespace bbiwarg
         public static readonly int HandFloodFillUpDiff = 2;
         public static readonly int HandFloodFillUpDiff = 2;
         public static readonly float HandMaxSize = 0.6f;
         public static readonly float HandMaxSize = 0.6f;
         public static readonly float HandMinSize = 0.01f;
         public static readonly float HandMinSize = 0.01f;
-        public static readonly float HandExtensionMaxSize = 0.5f * HandMaxSize;
+        public static readonly float HandExtensionMaxRelativeSize = 0.5f * HandMaxSize;
         public static readonly int HandExtendMaxDifference = 40;
         public static readonly int HandExtendMaxDifference = 40;
         public static readonly float HandThumbDefectMaxDistanceToThumb = FingerMaxWidth;
         public static readonly float HandThumbDefectMaxDistanceToThumb = FingerMaxWidth;
         public static readonly float HandThumbDefectMinThumbShortLengthRatio = 0.75f;
         public static readonly float HandThumbDefectMinThumbShortLengthRatio = 0.75f;
@@ -134,8 +124,8 @@ namespace bbiwarg
         public static readonly float PalmmYY = 0.00005f;
         public static readonly float PalmmYY = 0.00005f;
 
 
         //palm Grid
         //palm Grid
-        public static int PalmGridNumRows { get; private set; }
-        public static int PalmGridNumColumns { get; private set; }
+        public static readonly int PalmGridDefaultNumRows = 3;
+        public static readonly int PalmGridDefaultNumColumns = 4;
 
 
         // touch detection
         // touch detection
         public static readonly float TouchMinTouchValue = 0.3f;
         public static readonly float TouchMinTouchValue = 0.3f;
@@ -195,35 +185,5 @@ namespace bbiwarg
         public static readonly Color HandThumbDefectLineColor = Color.CornflowerBlue;
         public static readonly Color HandThumbDefectLineColor = Color.CornflowerBlue;
 
 
         public static readonly Color CalibrationPointColor = Color.Yellow;
         public static readonly Color CalibrationPointColor = Color.Yellow;
-
-        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;
-        }
     }
     }
 }
 }

+ 7 - 7
bbiwarg/Recognition/FingerRecognition/FingerDetector.cs

@@ -27,7 +27,7 @@ namespace bbiwarg.Recognition.FingerRecognition
             edgeImageAdapted = frameData.EdgeImage.copy();
             edgeImageAdapted = frameData.EdgeImage.copy();
             fingers = new List<Finger>();
             fingers = new List<Finger>();
 
 
-            Vector2D maxPixel = Parameters.ImageMaxPixel;
+            Vector2D maxPixel = depthImage.Size.MaxPixel;
             int maxX = maxPixel.IntX;
             int maxX = maxPixel.IntX;
             int maxY = maxPixel.IntY;
             int maxY = maxPixel.IntY;
 
 
@@ -81,7 +81,7 @@ namespace bbiwarg.Recognition.FingerRecognition
             Vector2D direction = startDirection;
             Vector2D direction = startDirection;
             Vector2D position = startSlice.Mid + Parameters.FingerStepSize * direction;
             Vector2D position = startSlice.Mid + Parameters.FingerStepSize * direction;
 
 
-            if (position.isInBound())
+            if (position.isInBound(depthImage.Size))
             {
             {
                 FingerSlice nextSlice = findFingerSliceFromMid(position, direction);
                 FingerSlice nextSlice = findFingerSliceFromMid(position, direction);
                 if (nextSlice != null)
                 if (nextSlice != null)
@@ -116,7 +116,7 @@ namespace bbiwarg.Recognition.FingerRecognition
             FingerSlice lastSlice = trail.EndSlice;
             FingerSlice lastSlice = trail.EndSlice;
             FingerSlice nextSlice;
             FingerSlice nextSlice;
 
 
-            while (currentPosition.isInBound() && gapCounter < Math.Min(numSlices, Parameters.FingerMaxGapCounter))
+            while (currentPosition.isInBound(depthImage.Size) && gapCounter < Math.Min(numSlices, Parameters.FingerMaxGapCounter))
             {
             {
                 nextSlice = findFingerSliceFromMid(currentPosition, currentDirection, reversed);
                 nextSlice = findFingerSliceFromMid(currentPosition, currentDirection, reversed);
 
 
@@ -179,9 +179,9 @@ namespace bbiwarg.Recognition.FingerRecognition
 
 
         private bool fingerSliceDepthTest(FingerSlice slice)
         private bool fingerSliceDepthTest(FingerSlice slice)
         {
         {
-            Int16 depthStart = depthImage.getDepthAt(slice.Start.moveWithinBound(slice.Direction.getInverse(), Parameters.FingerContourMargin));
+            Int16 depthStart = depthImage.getDepthAt(slice.Start.moveWithinBound(depthImage.Size, slice.Direction.getInverse(), Parameters.FingerContourMargin));
             Int16 depthMid = depthImage.getDepthAt(slice.Mid);
             Int16 depthMid = depthImage.getDepthAt(slice.Mid);
-            Int16 depthEnd = depthImage.getDepthAt(slice.End.moveWithinBound(slice.Direction, Parameters.FingerContourMargin));
+            Int16 depthEnd = depthImage.getDepthAt(slice.End.moveWithinBound(depthImage.Size, slice.Direction, Parameters.FingerContourMargin));
             return (depthStart > depthMid && depthMid < depthEnd);
             return (depthStart > depthMid && depthMid < depthEnd);
         }
         }
 
 
@@ -204,8 +204,8 @@ namespace bbiwarg.Recognition.FingerRecognition
         private bool isCrippleFinger(Finger finger)
         private bool isCrippleFinger(Finger finger)
         {
         {
             FingerSlice midSlice = finger.SliceTrail.MidSlice;
             FingerSlice midSlice = finger.SliceTrail.MidSlice;
-            Vector2D out1 = midSlice.Start.moveWithinBound(midSlice.Direction.getInverse(), Parameters.FingerOutMargin);
-            Vector2D out2 = midSlice.End.moveWithinBound(midSlice.Direction, Parameters.FingerOutMargin);
+            Vector2D out1 = midSlice.Start.moveWithinBound(depthImage.Size, midSlice.Direction.getInverse(), Parameters.FingerOutMargin);
+            Vector2D out2 = midSlice.End.moveWithinBound(depthImage.Size, midSlice.Direction, Parameters.FingerOutMargin);
 
 
             Int16 depthAtFinger = depthImage.getDepthAt(finger.MidPoint);
             Int16 depthAtFinger = depthImage.getDepthAt(finger.MidPoint);
             Int16 depthAtOut1 = depthImage.getDepthAt(out1);
             Int16 depthAtOut1 = depthImage.getDepthAt(out1);

+ 5 - 4
bbiwarg/Recognition/FingerRecognition/FingerSliceTrail.cs

@@ -42,7 +42,7 @@ namespace bbiwarg.Recognition.FingerRecognition
 
 
         public Vector2D getStartDirection()
         public Vector2D getStartDirection()
         {
         {
-            int innerStartIndex = Math.Min(NumSlices-1, Parameters.FingerNumSlicesForRelativeDirection);
+            int innerStartIndex = Math.Min(NumSlices - 1, Parameters.FingerNumSlicesForRelativeDirection);
             return (StartSlice.Mid - Slices[innerStartIndex].Mid).normalize();
             return (StartSlice.Mid - Slices[innerStartIndex].Mid).normalize();
         }
         }
 
 
@@ -66,15 +66,16 @@ namespace bbiwarg.Recognition.FingerRecognition
             fittedDirectionUpToDate = false;
             fittedDirectionUpToDate = false;
         }
         }
 
 
-        public Contour<Point> getContour(float margin) {
+        public Contour<Point> getContour(float margin)
+        {
             List<Point> pointsA = new List<Point>();
             List<Point> pointsA = new List<Point>();
             List<Point> pointsB = new List<Point>();
             List<Point> pointsB = new List<Point>();
 
 
             foreach (FingerSlice slice in Slices)
             foreach (FingerSlice slice in Slices)
             {
             {
                 Vector2D direction = slice.Direction;
                 Vector2D direction = slice.Direction;
-                pointsA.Add(slice.Start.moveWithinBound(direction.getInverse(), margin));
-                pointsB.Add(slice.End.moveWithinBound(direction, margin));
+                pointsA.Add(slice.Start + margin * direction.getInverse());
+                pointsB.Add(slice.End + margin * direction);
             }
             }
 
 
             pointsA.Reverse();
             pointsA.Reverse();

+ 25 - 1
bbiwarg/Recognition/FingerRecognition/FingerTracker.cs

@@ -9,14 +9,38 @@ using bbiwarg.Input.InputHandling;
 
 
 namespace bbiwarg.Recognition.FingerRecognition
 namespace bbiwarg.Recognition.FingerRecognition
 {
 {
-
     class FingerTracker : Tracker<Finger, TrackedFinger>
     class FingerTracker : Tracker<Finger, TrackedFinger>
     {
     {
+        public FingerTracker(ImageSize imageSize)
+            : base(imageSize)
+        {
+        }
+
         public void trackFingers(FrameData frameData) {
         public void trackFingers(FrameData frameData) {
             trackObjects(frameData.DetectedFingers);
             trackObjects(frameData.DetectedFingers);
             frameData.TrackedFingers = getCurrentObjectsWithState(TrackingState.Tracked);
             frameData.TrackedFingers = getCurrentObjectsWithState(TrackingState.Tracked);
         }
         }
 
 
+        public override float calculateSimilarity(TrackedFinger trackedFinger, Finger detectedFinger)
+        {
+            Vector2D tip, hand;
+            if (trackedFinger.shouldFingerBeReversed(detectedFinger))
+            {
+                tip = detectedFinger.HandPoint;
+                hand = detectedFinger.TipPoint;
+            }
+            else
+            {
+                tip = detectedFinger.TipPoint;
+                hand = detectedFinger.HandPoint;
+            }
+
+            float tipPointSimilarity = getPositionSimilarity(trackedFinger.TipPointPrediction, tip, Parameters.FingerTrackerMaxTipPointRelativeMove);
+            float handPointSimilarity = getPositionSimilarity(trackedFinger.HandPointPrediction, hand, Parameters.FingerTrackerMaxHandPointRelativeMove);
+
+            return tipPointSimilarity * handPointSimilarity;
+        }
+
         protected override TrackedFinger createTrackedObject(Finger detectedObject)
         protected override TrackedFinger createTrackedObject(Finger detectedObject)
         {
         {
             return new TrackedFinger(idPool.getNextUnusedID(), detectedObject, Parameters.FingerTrackerNumFramesDetectedUntilTracked, Parameters.FingerTrackerNumFramesLostUntilDeleted);
             return new TrackedFinger(idPool.getNextUnusedID(), detectedObject, Parameters.FingerTrackerNumFramesDetectedUntilTracked, Parameters.FingerTrackerNumFramesLostUntilDeleted);

+ 1 - 21
bbiwarg/Recognition/FingerRecognition/TrackedFinger.cs

@@ -51,27 +51,7 @@ namespace bbiwarg.Recognition.FingerRecognition
             }
             }
         }
         }
 
 
-        public override float calculateSimilarity(Finger detectedFinger)
-        {
-            Vector2D tip, hand;
-            if (shouldFingerBeReversed(detectedFinger))
-            {
-                tip = detectedFinger.HandPoint;
-                hand = detectedFinger.TipPoint;
-            }
-            else
-            {
-                tip = detectedFinger.TipPoint;
-                hand = detectedFinger.HandPoint;
-            }
-
-            float tipPointSimilarity = getPositionSimilarity(TipPointPrediction, tip, Parameters.FingerTrackerMaxTipPointRelativeMove);
-            float handPointSimilarity = getPositionSimilarity(HandPointPrediction, hand, Parameters.FingerTrackerMaxHandPointRelativeMove);
-
-            return tipPointSimilarity * handPointSimilarity;
-        }
-
-        private bool shouldFingerBeReversed(Finger detectedFinger)
+        public bool shouldFingerBeReversed(Finger detectedFinger)
         {
         {
             Vector2D meanDirection = Vector2D.mean(lastRawDirections);
             Vector2D meanDirection = Vector2D.mean(lastRawDirections);
             return meanDirection.isInOppositeDirection(detectedFinger.Direction);
             return meanDirection.isInOppositeDirection(detectedFinger.Direction);

+ 4 - 3
bbiwarg/Recognition/HandRecognition/Hand.cs

@@ -47,15 +47,16 @@ namespace bbiwarg.Recognition.HandRecognition
             Mask = Mask.Or(extendMask);
             Mask = Mask.Or(extendMask);
         }
         }
 
 
-        public void fillOverlappingFingers(List<Finger> otherFingers)
+        public void fillOverlappingFingers(List<Finger> otherFingers, ImageSize imageSize)
         {
         {
             foreach (Finger finger in otherFingers)
             foreach (Finger finger in otherFingers)
             {
             {
                 FingerSliceTrail trail = null;
                 FingerSliceTrail trail = null;
                 foreach (FingerSlice slice in finger.SliceTrail.Slices)
                 foreach (FingerSlice slice in finger.SliceTrail.Slices)
                 {
                 {
-                    Vector2D out1 = slice.Start.moveWithinBound(slice.Direction.getInverse(), Parameters.FingerContourMargin);
-                    Vector2D out2 = slice.End.moveWithinBound(slice.Direction, Parameters.FingerContourMargin);
+                    Vector2D direction = slice.Direction;
+                    Vector2D out1 = slice.Start.moveWithinBound(imageSize, direction.getInverse(), Parameters.FingerContourMargin);
+                    Vector2D out2 = slice.End.moveWithinBound(imageSize, direction, Parameters.FingerContourMargin); 
 
 
                     if (isInside(out1) && isInside(out2))
                     if (isInside(out1) && isInside(out2))
                     {
                     {

+ 6 - 6
bbiwarg/Recognition/HandRecognition/HandDetector.cs

@@ -82,10 +82,10 @@ namespace bbiwarg.Recognition.HandRecognition
 
 
         private Image<Gray, byte> getHandMask(Vector2D p)
         private Image<Gray, byte> getHandMask(Vector2D p)
         {
         {
-            Image<Gray, byte> mask = new Image<Gray, byte>(Parameters.ImageWidth + 2, Parameters.ImageHeight + 2);
+            Image<Gray, byte> mask = new Image<Gray, byte>(depthImage.Size.Width + 2, depthImage.Size.Height + 2);
             MCvConnectedComp comp = new MCvConnectedComp();
             MCvConnectedComp comp = new MCvConnectedComp();
             CvInvoke.cvFloodFill(modifiedHandDepthImage, p, new MCvScalar(255), new MCvScalar(Parameters.HandFloodFillDownDiff), new MCvScalar(Parameters.HandFloodFillUpDiff), out comp, Emgu.CV.CvEnum.CONNECTIVITY.FOUR_CONNECTED, Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, mask);
             CvInvoke.cvFloodFill(modifiedHandDepthImage, p, new MCvScalar(255), new MCvScalar(Parameters.HandFloodFillDownDiff), new MCvScalar(Parameters.HandFloodFillUpDiff), out comp, Emgu.CV.CvEnum.CONNECTIVITY.FOUR_CONNECTED, Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, mask);
-            return mask.Copy(new Rectangle(1, 1, Parameters.ImageWidth, Parameters.ImageHeight));
+            return mask.Copy(new Rectangle(1, 1, depthImage.Size.Width, depthImage.Size.Height));
         }
         }
 
 
         private void fixOverlappingFingers()
         private void fixOverlappingFingers()
@@ -106,8 +106,8 @@ namespace bbiwarg.Recognition.HandRecognition
                     foreach (Finger overlappingFinger in otherHandsFingers[hand])
                     foreach (Finger overlappingFinger in otherHandsFingers[hand])
                     {
                     {
                         FingerSlice midSlice = overlappingFinger.SliceTrail.MidSlice;
                         FingerSlice midSlice = overlappingFinger.SliceTrail.MidSlice;
-                        Vector2D midOut1 = midSlice.Start.moveWithinBound(midSlice.Direction.getInverse(), Parameters.FingerOutMargin);
-                        Vector2D midOut2 = midSlice.End.moveWithinBound(midSlice.Direction, Parameters.FingerOutMargin);
+                        Vector2D midOut1 = midSlice.Start.moveWithinBound(depthImage.Size, midSlice.Direction.getInverse(), Parameters.FingerOutMargin);
+                        Vector2D midOut2 = midSlice.End.moveWithinBound(depthImage.Size, midSlice.Direction, Parameters.FingerOutMargin);
                         Int16 depthAtMidOut1 = depthImage.getDepthAt(midOut1);
                         Int16 depthAtMidOut1 = depthImage.getDepthAt(midOut1);
                         Int16 depthAtMidOut2 = depthImage.getDepthAt(midOut2);
                         Int16 depthAtMidOut2 = depthImage.getDepthAt(midOut2);
                         bool midOut1InHand = hand.isInside(midOut1);
                         bool midOut1InHand = hand.isInside(midOut1);
@@ -169,7 +169,7 @@ namespace bbiwarg.Recognition.HandRecognition
             Image<Gray, byte> extendMask = getHandMask(p);
             Image<Gray, byte> extendMask = getHandMask(p);
             int numPixels = extendMask.CountNonzero()[0];
             int numPixels = extendMask.CountNonzero()[0];
 
 
-            if (numPixels <= Parameters.HandExtensionMaxSize * Parameters.ImageNumPixels)
+            if (numPixels <= Parameters.HandExtensionMaxRelativeSize * depthImage.Size.NumPixels)
                 hand.extendMask(extendMask);
                 hand.extendMask(extendMask);
         }
         }
 
 
@@ -177,7 +177,7 @@ namespace bbiwarg.Recognition.HandRecognition
         {
         {
             foreach (Hand hand in hands)
             foreach (Hand hand in hands)
             {
             {
-                hand.fillOverlappingFingers(otherHandsFingers[hand]);
+                hand.fillOverlappingFingers(otherHandsFingers[hand], depthImage.Size);
             }
             }
         }
         }
 
 

+ 11 - 0
bbiwarg/Recognition/HandRecognition/HandTracker.cs

@@ -5,17 +5,28 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Input.InputHandling;
 using bbiwarg.Input.InputHandling;
+using bbiwarg.Utility;
 
 
 namespace bbiwarg.Recognition.HandRecognition
 namespace bbiwarg.Recognition.HandRecognition
 {
 {
     class HandTracker : Tracker<Hand, TrackedHand>
     class HandTracker : Tracker<Hand, TrackedHand>
     {
     {
+        public HandTracker(ImageSize imageSize)
+            : base(imageSize)
+        {
+        }
+
         public void trackHands(FrameData frameData)
         public void trackHands(FrameData frameData)
         {
         {
             trackObjects(frameData.DetectedHands);
             trackObjects(frameData.DetectedHands);
             frameData.TrackedHands = getCurrentObjectsWithState(TrackingState.Tracked);
             frameData.TrackedHands = getCurrentObjectsWithState(TrackingState.Tracked);
         }
         }
 
 
+        public override float calculateSimilarity(TrackedHand trackedHand, Hand detectedHand)
+        {
+            return getPositionSimilarity(trackedHand.CentroidPrediction, detectedHand.Centroid, Parameters.HandTrackerMaxCentroidRelativeMove);
+        }
+
         protected override TrackedHand createTrackedObject(Hand detectedObject)
         protected override TrackedHand createTrackedObject(Hand detectedObject)
         {
         {
             return new TrackedHand(idPool.getNextUnusedID(), detectedObject, Parameters.HandTrackerNumFramesDetectedUntilTracked, Parameters.HandTrackerNumFramesLostUntilDeleted);
             return new TrackedHand(idPool.getNextUnusedID(), detectedObject, Parameters.HandTrackerNumFramesDetectedUntilTracked, Parameters.HandTrackerNumFramesLostUntilDeleted);

+ 0 - 7
bbiwarg/Recognition/HandRecognition/TrackedHand.cs

@@ -34,13 +34,6 @@ namespace bbiwarg.Recognition.HandRecognition
                 centroidKalman.getCorrectedPosition(detectedHand.Centroid);
                 centroidKalman.getCorrectedPosition(detectedHand.Centroid);
         }
         }
 
 
-        public override float calculateSimilarity(Hand detectedHand)
-        {
-            float centroidSimilarity = getPositionSimilarity(CentroidPrediction, detectedHand.Centroid, Parameters.HandTrackerMaxCentroidRelativeMove);
-
-            return centroidSimilarity;
-        }
-
         private void logStateChange()
         private void logStateChange()
         {
         {
             String stateAsString = CurrentState.ToString().ToLower();
             String stateAsString = CurrentState.ToString().ToLower();

+ 13 - 13
bbiwarg/Recognition/PalmRecognition/PalmDetector.cs

@@ -83,8 +83,8 @@ namespace bbiwarg.Recognition.PalmRecognition
             float palmLength = wristUpper.getDistanceTo(fingersUpper);
             float palmLength = wristUpper.getDistanceTo(fingersUpper);
             Vector2D directionWristFingers = thumbDefect.VectorLong.normalize();
             Vector2D directionWristFingers = thumbDefect.VectorLong.normalize();
             Vector2D directionUpperLower = thumbDefect.VectorLong.getOrthogonal(side == HandSide.Right).normalize();
             Vector2D directionUpperLower = thumbDefect.VectorLong.getOrthogonal(side == HandSide.Right).normalize();
-            Vector2D wristLower = wristUpper.moveWithinBound(directionUpperLower, palmWidth);
-            Vector2D fingersLower = (wristUpper + 0.75f * palmLength * directionWristFingers + 0.75f * palmWidth * directionUpperLower).moveInBound((directionUpperLower + directionWristFingers).getInverse().normalize());
+            Vector2D wristLower = wristUpper + palmWidth*directionUpperLower;
+            Vector2D fingersLower = wristUpper + 0.75f * palmLength * directionWristFingers + 0.75f * palmWidth * directionUpperLower;
 
 
             return new Palm(hand, thumbDefect, side, wristUpper, fingersUpper, fingersLower, wristLower);
             return new Palm(hand, thumbDefect, side, wristUpper, fingersUpper, fingersLower, wristLower);
         }
         }
@@ -100,9 +100,9 @@ namespace bbiwarg.Recognition.PalmRecognition
         private Vector2D findWristUpper(Hand hand, ConvexityDefect thumbDefect)
         private Vector2D findWristUpper(Hand hand, ConvexityDefect thumbDefect)
         {
         {
             Vector2D wristDirection = thumbDefect.VectorLong.getInverse().normalize();
             Vector2D wristDirection = thumbDefect.VectorLong.getInverse().normalize();
-            Vector2D wristUpper = thumbDefect.Inner.moveWithinBound(wristDirection, 5f);
-            Vector2D wristUpperNext = wristUpper + wristDirection;
-            while (wristUpperNext.isInBound() && hand.isInside(wristUpperNext))
+            Vector2D wristUpper = thumbDefect.Inner;
+            Vector2D wristUpperNext = wristUpper + 5*wristDirection;
+            while (wristUpperNext.isInBound(depthImage.Size) && hand.isInside(wristUpperNext))
             {
             {
                 wristUpper = wristUpperNext;
                 wristUpper = wristUpperNext;
                 wristUpperNext += wristDirection;
                 wristUpperNext += wristDirection;
@@ -117,14 +117,14 @@ namespace bbiwarg.Recognition.PalmRecognition
             Vector2D fingersUpper = thumbDefect.OuterLong;
             Vector2D fingersUpper = thumbDefect.OuterLong;
             Vector2D fingersUpperNext = fingersUpper + fingersDirection;
             Vector2D fingersUpperNext = fingersUpper + fingersDirection;
             bool handBelow = true;
             bool handBelow = true;
-            while (handBelow && fingersUpperNext.isInBound())
+            while (handBelow && fingersUpperNext.isInBound(depthImage.Size))
             {
             {
                 fingersUpper = fingersUpperNext;
                 fingersUpper = fingersUpperNext;
                 fingersUpperNext += fingersDirection;
                 fingersUpperNext += fingersDirection;
                 Vector2D below = fingersUpper.copy();
                 Vector2D below = fingersUpper.copy();
                 handBelow = false;
                 handBelow = false;
                 int distance = 0;
                 int distance = 0;
-                while (!handBelow && distance < Parameters.FingerMaxWidth && below.isInBound())
+                while (!handBelow && distance < Parameters.FingerMaxWidth && below.isInBound(depthImage.Size))
                 {
                 {
                     handBelow = hand.isInside(below);
                     handBelow = hand.isInside(below);
                     below += lowerDirection;
                     below += lowerDirection;
@@ -142,14 +142,14 @@ namespace bbiwarg.Recognition.PalmRecognition
             float maxWidth = float.MinValue;
             float maxWidth = float.MinValue;
             for (int i = 0; i < Parameters.PalmNumPositionsForPalmWidth; i++)
             for (int i = 0; i < Parameters.PalmNumPositionsForPalmWidth; i++)
             {
             {
-                Vector2D lower = current.moveWithinBound(lowerDirection, 10f);
-                float width = current.getDistanceTo(lower);
-                while (lower.isInBound() && hand.isInside(lower))
+                Vector2D lower = current;
+                Vector2D lowerNext = lower + 10 * lowerDirection;
+                while (lowerNext.isInBound(depthImage.Size) && hand.isInside(lowerNext))
                 {
                 {
-                    lower += lowerDirection;
-                    width += 1;
+                    lower = lowerNext;
+                    lowerNext += lowerDirection;
                 }
                 }
-                maxWidth = Math.Max(maxWidth, width);
+                maxWidth = Math.Max(maxWidth, current.getDistanceTo(lower));
                 current += step;
                 current += step;
             }
             }
             return maxWidth;
             return maxWidth;

+ 19 - 1
bbiwarg/Recognition/PalmRecognition/PalmTracker.cs

@@ -5,16 +5,34 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Input.InputHandling;
 using bbiwarg.Input.InputHandling;
+using bbiwarg.Utility;
 
 
 namespace bbiwarg.Recognition.PalmRecognition
 namespace bbiwarg.Recognition.PalmRecognition
 {
 {
     class PalmTracker : Tracker<Palm, TrackedPalm>
     class PalmTracker : Tracker<Palm, TrackedPalm>
     {
     {
-        public void trackPalms(FrameData frameData) {
+        public PalmTracker(ImageSize imageSize)
+            : base(imageSize)
+        {
+        }
+
+        public void trackPalms(FrameData frameData)
+        {
             trackObjects(frameData.DetectedPalms);
             trackObjects(frameData.DetectedPalms);
             frameData.TrackedPalms = getOptimizedPalms();
             frameData.TrackedPalms = getOptimizedPalms();
         }
         }
 
 
+        public override float calculateSimilarity(TrackedPalm trackedPalm, Palm detectedPalm)
+        {
+            float handSimilarity = (detectedPalm.Hand.TrackID == trackedPalm.LastObject.Hand.TrackID) ? 1 : 0;
+            float wristUpperSimilarity = getPositionSimilarity(trackedPalm.WristUpperPrediction, detectedPalm.WristUpper, Parameters.PalmTrackerMaxWristUpperRelativeMove);
+            float wristLowerSimilarity = getPositionSimilarity(trackedPalm.WristLowerPrediction, detectedPalm.WristLower, Parameters.PalmTrackerMaxWristLowerRelativeMove);
+            float fingersUpperSimilarity = getPositionSimilarity(trackedPalm.FingersUpperPrediction, detectedPalm.FingersUpper, Parameters.PalmTrackerMaxFingersUpperRelativeMove);
+            float fingersLowerSimilarity = getPositionSimilarity(trackedPalm.FingersLowerPrediction, detectedPalm.FingersLower, Parameters.PalmTrackerMaxFingersLowerRelativeMove);
+
+            return handSimilarity * wristUpperSimilarity * wristLowerSimilarity * fingersUpperSimilarity * fingersLowerSimilarity;
+        }
+
         protected override TrackedPalm createTrackedObject(Palm detectedPalm)
         protected override TrackedPalm createTrackedObject(Palm detectedPalm)
         {
         {
             return new TrackedPalm(idPool.getNextUnusedID(), detectedPalm, Parameters.PalmTrackerNumFramesDetectedUntilTracked, Parameters.PalmTrackerNumFramesLostUntilDeleted);
             return new TrackedPalm(idPool.getNextUnusedID(), detectedPalm, Parameters.PalmTrackerNumFramesDetectedUntilTracked, Parameters.PalmTrackerNumFramesLostUntilDeleted);

+ 0 - 13
bbiwarg/Recognition/PalmRecognition/TrackedPalm.cs

@@ -61,19 +61,6 @@ namespace bbiwarg.Recognition.PalmRecognition
             OptimizedPalm = new Palm(detectedPalm.Hand, detectedPalm.ThumbDefect, detectedPalm.HandSide, WristUpperPrediction, FingersUpperPrediction, FingersLowerPrediction, WristLowerPrediction);
             OptimizedPalm = new Palm(detectedPalm.Hand, detectedPalm.ThumbDefect, detectedPalm.HandSide, WristUpperPrediction, FingersUpperPrediction, FingersLowerPrediction, WristLowerPrediction);
         }
         }
 
 
-        public override float calculateSimilarity(Palm detectedPalm)
-        {
-            float handSimilarity = (detectedPalm.Hand.TrackID == LastObject.Hand.TrackID) ? 1 : 0;
-            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;
-
-            return similarity;
-        }
-
         private void logStateChange()
         private void logStateChange()
         {
         {
             String stateAsString = CurrentState.ToString().ToLower();
             String stateAsString = CurrentState.ToString().ToLower();

+ 4 - 5
bbiwarg/Recognition/TouchRecognition/TouchDetector.cs

@@ -41,8 +41,8 @@ namespace bbiwarg.Recognition.TouchRecognition
             {
             {
                 Vector2D tipPoint = finger.TipPoint;
                 Vector2D tipPoint = finger.TipPoint;
                 Vector2D direction = finger.Direction;
                 Vector2D direction = finger.Direction;
-                Vector2D tipPointInside = tipPoint.moveWithinBound(direction.getInverse(), Parameters.TouchTipInsideFactor);
-                Vector2D tipPointOutside = tipPoint.moveWithinBound(direction, Parameters.TouchTipOutsideFactor);
+                Vector2D tipPointInside = tipPoint.moveWithinBound(depthImage.Size, direction.getInverse(), Parameters.TouchTipInsideFactor);
+                Vector2D tipPointOutside = tipPoint.moveWithinBound(depthImage.Size, direction, Parameters.TouchTipOutsideFactor);
 
 
                 foreach (Palm palm in palms)
                 foreach (Palm palm in palms)
                 {
                 {
@@ -66,11 +66,10 @@ namespace bbiwarg.Recognition.TouchRecognition
 
 
         private Image<Gray, byte> getTouchMask(Vector2D touchPoint)
         private Image<Gray, byte> getTouchMask(Vector2D touchPoint)
         {
         {
-
             int minX = Math.Max(touchPoint.IntX - 2 * Parameters.TouchAreaSize / 3, 0);
             int minX = Math.Max(touchPoint.IntX - 2 * Parameters.TouchAreaSize / 3, 0);
-            int maxX = Math.Min(touchPoint.IntX + Parameters.TouchAreaSize / 3, Parameters.ImageWidth - 1);
+            int maxX = Math.Min(touchPoint.IntX + Parameters.TouchAreaSize / 3, depthImage.Size.Width - 1);
             int minY = Math.Max(touchPoint.IntY - 2 * Parameters.TouchAreaSize / 3, 0);
             int minY = Math.Max(touchPoint.IntY - 2 * Parameters.TouchAreaSize / 3, 0);
-            int maxY = Math.Min(touchPoint.IntY + Parameters.TouchAreaSize / 3, Parameters.ImageHeight - 1);
+            int maxY = Math.Min(touchPoint.IntY + Parameters.TouchAreaSize / 3, depthImage.Size.Height - 1);
 
 
             Vector2D relTouchPoint = new Vector2D(touchPoint.IntX - minX, touchPoint.IntY - minY);
             Vector2D relTouchPoint = new Vector2D(touchPoint.IntX - minX, touchPoint.IntY - minY);
             Rectangle rect = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);
             Rectangle rect = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);

+ 27 - 0
bbiwarg/Recognition/TouchRecognition/TouchEvent.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bbiwarg.Recognition.TouchRecognition
+{
+    public enum TouchEventType
+    {
+        Down,
+        Move,
+        Up
+    }
+
+    public class TouchEvent
+    {
+        public TouchEventType Type { get; private set; }
+        public Touch Touch { get; private set; }
+
+        public TouchEvent(TouchEventType type, Touch touch)
+        {
+            Type = type;
+            Touch = touch;
+        }
+    }
+}

+ 18 - 9
bbiwarg/Recognition/TouchRecognition/TouchTracker.cs

@@ -14,18 +14,26 @@ namespace bbiwarg.Recognition.TouchRecognition
 {
 {
     class TouchTracker : Tracker<Touch, TrackedTouch>
     class TouchTracker : Tracker<Touch, TrackedTouch>
     {
     {
-        private List<TouchEventArgs> touchEvents;
-        
-        public TouchTracker() {
-            touchEvents = new List<TouchEventArgs>();
+        private List<TouchEvent> touchEvents;
+
+        public TouchTracker(ImageSize imageSize)
+            : base(imageSize)
+        {
+            touchEvents = new List<TouchEvent>();
         }
         }
 
 
-        public void trackTouches(FrameData frameData) {
+        public void trackTouches(FrameData frameData)
+        {
             trackObjects(frameData.DetectedTouches);
             trackObjects(frameData.DetectedTouches);
             frameData.TrackedTouches = getOptimizedTouches();
             frameData.TrackedTouches = getOptimizedTouches();
             frameData.TouchEvents = flushTouchEvents();
             frameData.TouchEvents = flushTouchEvents();
         }
         }
 
 
+        public override float calculateSimilarity(TrackedTouch trackedTouch, Touch detectedTouch)
+        {
+            return (trackedTouch.FingerID == detectedTouch.Finger.TrackID) ? 1 : 0;
+        }
+
         protected override TrackedTouch createTrackedObject(Touch detectedObject)
         protected override TrackedTouch createTrackedObject(Touch detectedObject)
         {
         {
             TrackedTouch tt = new TrackedTouch(idPool.getNextUnusedID(), detectedObject, Parameters.TouchTrackerNumFramesDetectedUntilTracked, Parameters.TouchTrackerNumFramesLostUntilDeleted);
             TrackedTouch tt = new TrackedTouch(idPool.getNextUnusedID(), detectedObject, Parameters.TouchTrackerNumFramesDetectedUntilTracked, Parameters.TouchTrackerNumFramesLostUntilDeleted);
@@ -44,14 +52,15 @@ namespace bbiwarg.Recognition.TouchRecognition
             return optimizedTouchs;
             return optimizedTouchs;
         }
         }
 
 
-        private void touchEvent(TrackedTouch sender, TouchEventArgs e)
+        private void touchEvent(object sender, TouchEvent e)
         {
         {
             touchEvents.Add(e);
             touchEvents.Add(e);
         }
         }
 
 
-        public List<TouchEventArgs> flushTouchEvents() {
-            List<TouchEventArgs> flushedTouchEvents = touchEvents;
-            touchEvents = new List<TouchEventArgs>();
+        public List<TouchEvent> flushTouchEvents()
+        {
+            List<TouchEvent> flushedTouchEvents = touchEvents;
+            touchEvents = new List<TouchEvent>();
             return flushedTouchEvents;
             return flushedTouchEvents;
         }
         }
 
 

+ 7 - 39
bbiwarg/Recognition/TouchRecognition/TrackedTouch.cs

@@ -8,37 +8,16 @@ using bbiwarg.Utility;
 
 
 namespace bbiwarg.Recognition.TouchRecognition
 namespace bbiwarg.Recognition.TouchRecognition
 {
 {
-    public enum TouchEventType
-    {
-        Down,
-        Move,
-        Up
-    }
-
-    public delegate void TouchEventHandler(TrackedTouch sender, TouchEventArgs e);
+    public delegate void TouchEventHandler(object sender, TouchEvent 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>
     public class TrackedTouch : TrackedObject<Touch>
     {
     {
         private Kalman2DPositionFilter absolutePositionKalman;
         private Kalman2DPositionFilter absolutePositionKalman;
-        private int fingerID;
 
 
         public Vector2D AbsolutePositionPrediction { get { return absolutePositionKalman.getPrediction(); } }
         public Vector2D AbsolutePositionPrediction { get { return absolutePositionKalman.getPrediction(); } }
         public Touch OptimizedTouch { get; private set; }
         public Touch OptimizedTouch { get; private set; }
         public bool IsTouchActive { get; private set; }
         public bool IsTouchActive { get; private set; }
+        public int FingerID { get; private set; }
 
 
         public event TouchEventHandler TouchEvent;
         public event TouchEventHandler TouchEvent;
 
 
@@ -48,7 +27,7 @@ namespace bbiwarg.Recognition.TouchRecognition
             absolutePositionKalman = new Kalman2DPositionFilter(Parameters.TouchmXX, Parameters.TouchmXY, Parameters.TouchmYY);
             absolutePositionKalman = new Kalman2DPositionFilter(Parameters.TouchmXX, Parameters.TouchmXY, Parameters.TouchmYY);
             absolutePositionKalman.setInitialPosition(detectedTouch.AbsolutePosition);
             absolutePositionKalman.setInitialPosition(detectedTouch.AbsolutePosition);
 
 
-            fingerID = detectedTouch.Finger.TrackID;
+            FingerID = detectedTouch.Finger.TrackID;
             IsTouchActive = false;
             IsTouchActive = false;
 
 
             logStateChange();
             logStateChange();
@@ -85,21 +64,10 @@ namespace bbiwarg.Recognition.TouchRecognition
             OptimizedTouch = new Touch(AbsolutePositionPrediction, detectedTouch.Finger, detectedTouch.Palm);
             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()
         private void logStateChange()
         {
         {
             String stateAsString = CurrentState.ToString().ToLower();
             String stateAsString = CurrentState.ToString().ToLower();
-            Logger.log(String.Format("TouchEvent #{0} {1}", this.ID, stateAsString), LogSubject.TouchTracker);
+            Logger.log(String.Format("Touch #{0} {1}", this.ID, stateAsString), LogSubject.TouchTracker);
         }
         }
 
 
         private void TriggerTouchDown()
         private void TriggerTouchDown()
@@ -107,7 +75,7 @@ namespace bbiwarg.Recognition.TouchRecognition
             if (TouchEvent != null)
             if (TouchEvent != null)
             {
             {
                 IsTouchActive = true;
                 IsTouchActive = true;
-                TouchEvent(this, new TouchEventArgs(ID, TouchEventType.Down, OptimizedTouch));
+                TouchEvent(this, new TouchEvent(TouchEventType.Down, OptimizedTouch));
             }
             }
         }
         }
 
 
@@ -115,7 +83,7 @@ namespace bbiwarg.Recognition.TouchRecognition
         {
         {
             if (TouchEvent != null)
             if (TouchEvent != null)
             {
             {
-                TouchEvent(this, new TouchEventArgs(ID, TouchEventType.Move, OptimizedTouch));
+                TouchEvent(this, new TouchEvent(TouchEventType.Move, OptimizedTouch));
             }
             }
         }
         }
 
 
@@ -124,7 +92,7 @@ namespace bbiwarg.Recognition.TouchRecognition
             if (TouchEvent != null)
             if (TouchEvent != null)
             {
             {
                 IsTouchActive = false;
                 IsTouchActive = false;
-                TouchEvent(this, new TouchEventArgs(ID, TouchEventType.Up, OptimizedTouch));
+                TouchEvent(this, new TouchEvent(TouchEventType.Up, OptimizedTouch));
             }
             }
         }
         }
 
 

+ 0 - 9
bbiwarg/Recognition/Tracking/TrackedObject.cs

@@ -43,8 +43,6 @@ namespace bbiwarg.Recognition.Tracking
             NumFramesInCurrentState = 1;
             NumFramesInCurrentState = 1;
         }
         }
 
 
-        public abstract float calculateSimilarity(T detectedObject);
-
         public virtual void updateFrame(T detectedObject)
         public virtual void updateFrame(T detectedObject)
         {
         {
             if (detectedObject != null)
             if (detectedObject != null)
@@ -100,12 +98,5 @@ namespace bbiwarg.Recognition.Tracking
 
 
             return newState;
             return newState;
         }
         }
-
-        protected float getPositionSimilarity(Vector2D p1, Vector2D p2, float maxRelativeDistance)
-        {
-            float distance = p1.getDistanceTo(p2);
-            float similarity = Math.Max(1 - distance / (maxRelativeDistance * Parameters.ImageDiagonalLength), 0);
-            return similarity;
-        }
     }
     }
 }
 }

+ 17 - 3
bbiwarg/Recognition/Tracking/Tracker.cs

@@ -1,4 +1,6 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System;
+using bbiwarg.Utility;
 
 
 namespace bbiwarg.Recognition.Tracking
 namespace bbiwarg.Recognition.Tracking
 {
 {
@@ -6,14 +8,15 @@ namespace bbiwarg.Recognition.Tracking
         where T : TrackableObject
         where T : TrackableObject
         where TrackedT : TrackedObject<T>
         where TrackedT : TrackedObject<T>
     {
     {
-        private float minSimilarity;
+        private ImageSize imageSize;
         private List<Similarity<T, TrackedT>> similarities;
         private List<Similarity<T, TrackedT>> similarities;
         protected TrackIDPool idPool;
         protected TrackIDPool idPool;
 
 
         public List<TrackedT> TrackedObjects;
         public List<TrackedT> TrackedObjects;
 
 
-        public Tracker()
+        public Tracker(ImageSize imageSize)
         {
         {
+            this.imageSize = imageSize;
             reset();
             reset();
         }
         }
 
 
@@ -77,7 +80,7 @@ namespace bbiwarg.Recognition.Tracking
             {
             {
                 foreach (T detectedObject in detectedObjects)
                 foreach (T detectedObject in detectedObjects)
                 {
                 {
-                    float similarityValue = trackedObject.calculateSimilarity(detectedObject);
+                    float similarityValue = calculateSimilarity(trackedObject, 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)
                     if (similarity.Value > 0)
                         similarities.Add(similarity);
                         similarities.Add(similarity);
@@ -88,6 +91,9 @@ namespace bbiwarg.Recognition.Tracking
             similarities.Sort((s1, s2) => s2.Value.CompareTo(s1.Value));
             similarities.Sort((s1, s2) => s2.Value.CompareTo(s1.Value));
         }
         }
 
 
+        public abstract float calculateSimilarity(TrackedT trackedObject, T detectedObject);
+
+
         private void removeConcurringSimilarities(Similarity<T, TrackedT> similarity)
         private void removeConcurringSimilarities(Similarity<T, TrackedT> similarity)
         {
         {
             for (int i = similarities.Count - 1; i >= 0; i--)
             for (int i = similarities.Count - 1; i >= 0; i--)
@@ -123,5 +129,13 @@ namespace bbiwarg.Recognition.Tracking
         }
         }
 
 
         protected abstract TrackedT createTrackedObject(T detectedObject);
         protected abstract TrackedT createTrackedObject(T detectedObject);
+
+        protected float getPositionSimilarity(Vector2D p1, Vector2D p2, float maxRelativeDistance)
+        {
+            float distance = p1.getDistanceTo(p2);
+            float maxDistance = maxRelativeDistance * imageSize.DiagonalLength;
+            float similarity = Math.Max(1 - distance / maxDistance, 0);
+            return similarity;
+        }
     }
     }
 }
 }

+ 27 - 14
bbiwarg/TUIO/TuioCommunicator.cs

@@ -23,28 +23,33 @@ namespace bbiwarg.TUIO
             cursors = new Dictionary<int, TuioCursor>();
             cursors = new Dictionary<int, TuioCursor>();
         }
         }
 
 
-        public void handleNewFrameData(InputHandler sender, EventArgs e)
+        public void handleNewFrameData(object sender, NewProcessedFrameEventArgs e)
         {
         {
             server.initFrame();
             server.initFrame();
-            FrameData frameData = sender.FrameData;
-            lock (frameData) {
-                foreach (TouchEventArgs te in frameData.TouchEvents) {
-                    switch (te.Type) {
+            FrameData frameData = e.FrameData;
+            lock (frameData)
+            {
+                if (frameData.ResetFlag)
+                    reset();
+
+                foreach (TouchEvent te in frameData.TouchEvents)
+                {
+                    switch (te.Type)
+                    {
                         case TouchEventType.Down:
                         case TouchEventType.Down:
                             TuioCursor cursor = server.addTuioCursor(te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
                             TuioCursor cursor = server.addTuioCursor(te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
-                            cursors.Add(te.TrackID, cursor);
+                            cursors.Add(te.Touch.TrackID, cursor);
                             break;
                             break;
                         case TouchEventType.Move:
                         case TouchEventType.Move:
-                            server.updateTuioCursor(cursors[te.TrackID], te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
+                            server.updateTuioCursor(cursors[te.Touch.TrackID], te.Touch.RelativePosition.X, te.Touch.RelativePosition.Y);
                             break;
                             break;
                         case TouchEventType.Up:
                         case TouchEventType.Up:
-                            server.removeTuioCursor(cursors[te.TrackID]);
-                            cursors.Remove(te.TrackID);
+                            server.removeTuioCursor(cursors[te.Touch.TrackID]);
+                            cursors.Remove(te.Touch.TrackID);
                             break;
                             break;
                     }
                     }
                 }
                 }
             }
             }
-
             server.commitFrame();
             server.commitFrame();
         }
         }
 
 
@@ -62,12 +67,20 @@ namespace bbiwarg.TUIO
             cursors.Clear();
             cursors.Clear();
         }
         }
 
 
-        public static bool tryParseIPAddress(String ipString, out IPAddress ipAddress) {
-            return (IPAddress.TryParse(ipString, out ipAddress) && ipAddress.AddressFamily == AddressFamily.InterNetwork);
+        public static bool tryParseIPAddress(String ipIn, out String ipOut)
+        {
+            IPAddress ipAddress;
+            bool result = (IPAddress.TryParse(ipIn, out ipAddress) && ipAddress.AddressFamily == AddressFamily.InterNetwork);
+            if (result)
+                ipOut = ipAddress.ToString();
+            else
+                ipOut = null;
+            return result;
         }
         }
 
 
-        public static bool tryParsePort(String portString, out Int16 port) {
-            return Int16.TryParse(portString, out port);
+        public static bool tryParsePort(String portIn, out Int16 portOut)
+        {
+            return Int16.TryParse(portIn, out portOut);
         }
         }
     }
     }
 }
 }

+ 27 - 0
bbiwarg/Utility/ImageSize.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bbiwarg.Utility
+{
+    public class ImageSize
+    {
+        public int Width {get; private set;}
+        public int Height {get; private set;}
+        public Vector2D MaxPixel {get; private set;}
+        public float DiagonalLength { get { return MaxPixel.Length; } }
+        public int NumPixels { get { return Width * Height; } }
+
+        public ImageSize(int width, int height) {
+            Width = width;
+            Height = height;
+            MaxPixel = new Vector2D(width - 1, height - 1);
+        }
+
+        public Vector2D getAbsolutePoint(Vector2D relativePoint) {
+            return relativePoint.scale(MaxPixel);
+        }
+    }
+}

+ 1 - 1
bbiwarg/Utility/Logger.cs

@@ -28,7 +28,7 @@ namespace bbiwarg.Utility
 
 
         public static void log(string message, LogSubject subject)
         public static void log(string message, LogSubject subject)
         {
         {
-            if (Parameters.EnabledLogSubjects.HasFlag(subject))
+            if (Parameters.LoggerEnabledSubjects.HasFlag(subject))
                 Console.WriteLine("Frame: " + CurrentFrame + "\t" + message);
                 Console.WriteLine("Frame: " + CurrentFrame + "\t" + message);
         }
         }
     }
     }

+ 40 - 11
bbiwarg/Utility/Projection2DTo2D.cs

@@ -1,29 +1,58 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
+using System.Drawing;
 using System.Text;
 using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using Emgu.CV;
+using Emgu.CV.Structure;
 
 
 namespace bbiwarg.Utility
 namespace bbiwarg.Utility
 {
 {
     class Projection2DTo2D
     class Projection2DTo2D
     {
     {
-        private int sourceWidth;
-        private int sourceHeight;
-        private int destinationWidth;
-        private int destinationHeight;
-        private Dictionary<Vector2D, Vector2D> calibrationPoints;
+        private ImageSize sizeA;
+        private ImageSize sizeB;
+        private List<PointF> calibrationPointsA;
+        private List<PointF> calibrationPointsB;
+        private int numPointsForCalibration;
+        private HomographyMatrix homography;
 
 
         public bool IsCalibrated { get; private set; }
         public bool IsCalibrated { get; private set; }
 
 
-        public Projection2DTo2D(int sourceWidth, int sourceHeight, int destinationWidth, int destinationHeight) {
-            this.sourceWidth = sourceWidth;
-            this.sourceHeight = sourceHeight;
-            this.destinationWidth = destinationWidth;
-            this.destinationHeight = destinationHeight;
+        public Projection2DTo2D(ImageSize sizeA, ImageSize sizeB, int numPointsForCalibration = 4) {
+            this.sizeA = sizeA;
+            this.sizeB = sizeB;
+            this.numPointsForCalibration = numPointsForCalibration;
 
 
+            reset();
+        }
+
+        public void reset() {
+            homography = null;
             IsCalibrated = false;
             IsCalibrated = false;
-            calibrationPoints = new Dictionary<Vector2D, Vector2D>();
+            calibrationPointsA = new List<PointF>();
+            calibrationPointsB = new List<PointF>();
+        }
+
+        public void addCalibrationPoints(Vector2D pointA, Vector2D pointB) {
+            calibrationPointsA.Add(pointA);
+            calibrationPointsB.Add(pointB);
+
+            if (calibrationPointsA.Count == numPointsForCalibration)
+                calibrate();
+        }
+
+        public Vector2D projectPoint(Vector2D pointA) {
+            PointF[] pointfsB = new PointF[1] {pointA};
+            homography.ProjectPoints(pointfsB);
+            return new Vector2D(pointfsB[0]);
+        }
+
+        private void calibrate() {
+            homography = CameraCalibration.GetPerspectiveTransform(calibrationPointsA.ToArray(), calibrationPointsB.ToArray());
+            //homography = CameraCalibration.FindHomography(calibrationPointsA.ToArray(), calibrationPointsB.ToArray(), Emgu.CV.CvEnum.HOMOGRAPHY_METHOD.DEFAULT, 2);
+            IsCalibrated = true;
         }
         }
     }
     }
 }
 }

+ 7 - 7
bbiwarg/Utility/Vector2D.cs

@@ -80,9 +80,9 @@ namespace bbiwarg.Utility
             return (minX <= X && X <= maxX && minY <= Y && Y <= maxY);
             return (minX <= X && X <= maxX && minY <= Y && Y <= maxY);
         }
         }
 
 
-        public bool isInBound()
+        public bool isInBound(ImageSize imageSize)
         {
         {
-            return isInBound(Vector2D.Zero, Parameters.ImageMaxPixel);
+            return isInBound(Vector2D.Zero, imageSize.MaxPixel);
         }
         }
 
 
         public bool isInBound(Vector2D topLeft, Vector2D bottomRight)
         public bool isInBound(Vector2D topLeft, Vector2D bottomRight)
@@ -90,9 +90,9 @@ namespace bbiwarg.Utility
             return (X >= topLeft.X && X <= bottomRight.X && Y >= topLeft.Y && Y <= bottomRight.Y);
             return (X >= topLeft.X && X <= bottomRight.X && Y >= topLeft.Y && Y <= bottomRight.Y);
         }
         }
 
 
-        public Vector2D moveInBound(Vector2D inBoundDirection)
+        public Vector2D moveInBound(ImageSize imageSize, Vector2D inBoundDirection)
         {
         {
-            return moveInBound(Vector2D.Zero, Parameters.ImageMaxPixel, inBoundDirection);
+            return moveInBound(Vector2D.Zero, imageSize.MaxPixel, inBoundDirection);
         }
         }
 
 
         public Vector2D moveInBound(Vector2D topLeft, Vector2D bottomRight, Vector2D inBoundDirection)
         public Vector2D moveInBound(Vector2D topLeft, Vector2D bottomRight, Vector2D inBoundDirection)
@@ -103,10 +103,10 @@ namespace bbiwarg.Utility
             return position;
             return position;
         }
         }
 
 
-        public Vector2D moveWithinBound(Vector2D direction, float factor) {
+        public Vector2D moveWithinBound(ImageSize imageSize, Vector2D direction, float factor) {
             Vector2D newPosition = this + factor * direction;
             Vector2D newPosition = this + factor * direction;
-            if (!newPosition.isInBound())
-                newPosition = newPosition.moveInBound(direction.getInverse());
+            if (!newPosition.isInBound(imageSize))
+                newPosition = newPosition.moveInBound(imageSize, direction.getInverse());
             return newPosition;
             return newPosition;
         }
         }
 
 

+ 29 - 3
bbiwarg/bbiwarg.csproj

@@ -70,6 +70,8 @@
     <Reference Include="MathNet.Numerics">
     <Reference Include="MathNet.Numerics">
       <HintPath>lib\MathNet.Numerics.dll</HintPath>
       <HintPath>lib\MathNet.Numerics.dll</HintPath>
     </Reference>
     </Reference>
+    <Reference Include="Microsoft.VisualBasic" />
+    <Reference Include="Microsoft.VisualBasic.PowerPacks.Vs, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
     <Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
     <Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <SpecificVersion>False</SpecificVersion>
       <HintPath>lib\OpenTK.dll</HintPath>
       <HintPath>lib\OpenTK.dll</HintPath>
@@ -85,12 +87,25 @@
     <Reference Include="System.Xml" />
     <Reference Include="System.Xml" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
+    <Compile Include="Output\GlassesOutput\GlassesWindow.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Output\GlassesOutput\GlassesWindow.Designer.cs">
+      <DependentUpon>GlassesWindow.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Utility\ImageSize.cs" />
     <Compile Include="Input\InputHandling\FrameData.cs" />
     <Compile Include="Input\InputHandling\FrameData.cs" />
-    <Compile Include="Output\DebugOutput\DebugImages.cs" />
+    <Compile Include="Output\DebugOutput\DebugImageCreator.cs" />
+    <Compile Include="Output\DebugOutput\DebugWindow.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Output\DebugOutput\DebugWindow.Designer.cs">
+      <DependentUpon>DebugWindow.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Recognition\TouchRecognition\TouchEvent.cs" />
     <Compile Include="Utility\Projection2DTo2D.cs" />
     <Compile Include="Utility\Projection2DTo2D.cs" />
-    <Compile Include="Output\GlassesOutput\GlassesWindow.cs" />
+    <Compile Include="Output\GlassesOutput\GlassesWindowOld.cs" />
     <Compile Include="Parameters.cs" />
     <Compile Include="Parameters.cs" />
-    <Compile Include="Output\DebugOutput\DebugWindow.cs" />
     <Compile Include="Input\InputHandling\InputHandler.cs" />
     <Compile Include="Input\InputHandling\InputHandler.cs" />
     <Compile Include="Input\InputProviding\InputProvider.cs" />
     <Compile Include="Input\InputProviding\InputProvider.cs" />
     <Compile Include="Input\InputProviding\VideoInputProvider.cs" />
     <Compile Include="Input\InputProviding\VideoInputProvider.cs" />
@@ -177,6 +192,17 @@
       <Install>false</Install>
       <Install>false</Install>
     </BootstrapperPackage>
     </BootstrapperPackage>
   </ItemGroup>
   </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Output\DebugOutput\DebugWindow.resx">
+      <DependentUpon>DebugWindow.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Output\GlassesOutput\GlassesWindow.resx">
+      <DependentUpon>GlassesWindow.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <WCFMetadata Include="Service References\" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
        Other similar extension points exist, see Microsoft.Common.targets.