using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using bbiwarg.Utility; namespace bbiwarg.Recognition.Tracking { public delegate void TrackingStateChangedEventHandler(object sender, EventArgs e); class TrackableObjectHistory where T : TrackableObject { private static List usedIDs = new List(); public int ID { get; private set; } public List TrackedObjects { get; private set; } public List States { get; private set; } public T LastObject { get; private set; } public T CurrentObject { get { return TrackedObjects[TrackedObjects.Count - 1]; } } public TrackingState CurrentState { get { return States[States.Count - 1]; } } public int NumFramesInCurrentState { get; private set; } private int numFramesDetectedUntilTracked; private int numFramesLostUntilDeleted; private bool wasTrackedBefore; public event TrackingStateChangedEventHandler Detected; public event TrackingStateChangedEventHandler Tracked; public event TrackingStateChangedEventHandler Retracked; public event TrackingStateChangedEventHandler Lost; public event TrackingStateChangedEventHandler Deleted; 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) { ID = getNextUnusedID(); TrackedObjects = new List(); TrackedObjects.Add(null); States = new List(); States.Add(TrackingState.None); NumFramesInCurrentState = 1; this.numFramesDetectedUntilTracked = numFramesDetectedUntilTracked; this.numFramesLostUntilDeleted = numFramesLostUntilDeleted; this.wasTrackedBefore = false; } ~TrackableObjectHistory() { setIDUnused(ID); } public void addObjectToHistory(T detectedObject) { TrackingState previousState = CurrentState; TrackingState newState = TrackingState.None; //get newState if (detectedObject != null) { if (previousState == TrackingState.None) newState = TrackingState.Detected; else if (previousState == TrackingState.Lost) { if (wasTrackedBefore) newState = TrackingState.Tracked; else newState = TrackingState.Detected; } else if (previousState == TrackingState.Tracked) newState = TrackingState.Tracked; else if (previousState == TrackingState.Detected) { if (NumFramesInCurrentState == numFramesDetectedUntilTracked) newState = TrackingState.Tracked; else newState = TrackingState.Detected; } } else if (previousState == TrackingState.Lost && NumFramesInCurrentState == numFramesLostUntilDeleted) newState = TrackingState.Delete; else newState = TrackingState.Lost; //set trackedBefore if (newState == TrackingState.Tracked) wasTrackedBefore = true; //update numFramesInCurrentState if (newState == previousState) NumFramesInCurrentState++; else NumFramesInCurrentState = 1; //update lastObject if (detectedObject != null) { LastObject = detectedObject; detectedObject.setTrackID(ID); } //add current state+object TrackedObjects.Add(detectedObject); States.Add(newState); //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() { int id = 1; while (usedIDs.Contains(id)) id++; usedIDs.Add(id); return id; } public static void setIDUnused(int id) { usedIDs.Remove(id); } } }