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); }
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); }