OpenCV 学习笔记(模板匹配)

article/2025/11/9 18:44:51

OpenCV 学习笔记(模板匹配)

模板匹配是在一幅图像中寻找一个特定目标的方法之一。这种方法的原理非常简单,遍历图像中的每一个可能的位置,比较各处与模板是否“相似”,当相似度足够高时,就认为找到了我们的目标。

在 OpenCV 中,提供了相应的函数完成这个操作。

matchTemplate 函数:在模板和输入图像之间寻找匹配,获得匹配结果图像
minMaxLoc 函数:在给定的矩阵中寻找最大和最小值,并给出它们的位置

在具体介绍这两个函数之前呢,我们还要介绍一个概念,就是如何来评价两幅图像是否“相似”。
OpenCV 提供了 6 种计算两幅图像相似度的方法。

  1. 差值平方和匹配 CV_TM_SQDIFF
  2. 标准化差值平方和匹配 CV_TM_SQDIFF_NORMED
  3. 相关匹配 CV_TM_CCORR
  4. 标准相关匹配 CV_TM_CCORR_NORMED
  5. 相关匹配 CV_TM_CCOEFF
  6. 标准相关匹配 CV_TM_CCOEFF_NORMED

下面就分别来介绍。首先,先给出几个符号:
T(x,y) 用来表示我们的模板。 I(x,y) 是我们的目标图像。 R(x,y) 是用来描述相似度的函数。

差值平方和匹配 CV_TM_SQDIFF

这类方法利用图像与模板各个像素差值的平方和来进行匹配,最好匹配为 0。 匹配越差,匹配值越大。

R(x,y)=x,y(T(x,y)I(x+x,y+y))2

标准化差值平方和匹配 CV_TM_SQDIFF_NORMED

这个方法其实和差值平方和算法是类似的。只不过对图像和模板进行了标准化操作。

R(x,y)=x,y(T(x,y)I(x+x,y+y))2x,yT(x,y)2x,yI(x+x,y+y)2

这种标准化操作可以保证当模板和图像各个像素的亮度都乘上了同一个系数时,相关度不发生变化。

也就是说当 I(x,y) T(x,y) 变为 k×I(x,y) k×T(x,y) 时, R(x,y) 不发生变化。

相关匹配 CV_TM_CCORR

这类方法采用模板和图像的互相关计算作为相似度的度量方法,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。

R(x,y)=x,y(T(x,y)×I(x+x,y+y))

标准化相关匹配 CV_TM_CCORR_NORMED

这个方法和 标准化差值平方和匹配 类似,都是去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变亮或变暗k倍时结果不变。

R(x,y)=x,y(T(x,y)×I(x+x,y+y))x,yT(x,y)2x,yI(x+x,y+y)2

相关匹配 CV_TM_CCOEFF

这种方法也叫做相关匹配,但是和上面的 CV_TM_CCORR 匹配方法还是有不通过的。简单的说,这里是把图像和模板都减去了各自的平均值,使得这两幅图像都没有直流分量。

T(x,y)=T(x,y)x,yT(x,y)w×hI(x,y)=I(x,y)x,yI(x,y)w×hR(x,y)=x,y(T(x,y)×I(x+x,y+y))

标准相关匹配 CV_TM_CCOEFF_NORMED

这是 OpenCV 支持的最复杂的一种相似度算法。这里的相关运算就是数理统计学科的相关系数计算方法。具体的说,就是在减去了各自的平均值之外,还要各自除以各自的方差。经过减去平均值和除以方差这么两步操作之后,无论是我们的待检图像还是模板都被标准化了,这样可以保证图像和模板分别改变光照亮不影响计算结果。计算出的相关系数被限制在了 -1 到 1 之间,1 表示完全相同,-1 表示两幅图像的亮度正好相反,0 表示两幅图像之间没有线性关系。

T(x,y)=T(x,y)1w×hx,yT(x,y)x,yT(x,y)2I(x,y)=I(x,y)1w×hx,yI(x,y)x,yI(x,y)2R(x,y)=x,y(T(x,y)×I(x+x,y+y))

下面给个例子,我们的测试图像如下:
这里写图片描述

我们的模板如下:
这里写图片描述

程序中会用到 OpenCV 的函数包括:

void matchTemplate( InputArray image, InputArray templ,OutputArray result, int method );

其中 result 是一个矩阵,返回每一个点匹配的结果。

void minMaxLoc(InputArray src, CV_OUT double* minVal,CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0,CV_OUT Point* maxLoc=0, InputArray mask=noArray());

这个函数可以在一个矩阵中寻找最大点或最小点,并将位置返回回来。

下面是完整的测试程序。

#include <QCoreApplication>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"using namespace cv;int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);cv::Mat image = imread("D:/test.png", cv::IMREAD_COLOR );cv::Mat templateImage = imread("D:/template.png", cv::IMREAD_COLOR);int result_cols =  image.cols - templateImage.cols + 1;int result_rows = image.rows - templateImage.rows + 1;cv::Mat result = cv::Mat( result_cols, result_rows, CV_32FC1 );cv::matchTemplate( image, templateImage, result, CV_TM_SQDIFF );double minVal, maxVal;cv::Point minLoc, maxLoc, matchLoc;cv::minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );matchLoc = minLoc;cv::rectangle( image, cv::Rect(matchLoc, cv::Size(templateImage.cols, templateImage.rows) ), Scalar(0, 0, 255), 2, 8, 0 );imshow("", image);return a.exec();
}

输出结果是这样的。

这里写图片描述

其实上面的代码还可以封装一下。

double match(cv::Mat image, cv::Mat tepl, cv::Point &point, int method)
{int result_cols =  image.cols - tepl.cols + 1;int result_rows = image.rows - tepl.rows + 1;cv::Mat result = cv::Mat( result_cols, result_rows, CV_32FC1 );cv::matchTemplate( image, tepl, result, method );double minVal, maxVal;cv::Point minLoc, maxLoc;cv::minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );switch(method){case CV_TM_SQDIFF:case CV_TM_SQDIFF_NORMED:point = minLoc;return minVal;break;default:point = maxLoc;return maxVal;break;}
}

利用这个封装代码,我们可以把所有的匹配方法都实验一下。并且比较一下计算速度。

int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);cv::Mat image = imread("D:/test.png", cv::IMREAD_COLOR );cv::Mat tepl = imread("D:/template.png", cv::IMREAD_COLOR);cv::Point matchLoc;double value;int elapse;QTime t;t.start();value = match(image, tepl, matchLoc, CV_TM_SQDIFF);elapse = t.elapsed();qDebug("CV_TM_SQDIFF Time elapsed: %d ms", elapse);qDebug() << value;t.start();value = match(image, tepl, matchLoc, CV_TM_SQDIFF_NORMED);elapse = t.elapsed();qDebug("CV_TM_SQDIFF_NORMED Time elapsed: %d ms", elapse);qDebug() << value;t.start();value = match(image, tepl, matchLoc, CV_TM_CCORR);elapse = t.elapsed();qDebug("CV_TM_CCORR Time elapsed: %d ms", elapse);qDebug() << value;t.start();value = match(image, tepl, matchLoc, CV_TM_CCORR_NORMED);elapse = t.elapsed();qDebug("CV_TM_CCORR_NORMED Time elapsed: %d ms", elapse);qDebug() << value;t.start();value = match(image, tepl, matchLoc, CV_TM_CCOEFF);elapse = t.elapsed();qDebug("CV_TM_CCOEFF Time elapsed: %d ms", elapse);qDebug() << value;t.start();value = match(image, tepl, matchLoc, CV_TM_CCOEFF_NORMED);elapse = t.elapsed();qDebug("CV_TM_CCOEFF_NORMED Time elapsed: %d ms", elapse);qDebug() << value;cv::rectangle( image, cv::Rect(matchLoc, cv::Size(tepl.cols, tepl.rows) ), Scalar(0, 0, 255), 2, 8, 0 );imshow("", image);return a.exec();
}

输出结果如下:

CV_TM_SQDIFF Time elapsed: 734 ms
4
CV_TM_SQDIFF_NORMED Time elapsed: 699 ms
1.43391e-08
CV_TM_CCORR Time elapsed: 638 ms
2.78957e+08
CV_TM_CCORR_NORMED Time elapsed: 710 ms
1
CV_TM_CCOEFF Time elapsed: 721 ms
2.30675e+08
CV_TM_CCOEFF_NORMED Time elapsed: 759 ms
1

如果我们先将图像都转换为灰度图,那么计算速度会快很多。

CV_TM_SQDIFF Time elapsed: 249 ms
12
CV_TM_SQDIFF_NORMED Time elapsed: 246 ms
1.29052e-07
CV_TM_CCORR Time elapsed: 208 ms
9.29857e+07
CV_TM_CCORR_NORMED Time elapsed: 242 ms
1
CV_TM_CCOEFF Time elapsed: 246 ms
7.68916e+07
CV_TM_CCOEFF_NORMED Time elapsed: 281 ms
1

基本缩短到了 1/3 。所以,如果可以用灰度图来计算,就不要用彩色图。

我们还可以去掉模板大小对匹配度的影响:

double match(cv::Mat image, cv::Mat tepl, cv::Point &point, int method)
{int result_cols =  image.cols - tepl.cols + 1;int result_rows = image.rows - tepl.rows + 1;cv::Mat result = cv::Mat( result_cols, result_rows, CV_32FC1 );cv::matchTemplate( image, tepl, result, method );double minVal, maxVal;cv::Point minLoc, maxLoc;cv::minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );switch(method){case CV_TM_SQDIFF:point = minLoc;return minVal / (tepl.cols * tepl.cols);break;case CV_TM_SQDIFF_NORMED:point = minLoc;return minVal;break;case CV_TM_CCORR:case CV_TM_CCOEFF:point = maxLoc;return maxVal / (tepl.cols * tepl.cols);break;case CV_TM_CCORR_NORMED:case CV_TM_CCOEFF_NORMED:default:point = maxLoc;return maxVal;break;}
}

这时的结果如下:

CV_TM_SQDIFF Time elapsed: 705 ms
0.000609663
CV_TM_SQDIFF_NORMED Time elapsed: 682 ms
1.43391e-08
CV_TM_CCORR Time elapsed: 615 ms
42517.5
CV_TM_CCORR_NORMED Time elapsed: 698 ms
1
CV_TM_CCOEFF Time elapsed: 703 ms
35158.5
CV_TM_CCOEFF_NORMED Time elapsed: 757 ms
1

http://chatgpt.dhexx.cn/article/xDTx4W4I.shtml

相关文章

OpenCV-模板匹配 单个对象匹配、多个对象匹配

目录 概念步骤单个对象匹配代码实现一代码实现二 多个对象匹配代码实现 概念 模板匹配与剪辑原理很像&#xff0c;模板在原图像上从原点开始浮动&#xff0c;计算模板&#xff08;图像被模板覆盖的地方&#xff09;的差别程度&#xff0c;这个差别程度的计算方法在opencv里有六…

openCV——模板匹配

单模板匹配 import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cvshow(name, ndarray):img cv2.imshow(name, ndarray)cv2.waitKey(0)cv2.destroyAllWindows()模板匹配是指在当前图像 A 内寻找…

Python+Opencv实现模板匹配

目录 一、模板匹配简介二、传统模板匹配算法不足之处三、多尺度模板匹配实现步骤四、多尺度模板匹配实现代码五、多尺度模板匹配效果展示和分析六、思维扩展参考资料注意事项 一、模板匹配简介 所谓的模板匹配&#xff0c;即在给定的图片中查找和模板最相似的区域&#xff0c;该…

OpenCV数字图像处理实战二:模板匹配(C++)

OpenCV数字图像处理实战二&#xff1a;模板匹配&#xff08;C&#xff09; 1、模板匹配原理 模板匹配&#xff08;TemplateMatching&#xff09;就是在一幅图像中寻找和模板图像&#xff08;template&#xff09;最相似的区域&#xff0c;模板匹配不是基于直方图的&#xff0…

opencv 模板匹配形状匹配

文章目录 1. 找圆垫子1.1 得到模板1.2 形状匹配 2. 找瓜子 这是第四次作业要求 所以今天就趁机会讲讲模板匹配&#xff0c;正好之前的项目有一部分重要工作就是和模板匹配紧密相关&#xff0c;对于今天作业来说&#xff0c;之前的项目难度更大&#xff0c;因为涉及到许多要考虑…

Opencv——图像模板匹配

引言 什么是模板匹配呢&#xff1f; 看到这里大家是否会觉得很熟悉的感觉涌上心头&#xff01;在人脸识别是不是也会看见 等等。 模板匹配可以看作是对象检测的一种非常基本的形式。使用模板匹配&#xff0c;我们可以使用包含要检测对象的“模板”来检测输入图像中的对象。 …

OpenCV-模板匹配cv::matchTemplate

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 函数原型 void matchTemplate( InputArray image, InputArray templ,OutputArray result, int method, InputArray mask noArr…

OPENCV多种模板匹配使用对比

前文简单提到模板匹配中的一种&#xff1a;NCC多角度模板匹配&#xff0c;博主结合实际的检测项目&#xff08;已落地&#xff09;发现其准确率和稳定性有待提升&#xff0c;特别是一些复杂背景的图形&#xff0c;又或是模板选取不当都会造成不理想的效果&#xff1b;同时也借鉴…

基于opencv的模板匹配详解

1.什么是模板匹配 在OpenCV教程中这样解释模板匹配&#xff1a; 模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术。这里说的模板是我们已知的小图像&#xff0c;模板匹配就是在一副大图像中搜寻目标。模板就是我们已知的在图中要找的目标&#xff0c;…

OpenCV模板匹配(cv2.matchTemplate)

目录 摘要正文OpenCV模板匹配&#xff08;cv2.matchTemplate&#xff09;什么是模板匹配&#xff1f;OpenCV的 “cv2.matchTemplate” 函数配置开发环境项目结构使用OpenCV实施模板匹配OpenCV模板匹配结果总结 摘要 在本教程中&#xff0c;您将学习如何使用OpenCV和cv2.matchTe…

Opencv (C++)系列学习---模板匹配

目录 1.模板匹配的定义 2.API介绍 3.寻找最优匹配位置&#xff08;匹配后的配套操作&#xff09; 4.具体代码 1.模板匹配的定义 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域&#xff0c;该匹配方法并不是基于直方图&#xff0c;而是使用一个图像块在输入图像…

【OpenCV--模板匹配】

目录 一、模板匹配 1.定义&#xff1a; 2.实现&#xff1a; 二、霍夫线检测 1.原理&#xff1a; 2.实现&#xff1a; 三、霍夫圆检测 1.描述&#xff1a; 2.用法&#xff1a; 一、模板匹配 1.定义&#xff1a; 模板匹配就是在给定的图片中&#xff0c;查找和模板最相似的区域…

OpenCV学习笔记(十一)——模板匹配

模板匹配是指在当前图像A内寻找与图像B最相似的部分&#xff0c;一般将图像A称为输入图像&#xff0c;将图像B称为模板图像。模板匹配的操作方法是将模板图像B在图像A上滑动&#xff0c;遍历所有像素以完成匹配。 OpenCV学习笔记(十一&#xff09; 1. 模板匹配基础2. 多模板匹配…

opencv中的模板匹配

1 匹配函数 opencv 提供了一个专门用于模板匹配的函数 cv::matchTemplate();其调用方式如下&#xff1a; void cv::matchTemplate(cv::InputArray image, // 用于搜索的输入图像, 8U 或 32F, 大小 W-Hcv::InputArray templ, // 用于匹配的模板&#xff0c;和image类型相同&am…

【论文译文】BigGAN

译文仅供参考&#xff01; 原文是pdf&#xff0c;想下载的话可以戳&#xff1a;http://www.gwylab.com/pdf/biggan_chs.pdf

WGAN、WGAN-GP、BigGAN

一、WGAN概述 WGAN论文地址&#xff1a;https://arxiv.org/abs/1701.07875 在这篇论文中&#xff0c;作者研究了不同的测量方法&#xff0c;来描述模型生成样本和证实样本之间分布差距&#xff0c;或者说&#xff0c;不同的散度定义&#xff0c;在对比之后&#xff0c;认为EM…

tf hub bigGan 猫变狗

原文链接: tf hub bigGan 猫变狗 上一篇: tf hub mobile_net 使用 下一篇: tf hub 使用缓存 数据 根据输入的标签和噪声生成指定类别的图片&#xff0c;类似infogan 每次向着目标前进一小步&#xff0c;将其中的过程变化记录下来 import tensorflow as tf import n…

(2018, BigGAN)用于高保真自然图像合成的大规模 GAN 训练

Large scale gan training for high fidelity natural image synthesis 公众号&#xff1a;EDPJ 目录 0. 摘要 1. 简介 2. 背景 3. 扩展 GAN 3.1 使用截断技巧权衡多样性和保真度 3.2 总结 4. 分析 4.1 表征不稳定性&#xff1a;生成器 4.2 表征不稳定性&#xff1…

深度解读DeepMind新作:史上最强GAN图像生成器—BigGAN

在碎片化阅读充斥眼球的时代&#xff0c;越来越少的人会去关注每篇论文背后的探索和思考。 在这个栏目里&#xff0c;你会快速 get 每篇精选论文的亮点和痛点&#xff0c;时刻紧跟 AI 前沿成果。 点击本文底部的「阅读原文」即刻加入社区&#xff0c;查看更多最新论文推荐。 这…

基于飞桨实现BigGAN生成动漫图像——为艺术创作赋能

点击左上方蓝字关注我们 【飞桨开发者说】艾梦&#xff0c;深度学习业余选手&#xff0c;热衷于用AI创造新的可能性&#xff0c;努力探索发现未知的神奇世界。玩AI&#xff0c;我是认真的。 作为学力不足、码力有余的深度学习业余玩家&#xff0c;笔者在工作中忙里偷闲&#xf…