Opencv 6种模板匹配

模板匹配适用于能匹配上的场景。如果图片中根本就没有你想要的匹配对象,这里也会给出一个假的匹配结果。假到你根本就没法判断到底有没有这个目标


经过多次实验,第四种效果最好


  • cv::TM_SQDIFF 判断 minVal 越小,效果越好
    计算模板与目标图像的方差,由于是像素值差值的平方的和,所以值越小匹配程度越高;

  • cv::TM_SQDIFF_NORMED 判断 minVal 越接近0,效果越好
    范化的cv::TM_SQDIFF,取值为0-1之间,完美匹配返回值为0;

  • cv::TM_CCORR 判断 maxVal 越大,效果越好
    使用dot product计算匹配度,越高匹配度就好;

  • cv::TM_CCORR_NORMED 判断 maxVal 越接近1,效果越好
    范化的cv::TM_CCORR,0-1之间,我用的这个;

  • cv::TM_CCOEFF 判断 maxVal 越大,效果越好
    采用模板与目标图像像素与各自图像的平均值计算dot product,正值越大匹配度越高,负值越大图像的区别越大,但如果图像没有明显的特征(即图像中的像素值与平均值接近)则返回值越接近0;

  • cv::TM_CCOEFF_NORMED 判断 maxVal 越接近1,效果越好
    范化的cv::TM_CCOEFF,-1 ~ 1之间。

#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgproc/imgproc.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;

int max_Trackbar = 5; /// 函数声明 

void MatchingMethod( int, void* ); 

int main( int argc, char** argv ) 
{ /// 载入原图像和模板块 
	
	img = imread( "./003/2018-12-23_14-17-05.bmp", 1 ); 
	
	templ = imread( "./003/aa.bmp", 1 ); /// 创建窗口 
	
	namedWindow( image_window, CV_WINDOW_AUTOSIZE ); 
	
	namedWindow( result_window, CV_WINDOW_AUTOSIZE ); /// 创建滑动条 
	
	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 ); waitKey(0); 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 ); /// 进行匹配和标准化

	//match_method = CV_TM_CCORR_NORMED;
	
	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;
	} /// 让我看看您的最终结果 

	printf("%d   %d\n", matchLoc.x, matchLoc.y);

	printf("%f %f \n", maxVal, minVal);
	
	rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 ); 
	
	rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 ); 
	
	imshow( image_window, img_display ); 
	
	imshow( result_window, result ); 

	return; 

}

你可能感兴趣的:(opencv,Opencv模板匹配)