图像处理之模板匹配(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的灰度模板匹配技术,后续扩展多目标多角度、基于(边缘)特征、局部变形等的模板匹配技术,以提高模板在不同光照、不同角度下的鲁棒性。

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

相关推荐
喵叔哟12 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生18 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
不是二师兄的八戒41 分钟前
本地 PHP 和 Java 开发环境 Docker 化与配置开机自启
java·docker·php
怀澈12244 分钟前
高性能服务器模型之Reactor(单线程版本)
linux·服务器·网络·c++
爱编程的小生1 小时前
Easyexcel(2-文件读取)
java·excel
chnming19871 小时前
STL关联式容器之set
开发语言·c++
带多刺的玫瑰1 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
威桑1 小时前
MinGW 与 MSVC 的区别与联系及相关特性分析
c++·mingw·msvc
熬夜学编程的小王1 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
yigan_Eins1 小时前
【数论】莫比乌斯函数及其反演
c++·经验分享·算法