Opencv处理图像--模板匹配(单目标)
模板匹配说白了就是在一幅图中找出和给出的模板图最相似的图并给他框选出来。
目标匹配函数:
cvMatchTemplate( const CvArr* image, const CvArr* templ,
CvArr* result, int method );
image
待搜索图像
templ
模板图像
result
匹配结果
method
计算匹配程度的方法
关于匹配方法,使用不同的方法产生的结果的意义可能不太一样,有些返回的值越大表示匹配程度越好,而有些方法返回的值越小表示匹配程度越好
关于参数 method:
CV_TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
CV_TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
CV_TM_SQDIFF_NORMED 归一化平方差匹配法
CV_TM_CCORR_NORMED 归一化相关匹配法
CV_TM_CCOEFF_NORMED 归一化相关系数匹配法
通过cvMinMaxLoc获取最后的最佳匹配结果
代码:
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
//这个函数用不着,是处理多目标的
CvPoint getNextMinLoc(IplImage* result , int templatWidth,int templatHeight,double maxValIn , CvPoint lastLoc)
{
int y,x;
int startY,startX,endY,endX;
//计算大矩形的左上角坐标
startY = lastLoc.y - templatHeight;
startX = lastLoc.x - templatWidth;
//计算大矩形的右下角的坐标 大矩形的定义 可以看视频的演示
endY = lastLoc.y + templatHeight;
endX = lastLoc.x + templatWidth;
//不允许矩形越界
startY = startY < 0 ? 0 : startY;
startX = startX < 0 ? 0 : startX;
endY = endY > result->height-1 ? result->height-1 : endY;
endX = endX > result->width - 1 ? result->width - 1 : endX;
//将大矩形内部 赋值为最大值 使得 以后找的最小值 不会位于该区域 避免找到重叠的目标
for(y=startY;y<endY;y++)
{
for(x=startX;x<endX;x++)
{
cvSetReal2D(result,y,x,maxValIn);
}
}
double minVal,maxVal;
CvPoint minLoc,maxLoc;
//查找result中的最小值 及其所在坐标
cvMinMaxLoc(result,&minVal,&maxVal,&minLoc,&maxLoc,NULL);
return minLoc;
}
//直接从这里看
int main(int argc, char* argv[])
{
IplImage*src,*templat,*result,*show;
int srcW,templatW,srcH,templatH,resultW,resultH;
//加载源图像
src = cvLoadImage("src.jpg" , CV_LOAD_IMAGE_GRAYSCALE);
//用于显示结果
show = cvLoadImage("src.jpg");
//加载模板图像
templat = cvLoadImage("template.png" , CV_LOAD_IMAGE_GRAYSCALE);
if(!src || !templat)
{
printf("打开图片失败");
return 0;
}
srcW = src->width;
srcH = src->height;
templatW = templat->width;
templatH = templat->height;
if(srcW<templatW || srcH<templatH)
{
printf("模板不能比原图大");
return 0;
}
//计算结果矩阵的大小
resultW = srcW - templatW + 1;
resultH = srcH - templatH + 1;
//创建存放结果的空间
result = cvCreateImage(cvSize(resultW,resultH),32,1);
double minVal,maxVal;
CvPoint minLoc,maxLoc;
//调用模板匹配函数
cvMatchTemplate(src,templat,result,CV_TM_SQDIFF);
//查找最相似的值及其所在坐标
cvMinMaxLoc(result,&minVal,&maxVal,&minLoc,&maxLoc,NULL);
printf("minVal %f maxVal %f\n ",minVal,maxVal);
//绘制结果 ;
cvRectangle(show,minLoc,cvPoint(minLoc.x+templat->width,minLoc.y+templat->height),CV_RGB(0,255,0),1);
//显示结果
cvNamedWindow("show");
cvNamedWindow("tem");
cvShowImage("show",show);
cvShowImage("tem" , templat);
cvWaitKey(0);
return 0;
}
效果: