//模板匹配
private void btnCalc_Click(object sender, EventArgs e)
{
//输入图像
Image imageInput = new Image((Bitmap)pbInput.Image);
//模板图像
Image imageTemplate = new Image((Bitmap)pbTemplate.Image);
//缩放因子,更小的图像可以提高处理速度
double scale = 1d;
double.TryParse(txtScale.Text, out scale);
if (scale != 1d)
{
imageInput = imageInput.Resize(scale, INTER.CV_INTER_LINEAR);
imageTemplate = imageTemplate.Resize(scale, INTER.CV_INTER_LINEAR);
}
//色彩空间
string colorSpace = (string)cmbColorSpace.SelectedItem;
IImage imageInput2, imageTemplate2;
if (colorSpace == "Gray")
{
imageInput2 = imageInput.Convert();
imageTemplate2 = imageTemplate.Convert();
}
else if (colorSpace == "HSV")
{
imageInput2 = imageInput.Convert();
imageTemplate2 = imageTemplate.Convert();
}
else
{
imageInput2 = imageInput.Copy();
imageTemplate2 = imageTemplate.Copy();
}
//匹配方式数组
TM_TYPE[] tmTypes = new TM_TYPE[] { TM_TYPE.CV_TM_SQDIFF, TM_TYPE.CV_TM_SQDIFF_NORMED, TM_TYPE.CV_TM_CCORR, TM_TYPE.CV_TM_CCORR_NORMED, TM_TYPE.CV_TM_CCOEFF, TM_TYPE.CV_TM_CCOEFF_NORMED };
//输出图像(匹配结果)
Image[] imageResults = new Image[tmTypes.Length];
//依次执行每种匹配,并归一化结果
int i = 0;
double totalTime = 0d; //总共用时
double time; //每种匹配的用时
Stopwatch sw = new Stopwatch();
txtResult.Text += string.Format("开始执行匹配(色彩空间:{0},缩放因子:{1})/r/n", colorSpace, scale);
foreach (TM_TYPE tmType in tmTypes)
{
sw.Start();
//模板匹配(注意:因为接口IImage中没有名为MatchTemplate的定义,所以需要进行强制转换)
//Image imageResult = imageInput2.MatchTemplate(imageTemplate2, tmType);
Image imageResult;
if (colorSpace == "Gray")
imageResult = ((Image)imageInput2).MatchTemplate((Image)imageTemplate2, tmType);
else if (colorSpace == "HSV")
imageResult = ((Image)imageInput2).MatchTemplate((Image)imageTemplate2, tmType);
else
imageResult = ((Image)imageInput2).MatchTemplate((Image)imageTemplate2, tmType);
sw.Stop();
time = sw.Elapsed.TotalMilliseconds;
totalTime += time;
sw.Reset();
//归一化结果
CvInvoke.cvNormalize(imageResult.Ptr, imageResult.Ptr, 1d, 0d, NORM_TYPE.CV_MINMAX, IntPtr.Zero);
//找到最匹配的点,以及该点的值
double bestValue;
Point bestPoint;
FindBestMatchPointAndValue(imageResult, tmType, out bestValue, out bestPoint);
//在最匹配的点附近画一个跟模板一样大的矩形
Rectangle rect = new Rectangle(new Point(bestPoint.X - imageTemplate.Size.Width / 2, bestPoint.Y - imageTemplate.Size.Height / 2), imageTemplate.Size);
imageResult.Draw(rect, new Gray(bestValue), 2);
//保存结果图像到数组
imageResults[i] = imageResult;
i++;
//显示结果
txtResult.Text += string.Format("匹配方式:{0:G},用时:{1:F05}毫秒,最匹配的点:({2},{3}),最匹配的值:{4}/r/n", tmType, time, bestPoint.X, bestPoint.Y, bestValue);
}
txtResult.Text += string.Format("匹配结束,共用时:{0:F05}毫秒/r/n", totalTime);
//显示结果图像
pbResultSqdiff.Image = ImageConverter.ImageSingleToBitmap(imageResults[0]);
pbResultSqdiffNormalized.Image = ImageConverter.ImageSingleToBitmap(imageResults[1]);
pbResultCcorr.Image = ImageConverter.ImageSingleToBitmap(imageResults[2]);
pbResultCcorrNormalized.Image = ImageConverter.ImageSingleToBitmap(imageResults[3]);
pbResultCcoeff.Image = ImageConverter.ImageSingleToBitmap(imageResults[4]);
pbResultCcoeffNormalized.Image = ImageConverter.ImageSingleToBitmap(imageResults[5]);
//释放资源
imageInput.Dispose();
imageTemplate.Dispose();
imageInput2.Dispose();
imageTemplate2.Dispose();
foreach (Image imageResult in imageResults)
imageResult.Dispose();
}
//找到最匹配的点,以及该点的值
private void FindBestMatchPointAndValue(Image image, TM_TYPE tmType, out double bestValue, out Point bestPoint)
{
bestValue = 0d;
bestPoint = new Point(0, 0);
double[] minValues, maxValues;
Point[] minLocations, maxLocations;
image.MinMax(out minValues, out maxValues, out minLocations, out maxLocations);
//对于平方差匹配和归一化平方差匹配,最小值表示最好的匹配;其他情况下,最大值表示最好的匹配
if (tmType == TM_TYPE.CV_TM_SQDIFF || tmType == TM_TYPE.CV_TM_SQDIFF_NORMED)
{
bestValue = minValues[0];
bestPoint = minLocations[0];
}
else
{
bestValue = maxValues[0];
bestPoint = maxLocations[0];
}
}