python学opencv|读取图像(五十三)原理探索:使用cv.matchTemplate()函数实现最佳图像匹配

devtools/2025/2/7 15:25:36/

【1】引言

前序学习进程中,已经探索了使用cv.matchTemplate()函数实现最佳图像匹配的技巧,并且成功对两个目标进行了匹配。

相关文章链接为:python学opencv|读取图像(五十二)使用cv.matchTemplate()函数实现最佳图像匹配-CSDN博客

实际上,我们在这篇文章中重点体会了匹配效果,却没有真正剖析代码背后的运行逻辑。今天这篇文章的目标就是对代码背后逻辑稍微追溯一下。

【2】官网教程

【2.1】cv2.matchTemplate()函数

点击下方链接,直达cv2.matchTemplate()函数官网链接:

图1 cv2.matchTemplate()函数官网说明

图1所示的cv2.matchTemplate()函数官网说明中,有三处做了标记,它们彼此交织在一起。需要解读:

a.待匹配的大图像I大小为W X H,使用的模板T像素大小为w x h,获得的匹配效果R对应的的矩阵大小为(W-w+1,H-h+1);

b.使用不同的匹配方法后,再用minMaxLoc函数读取最佳匹配效果对应的左上角坐标时,有时候取最小值,如TM_SQDIFF,有时候取最大值,如TM_CCORR和TM_CCOEFF。

c.解读匹配方法请看第2.2节。

【2.2】cv2.matchTemplate()函数

点击链接,直达函数对匹配方法的解读:OpenCV: Object Detection

在这个页面,会看到不同的函数说明:

图2 匹配方法的数学公式

由图2可见,TM_SQDIFF采用的是减法计算,而TM_CCORR和TM_CCOEFF采用的乘法计算,所以相似度高的时候,TM_SQDIFF方法的计算值往往会接近0,而TM_CCORR和TM_CCOEFF方法就会在因为平方而取得更大的值。

所以“用minMaxLoc函数读取最佳匹配效果对应的左上角坐标时,有时候取最小值,如TM_SQDIFF,有时候取最大值,如TM_CCORR和TM_CCOEFF”就获得了解释。

【3】代码测试

【3.1】代码回顾

首先直接引用前一篇文章的完整代码:

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块# 读取图片
srcm = cv.imread('srcm.png') #读取图像srcx.png
srcg = cv.imread('srcg.png') #读取图像srcp.png
srcc = cv.imread('srcc.png') #读取图像srcp.png
rows,cols,cans=srcg.shape #读取图像属性
rowsc,colsc,cansc=srcc.shape #读取图像属性#匹配结果
results=cv.matchTemplate(srcm,srcg,cv.TM_CCORR_NORMED)
results1=cv.matchTemplate(srcm,srcc,cv.TM_CCORR_NORMED)#取值
minValue,maxValue,minLoc,maxLoc=cv.minMaxLoc(results)
minValuec,maxValuec,minLocc,maxLocc=cv.minMaxLoc(results1)#取最大坐标
resultPoint1=maxLoc
print("resultPoint1=",resultPoint1)#取最大坐标
resultPoint2=maxLocc
print("resultPoint2=",resultPoint2)#定义新坐标
resultPoint3=(resultPoint1[0]+cols,resultPoint1[1]+rows)
print("resultPoint3=",resultPoint3)#定义新坐标
resultPoint4=(resultPoint2[0]+colsc,resultPoint2[1]+rowsc)
print("resultPoint4=",resultPoint4)#作标记
cv.circle(srcm,(250,250),30,(0,255,0))
cv.rectangle(srcm,resultPoint1,resultPoint3,(0,255,0),2)
cv.rectangle(srcm,resultPoint2,resultPoint4,(200,180,55),2)# 显示结果
cv.imshow('srcm ', srcm)
cv.imshow('srcg ', srcg)
cv.imshow('srcc ', srcc)
cv.imwrite('srcgc.png',srcm)#窗口控制
cv.waitKey()  # 图像不关闭
cv.destroyAllWindows()  # 释放所有窗口

待匹配的图像I为:

图3 待匹配图像I:srcm.png

图4 模板T1 srcg.png

图5 模板T2 srcc.png

图6 匹配效果 srcgc.png  

上述代码全部使用了cv2.TM_CCORR_NORMED方法,所以需要调用最大值来代表最佳匹配效果的左上角坐标。

未验证不用方法对应最佳匹配效果的左上角坐标,现在应增加匹配方法。

【3.2】代码扩展

在直接引用前一篇文章的完整代码的基础上,不仅要增加匹配方法,还要显示出匹配结果。

#匹配计算
results=cv.matchTemplate(srcm,srcg,cv.TM_SQDIFF_NORMED) #TM_SQDIFF匹配方法
results1=cv.matchTemplate(srcm,srcc,cv.TM_CCORR_NORMED) #TM_CCORR匹配方法
print("result=",results) #输出匹配结果
print("result1=",results1) #输出匹配结果

代码先后使用了TM_SQDIFF和TM_CCORR两种方法,并且要求输出了匹配结果。

然后读取了调用minMaxLoc()函数对结果渠道的各个参数值:

#取值
minValue,maxValue,minLoc,maxLoc=cv.minMaxLoc(results)
minValuec,maxValuec,minLocc,maxLocc=cv.minMaxLoc(results1)
print("result.minValue=",minValue)
print("result1.minValuec=",minValuec)
print("result.maxValue=",maxValue)
print("result1.maxValuec=",maxValuec)
print("result.minLoc=",minLoc)
print("result1.minLocc=",minLocc)
print("result.maxLoc=",maxLoc)
print("result1.maxLocc=",maxLocc)

然后根据先前的分析思路,取最佳匹配矩阵的左上角坐标。

这时候TM_SQDIFF取最小值,TM_CCORR方法取最大值,之后还要叠加模板的大小,来画出整个匹配区域:

#取最小坐标
resultPoint1=minLoc
print("resultPoint1=",resultPoint1)#取最大坐标
resultPoint2=maxLocc
print("resultPoint2=",resultPoint2)#定义新坐标
resultPoint3=(resultPoint1[0]+cols,resultPoint1[1]+rows)
print("resultPoint3=",resultPoint3)#定义新坐标
resultPoint4=(resultPoint2[0]+colsc,resultPoint2[1]+rowsc)
print("resultPoint4=",resultPoint4)

之后为了突出匹配点,以最小和最大坐标Wie圆心,分别绘制半径为10和20的圆形:

#作标记
cv.circle(srcm,(minLoc),10,(255,255,0))
cv.circle(srcm,(maxLoc),20,(255,255,0))
cv.circle(srcm,(minLocc),10,(0,255,255))
cv.circle(srcm,(maxLocc),20,(0,255,255))
cv.circle(srcm,(250,250),30,(0,255,0))
cv.rectangle(srcm,resultPoint1,resultPoint3,(0,255,0),2)
cv.rectangle(srcm,resultPoint2,resultPoint4,(200,180,55),2)

然后输出所有图像:

# 显示结果
cv.imshow('srcm ', srcm)
cv.imwrite('srcgcw.png',srcm)
#窗口控制
cv.waitKey()  # 图像不关闭
cv.destroyAllWindows()  # 释放所有窗口

代码运行后,获得的匹配效果为:

图7 匹配效果srcgcw.png

由图7可见,TM_SQDIFF取最小值,TM_CCORR方法取最大值获得的最佳匹配图像实现了预期效果。

【4】细节说明

上述3.2节读取到的部分匹配结果矩阵为:

 图8 匹配结果矩阵

由图8可见,每个矩阵内部给出了很多值,这表明在矩阵内部,图像和模板是按照像素点逐个进行比对匹配。

【5】总结

掌握了python+opencv调用使用cv.matchTemplate()函数实现最佳图像匹配的执行原理和过程。

 


http://www.ppmy.cn/devtools/156854.html

相关文章

人工智能丨PyTorch 强化学习与自然语言处理

在当前快速发展的科技时代,深度学习和人工智能无疑是最受追捧的领域之一。而在这股浪潮中,PyTorch作为一种灵活而强大的深度学习框架,已经占据了重要的地位。无论是在强化学习还是自然语言处理中,PyTorch都提供了不容小觑的功能和…

技术选型对比:Redis 与 MySQL、Dubbo 与 Spring Cloud

在 Java 开发的技术选型过程中,深入了解不同技术的特点和适用场景是至关重要的。本文将对 Redis 与 MySQL 在保证数据一致性方面进行详细对比,并探讨 Dubbo 与 Spring Cloud 这两个微服务框架的差异,帮助开发者在实际项目中做出更合理的技术选…

【Linux高级IO】五种IO模型

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:Linux “ 登神长阶 ” 🌹🌹期待您的关注 🌹🌹 ❀ Linux高级IO 重新理解IOI/O模型阻塞式IO非阻塞式IO信号驱动IOIO多路转接异步IO 同步通信 vs…

React - jsx 语法

在 React 中,JSX(JavaScript XML)是一种语法扩展,它允许开发者在 JavaScript 代码中使用类似 HTML 的语法。JSX 提升了代码的可读性和可维护性,使得编写和构建用户界面更加直观。它被广泛应用于 React 组件的定义。 一…

风控系统指标版本管理,前端实现

个人博客:无奈何杨(wnhyang) 个人语雀:wnhyang Github:wnhyang - Overview 前言 本文算是前文《基于LiteFlow的风控系统指标版本控制》的完善。 前文已经说明了在基于规则引擎系统中版本管理的重要性,并…

【产品小白】什么是微服务

在数字化浪潮汹涌澎湃的当下,软件系统的规模持续扩张,复杂度呈指数级攀升。如何高效地开发软件,确保其后续的维护轻松便捷,同时具备强大的扩展能力,已然成为广大开发者待攻克的核心难题。微服务作为一种应运而生的前沿…

【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(三)

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:贪心算法篇–CSDN博客 文章目录 前言例题1.最优除法2.跳跃游戏23.跳跃游戏14.加油站5.单调递…

[c语言日寄]赋值操作对内存的影响

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…