模板匹配适用于能匹配上的场景。如果图片中根本就没有你想要的匹配对象,这里也会给出一个假的匹配结果。假到你根本就没法判断到底有没有这个目标
经过多次实验,第四种效果最好
-
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中的模板匹配算法,包括六种不同的匹配方法:cv::TM_SQDIFF、cv::TM_SQDIFF_NORMED、cv::TM_CCORR、cv::TM_CCORR_NORMED、cv::TM_CCOEFF和cv::TM_CCOEFF_NORMED。详细解释了每种方法的判断标准和适用场景,并提供了代码示例。
1500

被折叠的 条评论
为什么被折叠?



