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, } class Tracker where T : TrackableObject { public List> Histories { get; private set; } public List TrackedObjects { get; private set; } private List> similarities; private String className; private LogSubject logSubject; private int numFramesUntilTracked; private int numFramesUntilLost; private float minSimilarityForTracking; public Tracker(LogSubject logSubject, int numFramesUntilTracked, int numFramesUntilLost, float minSimilarityForTracking) { this.className = typeof(T).Name; this.logSubject = logSubject; this.numFramesUntilTracked = numFramesUntilTracked; this.numFramesUntilLost = numFramesUntilLost; 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 = new TrackableObjectHistory(logSubject, numFramesUntilTracked); 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 = new TrackableObjectHistory(logSubject, numFramesUntilTracked); 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) { if (unasignedHistory.CurrentState != TrackingState.Lost) Logger.log(className + " #" + unasignedHistory.ID + " lost", logSubject); 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)); Console.WriteLine("------"); foreach (SimilarityContainer sim in similarities) { Console.WriteLine(sim.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.Lost && history.NumFramesInCurrentState >= numFramesUntilLost) { Histories.RemoveAt(i); Logger.log(className + " #" + history.ID + " deleted", logSubject); } } } } }