首页 > 其他分享 >模板匹配(createTrackbar函数这样用)

模板匹配(createTrackbar函数这样用)

时间:2022-11-05 09:00:24浏览次数:59  
标签:createTrackbar 匹配 TM result 图像 match method 模板

一、模板匹配

模板匹配(TemplateMatching)就是在一幅图像中寻找和模板图像(template)最相似的区域,该方法原理简单计算速度快,能够应用于目标识别,目标跟踪等多个领域。

二、原理

1、cv::TM_SQDIFF:该方法使用平方差进行匹配,因此最佳的匹配结果在结果为0处,值越大匹配结果越差。

2、cv::TM_SQDIFF_NORMED:该方法使用归一化的平方差进行匹配,最佳匹配也在结果为0处。

3、cv::TM_CCORR:相关性匹配方法,该方法使用源图像与模板图像的卷积结果进行匹配,因此,最佳匹配位置在值最大处,值越小匹配结果越差。

4、cv::TM_CCORR_NORMED:归一化的相关性匹配方法,与相关性匹配方法类似,最佳匹配位置也是在值最大处。

5、cv::TM_CCOEFF:相关性系数匹配方法,该方法使用源图像与其均值的差、模板与其均值的差二者之间的相关性进行匹配,最佳匹配结果在值等于1处,最差匹配结果在值等于-1处,值等于0直接表示二者不相关。

6、cv::TM_CCOEFF_NORMED:归一化的相关性系数匹配方法,正值表示匹配的结果较好,负值则表示匹配的效果较差,也是值越大,匹配效果也好。

三、API

matchTemplate(

InputArrray image,  //源图像

InputArray templ,   //模板图像

OutputArray result,//输出结果  必须是单通道32位浮点数,假设源图像WxH,模版图像  w*h,到结果必须为W-w+1,H-h+1的大小

int method);          // 匹配方法,使用不同的方法产生的结果的意义可能不太一样,有些返回的值越大表示匹配程度越好,而有些方法返回的值越小表示匹配程度越好  

关于参数 method:  

TM_SQDIFF平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。

TM_CCORR相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。

TM_CCOEFF相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。

TM_SQDIFF_NORMED归一化平方差匹配法

TM_CCORR_NORMED归一化相关匹配法

TM_CCOEFF_NORMED归一化相关系数匹配法

四、示例代码

#include "mainwindow.h"
#include <QApplication>
#include <imgproc.hpp>
 
#define MYPICTUREPATH         "D:/Datum/Qt/Qt-Res/pic/"
 
using namespace std;
using namespace cv;
 
/// 全局变量 ///
Mat img;    //原始图像
Mat templ;    //模板图像
Mat result;   //匹配结果图像
 
const char* image_window = "Source Image";//原始图像显示窗口
const char* result_window = "Result window";//匹配结果图像显示窗口
 
bool useMask;
int maxTrackbar = 5;  //滑动条最大值(与匹配方法个数对应)
 
/// 函数声明 ///
void MatchingMethod( int match_method, void* );   //匹配函数
 
int main(int argc, char *argv[]) {
//! [0]
// 加载原始图像和模板图像
img = imread(MYPICTUREPATH "zhenhun.jpg");
templ = imread(MYPICTUREPATH "zhenhun_templ.jpg");
//! 创建显示窗口
namedWindow(image_window, WINDOW_AUTOSIZE);
namedWindow(result_window, WINDOW_AUTOSIZE);
//! 创建滑动条
String trackbar_label = "Method: \n \
0: TM_SQDIFF \n \
1: TM_SQDIFF_NORMED \n \
2: TM_CCORR \n \
3: TM_CCORR_NORMED \n \
4: TM_COEFF \n \
5: TM_COEFF_NORMED";
//! 参数:
//! 1滑动条名称
//! 2显示窗口名称
//! 3设置滑块初始值位置,设置为NULL
//! 4滑动条的最大值
//! 5回调函数,如:void MatchingMethod( int match_method, void*
//! );//滑动条的value会传给match_method 6用户传给回调函数的数据(默认值为0)
createTrackbar(trackbar_label, image_window, NULL, maxTrackbar, MatchingMethod);
MatchingMethod(0, NULL);
//! [0]
 
QApplication a(argc, argv);
return a.exec();
}
 
void MatchingMethod(int match_method, void *) {
Mat imgDisplay;
img.copyTo( imgDisplay );
// 匹配结果图像result为每个模板位置存储匹配结果
// 匹配结果图像result大小为:(W-w+1)*(H-h+1)
// 对于TM_SQDIFF和
// TM_SQDIFF_NORMED这两种方法,最小值为最佳匹配;对于别的方法最大值为最佳匹配
bool method_accepts_mask = (TM_SQDIFF == match_method || match_method == TM_CCORR_NORMED);
if (useMask && method_accepts_mask) {
//{ matchTemplate( img, templ, result, match_method, mask); }
matchTemplate(img, templ, result, match_method);
} else {
matchTemplate(img, templ, result, match_method);
}
if (match_method % 2 == 0) {
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
}
double minVal, maxVal;
Point minLoc, maxLoc;
Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
cout << "minVal  =" << minVal << minLoc << endl;
cout << "maxVal  =" << maxVal << maxLoc << endl;
cout << "(86,368)=" << result.at<float>(86, 368) << endl;
qDebug() << "---------------"<<match_method<<"----------------";
if (match_method == TM_SQDIFF || match_method == TM_SQDIFF_NORMED) {
matchLoc = minLoc;
} else {
matchLoc = maxLoc;
}
// 在原始图像和匹配结果图像中以最佳匹配点为左上角标出最佳匹配框
rectangle( imgDisplay, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), CV_RGB(255,0,0), 2, 8, 0 );
rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(255), 2, 8, 0 );
imshow( image_window, imgDisplay );
imshow( result_window, result );
 
//return;
}

五、匹配结果显示

 

 

六、疑问

匹配方法为TM_CCORR时,匹配结果好像不正确?

 

 

 

 

标签:createTrackbar,匹配,TM,result,图像,match,method,模板
From: https://www.cnblogs.com/zdt168/p/16859636.html

相关文章

  • 模板层(5)
    模版语法传值{{}}:变量相关{%%}:逻辑相关defindex(request):#模版语法可以传递的后端python数据类型n=123f=11.11s='我也现'b=Tru......
  • P3376 【模板】网络最大流(EK)
    #include<iostream>#include<queue>#include<cstring>usingnamespacestd;constlonglongN=5e3+1;longlongh[N],to[N<<1],nt[N<<1],fro......
  • P3387 【模板】缩点
    #include<iostream>#include<queue>#include<vector>usingnamespacestd;constintN=1e4+1;intn,m;vector<int>to[N];intval[N];voidadd......
  • 解读Vue3模板编译优化
    今天的文章打算学习下Vue3下的模板编译与Vue2下的差异,以及VDOM下Diff算法的优化。编译入口了解过Vue3的同学肯定知道Vue3引入了新的组合Api,在组件mount阶......
  • P3865 【模板】ST表
    【模板】ST表题目背景这是一道ST表经典题——静态区间最大值请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为\(O(1)\)。若使用更高时间复......
  • 【单片机/嵌入式】【梁山派】学习日志02:工程模板创建
    工程模板创建一、新建工程目录1.1包含文件(1)Project:存放工程文件,编译文件等。(2)Firmware:存放ARM内核文件,标准外设库文件等。(3)Hardware:存放开发板的硬件驱动文件。(4)App......
  • 字典树模板+初始化模板
    https://codeforces.com/contest/1658/problem/D2intl,r;intson[M][2],idx;inta[N];voidinit(){//初始化**idx=0;son[0][0]=son[0][1]=0;}......
  • 使用非类型的模板参数和传普通参数的区别?
     如上所示、想完成加法操作有两种写法一种是用一个模板、一种是用两个参数虽然功能上差不多、但其中的区别还是有的:函数调用时要把压栈而模板里的东西只会......
  • 模板、特化模板和普通函数混用时的的匹配顺序
      有普通函数、总是会先调普通的函数、如上图、鼠标停在foo(3.0)上时会有一个对于普通函数的高亮如果没普通函数、而是有特化、那么会调用特化:   总结:编译器......
  • 模板方法模式
    数据库连接对数据库的操作一般包括连接、打开、使用、关闭等步骤,在数据库操作模板类中我们定义了connDB()、openDB()、useDB()、closeDB()四个方法分别对应这四个步骤。对......