具体思路如下:首先,通过cvMatchTemplate模板进行匹配,匹配完成之后会产生一张结果单通道的灰色图像,再利用cvMinMaxLoc函数查找数组中全局最小值。每次最小值肯定只有一个,所以需要把每次找到的最小值(数组区域处理其它值,本文处理为最大值,也就是匹配最不像的值),这样就可以继续查找全局接剩余较小的区域了。
CvPoint getNextMinLoc(IplImage *result, CvPoint minLoc, int maxVaule, int templatW, int templatH)
{
// 先将第一个最小值点附近两倍模板宽度和高度的都设置为最大值防止产生干扰
int startX = minLoc.x - templatW;
int startY = minLoc.y - templatH;
int endX = minLoc.x + templatW;
int endY = minLoc.y + templatH;
if(startX < 0 || startY < 0)
{
startX = 0;
startY = 0;
}
if(endX > result->width - 1 || endY > result->height - 1)
{
endX = result->width - 1;
endY = result->height - 1;
}
for(int y = startY; y < endY; y++)
for(int x = startX; x < endX; x++)
cvSetReal2D(result, y, x, maxVaule);
double new_minVaule, new_maxValue;
CvPoint new_minLoc, new_maxLoc;
cvMinMaxLoc(result, &new_minVaule, &new_maxValue, &new_minLoc, &new_maxLoc);
return new_minLoc;
}
int main()
{
IplImage *src = cvLoadImage("E:/src.jpg");
IplImage *templat = cvLoadImage("E:/template.jpg");
IplImage *result; // 模板匹配结果
if(!src || !templat)
{
cout << "打开图片失败" << endl;
return 0;
}
int srcW, srcH, templatW, templatH, resultH, resultW;
srcW = src->width;
srcH = src->height;
templatW = templat->width;
templatH = templat->height;
if(srcW < templatW || srcH < templatH)
{
cout << "模板不能比原图小" << endl;
return 0;
}
resultW = srcW - templatW + 1;
resultH = srcH - templatH + 1;
result = cvCreateImage(cvSize(resultW, resultH), 32, 1); //匹配方法计算的结果最小值为float
cvMatchTemplate(src, templat, result, CV_TM_SQDIFF); //方差最小,匹配最好
double minValue, maxValue;
CvPoint minLoc, maxLoc;
cvMinMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc);
cvRectangle(src, minLoc, cvPoint(minLoc.x + templatW, minLoc.y+ templatH), cvScalar(0,0,255));
CvPoint new_minLoc;
// 计算下一个最小值
new_minLoc = getNextMinLoc(result, minLoc, maxValue, templatW, templatH);
cvRectangle(src, new_minLoc, cvPoint(new_minLoc.x + templatW, new_minLoc.y+ templatH), cvScalar(0,0,255));
cvNamedWindow("srcResult", 1);
cvNamedWindow("templat", 1);
cvShowImage("srcResult", src);
cvShowImage("templat", templat);
cvWaitKey(0);
cvReleaseImage(&result);
cvReleaseImage(&templat);
cvReleaseImage(&src);
return 0;
}