关于Opencv中matchTemplate函数个人理解
最近在给老师做一个图像拼接的东西,然后就用到了Opencv中的matchTemplate函数,在网上也有很多大神写了相关的博客:
菜鸟知识搬运工
已经有很多了关于这个函数的解释,我就主要从一些不好理解的地方解释一下吧,可能也不一定对_,同样也是为了给自己做一个回顾。
不想看的直接上参考文档.
函数原型:
void cv::matchTemplate(
cv::InputArray image, // 用于搜索的输入图像, 8U 或 32F, 大小 W*H
cv::InputArray templ, // 用于匹配的模板,和image类型相同, 大小 w*h
cv::OutputArray result, // 匹配结果图像, 类型 32F, 大小 (W-w+1)*(H-h+1)
int method // 用于比较的方法
);
函数参数解释:
templ:是小图,在image中进行步长为1的滑动,每一次都移动一个格子。
image:匹配图(大图,其中存在templ区域)。
如下图所示:红色部分为templ,背景棕黄色为image,templ从(0,0)处开始滑动。
method:
有以下六种:
enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
1. TM_SQDIFF,TM_SQDIFF_NORMED匹配数值越低表示匹配效果越好,其它四种反之。
2. TM_SQDIFF_NORMED,TM_CCORR_NORMED,TM_CCOEFF_NORMED是标准化的匹配,得到的最大值,最小值范围在0~1之间,其它则需要自己对结果矩阵归一化。
result:存放每一次templ和image进行比对得到相似度。
? 如上图可知,模板在待测图像上每次在横向或是纵向上移动一个像素,并作一次比较计算,由此,横向比较W-w+1次,纵向比较H-h+1次,从而得到一个(W-w+1)×(H-h+1)维的结果矩阵,result即是用图像来表示这样的矩阵,因而图像result的大小为(W-w+1)×(H-h+1)。匹配结果图像与原图像之间的大小关系,他们之间差了一个模板大小。
从result中获得最佳匹配区域
? 使用函数cvMinMaxLoc(result,&min_val,&max_val,&min_loc,&max_loc,NULL);从result中提取最大值(相似度最高)以及最大值的位置(即在result中该最大值max_val的坐标位置max_loc,即模板滑行时左上角的坐标,类似于图中的坐标(x,y)。
在这里有min_val,max_val。为什么会有两个值呢?
? 我的理解是由于我们的对比方法method的不同,对于匹配结果:有的方法是匹配数值越小匹配效果越好;有的方法则是匹配数值越大匹配效果越好。因此返回的是两种不同的结果。
? 这个函数中引用修改的无论是 min_loc 还是 max_loc返回的都是在当前选取的方法method上得到的最佳匹配的,image上templ最佳位置的左上角的点。由此可以得到最佳匹配区域:
rect=cvRect(max_loc.x,max_loc.y,tmp->width,tmp->height); //rect表示最佳的匹配的矩形区域。
具体的使用函数如下:
Point templateMatching(const Mat& srcImage,const Mat& templateImage)
{
Mat result;
int result_cols = srcImage.cols - templateImage.cols + 1;
int result_rows = srcImage.rows - templateImage.rows + 1;
if(result_cols < 0 || result_rows < 0)
{
qDebug() << "Please input correct image!";
return;
}
result.create(result_cols, result_rows, CV_32FC1);
//enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
matchTemplate(srcImage,templateImage,result,TM_CCOEFF_NORMED); //最好匹配为1,值越小匹配越差
double minVal = -1;
double maxVal;
Point minLoc;
Point maxLoc;
Point matchLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
//取大值(视匹配方法而定)
// matchLoc = minLoc;
matchLoc = maxLoc;
return matchLoc;
}
that's all thank you!