图像处理之模板匹配(C++)

图像处理之模板匹配(C++)


文章目录


前言

模板匹配的算法包括基于灰度的匹配、基于特征的匹配、基于组件的匹配、基于相关性的匹配以及局部变形匹配。本文对常见的模板匹配方法进行C++实现和应用。

常见模板匹配种类和应用场景:

  1. 基于灰度的匹配一般应用在没有缩放和旋转,颜色变化不大的场合。
  2. 基于特征的匹配一般应用在具有缩放和旋转,颜色变化较大的场合。
  3. 在模板各个组件有相对位移的情况下,使用基于组件的匹配算法。
  4. 在图像模糊,目标定位不依赖于边缘的情况下一般使用基于相关性的匹配。
  5. 目标有局部变形的情况使用局部变形匹配算法。

一、基于灰度的模板匹配

1.原理

基于灰度的模板匹配原理是在给定图像中寻找与预先定义的模板图像最相似的部分。该方法的基本思想是通过模板图像对给定图像(源图像)进行遍历计算两个图像之间的相似度。

相似度计算公式:

1.平方差匹配(匹配度越高,值越接近于0)

2.标准平方差匹配(匹配度越高,值越接近于0)

3.相关匹配(匹配度越高,值越接近于1)

4.标准相关匹配(匹配度越高,值越接近于1)

5.相关系数匹配(匹配度越高,值越接近于1)

6.标准相关系数匹配(匹配度越高,值越接近于1)

参数解释:

T'表示模板图像,I表示源图像;

x',y'对应模板矩阵对应的元素坐标;

x,y对应模板遍历源图像时左上角元素在源图像上的坐标;

T'(x',y')表示模板在(x',y')位置对应的灰度值;

I' (x'+x,y'+y)表示源图像在(x'+x,y'+y)位置对应的灰度值;

备注:上述的0和1不是实际值,而是对实际值进行归一化后的结果。

备注:图片来自opencv.org截图

2.代码实现

cpp 复制代码
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;


/*
* @param cv::Mat src    源图像,CV_8U或CV_32F
* @param cv::Mat temp   模板图像,CV_8U或CV_32F,src数据类型一致
* @param cv::Mat result 结果图
* @apram int method     相似度计算准则
* (cv::TM_SQDIFF、 cv::TM_SQDIFF_NORMED指方差匹配法、归一化方差匹配法)
* (cv::TM_CCORR、cv::TM_CCORR_NORMED、cv::TM_CCOEFF、cv::TM_CCOEFF_NORMED指相关、标准相关、相关系数、标准相关系数匹配)
* @brief 基于OpenCV实现的灰度模板匹配
*/
void MatchFunction(const cv::Mat& src,const cv::Mat& templ,cv::Mat& result,int match_method,cv::Point& matchLoc)
{
	// 计算结果图的尺寸
    int result_cols = src.cols - templ.cols + 1;
    int result_rows = src.rows - templ.rows + 1;

    result.create(result_rows, result_cols, CV_32FC1);

    //执行模板匹配
    matchTemplate(src, templ, result, match_method);

    //归一化
    normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());

    //定位模板匹配最相似的位置
    double minVal; double maxVal; Point minLoc; Point maxLoc;

    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(result, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar::all(0), 2, 8, 0);
}


int main()
{
    /// 以灰度图的形式加载源图像和模板图像
    cv::Mat img = cv::imread("F://work_study//algorithm_demo//baby.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat templ = cv::imread("F://work_study//algorithm_demo//template.jpg", cv::IMREAD_GRAYSCALE);

    if (img.empty() || templ.empty())
    {
        cout << "Can't read one of the images" << endl;
        return -1;
    }
    cv::Mat result;
    Point matchLoc;
    MatchFunction(img,templ, result, 0, matchLoc);

    cv::rectangle(img, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar::all(0), 2, 8, 0);

    cv::imshow("result", result);
    cv::imshow("src_result", img);

    waitKey(0);
    return 0;
}

3.结果展示

模板图片

结果图


总结

`本文实现了基于Opencv的灰度模板匹配技术,后续扩展多目标多角度、基于(边缘)特征、局部变形等的模板匹配技术,以提高模板在不同光照、不同角度下的鲁棒性。

因为笔者水平有限,有错误欢迎指出,代码本人均在本地运行实验正确,大家放心使用。

相关推荐
逊嘘6 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
van叶~8 分钟前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
morris13113 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
knighthood200119 分钟前
解决:ros进行gazebo仿真,rviz没有显示传感器数据
c++·ubuntu·ros
七星静香38 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员39 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU39 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie642 分钟前
在IDEA中使用Git
java·git
半盏茶香1 小时前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
小堇不是码农1 小时前
在VScode中配置C_C++环境
c语言·c++·vscode