一、模板匹配概念
模板匹配是一项在一副图像中寻找与另一幅模板图像最匹配(相似)部分的技术。模板匹配不是基于直方图的,而是通过在输入图像上滑动图像块(模板)同时对比相似度,来对模板和输入图像进行匹配的一种方法。
应用:
(1)目标查找定位
(2)运动物体跟踪
1、模板匹配 --- matchTemplate()
CV_EXPORTS_W void matchTemplate(InputArray image, InputArray temp1, OutputArray result, int method);
image:待搜索图像(大图)
temp1:搜索模板,需和原图一样数据类型且尺寸大小不能大于源图像
reuslt:比较结果的映射图像,其必须为单通道的,32位浮点型图像,如果原图(待搜索图像)尺寸为W*H,二temp1的尺寸为w*h,则result的尺寸一定是(W-w+1)*(H-h+1)
method:指定的匹配方法,有如下六种:
1 TM_SQDIFF --- 平方差匹配法(最好匹配0)
2 TM_SQDIFF_NORMED --- 归一化平方差匹配法(最好匹配0)
3 TM_CCORR --- 相关匹配法(最坏匹配0)
4 TM_CCORR_NORMED ---归一化相关匹配法(最坏匹配0)
5 TM_CCOEFF --- 系数匹配法(最好匹配1)
6 TM_CCOEFF_NORMED --- 归一化系数匹配法(最好匹配1)
平方差匹配 method=TM_SQDIFF:最好匹配为0,匹配越差,匹配值越大
标准平方差匹配 method=TM_SQDIFF_NORMED:
相关匹配 method=TM_CCORR
这类方法采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。
标准相关匹配 method=TM_CCORR_NORMED
相关匹配 method=TM_CCOEFF
标准相关匹配 method=TM_CCOEFF_NORMED
这类方法将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示匹配很差,0表示没有任何相关性(随机序列)。
2、矩阵归一化 --- normalize()
1 C++: void normalize(InputArray src,OutputArray dst, double alpha=1,
double beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray() )
src:输入源图像,Mat类型
dst:输出结果图像,需要和原图一样的尺寸和类型
alpha:归一化后的最小值,默认为1
beta:归一化后的最大值,默认为0
norm_type:归一化类型,可选:NORM_INF, NORM_L1, NORM_L2(默认)等
dtype:默认值为-1,此参数为负值时,输出矩阵和src有同样的类型
mask:可选的掩码操作
normallize()函数的作用是进行矩阵归一化。
3、寻找最值 --- minMaxLoc()
1 CV_EXPORTS_W void minMaxLoc(InputArray src, CV_OUT double* minVal, CV_OUT double* maxVal = 0, CV_OUT Point* minLoc=0, CV_OUT Point* maxLoc=0, InputArray mask=noArray());
src:输入源图像,单通道图像
minVal:返回最小值的指针,若无需返回,则置为0
maxVal:返回最大值的指针,若无需返回,则置为0
minLoc:返回最小位置的指针,若无需返回,则置为0
maxLoc:返回最大位置的指针,若无需返回,则置为0
mask:可选的掩码操作
minMaxLoc()函数的作用是在数组中找到全局最小值和最大值
单模板匹配code:
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat temp=imread("zi.jpg");
Mat src=imread("mu.jpg");
Mat dst=src.clone();
imshow("temp",temp);
int width=src.cols-temp.cols+1;//result宽度
int height=src.rows-temp.rows+1;//result高度
Mat result(height,width,CV_32FC1);//创建结果映射图像
matchTemplate(src, temp, result, TM_SQDIFF); //平方差匹配法(最好匹配0)
//matchTemplate(srcImg, templateImg, resultImg, CV_TM_SQDIFF_NORMED); //归一化平方差匹配法(最好匹配0)
//matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCORR); //相关匹配法(最坏匹配0)
//matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCORR_NORMED); //归一化相关匹配法(最坏匹配0)
//matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCOEFF); //系数匹配法(最好匹配1)
//matchTemplate(src,temp,result, TM_CCOEFF);//化相关系数匹配,最佳值1
imshow("result",result);
normalize(result,result,0,1,NORM_MINMAX,-1);//归一化到0-1范围
double minValue,maxValue;
Point minLoc,maxLoc;
minMaxLoc(result,&minValue,&maxValue,&minLoc,&maxLoc);
cout<<"minValue="<<minValue<<endl;
cout<<"maxValue="<<maxValue<<endl;
rectangle(dst,maxLoc,Point(maxLoc.x+temp.cols,maxLoc.y+temp.rows),Scalar(0,255,0),2,8);
imshow("dst",dst);
waitKey(0);
return 0;
}
另:模板匹配要求图片一定是 32位 图片,详情见零一博客