本文主要介绍opencv中图像匹配函数
并用示例解释和演示6中匹配方式
imshow的说明(为后续部分结果归一化后再显示说明原因)
1,如果原始图片是8位无符号整数,就按照原来的数字进行显示。也就是数字范围是[0,255]
2,如果原始图片是16位无符号整数或者32位整数,就除以256进行显示。也就是说0到256*256的范围被压缩到0到255。
3,如果图片是32位或者64位的浮点类型数据,那么像素值就会乘以255。也就是说,0到1的范围被映射到0到255.
void cv::matchTemplate(
cv::InputArray image, // 用于搜索的输入图像
cv::InputArray teml, // 用于匹配的模板,和image类型相同
cv::OutputArray result, // 匹配结果图像, 类型 32F
int method // 用于比较的方法,opencv提供6种
}
matchTemplate(source_image, template_image, target_image, TM_CCOEFF_NORMED);//匹配函数调用
double minVal, maxVal; //用于存储匹配值的最大值和最小值
Point minLoc, maxLoc; //用于存储匹配最大值的位置和最小值的位置
//寻找最佳匹配位置
minMaxLoc(target_image, &minVal, &maxVal, &minLoc, &maxLoc);
//画圈标出匹配点,这里使用maxLoc还是minLoc和选择的匹配method有关
circle(source_image, Point(maxLoc.x + template_image.cols / 2, maxLoc.y + template_image.rows / 2), 10, Scalar(0, 0, 255), 2, 8, 0);
基本概念:该方法使用归一化的平方差进行匹配,最佳匹配也在结果为0处。
这个公式中可以将 T , I T , I T,I 的每个值排列起来看作一个向量,公式可以转化为 R = ∣ T − I ∣ 2 ∣ T ∣ ∣ I ∣ R = \frac{|T-I|^2}{|T|\,|I|} R=∣T∣∣I∣∣T−I∣2
因为匹配的结果矩阵已经进行了归一化,因此我们可以直接进行显示
可以看到,这种方法也能很好实现匹配
这种标准化操作可以保证当模板和图像各个像素的亮度都乘上了同一个系数时,相关度不发生变化。也就是说当 I ( x , y ) I(x,y) I(x,y) 和 T ( x , y ) T(x,y) T(x,y) 变为 k × I ( x , y ) k×I(x,y) k×I(x,y) 和 k × T ( x , y ) k×T(x,y) k×T(x,y) 时, R ( x , y ) R(x,y) R(x,y) 不发生变化
基本概念:相关性匹配方法,该方法使用源图像与模板图像的卷积结果进行匹配,因此,最佳匹配位置在值最大处,值越小匹配结果越差。
基本概念:在减去了各自的平均值之外,还要各自除以各自的方差。经过减去平均值和除以方差这么两步操作之后,无论是我们的待检图像还是模板都被标准化了,这样可以保证图像和模板分别改变光照亮不影响计算结果。计算出的相关系数被限制在了 -1 到 1 之间,1 表示完全相同,-1 表示两幅图像的亮度正好相反,0 表示两幅图像之间没有线性关系。
三通道像素值均增加 80
#include
#include
#include"opencv2/imgproc/imgproc.hpp"
#include"opencv2/opencv.hpp"
using namespace std;
using namespace cv;
Mat source_image;
Mat template_image;
Mat target_image;
int main()
{
source_image = imread("D:\\cLion\\project\\02.jpg");
template_image = imread("D:\\cLion\\project\\02_temp.jpg");
//调整大小时使用
// for(int i = 0 ; i < template_image.rows ; i++)
// for(int j = 0 ; j < template_image.cols ; j++)
// for(int c = 0 ; c < 3 ; c++)
// template_image.at(i,j)[c] = saturate_cast(template_image.at(i,j)[c] + 80);
matchTemplate(source_image, template_image, target_image, TM_SQDIFF);
double minVal, maxVal; //存储匹配的最大值和最小值
Point minLoc, maxLoc; //存储匹配最大值的位置和最小值的位置0
//寻找最佳匹配位置
minMaxLoc(target_image, &minVal, &maxVal, &minLoc, &maxLoc);
//Point中使用max或min根据具体方法确定
circle(source_image, Point(minLoc.x + template_image.cols / 2, minLoc.y + template_image.rows / 2), 10, Scalar(0, 0, 255), 2, 8, 0);
normalize(target_image, target_image, 0, 1, NORM_MINMAX);
imshow("Source Window" , source_image);
imshow("Template Window" , template_image);
imshow("Target Window" , target_image);
waitKey(0);
}