Wednesday, November 16, 2011

Brand new day

Well, as the saying goes no rest for the wicked, I'm giving particle filter another chance and I'm not getting up until it's done.
The paper I'm following is Object Tracking with an Adaptive Color-Based Particle Filter.

Matching the detected objects with the tracked objects is a delicate process.
Currently my approach is weighted average sum of :
  • Rectangle similarity (location, width, height) (0.4f)
  • Percentage of rectangles intersection (0.3f)
  • Histogram compare with  Correlation metric (0.3f)
 Maybe it's too sensitive but it's a good start

        /// <summary>
        /// Given the detected and tracked objects, match each detected object to at most one tracked object
        /// If no matches are found return -1 to the entry for the detected object
        /// </summary>
        /// <param name="_detections">An array of detected rectangle</param>
        /// <param name="_trackedObjects">An array of tracked objects</param>
        /// <returns>An array with the tracked object's index that is matched to the detected object</returns>
        public static int[] MatchDetections(
            Rectangle[] _detections, 
            TrackedObject[] _trackedObjects,
            Image<Gray, byte>[] _imageChannels)
        {
            float[] weights = new float[] { 0.4f, 0.3f, 0.3f };
            bool[] searched = new bool[_detections.Length];
            int[] matches = new int[_detections.Length];
            float[,] metrics = new float[_detections.Length, _trackedObjects.Length];
            Rectangle rectDetection, rectTracked;
            DenseHistogram histDetection, histTracked;

            // for each detected object compute its 
            // matching metric with all the other tracked objects
            for (int i = 0; i < _detections.Length; i++)
            {
                matches[i] = -1;
                rectDetection = _detections[i];
                rectDetection.Inflate(-rectDetection.Width / 10, -rectDetection.Height / 10);
                histDetection = OpenCVExtended.HistogramAtLocation(_imageChannels, rectDetection, true);
                for (int j = 0; j < _trackedObjects.Length; j++)
                {
                    histTracked = _trackedObjects[j].Histogram;
                    rectTracked = _trackedObjects[j].TrackWindow;

                    metrics[i, j] =
                        OpenCVExtended.RectangleSimilarity(rectDetection, rectTracked) * weights[0] +
                        Math.Max(OpenCVExtended.IntersectionAreaPercentage(rectDetection, rectTracked), 
                            OpenCVExtended.IntersectionAreaPercentage(rectTracked, rectDetection)) * weights[1] +
                        (1.0f - (float)CvInvoke.cvCompareHist(histTracked, histDetection, HIST_METHOD)) * weights[2];
                }
            }
            
            // Given the metric matrix make the best matches 
            // between the detected and tracked objects
            for (int k = 0; k < _detections.Length; k++)
            {
                int topDetection = -1, topTracked = -1;
                float topMetric = float.MinValue;
                for (int i = 0; i < _detections.Length; i++)
                    for (int j = 0; j < _trackedObjects.Length; j++)
                        if (topMetric < metrics[i, j])
                        {
                            topMetric = metrics[i, j];
                            topDetection = i;
                            topTracked = j;
                        }
                // if a value is selected then set to minimum float  
                // the row and collumn of the selected value
                if (topMetric > float.MinValue)
                {
                    for (int j = 0; j < _trackedObjects.Length; j++)
                        metrics[topDetection, j] = float.MinValue;
                    for (int i = 0; i < _detections.Length; i++)
                        metrics[i, topTracked] = float.MinValue;
                }
                // if topmetric exceeds a given threshold then make the assignment
                if (topDetection != -1 && topMetric > MIN_SIMILARITY)
                    matches[topDetection] = topTracked;
            }
            return matches;
        }



PS Haar training is still going...