OpenCV模板匹配算法详解

article/2025/11/9 18:46:43

本博客在https://www.cnblogs.com/zhaoweiwei/p/OpenVC_matchTemplate.html基础上进行更加详细的注解。当初有几个地方看的比较费劲,但是里面没有注释,现给加上,主要是那些带黄色及红色部分的注释。

在此向weiwei22844致敬。

 

模板匹配是在一幅图像中寻找一个特定目标的方法之一,这种方法的原理非常简单,遍历图像中的每一个可能的位置,比较各处与模板是否相似,当相似度足够高时,就认为找到了我们的目标。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表示模板图像,I表示待匹配图像,切模板图像的宽为w高为h,用R表示匹配结果,匹配过程如下图所示:

https://images2015.cnblogs.com/blog/465567/201606/465567-20160615140604354-595687194.jpg

上述6中匹配方法可用以下公式进行描述:

较新版本的OpenCV库中的模板匹配已经进行了较多的算法改进,直接看新版本中的算法需要了解很多相关理论知识,所以我们结合OpenCV0.9.5的源码进行讲解,该版本的源码基本上是C风格代码,对于初学者来说更容易进行理解(如果要对OpenCV源码进行研究,建议用该版本进行入门),下面以第6项归一化相关系数匹配法为例进行分析。

 

 源码部分及注解

   /******************参数说明***************************** pImage: 待匹配图像数据,相对要大于或等于模板图像的宽和高* imageStep: 待匹配图像宽(width*depth并以4字节对齐)* roiSize: 待匹配图像尺寸* pTemplate: 模板图像数据(在大图pImage里去找这个模板pTemplate图像)* templStep: 模板图像宽* templSize: 模板图像尺寸* pResult: 匹配结果* resultStep: 匹配结果宽* pBuffer: 中间结果数据缓存*/IPCVAPI_IMPL( CvStatus, icvMatchTemplate_CoeffNormed_32f_C1R,(const float *pImage, int imageStep, CvSize roiSize,const float *pTemplate, int templStep, CvSize templSize,float *pResult, int resultStep, void *pBuffer) ){float *imgBuf = 0;              // 待匹配图像相关数据float *templBuf = 0;            // 模板图像数据double *sumBuf = 0;             // 待匹配图像遍历块单行和double *sqsumBuf = 0;           // 待匹配图像遍历块单行平方和double *resNum = 0;             // 模板图像和待匹配图像遍历块内积double *resDenom = 0;           // 待匹配图像遍历块累加和及待匹配图像遍历块平方累加和double templCoeff = 0;          // 模板图像均分差倒数double templSum = 0;            // 模板图像累加和int winLen = templSize.width * templSize.height;double winCoeff = 1. / (winLen + DBL_EPSILON);          // + DBL_EPSILON 加一个小整数防止分母为零CvSize resultSize = cvSize( roiSize.width - templSize.width + 1,roiSize.height - templSize.height + 1 );int x, y;// 计算imgBuf、templBuf、sumBuf、sqsumBuf、resNum、resDenom大小并分配存储空间CvStatus result = icvMatchTemplateEntry( pImage, imageStep, roiSize,pTemplate, templStep, templSize,pResult, resultStep, pBuffer,cv32f, 1, 1,(void **) &imgBuf, (void **) &templBuf,(void **) &sumBuf, (void **) &sqsumBuf,(void **) &resNum, (void **) &resDenom );if( result != CV_OK )return result;imageStep /= sizeof_float;templStep /= sizeof_float;resultStep /= sizeof_float;/* calc common statistics for template and image */{const float *rowPtr = (const float *) imgBuf;double templSqsum = icvCrossCorr_32f_C1( templBuf, templBuf, winLen );          // 模板图像平方累加和 Sqsum +=I(x,y)*I(x,y)templSum = icvSumPixels_32f_C1( templBuf, winLen );                             // 模板图像累加和  Sum +=I(x,y)templCoeff = (double) templSqsum - ((double) templSum) * templSum * winCoeff;   // 模板图像均方差的平方//templCoeff = sum(I(x,y)*I(x,y))-(sum(I(x,y))*sum(I(x,y)/width*heighttemplCoeff = icvInvSqrt64d( fabs( templCoeff ) + FLT_EPSILON );                 // 模板图像均方差倒数 //正好是公式6分母的左半部分//下面按每rows 进行滑动,Mat里的rows,相对于图像的height,有效区域是模板的大小for( y = 0; y < roiSize.height; y++, rowPtr += templSize.width ){sumBuf[y] = icvSumPixels_32f_C1( rowPtr, templSize.width );                 // 待匹配图像按模板图像宽度求每行之和(遍历位置第一列)sqsumBuf[y] = icvCrossCorr_32f_C1( rowPtr, rowPtr, templSize.width );       // 待匹配图像按模板图像宽度求每行平方之和(遍历位置第一列)}}/* main loop - through x coordinate of the result从结果矩阵result的x坐标进行滑动*/for( x = 0; x < resultSize.width; x++ ){double sum = 0;double sqsum = 0;float *imgPtr = imgBuf + x;                                                      // 待匹配图像内存部分的起始位置/* update sums and image band buffer */                                          // 如果不是第0列需重新更新sumBuf,sqsumBuf[y],更新后sumBuf为遍历位置第x列每行之和(行宽为模板图像宽)相当于最左边一列数据要随着x滑动需要实时更新。更新方法就是新的最右边一列数据减去老的最左边的一列数据就可以了。if( x > 0 ){const float *src = pImage + x + templSize.width - 1; //图像数据源起始地址float *dst = imgPtr - 1;  // float *imgPtr = imgBuf + x;float out_val = dst[0]; //这次模板宽度起始的位置的前一个像素dst += templSize.width;for( y = 0; y < roiSize.height; y++, src += imageStep, dst += templSize.width ){float in_val = src[0];//原图(x,y)的数据sumBuf[y] += in_val - out_val;//求原图像一列的像素差值总和sqsumBuf[y] += (in_val - out_val) * (in_val + out_val);//x^2-y^2out_val = dst[0];//作为上一行的数据dst[0] = (float) in_val; //设置dst[0]}}for( y = 0; y < templSize.height; y++ )                                          // 单独求遍历位置第x列,遍历块累加和sum及平方差累加和sqsum{sum += sumBuf[y];sqsum += sqsumBuf[y];}//对x列下y行部分进行预先处理for( y = 0; y < resultSize.height; y++, imgPtr += templSize.width ){double res = icvCrossCorr_32f_C1( imgPtr, templBuf, winLen );               // 求模板图像和待匹配图像y行x列处遍历块的内积 //res +=imgPtr(x,y)*templBuf(x,y)//分子左上部分卷积if( y > 0 )              // 如果不是第0行需更新遍历块累加和sum及平方累加和sqsum更新方法是新的最下面一行减去老的最上面一行就可以了{sum -= sumBuf[y - 1];sum += sumBuf[y + templSize.height - 1];sqsum -= sqsumBuf[y - 1];sqsum += sqsumBuf[y + templSize.height - 1];}resNum[y] = res;resDenom[y] = sum;resDenom[y + resultSize.height] = sqsum;}//进行最后汇总计算,基于x列滑动的结果再进行结果矩阵的y行列滑动for( y = 0; y < resultSize.height; y++ ){double sum = ((double) resDenom[y]);double wsum = winCoeff * sum;//分子右半部分第一项double res = ((double) resNum[y]) - wsum * templSum; //公式6的分子部分// wsum * templSum 表示分子右半部分;double nrm_s = ((double) resDenom[y + resultSize.height]) - wsum * sum;//上面表示分母右边开根号里的内容 (I(x,y)*I(x,y))-1/width/height*sum(temp(x,y))*sum(temp(x,y))res *= templCoeff * icvInvSqrt64d( fabs( nrm_s ) + FLT_EPSILON );//公式6的分母右半部分pResult[x + y * resultStep] = (float) res;//把结果相似度值存入结果矩阵x列y行中}}return CV_OK;}

 


http://chatgpt.dhexx.cn/article/7wjBhrxt.shtml

相关文章

OpenCV 模板匹配(Template Match)

文章目录 模板匹配介绍模板匹配定义匹配算法平方差归一化的平方差相关性归一化的相关性相关性系数归一化的相关性系数 相关API代码示例 模板匹配介绍 模板匹配定义 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域。 所以模板匹配首先需要一个模板图像T&#xff…

OpenCV 模板匹配

模板匹配就是在大图中找小图&#xff0c;也就说在一幅图像中寻找另一幅模板图像的位置。 案例来源于傅老师。 模板匹配的操作方法是将模板图像B在图像A上滑动&#xff0c;遍历所有像素以完成匹配。 工作原理&#xff1a;在带检测图像上&#xff0c;从左到右&#xff0c;从上…

13 -- OpenCV学习—模板匹配

模板匹配 1.模板匹配 模板匹配&#xff1a;在给定的模板中查找最相似的区域 实现流程&#xff1a; 准备两幅图像 &#xff08;1&#xff09;原图 &#xff08;2&#xff09;模板图滑动模板块和原图像进行比对对于每个像素位置。将计算结果存在矩阵中&#xff0c;输入图像大小…

opencv模板匹配步骤及Code

opencv模板匹配步骤及Code 首先介绍一下模板匹配的适用场景&#xff1a; 1、图像检索 2、目标跟踪 简单的说&#xff0c;模板匹配最主要的功能就是在一幅图像中去寻找和另一幅模板图像中相似度最高的部分&#xff0c;这就是模板匹配。 比如&#xff0c;在下面这图片中: 我们要…

OpenCV 学习笔记(模板匹配)

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

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