using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using bbiwarg.Graphics; using bbiwarg.Utility; namespace bbiwarg.Recognition.Tracking { public enum TrackingState { None = 0, Detected = 1, Tracked = 2, Lost = 3, Delete = 4 } abstract class Tracker where T : TrackableObject { public List> Histories { get; private set; } public List TrackedObjects { get; private set; } private List> similarities; private int numFramesDetectedUntilTracked; private int numFramesLostUntilDeleted; private float minSimilarityForTracking; public Tracker(int numFramesDetectedUntilTracked, int numFramesLostUntilDeleted, float minSimilarityForTracking) { this.numFramesDetectedUntilTracked = numFramesDetectedUntilTracked; this.numFramesLostUntilDeleted = numFramesLostUntilDeleted; this.minSimilarityForTracking = minSimilarityForTracking; reset(); } public void reset() { Histories = new List>(); TrackedObjects = new List(); } public void updateFrame(List detectedObjects) { if (Histories.Count == 0) { foreach (T detectedObject in detectedObjects) { TrackableObjectHistory history = createNewHistory(); history.addObjectToHistory(detectedObject); Histories.Add(history); } } else { updateHistories(detectedObjects); removeLongLostObjects(); } } private void updateHistories(List detectedObjects) { TrackedObjects = new List(); List> unasignedHistories = new List>(); foreach (TrackableObjectHistory history in Histories) unasignedHistories.Add(history); List unasignedDetectedObjects = new List(); foreach (T detectedObject in detectedObjects) unasignedDetectedObjects.Add(detectedObject); //asign previously tracked objects to their best fits of detectedObjects createSimilarities(detectedObjects); while (similarities.Count > 0) { SimilarityContainer maxSimilarity = similarities[0]; TrackableObjectHistory history = maxSimilarity.History; T detectedObject = maxSimilarity.DetectedObject; history.addObjectToHistory(detectedObject); TrackedObjects.Add(detectedObject); unasignedHistories.Remove(history); unasignedDetectedObjects.Remove(detectedObject); removeConcurringSimilarities(maxSimilarity); } //add new history for each new unasigned detectedObject foreach (T unasignedDetectedObject in unasignedDetectedObjects) { TrackableObjectHistory newHistory = createNewHistory(); newHistory.addObjectToHistory(unasignedDetectedObject); Histories.Add(newHistory); } //add null-object to each unasigned history (didn't find a best fit during this frame -> lost track) foreach (TrackableObjectHistory unasignedHistory in unasignedHistories) { unasignedHistory.addObjectToHistory(null); } } private void createSimilarities(List detectedObjects) { similarities = new List>(); foreach (TrackableObjectHistory history in Histories) { foreach (T detectedObject in detectedObjects) { SimilarityContainer similarityContainer = new SimilarityContainer(history, detectedObject); if (similarityContainer.Similarity > minSimilarityForTracking) { similarities.Add(similarityContainer); } } } // sort depending on similarity-value similarities.Sort((fs1, fs2) => fs2.Similarity.CompareTo(fs1.Similarity)); } private void removeConcurringSimilarities(SimilarityContainer removeSimilarity) { for (int i = similarities.Count - 1; i >= 0; i--) { SimilarityContainer similarity = similarities[i]; if (similarity.History == removeSimilarity.History || similarity.DetectedObject == removeSimilarity.DetectedObject) similarities.RemoveAt(i); } } private void removeLongLostObjects() { for (int i = Histories.Count - 1; i >= 0; i--) { TrackableObjectHistory history = Histories[i]; if (history.CurrentState == TrackingState.Delete) { Histories.RemoveAt(i); } } } private TrackableObjectHistory createNewHistory() { TrackableObjectHistory history = new TrackableObjectHistory(numFramesDetectedUntilTracked, numFramesLostUntilDeleted); history.Detected += onDetect; history.Tracked += onTrack; history.Retracked += onRetrack; history.Lost += onLoose; history.Deleted += onDelete; return history; } 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); } }