关于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!