模板匹配,顾名思义,即在一副图像中寻找和另一幅图像最相似(匹配)的部分。前段时间做实验
用到了模板匹配算法,之前作的笔记先放到博客上.
1.1 Rect()函数
Mat Image = imread(“0.png”)
Mat templateimage = Image(Rect(x, y, n,m));
即我们先定位到坐标为(x,y)这个像素点,然后以这个点为起点,往右下划出一个n列m行的区域
参考博客:https://blog.csdn.net/weixin_30954607/article/details/95317294
1.2 nameWindow()函数
namedWindow( image_window, CV_WINDOW_AUTOSIZE ); // 窗口名称,窗口标识 CV_WINDOW_AUTOSIZE是自动调整窗口大小以适应图片尺寸
namedWindow( result_window, CV_WINDOW_AUTOSIZE );
创建窗口。第一个参数是窗口名称,第二个窗口是int类型的Flag可以填写以下的值:
WINDOW_NORMAL //设置了这个值,用户便可以改变窗口的大小(没有限制)
WINDOW_AUTOSIZE //如果设置了这个值,窗口大小会自动调整以适应所显示的图像,并且不能手动改变窗口大小
1.3 createTrackba()函数
createTrackbar(const string& trackbarname, const string& winname,
int* value, int count,
TrackbarCallback onChange = 0,
void* userdata = 0);
参数1. trackbarname:滑动空间的名称;
参数2. winname:滑动空间用于依附的图像窗口的名称;
参数3. value:初始化阈值;
参数4. count:滑动控件的刻度范围;
参数5. TrackbarCallback是回调函数.
1.4 matchTemplate()函数
matchTemplate( img, templ, result, match_method );
即模板匹配函数,参数含义分别为:待匹配图像,模版图像,输出结果图像,匹配方法.
匹配方法就是采取何种计算方式来衡量模板图像和代匹配图像某部分的相似(匹配)程度.
opencv提供了6种方法:
平方差匹配法 CV_TM_SQDIFF
归一化平方差匹配法 CV_TM_SQDIFF_NORMED
相关匹配法 CV_TM_CCORR
归一化相关匹配法 CV_TM_CCORR_NORMED
系数匹配法 CV_TM_CCOEFF
化相关系数匹配法 CV_TMCCOEFF_NORMED
需要注意的是对于方法SQDIFF和SQDIFF_NORMED两种方法来讲,越小的值就有着更高的匹配结果,而其余的方法则是数值越大匹配效果越好.
参考博客:https://blog.csdn.net/keith_bb/article/details/70050080
1.5 normalize()归一化函数
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
参数含义:输入数组,输出数组,normalize的最小值,normalize的最大值,归一化类型,当type为负数的时候输出的type和输入的type相同.
归一化函数是为了后面数据处理的方便,其次是保证程序运行时收敛加快.
1.6 minMaxLoc()函数
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
用于检测矩阵中最大值和最小值的像素点位置.
2.1 原理
让模板图片在待匹配图片上的一次次滑动(从左到右,从上到下一个像素为单位的移动),然后将两张图片的像素值进行比对,然后选择相似度最高的部分进行标记,当遇到相似度更高的部分时更换标记部分。扫描完毕之后,将相似度最高的部分标记出来,作为图片进行输出.
2.2 实验代码
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include
using namespace std;
using namespace cv;
Mat img; Mat templ; Mat result;
char* image_window = "Original Image"; //窗口名称定义
char* result_window = "Result window"; //窗口名称定义
int match_method;
int max_Trackbar = 5;
void MatchingMethod( int, void* )
{
Mat img_display;
img.copyTo( img_display ); //将img的内容copy到img_display
/// 创建输出结果矩阵
int result_cols = img.cols - templ.cols + 1;//计算用于储存匹配结果的输出图像矩阵的大小
int result_rows = img.rows - templ.rows + 1;
result.create( result_cols, result_rows, CV_32FC1 );//被创建矩阵的列数,行数,以CV_32FC1形式储存
/// 进行匹配和标准化
matchTemplate( img, templ, result, match_method ); //待匹配图像,模版图像,输出结果图像,匹配方法
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );//归一化
/// 通过函数 minMaxLoc 定位最匹配的位置
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );//检测矩阵中最大值和最小值的像素位置
/// 对于方法 SQDIFF和SQDIFF_NORMED, 越小的数值代表更高的匹配结果. 而对于其他方法, 数值越大匹配越好
if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
{ matchLoc = minLoc; }
else
{ matchLoc = maxLoc; }
/// 最终结果
rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar(0,0,255), 2, 8, 0 ); //用矩形框起来框出最佳匹配位置
rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar(0,0,255), 2, 8, 0 );
imshow( image_window, img_display );//输出最终的到的结果
imwrite("result.png",img_display); //将得到的结果写到源代码目录下
imshow( result_window, result ); //输出匹配结果矩阵
return;
}
/*主函数*/
int main( int argc, char** argv )
{
img = imread("./../1.png");//载入待匹配图像
templ = imread("./../2.png");//载入模版图像
/// 创建窗口
namedWindow( image_window, CV_WINDOW_AUTOSIZE ); //窗口名称,窗口标识CV_WINDOW_AUTOSIZE是自动调整窗口大小以适应图片尺寸
namedWindow( result_window, CV_WINDOW_AUTOSIZE );
/// 创建滑动条
createTrackbar("jackchen", image_window, &match_method, max_Trackbar, MatchingMethod );
MatchingMethod( 0, 0 );//初始化显示
waitKey(0);
return 0;
}
待匹配图像: