private void DrawDebugInfo(Graphics canvas, AbstractTrackPoint point, RectangleF search) { TrackPointBlock tpb = point as TrackPointBlock; if (tpb == null) { return; } Font f = new Font("Consolas", 8, FontStyle.Bold); string text = string.Format("simi:{0:0.000}, age:{1}, pos:{2:0.000}×{3:0.000}", tpb.Similarity, tpb.TemplateAge, tpb.Point.X, tpb.Point.Y); Brush b = tpb.Similarity > parameters.TemplateUpdateThreshold ? Brushes.Green : Brushes.Red; canvas.DrawString(text, f, b, search.Location.Translate(0, -25)); f.Dispose(); }
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 AbstractTrackPoint CreateTrackPoint(bool _bManual, int _x, int _y, double _fSimilarity, long _t, Bitmap _CurrentImage, List <AbstractTrackPoint> _previousPoints) { // Creates a TrackPoint from the input image at the given coordinates. // Stores algorithm internal data in the point, to help next match. // _t is in relative timestamps from the first point. // Copy the template from the image into its own Bitmap. Bitmap tpl = new Bitmap(m_BlockSize.Width, m_BlockSize.Height, PixelFormat.Format24bppRgb); bool bUpdateWithCurrentImage = true; if (!_bManual && _previousPoints.Count > 0 && _fSimilarity > m_fTemplateUpdateSimilarityThreshold) { // Do not update the template if it's not that different. TrackPointBlock prevBlock = _previousPoints[_previousPoints.Count - 1] as TrackPointBlock; if (prevBlock != null && prevBlock.Template != null) { tpl = AForge.Imaging.Image.Clone(prevBlock.Template); bUpdateWithCurrentImage = false; } } if (bUpdateWithCurrentImage) { BitmapData imageData = _CurrentImage.LockBits(new Rectangle(0, 0, _CurrentImage.Width, _CurrentImage.Height), ImageLockMode.ReadOnly, _CurrentImage.PixelFormat); BitmapData templateData = tpl.LockBits(new Rectangle(0, 0, tpl.Width, tpl.Height), ImageLockMode.ReadWrite, tpl.PixelFormat); int pixelSize = 3; int tplStride = templateData.Stride; int templateWidthInBytes = m_BlockSize.Width * pixelSize; int tplOffset = tplStride - templateWidthInBytes; int imgStride = imageData.Stride; int imageWidthInBytes = _CurrentImage.Width * pixelSize; int imgOffset = imgStride - (_CurrentImage.Width * pixelSize) + imageWidthInBytes - templateWidthInBytes; int startY = _y - (m_BlockSize.Height / 2); int startX = _x - (m_BlockSize.Width / 2); if (startX < 0) { startX = 0; } if (startY < 0) { startY = 0; } unsafe { byte *pTpl = (byte *)templateData.Scan0.ToPointer(); byte *pImg = (byte *)imageData.Scan0.ToPointer() + (imgStride * startY) + (pixelSize * startX); for (int row = 0; row < m_BlockSize.Height; row++) { if (startY + row > imageData.Height - 1) { break; } for (int col = 0; col < templateWidthInBytes; col++, pTpl++, pImg++) { if (startX * pixelSize + col < imageWidthInBytes) { *pTpl = *pImg; } } pTpl += tplOffset; pImg += imgOffset; } } _CurrentImage.UnlockBits(imageData); tpl.UnlockBits(templateData); } #region Monitoring if (m_bMonitoring && bUpdateWithCurrentImage) { // 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); tpl.Save(iFileName); } #endregion TrackPointBlock tpb = new TrackPointBlock(_x, _y, _t, tpl); tpb.IsReferenceBlock = _bManual; tpb.Similarity = _bManual ? 1.0f : _fSimilarity; return(tpb); }
public override bool Track(List <AbstractTrackPoint> previousPoints, Bitmap currentImage, long position, 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 scores, stored in the TrackPoints tracked so far. //--------------------------------------------------------------------- TrackPointBlock lastTrackPoint = (TrackPointBlock)previousPoints[previousPoints.Count - 1]; PointF lastPoint = lastTrackPoint.Point; PointF subpixel = new PointF(lastPoint.X - (int)lastPoint.X, lastPoint.Y - (int)lastPoint.Y); bool matched = false; currentPoint = null; if (lastTrackPoint.Template != null && currentImage != null) { // Center search zone around last point. PointF searchCenter = lastPoint; Rectangle searchZone = new Rectangle((int)(searchCenter.X - (searchWindow.Width / 2)), (int)(searchCenter.Y - (searchWindow.Height / 2)), searchWindow.Width, searchWindow.Height); searchZone.Intersect(new Rectangle(0, 0, currentImage.Width, currentImage.Height)); //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 <Bgra, Byte> cvImage = new Image <Bgra, Byte>(imageData.Width, imageData.Height, imageData.Stride, imageData.Scan0); Image <Bgra, Byte> cvTemplate = new Image <Bgra, 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 double bestScore = 0; PointF bestCandidate = new PointF(-1, -1); Point minLoc = Point.Empty; Point maxLoc = Point.Empty; double min = 0; double max = 0; CvInvoke.cvMinMaxLoc(similarityMap.Ptr, ref min, ref max, ref minLoc, ref maxLoc, IntPtr.Zero); if (max > similarityTreshold) { PointF loc = RefineLocation(similarityMap.Data, maxLoc, parameters.RefinementNeighborhood); // The template matching was done on a template aligned with the integer part of the actual position. // We reinject the floating point part of the orginal positon into the result. loc = loc.Translate(subpixel.X, subpixel.Y); bestCandidate = new PointF(searchZone.Left + loc.X + tpl.Width / 2, searchZone.Top + loc.Y + tpl.Height / 2); bestScore = max; } #region Monitoring if (monitoring) { // 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:\Users\Joan\Videos\Kinovea\Video Testing\Tracking\simimap"; bmpMap.Save(tplDirectory + String.Format(@"\simiMap-{0:000}-{1:0.00}.bmp", previousPoints.Count, bestScore)); } #endregion // Result of the matching. if (bestCandidate.X != -1 && bestCandidate.Y != -1) { currentPoint = CreateTrackPoint(false, bestCandidate, bestScore, position, img, previousPoints); ((TrackPointBlock)currentPoint).Similarity = bestScore; } else { // No match. Create the point at the center of the search window (whatever that might be). currentPoint = CreateTrackPoint(false, lastPoint, 0.0f, position, img, previousPoints); log.Debug("Track failed. No block over the similarity treshold in the search window."); } matched = true; } else { // No image. (error case ?) // Create the point at the last point location. currentPoint = CreateTrackPoint(false, lastPoint, 0.0f, position, currentImage, previousPoints); log.Debug("Track failed. No input image, or last point doesn't have any cached block image."); } return(matched); }
public override AbstractTrackPoint CreateTrackPoint(bool manual, PointF p, double similarity, long t, Bitmap currentImage, List <AbstractTrackPoint> previousPoints) { // Creates a TrackPoint from the input image at the given coordinates. // Stores algorithm internal data in the point, to help next match. // _t is in relative timestamps from the first point. // Copy the template from the image into its own Bitmap. Bitmap tpl = new Bitmap(blockWindow.Width, blockWindow.Height, PixelFormat.Format32bppPArgb); int age = 0; bool updateWithCurrentImage = true; if (!manual && previousPoints.Count > 0 && similarity > templateUpdateThreshold || similarity < similarityTreshold) { // Do not update the template if it's not that different. TrackPointBlock prevBlock = previousPoints[previousPoints.Count - 1] as TrackPointBlock; if (prevBlock != null && prevBlock.Template != null) { tpl = AForge.Imaging.Image.Clone(prevBlock.Template); updateWithCurrentImage = false; age = prevBlock.TemplateAge + 1; } } if (updateWithCurrentImage) { BitmapData imageData = currentImage.LockBits(new Rectangle(0, 0, currentImage.Width, currentImage.Height), ImageLockMode.ReadOnly, currentImage.PixelFormat); BitmapData templateData = tpl.LockBits(new Rectangle(0, 0, tpl.Width, tpl.Height), ImageLockMode.ReadWrite, tpl.PixelFormat); int pixelSize = 4; int tplStride = templateData.Stride; int templateWidthInBytes = blockWindow.Width * pixelSize; int tplOffset = tplStride - templateWidthInBytes; int imgStride = imageData.Stride; int imageWidthInBytes = currentImage.Width * pixelSize; int imgOffset = imgStride - (currentImage.Width * pixelSize) + imageWidthInBytes - templateWidthInBytes; int startY = (int)(p.Y - (blockWindow.Height / 2.0)); int startX = (int)(p.X - (blockWindow.Width / 2.0)); if (startX < 0) { startX = 0; } if (startY < 0) { startY = 0; } unsafe { byte *pTpl = (byte *)templateData.Scan0.ToPointer(); byte *pImg = (byte *)imageData.Scan0.ToPointer() + (imgStride * startY) + (pixelSize * startX); for (int row = 0; row < blockWindow.Height; row++) { if (startY + row > imageData.Height - 1) { break; } for (int col = 0; col < templateWidthInBytes; col++, pTpl++, pImg++) { if (startX * pixelSize + col < imageWidthInBytes) { *pTpl = *pImg; } } pTpl += tplOffset; pImg += imgOffset; } } currentImage.UnlockBits(imageData); tpl.UnlockBits(templateData); } #region Monitoring if (monitoring && updateWithCurrentImage) { // Save current template to file, to visually monitor the drift. string tplDirectory = @"C:\Users\Joan\Videos\Kinovea\Video Testing\Tracking\simimap"; 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); tpl.Save(iFileName); } #endregion TrackPointBlock tpb = new TrackPointBlock(p.X, p.Y, t, tpl); tpb.TemplateAge = age; tpb.IsReferenceBlock = manual; tpb.Similarity = manual ? 1.0f : similarity; return(tpb); }
public override AbstractTrackPoint CreateTrackPoint(bool _bManual, int _x, int _y, double _fSimilarity, long _t, Bitmap _CurrentImage, List <AbstractTrackPoint> _previousPoints) { // Creates a TrackPoint from the input image at the given coordinates. // Stores algorithm internal data in the point, to help next match. // _t is in relative timestamps from the first point. Bitmap tpl = new Bitmap(m_BlockSize.Width, m_BlockSize.Height, PixelFormat.Format24bppRgb); Graphics g = Graphics.FromImage(tpl); UpdateStrategy strategy = m_UpdateStrategy; if (_bManual) { // No points yet, or the user manually changed the point. // Use the block from the current image. strategy = UpdateStrategy.Current; } switch (strategy) { case UpdateStrategy.Original: // No update, we keep the original block. g.DrawImage(((TrackPointBlock)_previousPoints[0]).Template, 0, 0); break; case UpdateStrategy.Mixed: { // Update the template with a mix of the current block around match and the original block selected. // Paste the new block. Rectangle rDst = new Rectangle(0, 0, m_BlockSize.Width, m_BlockSize.Height); Rectangle rSrc = new Rectangle(_x - (m_BlockSize.Width / 2), _y - (m_BlockSize.Height / 2), m_BlockSize.Width, m_BlockSize.Height); g.DrawImage(_CurrentImage, rDst, rSrc, GraphicsUnit.Pixel); // Paste the original block at 50%. ColorMatrix mergeMatrix = new ColorMatrix(); mergeMatrix.Matrix00 = 1.0f; mergeMatrix.Matrix11 = 1.0f; mergeMatrix.Matrix22 = 1.0f; mergeMatrix.Matrix33 = 0.5f; mergeMatrix.Matrix44 = 1.0f; ImageAttributes mergeImgAttr = new ImageAttributes(); mergeImgAttr.SetColorMatrix(mergeMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); //g.DrawImage(m_SyncMergeImage, rSyncDst, 0, 0, m_SyncMergeImage.Width, m_SyncMergeImage.Height, GraphicsUnit.Pixel, m_SyncMergeImgAttr); Bitmap originalTpl = ((TrackPointBlock)_previousPoints[0]).Template; g.DrawImage(originalTpl, rDst, 0, 0, m_BlockSize.Width, m_BlockSize.Height, GraphicsUnit.Pixel, mergeImgAttr); break; } case UpdateStrategy.Current: case UpdateStrategy.Both: default: { // Update the template with the block around the new position. Rectangle rDst = new Rectangle(0, 0, m_BlockSize.Width, m_BlockSize.Height); Rectangle rSrc = new Rectangle(_x - (m_BlockSize.Width / 2), _y - (m_BlockSize.Height / 2), m_BlockSize.Width, m_BlockSize.Height); g.DrawImage(_CurrentImage, rDst, rSrc, GraphicsUnit.Pixel); break; } } TrackPointBlock tpb = new TrackPointBlock(_x, _y, _t, tpl); tpb.IsReferenceBlock = _bManual; tpb.Similarity = _bManual ? 1.0f : 0; return(tpb); }
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); }