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:归一化的相关性系数匹配方法,正值表示匹配的结果较好,负值则表示匹配的效果较差,也是值越大,匹配效果也好。
匹配方法的选取根据实际情况而定,原文:https://blog.****.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表示的矩形区域即是最佳的匹配区域。
上面确定最佳位置是用了max_loc。但是确定矩形位置是使用的是max_loc还是min_loc,这个跟匹配时采用的方法参数有关,具体如下:
关于参数 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.****.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张图中可以看到,中上方位有一个最亮点或最暗点,该点几位最佳匹配点,以该点为左上顶点画一个与模板大小相同的矩形即为匹配得到的目标。