我们先介绍以下模板匹配的原理
类似于滑块验证码,当匹配的图片与原图存在相似的时候可认为匹配成功,并且继续遍历全图,找到相似度的地方会自带替换掉原来匹配的模块。其算法原理是逐一计算匹配图片和模板图片ROI像素相关程度
int main()
{
Mat src1,src2,src3;
src1 =imread("C://Users//Administrator//Desktop//cph.png");//原图
src2 = imread("C://Users//Administrator//Desktop//cph2.png");//模板图
int row = src1.rows - src2.rows + 1;//结果矩阵行数,=原图和模板图行数对其的次数
int col = src1.cols - src2.cols + 1;//结果矩阵列数,=原图和模板图列数对其的次数
src3.create(col, row, CV_32FC1);//比较结果的矩阵,实际上存储的每个点是原图与模板图每个点匹配的相似度,32位单通道(为了寻找最大和最小值)
matchTemplate(src1, src2, src3, 1);//进行匹配,将其匹配相似度存放到src3.其中0-5是6种匹配方法
normalize(src3, src3, 0, 1, NORM_MINMAX);//矩阵归一化处理,用于调节对比度 避免光线和环境灰暗影响过大。0-1是min-max范围 ,NORM_MINMAX是归一化的一种类型。(模板匹配方法1,3,5需要用到)
double minvalue;//匹配程度最小
double maxvalue;//匹配程度最大
Point minloction;//最小的坐标点
Point maxloction;//最大的坐标点
minMaxLoc(src3, &minvalue, &maxvalue, &minloction, &maxloction);//寻找匹配程度,也就是结果矩阵中最大和最小值,也就是结果图中灰度最高和最低的两个点,不同的匹配方法有的以最大为佳匹配位置,有的以最小为佳。如果存在多个最大最小值则以第一次为准
cout << "匹配系数最小:" << minvalue << endl;
cout << "匹配最大:" << maxvalue << endl;
//rectangle(src1, Point(maxloction.x +src2.cols, maxloction.y + src2.rows),maxloction, Scalar(0, 0, 255), 1, 1, 0);//画一个矩形来标记匹配后的区域 参数为(图,左上角坐标,右下角坐标,线条颜色,线条粗细,类型,坐标点位数)
rectangle(src1, minloction, Point(minloction.x + src2.cols, minloction.y + src2.rows), Scalar(0, 0, 255), 1, 1, 0);//
imshow("img", src1);
imshow("img2", src3);
waitKey(0);
return 0;
我们先看src3 在各匹配方法的差异
(x,y是此时原图匹配位置的坐标,也就是此时结果矩阵的左上角坐标,x‘,y’是模板图遍历的坐标点)
这里是按匹配系数最小值计算,我们发现img2中最黑的地方是最佳匹配位置
方法0
平方差匹配法(0最佳,越高越差)
我们用最小值匹配,发现它很接近0
再看方法1
归一化平方差匹配法(0最佳)
匹配程度更小,比方法0更好
下面用的是匹配程度最大相关,我们需要改动代码,我们发现img2中最白的地方是最佳匹配位置
rectangle(src1, maxloction, Point(maxloction.x + src2.cols, maxloction.y + src2.rows), Scalar(0, 0, 255), 1, 1, 0)
方法2
相关性匹配方法(值越高越好,越小越差)
我们可以发现此方法最亮的地方不在最佳匹配位置,匹配失败
方法3
归一化的相关性匹配方法(值越高越好)
方法4·
相关性系数匹配方法(匹配效果好坏在1~-1间,0表示无关)
方法5
归一化的相关性系数匹配方法(值越高越好,越低越差)