소스 검색

-touchtracker now has touchDown/Move/up events
-added tuioCommunicator using touchtracker events
-changed touchEventvisualizer to use touchtracker events

Alexander Hendrich 10 년 전
부모
커밋
2726e9e60d

+ 5 - 5
bbiwarg/Constants.cs

@@ -12,7 +12,7 @@ namespace bbiwarg
     class Constants
     {
         // Logger
-        public static readonly LogSubject LogLevel = LogSubject.TouchTracker;
+        public static readonly LogSubject LogLevel = LogSubject.TouchEvents;
             //LogSubject.Timer;
         
         // Output
@@ -91,10 +91,10 @@ namespace bbiwarg
         public static readonly int PalmGridColumns = 3;
 
         // touch detection
-        public static readonly float TouchEventMinTouchValue = 0.25f;
+        public static readonly float TouchEventMinTouchValue = 0.3f;
         public static readonly int TouchEventAreaSize = 30;
-        public static readonly int TouchEventFloodfillLowDiff = 0;
-        public static readonly int TouchEventFloodfillHighDiff = 2;
+        public static readonly int TouchEventFloodfillLowDiff = 1;
+        public static readonly int TouchEventFloodfillHighDiff = 3;
         public static readonly int TouchEventTipInsideFactor = 1;
         public static readonly int TouchEventTipOutsideFactor = 7;
         public static readonly float TouchmXX = 0.005481396f;
@@ -128,7 +128,7 @@ namespace bbiwarg
         public static readonly Color TouchEventAreaNonMatchedSubtractColor = Color.DarkSlateGray;
         public static readonly Color TouchEventStatusBarColor = Color.Green;
 
-        public static readonly Color TouchEventVisualizerLineColor = Color.Blue;
+        public static readonly Color TouchEventVisualizerLineColor = Color.Yellow;
         public static readonly Color TouchEventVisualizerPointColor = Color.Red;
         public static readonly Color TouchEventVisualizerGridColor = Color.White;
 

+ 13 - 107
bbiwarg/Graphics/TouchEventVisualizer.cs

@@ -27,22 +27,24 @@ namespace bbiwarg.Graphics
             this.kalmanFilters = new Dictionary<int, Kalman2DPositionFilter>();
         }
 
-        public void addTouchEvent(int trackID, Vector2D relPos) {
-            positions.Add(trackID, new List<Vector2D>());
-            positions[trackID].Add(relPos);
+        public void touchDown(object sender, PalmTouchEventArgs ptea)
+        {
+            positions.Add(ptea.TrackID, new List<Vector2D>());
+            positions[ptea.TrackID].Add(ptea.Position);
 
             Kalman2DPositionFilter kalmanFilter = new Kalman2DPositionFilter(Constants.TouchmXX, Constants.TouchmXY, Constants.TouchmYY, Constants.TouchProcessNoise);
-            kalmanFilter.setInitialPosition(relPos);
-            kalmanFilters.Add(trackID, kalmanFilter);
+            kalmanFilter.setInitialPosition(ptea.Position);
+            kalmanFilters.Add(ptea.TrackID, kalmanFilter);
         }
 
-        public void updateTouchEvent(int trackID, Vector2D relPos) {
-            positions[trackID].Add(kalmanFilters[trackID].getCorrectedPosition(relPos));
+
+        public void touchMove(object sender, PalmTouchEventArgs ptea) {
+            positions[ptea.TrackID].Add(kalmanFilters[ptea.TrackID].getCorrectedPosition(ptea.Position));
         }
 
-        public void removeTouchEvent(int trackID) {
-            positions.Remove(trackID);
-            kalmanFilters.Remove(trackID);
+        public void touchUp(object sender, PalmTouchEventArgs ptea) {
+            positions.Remove(ptea.TrackID);
+            kalmanFilters.Remove(ptea.TrackID);
         }
 
         public void updateImage() {
@@ -78,103 +80,7 @@ namespace bbiwarg.Graphics
             }
         }
 
-
-        /*
-        public void addPalmTouchEvent(PalmTouchEvent e, int currentFrame)
-        {
-            Vector2D pos;
-            if (lastUpdated == -1 || (currentFrame - lastUpdated) > 5 || currentTouchPositions == null || kalmanFilter == null)
-            {
-                lastTouchPositions = currentTouchPositions;
-                currentTouchPositions = new List<Vector2D>();
-                kalmanFilter = new Kalman2DPositionFilter(Constants.TouchmXX, Constants.TouchmXY, Constants.TouchmYY, Constants.TouchProcessNoise);
-                kalmanFilter.setInitialPosition(e.RelativePalmPosition);
-                pos = e.RelativePalmPosition;
-            }
-            else
-            {
-                pos = kalmanFilter.getCorrectedPosition(e.RelativePalmPosition);
-            }
-
-
-            int size = Math.Min(width, height);
-            currentTouchPositions.Add(new Vector2D((int)(pos.X * size), (int)(size - pos.Y * size)));
-
-            lastUpdated = currentFrame;
-        }
-
-        public void updateImage()
-        {
-            OutputImage = new OutputImage(width, height);
-            bool touched = currentTouchPositions != null;
-            int touchX = touched ? currentTouchPositions.Last<Vector2D>().IntX : -1;
-            int touchY = touched ? currentTouchPositions.Last<Vector2D>().IntY : -1;
-
-            //-- Border --
-            int size = Math.Min(width, height);
-            OutputImage.drawRectangle(0, 0, size - 1, size - 1, Color.White);
-
-
-            //-- Grid --
-            int numRows = Constants.PalmGridRows;
-            int numColumns = Constants.PalmGridColumns;
-            int cellX1 = -1;
-            int cellY1 = -1;
-            int cellX2 = -1;
-            int cellY2 = -1;
-            int tmp = -1;
-            int tmp2 = -1;
- 
-            for (int i = 0; i < numRows; i++)
-            {
-                tmp = size / numRows * i;
-                tmp2 = size / numRows * (i + 1);
-                OutputImage.drawLineSegment(new LineSegment2D(new Vector2D(0, tmp), new Vector2D(size - 2, tmp)), Constants.PalmGridColor);
-                if (touched)
-                    if (touchY >= tmp && touchY < tmp2)
-                    {
-                        cellY1 = tmp;
-                        cellY2 = tmp2;
-                    }
-            }
-            for (int i = 0; i < numColumns; i++)
-            {
-                tmp = size / numColumns * i;
-                tmp2 = size / numColumns * (i + 1);
-                OutputImage.drawLineSegment(new LineSegment2D(new Vector2D(tmp, 0), new Vector2D(tmp, size - 2)), Constants.PalmGridColor);
-                if (touched)
-                    if (touchX >= tmp && touchX < tmp2)
-                    {
-                        cellX1 = tmp;
-                        cellX2 = tmp2;
-                    }
-            }
-
-            if (touched)
-                OutputImage.drawRectangle(cellX1, cellY1, size/numColumns, size/numRows, Constants.PalmGridColor, -1);
-
-            //-- Current Touch Event --
-            if (touched)
-            {
-                for (int i = 1; i < currentTouchPositions.Count; ++i)
-                {
-                    OutputImage.drawLineSegment(new LineSegment2D(currentTouchPositions[i - 1], currentTouchPositions[i]), Constants.TouchEventVisualizerLineColor);
-                }
-                OutputImage.fillCircle(touchX, touchY, 3, Constants.TouchEventVisualizerPointColor);
-            }
-            //-- Last Touch Event --
-            if (lastTouchPositions != null)
-            {
-                for (int i = 1; i < lastTouchPositions.Count; ++i)
-                {
-                    OutputImage.drawLineSegment(new LineSegment2D(lastTouchPositions[i - 1], lastTouchPositions[i]), Constants.TouchEventVisualizerLineColor);
-                }
-                OutputImage.fillCircle(lastTouchPositions.Last<Vector2D>().IntX, lastTouchPositions.Last<Vector2D>().IntY, 3, Constants.TouchEventVisualizerPointColor);
-            }
-
-        }
-        */
-        public void Reset()
+        public void reset()
         {
             OutputImage = new OutputImage(width, height);
             positions.Clear();

+ 29 - 19
bbiwarg/Recognition/FingerRecognition/FingerTracker.cs

@@ -18,29 +18,39 @@ namespace bbiwarg.Recognition.FingerRecognition
 
         }
 
-        protected override void onStateChanged(object sender, TrackingStateChangeEventArgs e)
+        protected override void onDetect(object sender, EventArgs e)
         {
             TrackableObjectHistory<Finger> history = (TrackableObjectHistory<Finger>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("Finger #" + history.ID.ToString() + " detected", LogSubject.FingerTracker);
+        }
+
+        protected override void onTrack(object sender, EventArgs e)
+        {
+            TrackableObjectHistory<Finger> history = (TrackableObjectHistory<Finger>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("Finger #" + history.ID.ToString() + " tracked", LogSubject.FingerTracker);
+        }
 
-            //log
+        protected override void onRetrack(object sender, EventArgs e)
+        {
+            TrackableObjectHistory<Finger> history = (TrackableObjectHistory<Finger>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("Finger #" + history.ID.ToString() + " retracked", LogSubject.FingerTracker);
+        }
+
+        protected override void onLoose(object sender, EventArgs e)
+        {
+            TrackableObjectHistory<Finger> history = (TrackableObjectHistory<Finger>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("Finger #" + history.ID.ToString() + " lost", LogSubject.FingerTracker);
+        }
+
+        protected override void onDelete(object sender, EventArgs e)
+        {
+            TrackableObjectHistory<Finger> history = (TrackableObjectHistory<Finger>)sender;
             if (history.NumFramesInCurrentState == 1)
-            {
-                switch (e.NextState)
-                {
-                    case TrackingState.Detected:
-                        Logger.log("Finger #" + history.ID.ToString() + " detected", LogSubject.FingerTracker);
-                        break;
-                    case TrackingState.Tracked:
-                        Logger.log("Finger #" + history.ID.ToString() + " tracked", LogSubject.FingerTracker);
-                        break;
-                    case TrackingState.Lost:
-                        Logger.log("Finger #" + history.ID.ToString() + " lost", LogSubject.FingerTracker);
-                        break;
-                    case TrackingState.Delete:
-                        Logger.log("Finger #" + history.ID.ToString() + " deleted", LogSubject.FingerTracker);
-                        break;
-                }
-            }
+                Logger.log("Finger #" + history.ID.ToString() + " deleted", LogSubject.FingerTracker);
         }
     }
 }

+ 7 - 8
bbiwarg/Recognition/TouchRecognition/TouchDetector.cs

@@ -44,17 +44,16 @@ namespace bbiwarg.Recognition.TouchRecognition
 
                 if (touchValue > Constants.TouchEventMinTouchValue)
                 {
-                    outputImage.fillCircle(tipPointOutside.IntX, tipPointOutside.IntY, 5, Constants.TouchEventDetectedColor);
-
-                    TouchEvent touchEvent;
+                    
                     if (palmQuad != null && palmQuad.isInside(tipPointOutside))
-                        touchEvent = new PalmTouchEvent(tipPointOutside, touchMask, finger, palmQuad);
+                    {
+                        outputImage.fillCircle(tipPointOutside.IntX, tipPointOutside.IntY, 5, Constants.TouchEventDetectedColor);
 
-                    else
-                        touchEvent = new TouchEvent(tipPointOutside, touchMask, finger);
+                        TouchEvent touchEvent = new PalmTouchEvent(tipPointOutside, touchMask, finger, palmQuad);
+                        TouchEvents.Add(touchEvent);
+                        finger.setTouchEvent(touchEvent);
+                    }
 
-                    TouchEvents.Add(touchEvent);
-                    finger.setTouchEvent(touchEvent);
                 }
 
                 outputImage.fillCircle(tipPoint.IntX, tipPoint.IntY, 3, Constants.TouchEventTipColor);

+ 1 - 1
bbiwarg/Recognition/TouchRecognition/TouchEvent.cs

@@ -37,7 +37,7 @@ namespace bbiwarg.Recognition.TouchRecognition
             TouchEvent compareTouchEvent = (TouchEvent)compareObject;
 
             //finger similarity
-            float fingerSimilarity = (Finger.TrackID == compareTouchEvent.Finger.TrackID) ? 1 : 0;
+            float fingerSimilarity = (Finger.TrackID == compareTouchEvent.Finger.TrackID) ? 1 : 0.5f;
 
             //position similarity
             float distance = Position.getDistanceTo(compareTouchEvent.Position);

+ 102 - 48
bbiwarg/Recognition/TouchRecognition/TouchTracker.cs

@@ -8,76 +8,130 @@ using bbiwarg.Images;
 using bbiwarg.Graphics;
 using bbiwarg.Recognition.Tracking;
 using bbiwarg.Utility;
-using TUIO;
 
 namespace bbiwarg.Recognition.TouchRecognition
 {
+    public class PalmTouchEventArgs : EventArgs
+    {
+        public int TrackID { get; private set; }
+        public Vector2D Position { get; private set; }
+
+        public PalmTouchEventArgs(int trackID, Vector2D position)
+        {
+            TrackID = trackID;
+            Position = position;
+        }
+    }
+
+    public delegate void PalmTouchEventHandler(object sender, PalmTouchEventArgs e);
+
     class TouchTracker : Tracker<TouchEvent>
     {
         public List<TouchEvent> TouchEvents { get { return TrackedObjects; } }
-        private TuioServer tuioServer;
-        private Dictionary<int, TuioCursor> tuioCursors;
-        private TouchEventVisualizer touchEventVisualizer;
+        public Dictionary<int, Kalman2DPositionFilter> kalmanFilters;
+        public event PalmTouchEventHandler PalmTouchDown;
+        public event PalmTouchEventHandler PalmTouchMove;
+        public event PalmTouchEventHandler PalmTouchUp;
+
+        protected virtual void OnPalmTouchDown(PalmTouchEventArgs e) { if (PalmTouchDown != null) PalmTouchDown(this, e); }
+        protected virtual void OnPalmTouchMove(PalmTouchEventArgs e) { if (PalmTouchMove != null) PalmTouchMove(this, e); }
+        protected virtual void OnPalmTouchUp(PalmTouchEventArgs e) { if (PalmTouchUp != null) PalmTouchUp(this, e); }
 
-        public TouchTracker(TuioServer tuioServer, TouchEventVisualizer touchEventVisualizer)
+        public TouchTracker()
             : base(Constants.TouchEventNumFramesDetectedUntilTracked, Constants.TouchEventNumFramesLostUntilDeleted, Constants.TouchEventMinSimilarityForTracking)
         {
-            this.tuioServer = tuioServer;
-            this.tuioCursors = new Dictionary<int, TuioCursor>();
-            this.touchEventVisualizer = touchEventVisualizer;
+            kalmanFilters = new Dictionary<int, Kalman2DPositionFilter>();
         }
 
         public new void reset() {
-            tuioCursors.Clear();
-            touchEventVisualizer.Reset();
+            foreach (int id in kalmanFilters.Keys) {
+                OnPalmTouchUp(new PalmTouchEventArgs(id, kalmanFilters[id].getPrediction()));
+            }
+            kalmanFilters.Clear();
             base.reset();
         }
 
-        public new void updateFrame(List<TouchEvent> detectedObjects)
+        protected override void onDetect(object sender, EventArgs e)
         {
-            tuioServer.initFrame();
-            base.updateFrame(detectedObjects);
-            tuioServer.commitFrame();
-            touchEventVisualizer.updateImage();
+            TrackableObjectHistory<TouchEvent> history = (TrackableObjectHistory<TouchEvent>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("TouchEvent #" + history.ID.ToString() + " detected", LogSubject.TouchTracker);
         }
 
-        protected override void onStateChanged(object sender, TrackingStateChangeEventArgs e)
+        protected override void onTrack(object sender, EventArgs e)
         {
             TrackableObjectHistory<TouchEvent> history = (TrackableObjectHistory<TouchEvent>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("TouchEvent #" + history.ID.ToString() + " tracked", LogSubject.TouchTracker);
+
+            if (history.LastObject is PalmTouchEvent)
+            {
+                PalmTouchEvent pte = (PalmTouchEvent)history.LastObject;
+                if (history.NumFramesInCurrentState == 1)
+                    palmTouchDown(history.ID, pte.RelativePalmPosition);
+                else
+                    palmTouchMove(history.ID, pte.RelativePalmPosition);
+            }
+        }
+
+        protected override void onRetrack(object sender, EventArgs e)
+        {
+            TrackableObjectHistory<TouchEvent> history = (TrackableObjectHistory<TouchEvent>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("TouchEvent #" + history.ID.ToString() + " retracked", LogSubject.TouchTracker);
+
+            if (history.LastObject is PalmTouchEvent)
+            {
+                PalmTouchEvent pte = (PalmTouchEvent)history.LastObject;
+                palmTouchMove(history.ID, pte.RelativePalmPosition);
+            }
+            else throw new ArgumentException();
+        }
+
+        protected override void onLoose(object sender, EventArgs e)
+        {
+            TrackableObjectHistory<TouchEvent> history = (TrackableObjectHistory<TouchEvent>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("TouchEvent #" + history.ID.ToString() + " lost", LogSubject.TouchTracker);
+        }
+
+        protected override void onDelete(object sender, EventArgs e)
+        {
+            TrackableObjectHistory<TouchEvent> history = (TrackableObjectHistory<TouchEvent>)sender;
+            if (history.NumFramesInCurrentState == 1)
+                Logger.log("TouchEvent #" + history.ID.ToString() + " deleted", LogSubject.TouchTracker);
+
+            if (history.LastObject is PalmTouchEvent)
+            {
+                PalmTouchEvent pte = (PalmTouchEvent)history.LastObject;
+                palmTouchUp(history.ID, pte.RelativePalmPosition);
+            }
+            else throw new ArgumentException();
+        }
+
+
+        private void palmTouchDown(int id, Vector2D relPos) {
+            Kalman2DPositionFilter kalmanFilter = new Kalman2DPositionFilter(Constants.TouchmXX, Constants.TouchmXY, Constants.TouchmYY, Constants.TouchProcessNoise);
+            kalmanFilter.setInitialPosition(relPos);
+            kalmanFilters.Add(id, kalmanFilter);
+            OnPalmTouchDown(new PalmTouchEventArgs(id, relPos));
+            Logger.log("TouchEvent #" + id.ToString() + " touchDown at (" + relPos.X + ", " + relPos.Y + ")", LogSubject.TouchEvents);
+        }
+
+        private void palmTouchMove(int id, Vector2D relPos) {
+            Vector2D correctedRelPos = kalmanFilters[id].getCorrectedPosition(relPos);
+            OnPalmTouchMove(new PalmTouchEventArgs(id, correctedRelPos));
+            Logger.log("TouchEvent #" + id.ToString() + " touchMove to (" + relPos.X + ", " + relPos.Y + ")", LogSubject.TouchEvents);
+        }
 
-            TouchEvent currentTouchEvent = history.LastObject;
-            if (currentTouchEvent is PalmTouchEvent)
+        private void palmTouchUp(int id, Vector2D relPos) {
+            Kalman2DPositionFilter kalmanFilter;
+            if (kalmanFilters.TryGetValue(id, out kalmanFilter))
             {
-                PalmTouchEvent currentPalmTouchEvent = (PalmTouchEvent)currentTouchEvent;
-                Vector2D currentRelativePosition = currentPalmTouchEvent.RelativePalmPosition;
-                TuioCursor tuioCursor;
-                switch (e.NextState)
-                {
-                    case TrackingState.Tracked:
-                        if (tuioCursors.TryGetValue(history.ID, out tuioCursor))
-                        {
-                            tuioServer.updateTuioCursor(tuioCursor, currentRelativePosition.X, currentRelativePosition.Y);
-                            touchEventVisualizer.updateTouchEvent(history.ID, currentRelativePosition);
-                            Logger.log("TouchEvent #" + history.ID.ToString() + " touchMove to (" + currentRelativePosition.X + ", " + currentRelativePosition.Y + ")", LogSubject.TouchTracker);
-                        }
-                        else
-                        {
-                            TuioCursor newTuioCursor = tuioServer.addTuioCursor(currentRelativePosition.X, currentRelativePosition.Y);
-                            tuioCursors.Add(history.ID, newTuioCursor);
-                            touchEventVisualizer.addTouchEvent(history.ID, currentRelativePosition);
-                            Logger.log("TouchEvent #" + history.ID.ToString() + " touchDown at (" + currentRelativePosition.X + ", " + currentRelativePosition.Y + ")", LogSubject.TouchTracker);
-                        }
-                        break;
-                    case TrackingState.Delete:
-                        if (tuioCursors.TryGetValue(history.ID, out tuioCursor))
-                        {
-                            tuioServer.removeTuioCursor(tuioCursor);
-                            tuioCursors.Remove(history.ID);
-                            touchEventVisualizer.removeTouchEvent(history.ID);
-                            Logger.log("TouchEvent #" + history.ID.ToString() + " touchUp at (" + currentRelativePosition.X + ", " + currentRelativePosition.Y + ")", LogSubject.TouchTracker);
-                        }
-                        break;
-                }
+                Vector2D correctedRelPos = kalmanFilter.getCorrectedPosition(relPos);
+                OnPalmTouchUp(new PalmTouchEventArgs(id, correctedRelPos));
+                kalmanFilters.Remove(id);
+                Logger.log("TouchEvent #" + id.ToString() + " touchUp at (" + relPos.X + ", " + relPos.Y + ")", LogSubject.TouchEvents);
             }
         }
     }

+ 43 - 17
bbiwarg/Recognition/Tracking/TrackableObjectHistory.cs

@@ -7,19 +7,7 @@ using bbiwarg.Utility;
 
 namespace bbiwarg.Recognition.Tracking
 {
-    public class TrackingStateChangeEventArgs : EventArgs
-    {
-        public TrackingState NextState { get; private set; }
-        public TrackingState PreviousState { get; private set; }
-
-        public TrackingStateChangeEventArgs(TrackingState nextState, TrackingState previousState)
-        {
-            NextState = nextState;
-            PreviousState = previousState;
-        }
-    }
-
-    public delegate void TrackingStateChangedEventHandler(object sender, TrackingStateChangeEventArgs e);
+    public delegate void TrackingStateChangedEventHandler(object sender, EventArgs e);
 
     class TrackableObjectHistory<T> where T : TrackableObject
     {
@@ -33,10 +21,19 @@ namespace bbiwarg.Recognition.Tracking
         public int NumFramesInCurrentState { get; private set; }
         private int numFramesDetectedUntilTracked;
         private int numFramesLostUntilDeleted;
+        private bool wasTrackedBefore;
 
-        public event TrackingStateChangedEventHandler StateChanged;
+        public event TrackingStateChangedEventHandler Detected;
+        public event TrackingStateChangedEventHandler Tracked;
+        public event TrackingStateChangedEventHandler Retracked;
+        public event TrackingStateChangedEventHandler Lost;
+        public event TrackingStateChangedEventHandler Deleted;
 
-        protected virtual void OnStateChanged(TrackingStateChangeEventArgs e) { if (StateChanged != null) StateChanged(this, e); }
+        protected virtual void OnDetect(EventArgs e) { if (Detected != null) Detected(this, e); }
+        protected virtual void OnTrack(EventArgs e) { if (Tracked != null) Tracked(this, e); }
+        protected virtual void OnRetrack(EventArgs e) { if (Retracked != null) Retracked(this, e); }
+        protected virtual void OnLoose(EventArgs e) { if (Lost != null) Lost(this, e); }
+        protected virtual void OnDelete(EventArgs e) { if (Deleted != null) Deleted(this, e); }
 
         public TrackableObjectHistory(int numFramesDetectedUntilTracked, int numFramesLostUntilDeleted)
         {
@@ -48,6 +45,7 @@ namespace bbiwarg.Recognition.Tracking
             NumFramesInCurrentState = 1;
             this.numFramesDetectedUntilTracked = numFramesDetectedUntilTracked;
             this.numFramesLostUntilDeleted = numFramesLostUntilDeleted;
+            this.wasTrackedBefore = false;
         }
 
         ~TrackableObjectHistory()
@@ -66,7 +64,12 @@ namespace bbiwarg.Recognition.Tracking
                 if (previousState == TrackingState.None)
                     newState = TrackingState.Detected;
                 else if (previousState == TrackingState.Lost)
-                    newState = TrackingState.Tracked;
+                {
+                    if (wasTrackedBefore)
+                        newState = TrackingState.Tracked;
+                    else
+                        newState = TrackingState.Detected;
+                }
                 else if (previousState == TrackingState.Tracked)
                     newState = TrackingState.Tracked;
                 else if (previousState == TrackingState.Detected)
@@ -82,6 +85,10 @@ namespace bbiwarg.Recognition.Tracking
             else
                 newState = TrackingState.Lost;
 
+            //set trackedBefore
+            if (newState == TrackingState.Tracked)
+                wasTrackedBefore = true;
+
             //update numFramesInCurrentState
             if (newState == previousState)
                 NumFramesInCurrentState++;
@@ -95,9 +102,28 @@ namespace bbiwarg.Recognition.Tracking
                 detectedObject.setTrackID(ID);
             }
 
+            //add current state+object
             TrackedObjects.Add(detectedObject);
             States.Add(newState);
-            OnStateChanged(new TrackingStateChangeEventArgs(newState, previousState));
+
+            //fire event
+            switch (newState) {
+                case TrackingState.Detected:
+                    OnDetect(EventArgs.Empty);
+                    break;
+                case TrackingState.Tracked:
+                    if (previousState == TrackingState.Lost)
+                        OnRetrack(EventArgs.Empty);
+                    else
+                        OnTrack(EventArgs.Empty);
+                    break;
+                case TrackingState.Lost:
+                    OnLoose(EventArgs.Empty);
+                    break;
+                case TrackingState.Delete:
+                    OnDelete(EventArgs.Empty);
+                    break;
+            }
         }
 
         public static int getNextUnusedID()

+ 10 - 2
bbiwarg/Recognition/Tracking/Tracker.cs

@@ -147,10 +147,18 @@ namespace bbiwarg.Recognition.Tracking
         private TrackableObjectHistory<T> createNewHistory()
         {
             TrackableObjectHistory<T> history = new TrackableObjectHistory<T>(numFramesDetectedUntilTracked, numFramesLostUntilDeleted);
-            history.StateChanged += onStateChanged;
+            history.Detected += onDetect;
+            history.Tracked += onTrack;
+            history.Retracked += onRetrack;
+            history.Lost += onLoose;
+            history.Deleted += onDelete;
             return history;
         }
 
-        protected abstract void onStateChanged(object sender, TrackingStateChangeEventArgs e);
+        protected abstract void onDetect(object sender, EventArgs e);
+        protected abstract void onTrack(object sender, EventArgs e);
+        protected abstract void onRetrack(object sender, EventArgs e);
+        protected abstract void onLoose(object sender, EventArgs e);
+        protected abstract void onDelete(object sender, EventArgs e);
     }
 }

+ 55 - 0
bbiwarg/Server/TuioCommunicator.cs

@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using bbiwarg.Recognition.TouchRecognition;
+using bbiwarg.Utility;
+using TUIO;
+
+namespace bbiwarg.Server
+{
+    class TuioCommunicator
+    {
+        private TuioServer server;
+        private Dictionary<int, TuioCursor> cursors;
+
+        public TuioCommunicator(string host, int port) {
+            server = new TuioServer(host, port);
+            cursors = new Dictionary<int, TuioCursor>();
+        }
+
+        public void touchDown(object sender, PalmTouchEventArgs ptea) {
+            TuioCursor cursor = server.addTuioCursor(ptea.Position.X, ptea.Position.Y);
+            cursors.Add(ptea.TrackID, cursor);
+        }
+
+        public void touchMove(object sender, PalmTouchEventArgs ptea) {
+            server.updateTuioCursor(cursors[ptea.TrackID], ptea.Position.X, ptea.Position.Y);
+        }
+
+        public void touchUp(object sender, PalmTouchEventArgs ptea) {
+            server.removeTuioCursor(cursors[ptea.TrackID]);
+            cursors.Remove(ptea.TrackID);
+        }
+
+        public void close() {
+            server.close();
+        }
+
+        public void initFrame() {
+            server.initFrame();
+        }
+
+        public void commitFrame() {
+            server.commitFrame();
+        }
+
+        public void reset() {
+            foreach (int id in cursors.Keys) {
+                server.removeTuioCursor(cursors[id]);
+            }
+            cursors.Clear();
+        }
+    }
+}

+ 2 - 1
bbiwarg/Utility/Logger.cs

@@ -16,7 +16,8 @@ namespace bbiwarg.Utility
         TouchDetector = 16,
         TouchTracker = 32,
         TUIOServer = 64,
-        Timer = 128
+        Timer = 128,
+        TouchEvents = 256
     }
     static class Logger
     {

+ 1 - 1
bbiwarg/Utility/Vector2D.cs

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
 
 namespace bbiwarg.Utility
 {
-    class Vector2D
+    public class Vector2D
     {
         public static Vector2D Zero { get { return new Vector2D(0, 0); } }
         public float X { get; private set; }

+ 30 - 11
bbiwarg/VideoHandle.cs

@@ -16,7 +16,7 @@ using bbiwarg.InputProviders;
 using Emgu.CV;
 using Emgu.CV.Structure;
 using bbiwarg.Graphics;
-using TUIO;
+using bbiwarg.Server;
 
 namespace bbiwarg
 {
@@ -25,8 +25,6 @@ namespace bbiwarg
         private IInputProvider inputProvider;
         private InputFrame inputFrame;
 
-        private TuioServer tuioServer;
-        private TuioCursor currentTouchevent;
 
         public int Width { get; private set; }
         public int Height { get; private set; }
@@ -58,6 +56,7 @@ namespace bbiwarg
         private TouchTracker touchTracker;
 
         private TouchEventVisualizer touchEventVisualizer;
+        private TuioCommunicator tuioCommunicator;
 
         private int videoFrame = 0;
 
@@ -78,7 +77,7 @@ namespace bbiwarg
         public void stop()
         {
             inputProvider.stop();
-            tuioServer.close();
+            tuioCommunicator.close();
         }
 
         public bool sourceIsMovie()
@@ -119,23 +118,39 @@ namespace bbiwarg
         private void initTrackers()
         {
             palmDetector = new PalmDetector();
-            tuioServer = new TuioServer(Constants.TuioIP, Constants.TuioPort);
-            touchEventVisualizer = new TouchEventVisualizer(Constants.ImageWidth, Constants.ImageHeight);
 
             fingerTracker = new FingerTracker();
-            touchTracker = new TouchTracker(tuioServer, touchEventVisualizer);
+            touchTracker = new TouchTracker();
+
+            //register touchEventVisualizer to touchTracker
+            touchEventVisualizer = new TouchEventVisualizer(Constants.ImageWidth, Constants.ImageHeight);
+            touchTracker.PalmTouchDown += touchEventVisualizer.touchDown;
+            touchTracker.PalmTouchMove += touchEventVisualizer.touchMove;
+            touchTracker.PalmTouchUp += touchEventVisualizer.touchUp;
+
+            //register tuiCommunicator to touchTracker
+            tuioCommunicator = new TuioCommunicator(Constants.TuioIP, Constants.TuioPort);
+            touchTracker.PalmTouchDown += tuioCommunicator.touchDown;
+            touchTracker.PalmTouchMove += tuioCommunicator.touchMove;
+            touchTracker.PalmTouchUp += tuioCommunicator.touchUp;
+
+            //register 
         }
 
         private void processFrameUpdate()
         {
+            Timer.start("processFrameUpdate");
+
             Logger.CurrentFrame = CurrentFrame;
             bool newStarted = (lastFrame - CurrentFrame >= 20);
-            Timer.start("processFrameUpdate");
+            tuioCommunicator.initFrame();
 
             if (newStarted) {
                 //reset trackers
                 touchTracker.reset();
                 fingerTracker.reset();
+                touchEventVisualizer.reset();
+                tuioCommunicator.reset();
             }
 
             //read data from inputProvider
@@ -216,11 +231,13 @@ namespace bbiwarg
             {
                 OutputImages[3].fillCircle(te.Position.IntX, te.Position.IntY, 5, Constants.TouchEventTrackedColor);
             }
+            Timer.stop("touchTracking");
 
+            //touchEventVisualizer
+            touchEventVisualizer.updateImage();
             OutputImages[4] = touchEventVisualizer.OutputImage;
-            Timer.stop("touchTracking");
 
-           
+
             // add borders
             for (int i = 0; i < Constants.OutputNumImages; i++)
             {
@@ -228,8 +245,10 @@ namespace bbiwarg
 
             }
 
-            Timer.stop("processFrameUpdate");
+
             lastFrame = CurrentFrame;
+            tuioCommunicator.commitFrame();
+            Timer.stop("processFrameUpdate");
         }
     }
 }

+ 1 - 0
bbiwarg/bbiwarg.csproj

@@ -98,6 +98,7 @@
     <Compile Include="Server\OSC.NET\OSCMessage.cs" />
     <Compile Include="Server\OSC.NET\OSCPacket.cs" />
     <Compile Include="Server\OSC.NET\OSCTransmitter.cs" />
+    <Compile Include="Server\TuioCommunicator.cs" />
     <Compile Include="Server\TUIO\TuioContainer.cs" />
     <Compile Include="Server\TUIO\TuioCursor.cs" />
     <Compile Include="Server\TUIO\TuioPoint.cs" />