1。首先说明模板匹配的用途:
1)在目标图像中寻找到特定图像的位置,(比如在一群小黄人中找到斯图尔特Stuart ,哈哈 ,开个玩笑)
2)计算两张图片的相似度。(要求两张图片大小一样)
2. opencv中文论坛上有对模板匹配(matchTemplate)的应用实例,介绍的很详细,但是中间有一部分有点问题,完全按他的做出来的数据可能是不对的。
#include <stdio.h> #include <iostream> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv.hpp> using namespace std; using namespace cv; // 全局变量 Mat img; Mat templ; Mat result; char* image_window = "Source Image"; char* result_window = "Result window"; int match_method=0; int max_Trackbar = 5; //函数声明 void MatchingMethod(int , void*); //主函数 int main() { //载入目标图像(Src) 和 特定图像(template) img = imread("E:\\Pic_file\\6666.jpg"); //src templ = imread("E:\\Pic_file\\6667.jpg"); //templat namedWindow(image_window); namedWindow(result_window); char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED"; createTrackbar(trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod); MatchingMethod(0,0); cout << "Hello World!" << endl; return 0; } //简单的滑动条的回调函数 void MatchingMethod(int, void *) { Mat img_display; img.copyTo(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 ); //进行匹配和标准化 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()); //<span class="c1">对于方法 SQDIFF 和 SQDIFF_NORMED, 越小的数值代表更高的匹配结果. 而对于其他方法, 数值越大匹配越好</span> 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::all(255), 2, 8, 0 ); rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(255), 2, 8, 0 ); cout<<"( "<<matchLoc.x<<" , "<<matchLoc.y<<") "<<endl; imshow( image_window, img_display ); imshow( result_window, result ); waitKey(1); return; }
目标图像(Src):
特定图像(template):
0.CV_TM_SQDIFF匹配的结果:
1.CV_TM_SQDIFF_NORMED匹配的结果:
2. CV_TM_CCORR的匹配结果:
3.CV_TM_CCORR_NORMED匹配结果:
4.CV_TM_CCOEFF的匹配结果:
5.CV_TM_CCOEFF_NORMED的匹配结果:
说明:对于CV_TM_SQDIFF、CV_TM_SQDIFF_NORMED、CV_TM_CCORR、CV_TM_CCORR_NORMED、CV_TM_CCOEFF、CV_TM_CCOEFF_NORMED
这6种匹配方法 带 NORMED 的和 CV_TM_CCOEFF 的是不需要归一化的,也就是说不用 normalize 函数
3. 拓展应用,获得两个图像的相似度
至此,模板匹配的代码结束。喜欢请点赞,谢谢,头一次写博客,内容可能不是很详细,有什么问题,欢迎随时提问。要匹配2个图片,图片的尺寸要一致,即Src和template 是的大小一样,以下程序是拿一张相同的照片做匹配,并将结果输出到显示。
代码如下:
#include <stdio.h> #include <iostream> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv.hpp> using namespace std; using namespace cv; // 全局变量 Mat img; Mat templ; Mat result; char* image_window = "Source Image"; char* result_window = "Result window"; int match_method=0; int max_Trackbar = 5; //函数声明 void MatchingMethod(int , void*); //主函数 int main() { img = imread("E:\\Pic_file\\6666.jpg"); //src templ = imread("E:\\Pic_file\\6666.jpg"); //templat namedWindow(image_window); namedWindow(result_window); char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED"; createTrackbar(trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod); MatchingMethod(0,0); cout << "Hello World!" << endl; return 0; } void MatchingMethod(int, void *) { Mat img_display; img.copyTo(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 ); matchTemplate(img, templ, result, match_method); // normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() ); float a=((float*)(result.data))[0]; cout<<" result = "<<a<<endl; double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc; minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc,Mat()); 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::all(255), 2, 8, 0 ); rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(255), 2, 8, 0 ); cout<<"( "<<matchLoc.x<<" , "<<matchLoc.y<<") "<<endl; imshow( image_window, img_display ); imshow( result_window, result );waitKey(0); return; }
6种匹配方法的测试结果如下:0.CV_TM_SQDIFF匹配的结果:
1.CV_TM_SQDIFF_NORMED匹配的结果:
2. CV_TM_CCORR的匹配结果:
3. CV_TM_CCORR_NORMED匹配结果:
4.CV_TM_CCOEFF的匹配结果:
5.CV_TM_CCOEFF_NORMED的匹配结果: