OpenCV3学习(8.3)模板匹配函数matchTemplate详解
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:归⼀化的相关性系数匹配⽅法,正值表⽰匹配的结果较好,负值则表⽰匹配的效果较差,也是值越⼤,匹配效果也好。
匹配⽅法的选取根据实际情况⽽定,原⽂:blog.csdn/guduruyu/article/details/69231259
假设褐⾊的⼤图为待测图⽚,红⾊⼩图为模板图⽚。
这个函数返回值result的值:
模板匹配函数cvMatchTemplate依次计算模板与待测图⽚的重叠区域的相似度,并将结果存⼊映射图
像result当中,也就是说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:
实例:
#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.ws),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:
rectangle函数opencv
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),即累加次数)。