opencv实现了一部分通过模板与目标图像进行寻找最佳匹配的方面matchTemplat();这个方法网上有很多讲解,基本思想是将模板图像在目标图像上滑动逐一对比,通过统计的基本方法进行匹配,比如方差检验,相关性检验等方法来寻找最佳匹配;

	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是原图, Result 是结果,也是这个函数返回值,method表示比较所用的方法;

opencv中支持的比较方法有六种,分别如下:

1、cv::TM_SQDIFF:该方法使用平方差进行匹配,因此最佳的匹配结果在结果为0处,值越大匹配结果越差。

2、cv::TM_SQDIFF_NORMED:该方法使用归一化的平方差进行匹配,最佳匹配也在结果为0处。

3、cv::TM_CCORR:相关性匹配方法,该方法使用源图像与模板图像的卷积结果进行匹配,因此,最佳匹配位置在值最大处,值越小匹配结果越差。

4、cv::TM_CCORR_NORMED:归一化的相关性匹配方法,与相关性匹配方法类似,最佳匹配位置也是在值最大处。

5、cv::TM_CCOEFF:相关性系数匹配方法,该方法使用源图像与其均值的差、模板与其均值的差二者之间的相关性进行匹配,最佳匹配结果在值等于1处,最差匹配结果在值等于-1处,值等于0直接表示二者不相关。

6、cv::TM_CCOEFF_NORMED:归一化的相关性系数匹配方法,正值表示匹配的结果较好,负值则表示匹配的效果较差,也是值越大,匹配效果也好。

匹配方法的选取根据实际情况而定,原文:https://blog.csdn.net/guduruyu/article/details/69231259 

                               
假设褐色的大图为待测图片,红色小图为模板图片。

这个函数返回值result的值:

   

       1.result数据的含义

       模板匹配函数cvMatchTemplate依次计算模板与待测图片的重叠区域的相似度,并将结果存入映射图像result当中,也就是说result图像中的每一个点的值代表了一次相似度比较结果。

      2.result的尺寸大小

       如图可知,模板在待测图像上每次在横向或是纵向上移动一个像素,并作一次比较计算,由此,横向比较W-w+1次,纵向比较H-h+1次,从而得到一个(W-w+1)×(H-h+1)维的结果矩阵,result即是用图像来表示这样的矩阵,因而图像result的大小为(W-w+1)×(H-h+1)。匹配结果图像与原图像之间的大小关系,他们之间差了一个模板大小。

       3.如何从result中获得最佳匹配区域

       使用函数cvMinMaxLoc(result,&min_val,&max_val,&min_loc,&max_loc,NULL);从result中提取最大值(相似度最高)以及最大值的位置(即在result中该最大值max_val的坐标位置max_loc,即模板滑行时左上角的坐标,类似于图中的坐标(x,y)。

       由此得到:rect=cvRect(max_loc.x,max_loc.y,tmp->width,tmp->height); rect表示最佳的匹配的矩形区域。

参数 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 归一化相关系数匹配法

下面是不同的比较方法,可以使用其中的一种 (I 表示图像,T 是模板, R是结果. 模板与图像重叠区域 x'=0..w-1, y'=0..h-1 之间求和): 

                

               

函数完成后,使用minMaxLoc寻找最大值或最小值。

from:https://blog.csdn.net/OPPOA113/article/details/24933831

实例:

#include<iostream>
#include<opencv2\opencv.hpp>

using namespace std;
using namespace cv;

int main() {
//模板匹配
	Mat src = imread("111.jpg", 1);
	Mat templ = imread("111temp.jpg", 1);
	Mat ftmp[6];
	double minVal; double maxVal; Point minLoc; Point maxLoc;
	Point matchLoc;
	for (int i = 0; i < 6; i++) {
		matchTemplate(src, templ, ftmp[i], i);//用6种匹配方式
		normalize(ftmp[i], ftmp[i], 1, 0, NORM_MINMAX);
		minMaxLoc(ftmp[i], &minVal, &maxVal, &minLoc, &maxLoc);找到最佳匹配点
		rectangle(src,Rect(maxLoc.x,maxLoc.y,templ.cols,templ.rows),1,8,0 );//这一行代码并不完善,因为有的匹配方法是以最小值作为最佳匹配点
	}
	imshow("src", src); imshow("template", templ); 
	imshow("0", ftmp[0]); imshow("1", ftmp[1]); 
	imshow("2", ftmp[2]); imshow("3", ftmp[3]); 
	imshow("4", ftmp[4]); imshow("5", ftmp[5]);
	
	waitKey();
}

111temp: 

111:

匹配结果result:

从上面6张图中可以看到,中上方位有一个最亮点或最暗点,该点几位最佳匹配点,以该点为左上顶点画一个与模板大小相同的矩形即为匹配得到的目标。

补充一些其他常见的模板匹配方法:

1、MAD算法

平均绝对差算法(Mean Absolute Differences,简称MAD算法)。

设S(x,y)是大小为mxn的搜索图像,T(x,y)是MxN的模板图像,分别如下图(a)、(b)所示,我们的目的是:在(a)中找到与(b)匹配的区域。

                                                

算法思路:
        在搜索图S中,以(i,j)为左上角,取MxN大小的子图,计算其与模板的相似度;遍历整个搜索图,在所有能够取到的子图中,找到与模板图最相似的子图作为最终匹配结果。MAD算法的相似性测度公式如下。显然,平均绝对差D(i,j)越小,表明越相似,故只需找到最小的D(i,j)即可确定能匹配的子图位置:

                                

其中:

算法优点:
①思路简单,容易理解(子图与模板图对应位置上,灰度值之差的绝对值总和,再求平均,实质:是计算的是子图与模板图的L1距离的平均值)。②运算过程简单,匹配精度高。

缺点:
①运算量偏大。②对噪声非常敏感。

2、SAD算法
        绝对误差和算法(Sum of Absolute Differences,简称SAD算法)。实际上,SAD算法与MAD算法思想几乎是完全一致,只是其相似度测量公式有一点改动(计算的是子图与模板图的L1距离)。

                           

3、SSD算法

        误差平方和算法(Sum of Squared Differences,简称SSD算法),也叫差方和算法。实际上,SSD算法与SAD算法如出一辙,只是其相似度测量公式有一点改动(计算的是子图与模板图的L2距离)。这里不再赘述。

                             

4、MSD算法

        平均误差平方和算法(Mean Square Differences,简称MSD算法),也称均方差算法。实际上,MSD之余SSD,等同于MAD之余SAD(计算的是子图与模板图的L2距离的平均值),故此处不再赘述。

5、SSDA算法

     序贯相似性检测算法(Sequential Similiarity Detection Algorithm,简称SSDA算法),它是对传统模板匹配算法的改进,比MAD算法快几十到几百倍。

SSDA算法描述如下:

①定义绝对误差:       

其中是搜索图中的一个子图,带有上划线的分别表示子图、模板的均值:

           

 

实际上,绝对误差就是子图与模板图各自去掉其均值后,对应位置之差的绝对值。

②设定阈值Th

③在模板图中随机选取不重复的像素点,计算与当前子图的绝对误差,将误差累加,当误差累加值超过了Th时,记下累加次数H,所有子图的累加次数H用一个表R(i,j)来表示。SSDA检测定义为:

                         
    下图给出了A、B、C三点的误差累计增长曲线,其中A、B两点偏离模板,误差增长得快;C点增长缓慢,说明很可能是匹配点(图中Tk相当于上述的Th,即阈值;I(i,j)相当于上述R(i,j),即累加次数)。

                                                

④在计算过程中,随机点的累加误差和超过了阈值(记录累加次数H)后,则放弃当前子图转而对下一个子图进行计算。遍历完所有子图后,选取最大R值所对应的(i,j)子图作为匹配图像【若R存在多个最大值(一般不存在),则取累加误差最小的作为匹配图像】。

        由于随机点累加值超过阈值Th后便结束当前子图的计算,所以不需要计算子图所有像素,大大提高了算法速度;为进一步提高速度,可以先进行粗配准,即:隔行、隔离的选取子图,用上述算法进行粗糙的定位,然后再对定位到的子图,用同样的方法求其8个邻域子图的最大R值作为最终配准图像。这样可以有效的减少子图个数,减少计算量,提高计算速度
from:https://blog.csdn.net/hujingshuang/article/details/47759579

GitHub 加速计划 / opencv31 / opencv
77.38 K
55.71 K
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:2 个月前 )
c3747a68 Added Universal Windows Package build to CI. 11 天前
9b635da5 - 11 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐