Example #1
0
        public override bool Track(List <AbstractTrackPoint> _previousPoints, Bitmap _CurrentImage, long _t, out AbstractTrackPoint _currentPoint)
        {
            //---------------------------------------------------------------------
            // The input informations we have at hand are:
            // - The current bitmap we have to find the point into.
            // - The coordinates of all the previous points tracked.
            // - Previous tracking infos, stored in the TrackPoints tracked so far.
            //---------------------------------------------------------------------

            TrackPointBlock lastTrackPoint = (TrackPointBlock)_previousPoints[_previousPoints.Count - 1];
            Point           lastPoint      = lastTrackPoint.ToPoint();

            bool bMatched = false;

            _currentPoint = null;

            if (lastTrackPoint.Template != null && _CurrentImage != null)
            {
                // Center search zone around last point.
                Point     searchCenter = lastPoint;
                Rectangle searchZone   = new Rectangle(searchCenter.X - (m_SearchWindowSize.Width / 2),
                                                       searchCenter.Y - (m_SearchWindowSize.Height / 2),
                                                       m_SearchWindowSize.Width,
                                                       m_SearchWindowSize.Height);

                searchZone.Intersect(new Rectangle(0, 0, _CurrentImage.Width, _CurrentImage.Height));

                double fBestScore    = 0;
                Point  bestCandidate = new Point(-1, -1);

                //Image<Bgr, Byte> cvTemplate = new Image<Bgr, Byte>(lastTrackPoint.Template);
                //Image<Bgr, Byte> cvImage = new Image<Bgr, Byte>(_CurrentImage);

                Bitmap img = _CurrentImage;
                Bitmap tpl = lastTrackPoint.Template;

                BitmapData imageData    = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly, img.PixelFormat);
                BitmapData templateData = tpl.LockBits(new Rectangle(0, 0, tpl.Width, tpl.Height), ImageLockMode.ReadOnly, tpl.PixelFormat);

                Image <Bgr, Byte> cvImage    = new Image <Bgr, Byte>(imageData.Width, imageData.Height, imageData.Stride, imageData.Scan0);
                Image <Bgr, Byte> cvTemplate = new Image <Bgr, Byte>(templateData.Width, templateData.Height, templateData.Stride, templateData.Scan0);

                cvImage.ROI = searchZone;

                int resWidth  = searchZone.Width - lastTrackPoint.Template.Width + 1;
                int resHeight = searchZone.Height - lastTrackPoint.Template.Height + 1;

                Image <Gray, Single> similarityMap = new Image <Gray, Single>(resWidth, resHeight);

                //CvInvoke.cvMatchTemplate(cvImage.Ptr, cvTemplate.Ptr, similarityMap.Ptr, TM_TYPE.CV_TM_SQDIFF_NORMED);
                //CvInvoke.cvMatchTemplate(cvImage.Ptr, cvTemplate.Ptr, similarityMap.Ptr, TM_TYPE.CV_TM_CCORR_NORMED);
                CvInvoke.cvMatchTemplate(cvImage.Ptr, cvTemplate.Ptr, similarityMap.Ptr, TM_TYPE.CV_TM_CCOEFF_NORMED);

                img.UnlockBits(imageData);
                tpl.UnlockBits(templateData);

                // Find max
                Point  p1   = new Point(0, 0);
                Point  p2   = new Point(0, 0);
                double fMin = 0;
                double fMax = 0;

                CvInvoke.cvMinMaxLoc(similarityMap.Ptr, ref fMin, ref fMax, ref p1, ref p2, IntPtr.Zero);

                if (fMax > m_fSimilarityTreshold)
                {
                    bestCandidate = new Point(searchZone.Left + p2.X + tpl.Width / 2, searchZone.Top + p2.Y + tpl.Height / 2);
                    fBestScore    = fMax;
                }

                #region Monitoring
                if (m_bMonitoring)
                {
                    // Save the similarity map to file.
                    Image <Gray, Byte> mapNormalized = new Image <Gray, Byte>(similarityMap.Width, similarityMap.Height);
                    CvInvoke.cvNormalize(similarityMap.Ptr, mapNormalized.Ptr, 0, 255, NORM_TYPE.CV_MINMAX, IntPtr.Zero);

                    Bitmap bmpMap = mapNormalized.ToBitmap();

                    string tplDirectory = @"C:\Documents and Settings\Administrateur\Mes documents\Dev  Prog\Videa\Video Testing\Tracking\Template Update";
                    bmpMap.Save(tplDirectory + String.Format(@"\simiMap-{0:000}-{1:0.00}.bmp", _previousPoints.Count, fBestScore));
                }
                #endregion

                // Result of the matching.
                if (bestCandidate.X != -1 && bestCandidate.Y != -1)
                {
                    // Save template in the point.
                    _currentPoint = CreateTrackPoint(false, bestCandidate.X, bestCandidate.Y, fBestScore, _t, img, _previousPoints);
                    ((TrackPointBlock)_currentPoint).Similarity = fBestScore;

                    bMatched = true;
                }
                else
                {
                    // No match. Create the point at the center of the search window (whatever that might be).
                    _currentPoint = CreateTrackPoint(false, searchCenter.X, searchCenter.Y, 0.0f, _t, img, _previousPoints);
                    log.Debug("Track failed. No block over the similarity treshold in the search window.");
                }
            }
            else
            {
                // No image. (error case ?)
                // Create the point at the last point location.
                _currentPoint = CreateTrackPoint(false, lastTrackPoint.X, lastTrackPoint.Y, 0.0f, _t, _CurrentImage, _previousPoints);
                log.Debug("Track failed. No input image, or last point doesn't have any cached block image.");
            }

            return(bMatched);
        }
Example #2
0
        public override bool Track(List <AbstractTrackPoint> _previousPoints, Bitmap _CurrentImage, long _t, out AbstractTrackPoint _currentPoint)
        {
            //---------------------------------------------------------------------
            // The input informations we have at hand are:
            // - The current bitmap we have to find the point into.
            // - The coordinates of all the previous points tracked.
            // - Previous tracking infos, stored in the TrackPoints tracked so far.
            //---------------------------------------------------------------------

            TrackPointBlock lastTrackPoint = (TrackPointBlock)_previousPoints[_previousPoints.Count - 1];
            Point           lastPoint      = lastTrackPoint.ToPoint();

            // Compute the projected point.
            // (coordinate of the point that would keep following the same motion as in last step).
            Point forecast;

            if (_previousPoints.Count > 1)
            {
                Point penultimate = _previousPoints[_previousPoints.Count - 2].ToPoint();

                int dx = lastPoint.X - penultimate.X;
                int dy = lastPoint.Y - penultimate.Y;

                forecast = new Point(lastPoint.X + dx, lastPoint.Y + dy);
            }
            else
            {
                forecast = _previousPoints[0].ToPoint();
            }

            bool bMatched = false;

            _currentPoint = null;

            if (lastTrackPoint.Template != null && _CurrentImage != null)
            {
                // Center search zone around last point.
                Point     searchCenter = lastPoint;
                Rectangle searchZone   = new Rectangle(searchCenter.X - (m_SearchWindowSize.Width / 2),
                                                       searchCenter.Y - (m_SearchWindowSize.Height / 2),
                                                       m_SearchWindowSize.Width,
                                                       m_SearchWindowSize.Height);

                // Convert to grayscale prior to match, if necessary.
                Bitmap workingImage = m_bWorkOnGrayscale ? Grayscale.CommonAlgorithms.BT709.Apply(_CurrentImage) : _CurrentImage;

                double fBestScore    = 0;
                Point  bestCandidate = new Point(-1, -1);

                if (m_UpdateStrategy == UpdateStrategy.Both)
                {
                    // Try to match the initial reference block in the image first.
                    // If it gets a score over a given threshold, we give it the priority over the I-1 block.
                    // This is an attempt at correcting the drift issue.

                    // Find the last reference block. (last block manually choosen by user.)
                    int iLastReferenceBlock = 0;
                    for (int b = _previousPoints.Count - 1; b >= 0; b--)
                    {
                        if (((TrackPointBlock)_previousPoints[b]).IsReferenceBlock)
                        {
                            iLastReferenceBlock = b;
                            break;
                        }
                    }

                    Bitmap originalTemplate        = ((TrackPointBlock)_previousPoints[iLastReferenceBlock]).Template;
                    Bitmap workingOriginalTemplate = m_bWorkOnGrayscale ? Grayscale.CommonAlgorithms.BT709.Apply(originalTemplate) : originalTemplate;

                    ITemplateMatching originalMatcher;
                    if (m_bCorrelationMatching)
                    {
                        originalMatcher = new CorrelationTemplateMatching(m_fOriginalSimilarityThreshold);
                    }
                    else
                    {
                        originalMatcher = new ExhaustiveTemplateMatching(m_fOriginalSimilarityThreshold);
                    }

                    TemplateMatch[] matchingsOriginal = originalMatcher.ProcessImage(workingImage, workingOriginalTemplate, searchZone);

                    if (matchingsOriginal.Length > 0)
                    {
                        // We found a block with a very good similarity to the original block selected by the user.
                        // It will take precedence over the I-1 block.
                        TemplateMatch tm = matchingsOriginal[0];
                        bestCandidate = new Point(tm.Rectangle.Left + (tm.Rectangle.Width / 2), tm.Rectangle.Top + (tm.Rectangle.Height / 2));
                        fBestScore    = tm.Similarity;

                        if (m_bMonitoring)
                        {
                            log.Debug(String.Format("Original template found with good similarity ({0:0.000}), {1} candidates.", tm.Similarity, matchingsOriginal.Length));
                        }
                    }
                    else
                    {
                        log.Debug(String.Format("Original template not found"));
                    }
                }

                if (bestCandidate.X == -1 || bestCandidate.Y == 1)
                {
                    Bitmap workingTemplate = m_bWorkOnGrayscale ? Grayscale.CommonAlgorithms.BT709.Apply(lastTrackPoint.Template) : lastTrackPoint.Template;

                    ITemplateMatching templateMatcher;
                    if (m_bCorrelationMatching)
                    {
                        templateMatcher = new CorrelationTemplateMatching(m_fSimilarityTreshold);
                    }
                    else
                    {
                        templateMatcher = new ExhaustiveTemplateMatching(m_fSimilarityTreshold);
                    }

                    TemplateMatch[] matchings = templateMatcher.ProcessImage(workingImage, workingTemplate, searchZone);

                    if (matchings.Length > 0)
                    {
                        // Find the best candidate.
                        // Score is weighted average of : similarity and closeness to forecast.
                        int    iBestCandidate  = -1;
                        double fWinnerDistance = 0;
                        for (int i = 0; i < matchings.Length; i++)
                        {
                            TemplateMatch tm = matchings[i];
                            //if(_previousPoints.Count > 1)
                            {
                                Point  candidatePoint      = new Point(tm.Rectangle.Left + (tm.Rectangle.Width / 2), tm.Rectangle.Top + (tm.Rectangle.Height / 2));
                                double fDistanceToForecast = CalibrationHelper.PixelDistance(candidatePoint, forecast);
                                double fScore = GetScore(tm.Similarity, fDistanceToForecast, m_fMaxDistance);

                                if (fScore > fBestScore)
                                {
                                    fBestScore      = fScore;
                                    fWinnerDistance = fDistanceToForecast;
                                    iBestCandidate  = i;
                                    bestCandidate   = candidatePoint;
                                }
                            }
                        }
                        if (m_bMonitoring)
                        {
                            log.Debug(String.Format("Last template found with : Score:{0:0.000}, Similarity:{1:0.000} (index:{2:00}/{3:00}), Distance to forecast (px):{4:0.00}",
                                                    fBestScore,
                                                    matchings[iBestCandidate].Similarity,
                                                    iBestCandidate,
                                                    matchings.Length,
                                                    fWinnerDistance));
                        }
                    }
                    else
                    {
                        log.Debug(String.Format("Last template not found, or score too low."));
                    }
                }

                // Result of the matching.
                if (bestCandidate.X != -1 && bestCandidate.Y != -1)
                {
                    // Save template in the point.
                    _currentPoint = CreateTrackPoint(false, bestCandidate.X, bestCandidate.Y, fBestScore, _t, _CurrentImage, _previousPoints);
                    ((TrackPointBlock)_currentPoint).Similarity = fBestScore;

                    // Finally, it is only considered a match if the score is over the threshold.
                    if (fBestScore >= m_fScoreTreshold || _previousPoints.Count == 1)
                    {
                        bMatched = true;
                    }
                }
                else
                {
                    // No match. Create the point at the center of the search window (whatever that might be).
                    _currentPoint = CreateTrackPoint(false, searchCenter.X, searchCenter.Y, fBestScore, _t, _CurrentImage, _previousPoints);
                    log.Debug("Track failed. No block over the similarity treshold in the search window.");
                }

                #region Monitoring
                if (m_bMonitoring)
                {
                    // Save current template to file, to visually monitor the drift.
                    string tplDirectory = @"C:\Documents and Settings\Administrateur\Mes documents\Dev  Prog\Videa\Video Testing\Tracking\Template Update";
                    if (_previousPoints.Count == 1)
                    {
                        // Clean up folder.
                        string[] tplFiles = Directory.GetFiles(tplDirectory, "*.bmp");
                        foreach (string f in tplFiles)
                        {
                            File.Delete(f);
                        }
                    }
                    String iFileName = String.Format("{0}\\tpl-{1:000}.bmp", tplDirectory, _previousPoints.Count);
                    ((TrackPointBlock)_currentPoint).Template.Save(iFileName);
                }
                #endregion
            }
            else
            {
                // No image. (error case ?)
                // Create the point at the last point location.
                _currentPoint = CreateTrackPoint(false, lastTrackPoint.X, lastTrackPoint.Y, 0.0f, _t, _CurrentImage, _previousPoints);
                log.Debug("Track failed. No input image, or last point doesn't have any cached block image.");
            }

            return(bMatched);
        }