首页 > 其他分享 >【opencv学习笔记】028之模板匹配——matchTemplate函数详解

【opencv学习笔记】028之模板匹配——matchTemplate函数详解

时间:2024-01-12 23:13:18浏览次数:35  
标签:matchTemplate 匹配 sum CV opencv TM 图像 028 模板

目录

​ ​一、前言​

​ ​二、模板匹配​

 ​1、模板匹配是个啥​​

​ ​2、常用匹配算法​

​​ ​3、API​

​ ​4、代码展示​

 ​5、执行结果


一、前言

遭遇了点突发情况,所以今天更新的有点晚,也不知道能不能等到今天发出去了。

终于可以从模板匹配开始了,说明基础博客即将更新完毕,下一步,开始更新机器学习算法博客,感谢大家的鼎力支持。

如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:

 

二、模板匹配

1、模板匹配是个啥

我们先来了解一下模板匹配是个啥。

我们先不说定义,先从理解开始,单纯的理解这个概念:

就是有一个模板,然后我有一个大图像要去和模板匹配。

这个解释很暴力有木有!

那接下来我们来介绍一下标准的解释和定义。

模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。

根据上面的解释呢,我们就能得到如下定义:

模板就是一副已知的小图像,而模板匹配就是在一副大图像中搜寻目标,已知该图中有要找的目标,且该目标同模板有相同的尺寸、方向和图像元素,通过一定的算法可以在图中找到目标,确定其坐标位置。

 

比如上面这个图中,左边大的是图像,右面小的是模板。

这里我们注意到一个描述:

相同的尺寸、方向和图像元素

这就说明,我们要找的模板是里图像里标标准准存在的,这里说的标标准准,就是说,一旦图像或者模板发生变化,比如旋转,修改某几个像素,图像翻转等操作之后,我们就无法进行匹配了,这也是这个算法的弊端。

所以这种匹配算法,相当于“人工智障式”匹配,就是在待检测图像上,从左到右,从上向下对模板图像与小东西的图像进行比对。

2、常用匹配算法

我们会经常使用到如下六个匹配算法:

1.平方差匹配 method=CV_TM_SQDIFF

2.标准平方差匹配 method=CV_TM_SQDIFF_NORMED

3.相关匹配 method=CV_TM_CCORR

4.标准相关匹配 method=CV_TM_CCORR_NORMED

5.相关匹配 method=CV_TM_CCOEFF

6.标准相关匹配 method=CV_TM_CCOEFF_NORMED

之后我们会讲到一个API,里面有一个参数method,它是指比较方法,主要方法在cv::TemplateMatchModes。就是如下几个:

enum TemplateMatchModes {
    TM_SQDIFF = 0, //!< \f[R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2\f]
    TM_SQDIFF_NORMED = 1, //!< \f[R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f]
    TM_CCORR = 2, //!< \f[R(x,y)= \sum _{x',y'} (T(x',y') \cdot I(x+x',y+y'))\f]
    TM_CCORR_NORMED = 3, //!< \f[R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f]
    TM_CCOEFF = 4, //!< \f[R(x,y)= \sum _{x',y'} (T'(x',y') \cdot I'(x+x',y+y'))\f]
    //!< where
    //!< \f[\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}\f]
    TM_CCOEFF_NORMED = 5 //!< \f[R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }\f]
};

 

1.平方差匹配-CV_TM_SQDIFF

从名字来理解,平方差匹配就是通过计算每个像素点的差的平方的和,和数学中统计里面的平方差类似。但是因为我们要的只是一个值,所以我们最后不需要求平均。

其公式如下:

如果相近,则每个差都很小,最终的和也很小,如果完全一致,则差为0,所以最好的匹配就是这个值为零的时候。值越大,匹配越差。

2.标准平方差匹配-CV_TM_SQDIFF_NORMED

这个只是对上面的进行了标准化处理,经过处理后,上面的值就不会太大。

 

3.相关匹配-CV_TM_CCORR

这类方法采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。

4.标准相关匹配-CV_TM_CCORR_NORMED

这个只是对上面的进行了标准化处理,经过处理后,上面的值就不会太大。

5.相关匹配-CV_TM_CCOEFF

这类方法将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。

6.标准相关匹配-CV_TM_CCOEFF_NORMED

这个只是对上面的进行了标准化处理,经过处理后,上面的值就不会太大。

匹配算法很多,但是具体用哪一个,我们要根据自己的需要进行选择, 也可能需要尝试去对比。

 

3、API

接下来我们讲一下API。

void matchTemplate(
InputArray image,
InputArray templ,
OutputArray result,
int method,
InputArray mask = noArray()
);
函数参数含义如下:

(1)InputArray类型的src ,运行搜索的图像。它必须是8位或32位浮点。

(2)InputArray类型的templ,已搜索模板。它不能大于源映像,并且具有相同的数据类型。。

(3)OutputArray类型的result,比较结果的映射。它必须是单通道32位浮点。

(4)int类型的method,指定比较方法的参数,请参见cv::TemplateMatchModes。

(5)InputArray类型的mask,搜索模板的掩码。它必须与temp具有相同的数据类型和大小。默认情况下不设置。

 

4、代码展示

 

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

Mat src; Mat templ; Mat result;
char* src_window = "【输入图像】";
char* result_window = "【结果窗口】";

int match_method;
int max_Trackbar = 5;

// 函数声明
void MatchingMethod(int, void*);

int main()
{
    src = imread("E:/image/girl2.png");
    templ = imread("E:/image/girl2_1.png");
    if (!src.data || !templ.data)
    {
    cout << "could not load image !";
    return -1;
    }

    // 创建窗口
    namedWindow(src_window, CV_WINDOW_AUTOSIZE);
    namedWindow(result_window, CV_WINDOW_AUTOSIZE);

    imshow(src_window, src);

    // 创建滑动条
    char* trackbar_label = "Method";
    createTrackbar(trackbar_label, src_window, &match_method, max_Trackbar, MatchingMethod);

    MatchingMethod(0, 0);

    waitKey(0);
    return 0;
}

void MatchingMethod(int, void*)
{
    // 将被显示的原图像
    Mat src_display;
    src.copyTo(src_display);

    // 创建输出结果的矩阵
    int result_cols = src.cols - templ.cols + 1;
    int result_rows = src.rows - templ.rows + 1;

    result.create(result_cols, result_rows, CV_32FC1);

    // 进行匹配和标准化
    matchTemplate(src, 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(src_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(src_window, src_display);
    imshow(result_window, result);

    return;
}

 

5、执行结果

原图

 

模板

 

匹配结果

 

大家也可以自己尝试一下呀,一定要多做练习!

标签:matchTemplate,匹配,sum,CV,opencv,TM,图像,028,模板
From: https://www.cnblogs.com/vgoo/p/17961757

相关文章

  • c++ opencv直线检测
     #include<opencv2/opencv.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>usingnamespacecv;intmain(intargc,char**argv){//读取图像Matsrc=imread(argv[1],CV_LOAD_IMAGE_COLOR);if......
  • 【C++】OpenCV4-线条、矩形、圆形、椭圆等图形的绘制与填充、RNG随机函数的使用
    图形的绘制与填充://图形的绘制与填充Matcanvas=Mat::zeros(Size(512,512),CV_8UC3);namedWindow("canvas",WINDOW_AUTOSIZE);//相关绘制API演示//绘制直线line(canvas,Point(10,10),Point(400,400),Scalar(255,0,0),1,LINE_8);//绘制矩形Rectrect(150,1......
  • agx orin 使用 sdm 刷机后,vscode 使用 C++ 版本的 opencv, 出现红色的波浪线,但是程序
    原因:vscode没有链接好opencv的头文件先找到opencv头文件的位置:sudofind/-iname"opencv"/usr/include/opencv4/usr/include/opencv4/opencv2解决:ctril+sheft+p:打开:c_cpp_properties.json,写入:"includePath":["${workspaceFo......
  • 使用OpenCV实现视频去抖
    使用OpenCV实现视频去抖整体步骤:设置输入输出视频寻找帧之间的移动:使用opencv的特征检测器,检测前一帧的特征,并使用Lucas-Kanade光流算法在下一帧跟踪这些特征,根据两组点,将前一个坐标系映射到当前坐标系完成刚性(欧几里得)变换,最后使用数组纪录帧之间的运动。计算帧之间的平滑运......
  • 《基于树莓派和Arduino入门机器人学:使用Python和OpenCV》-第二版
    书籍:BeginningRoboticswithRaspberryPiandArduino:UsingPythonandOpenCV,2nd作者:JeffCicolani出版:Apress本文内容转载自公众号【一点人工一点智能】关注51CTO@一点人工一点智能,了解更多移动机器人&人工智能信息01 书籍介绍学习如何使用树莓派与Arduino结合来构建具有先......
  • OpenCV
    OpenCV(OpenSourceComputerVisionLibrary)是一个开源的计算机视觉OpenCV(OpenSourceComputerVisionLibrary)是一个开源的计算机视觉库,它包含了许多常用的图像处理和计算机视觉算法。OpenCV由一系列C函数和少量C++类构成,同时也提供了Python、Ruby、MATLAB等语言的接口,实现......
  • OpenCV
    OpenCV(OpenSourceComputerVisionLibrary)是一个开源的计算机视觉OpenCV(OpenSourceComputerVisionLibrary)是一个开源的计算机视觉库,它包含了许多常用的图像处理和计算机视觉算法。OpenCV由一系列C函数和少量C++类构成,同时也提供了Python、Ruby、MATLAB等语言的接口,实现......
  • opencv库图像基础3直方图-python
    opencv库图像基础3直方图-python直方图是什么OpenCV中的直方图是图像中像素值分布情况的统计表示。它是图像空间域内像素值分布的图形表示,以便更好地理解颜色分布。灰度直方图是图像中每个像素灰度值出现的次数或频数的统计结果。它只反映该图像中灰度值出现的频率,而未反映某......
  • OpenCV入门01:图像处理简介/图像的基础操作
    项目开源,地址:https://gitee.com/zccbbg/opencv_study文章目录图像处理简介灰度图像二值图像彩色图opencv介绍图像基础操作图像读取与显示绘制几何图形图像的属性其他操作算数操作加法混合图像色彩空间转换图像处理简介灰度图像●灰度图像是由灰度级组成的图像,每个像素的灰度级......
  • C++ opencv检测圆
     #include<opencv2/opencv.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>#include<iostream>usingnamespacecv;usingnamespacestd;intmain(intargc,char**argv){//读取图像Matsrc......