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

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

相关推荐
蜀黍@猿16 分钟前
C/C++基础错题归纳
c++
V+zmm1013430 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
雨中rain31 分钟前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
游客5201 小时前
opencv中的常用的100个API
图像处理·人工智能·python·opencv·计算机视觉
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
ALISHENGYA2 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
arong_xu2 小时前
现代C++锁介绍
c++·多线程·mutex
汤姆和杰瑞在瑞士吃糯米粑粑2 小时前
【C++学习篇】AVL树
开发语言·c++·学习