Python OpenCV实现图像模板匹配详解


Posted in Python onApril 07, 2022

1.什么是模板匹配及模板匹配方法matchTemplate()

介绍

提供一个模板图像,一个目标图像,且满足模板图像是目标图像的一部分,从目标图像中寻找特定的模板图像的过程,即为模板匹配。OpenCV提供了matchTemplate()方法帮助我们实现模板匹配。

该方法语法如下:

cv2.matchTemplate(image, templ, method, result=None, mask=None)

其中

image 即目标图像

templ 即模板图像

method 是匹配的方式

mask 即掩模,可选。只有当method为cv2.TM_SQDIFF或cv2.TM_CCORR_NORMED时才支持此参数。

method参数可以是以下值:

参数值 描述
cv2.TM_SQDIFF 差值平方和匹配,也称平方差匹配。可以理解为是基于差异程度的匹配,差异程度越小,匹配程度越高。完全匹配时值差值平方和为0。
cv2.TM_SQDIFF_NORMED 相关匹配。 可以理解为是基于相似程度的匹配,相似程度越高,计算结果越大,匹配程度就越高。
cv2.TM_CCORR 标准相关匹配。 规则同上。
cv2.TM_CCORR_NORMED 相关系数匹配
cv2.TM_CCOEFF 相关系数匹配。也是基于相似程度的匹配,计算结果是一个-1到1的浮点数,1表示完全匹配,0表示毫无关系,-1表示两张图片亮度刚好相反。
cv2.TM_CCOEFF_NORMED 标准相关系数匹配,规则同上。

使用matchTemplate()方法,模板会将图像中的每一块区域都覆盖一遍,并每次都使用所选的method方法进行计算,每次的计算结果最后以一个二维数组的形式返回给我们。

素材准备

为方便展示,特准备以下图片素材:

选择世界名画《三英战吕布》(test.png),图像shape为(738, 675, 3):

Python OpenCV实现图像模板匹配详解

从中抠出一部分图像元素作为下边要用的模板素材。取材代码如下( 不建议截图,截图抠出来的不一定能保证尺寸):

import cv2
img = cv2.imread("test.png")

print(img.shape)
# 电灯
img1 = img[20:220, 320:480, :]
# 虎牢关牌匾
img2 = img[75:150, 200:310, :]
# 青龙刀
img3 = img[170:530, 575:650, :]
# 关云长
img4 = img[270:670, 160:330, :]


cv2.imshow("img0", img)
cv2.imshow("img1", img1)
cv2.imshow("img2", img2)
cv2.imshow("img3", img3)
cv2.imshow("img4", img4)
cv2.waitKey()
cv2.destroyAllWindows()

cv2.imwrite('template_pic1.jpg', img1)
cv2.imwrite('template_pic2.jpg', img2)
cv2.imwrite('template_pic3.jpg', img3)
cv2.imwrite('template_pic4.jpg', img4)

取出的模板素材如下:

电灯

Python OpenCV实现图像模板匹配详解

虎牢关牌匾

Python OpenCV实现图像模板匹配详解

青龙刀

Python OpenCV实现图像模板匹配详解

关云长

Python OpenCV实现图像模板匹配详解

2.单模板匹配

单模板匹配,即在匹配时中只使用到一个模板的匹配过程。具体又可以分为单目标匹配和多目标匹配。

2.1 单目标匹配

单目标匹配,即模板在目标图像中只匹配 匹配程度最高的一个匹配结果。

这需要找出这一次匹配结果所在位置的坐标来确定其位置,

OpenCV提供了cv2.minMAXLoc()来实现。

该方法参数为matchTemplate()的返回值,会返回一个元组,元组中有四个值,分别是最小值、最大值、最小值时图像左上角顶点坐标,最大值时图像左上角顶点坐标。

接下来,使用 电灯(template_pic1) 图片来匹配原图,并用红色的矩形在原图像中圈出模板图像,使用标准差值平方和的匹配方式,代码如下:

import cv2
img = cv2.imread("test.png")

templ = cv2.imread("template_pic1.jpg")
height, width, c = templ.shape
results = cv2.matchTemplate(img, templ, cv2.TM_SQDIFF_NORMED)
# 获取匹配结果中的最小值、最大值、最小值坐标和最大值坐标
minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(results)
resultPoint1 = minLoc
resultPoint2 = (resultPoint1[0] + width, resultPoint1[1] + height)
cv2.rectangle(img, resultPoint1, resultPoint2, (0, 0, 255), 2)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()

如图所示,成功标出了模板图。

Python OpenCV实现图像模板匹配详解

如果要从多幅图像中,找出与模板最匹配的结果,

以标准差值平方和的匹配方式为例,
则可以对这些图像进行遍历,并比较每幅图像对应结果中的最小值,找出最小值中的最小值,则为最佳匹配项。

以两幅图像为例,将原图翻转一次,生成一张新的图像(翻转后结果与原图较像,但差异巨大)

翻转产生素材(test1.png)

import cv2
img = cv2.imread("test.png")
dst1 = cv2.flip(img, 1)
cv2.imshow("dst1", dst1)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('test1.png', dst1)        

Python OpenCV实现图像模板匹配详解

然后使用模板 关云长 (template_pic4.jpg)对两幅图像进行匹配,输出最佳匹配结果,并画红框展示:

import cv2

image = []
image.append(cv2.imread("test.png"))
image.append(cv2.imread("test1.png"))
templ = cv2.imread("template_pic4.jpg")
height, width, c = templ.shape

# 循环变量初始化
# 这里只是随便设定一个值,该值并无意义,只是为了定义该变量
# 使用TM_SQDIFF_NORMED计算方法,计算出的结果通常是小于1的,所以minValue可以设置为1。如果是TM_SQDIFF计算方法,则就不行了,计算出来的值会很大。代码就不再有效,需要把minMax设得更大,或者做其他修改。
index = -1
minValue = 1
minLoc1 = (0, 0)

# 遍历每幅图像
for i in range(0, len(image)):
    results = cv2.matchTemplate(image[i], templ, cv2.TM_SQDIFF_NORMED)
    min = cv2.minMaxLoc(results)[0]
    if min < minValue:
        minValue = min
        minLoc1 = cv2.minMaxLoc(results)[2]
        index = i

minLoc2 = (minLoc1[0] + width, minLoc1[1] + height)
cv2.rectangle(image[index], minLoc1, minLoc2, (0, 0, 255), 2)
cv2.imshow("result", image[index])
cv2.waitKey()
cv2.destroyAllWindows()

如图,test.png中的关云长与模板更为匹配。

Python OpenCV实现图像模板匹配详解

2.2 多目标匹配

多目标匹配,即在目标图像中匹配出所有与模板图像匹配的结果。可以使用相关匹配或相关系数匹配。

素材准备

还以原图像"test.png"为参照,

为了产生方便我们做示例的图像,我们在该图像的基础上多加一盏电灯,生成"test2.png"

import cv2
img = cv2.imread("test.png")
templ = cv2.imread("template_pic1.jpg")
img[20:220, 30:190, :] = templ
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite('test2.png', img)      

Python OpenCV实现图像模板匹配详解

多目标匹配

多目标匹配即对matchTemplate()匹配的总的结果,的计算情况数据,使用for循环遍历,并设定一个判断标准。

如使用标准相关系数(cv2.TM_CCOEFF_NORMED)的方法判断,如:如果计算值大于0.99,则我们认为匹配成功了。

使用电灯模板"template_pic1.jpg",匹配图像test2.png。并对匹配的结果用红色的矩形框标记。

代码示例如下:

import cv2
img = cv2.imread("test2.png")
templ = cv2.imread("template_pic1.jpg")
height, width, c = templ.shape
# 按照标准相关系数匹配
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)
for y in range(len(results)):
    for x in range(len(results[y])):
        if results[y][x] > 0.99:
            cv2.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2)
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()

程序执行结果如下,成功匹配出了两盏灯。

Python OpenCV实现图像模板匹配详解

3.多模板匹配

多模板匹配,即进行了n次单模板的匹配过程。 

直接上示例:

在test.png中匹配电灯、青龙刀、虎牢关牌匾、关云长四个图像模板:

import cv2


def myMatchTemplate(img, templ):
    height, width, c = templ.shape
    results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)
    loc = list()
    for i in range(len(results)):
        for j in range(len(results[i])):
            if results[i][j] > 0.99:
                loc.append((j, i, j + width, i + height))
    return loc

# 读取原始图像
img = cv2.imread("test.png")  
# 模板列表
templs = list()  
templs.append(cv2.imread("template_pic1.jpg"))
templs.append(cv2.imread("template_pic2.jpg"))
templs.append(cv2.imread("template_pic3.jpg"))
templs.append(cv2.imread("template_pic4.jpg"))


loc = list()  
for t in templs: 
    loc += myMatchTemplate(img, t) 

# 遍历所有红框的坐标
for i in loc:  
    cv2.rectangle(img, (i[0], i[1]), (i[2], i[3]), (0, 0, 255), 2) 

cv2.imshow("img", img) 
cv2.waitKey() 
cv2.destroyAllWindows()

匹配效果如下:

Python OpenCV实现图像模板匹配详解

以上就是Python OpenCV实现图像模板匹配详解的详细内容,更多关于Python OpenCV图像模板匹配的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python文件夹与文件的相关操作(推荐)
Jul 25 Python
Java分治归并排序算法实例详解
Dec 12 Python
Python实现查看系统启动项功能示例
May 10 Python
Python常用爬虫代码总结方便查询
Feb 25 Python
Python Flask框架扩展操作示例
May 03 Python
详解如何设置Python环境变量?
May 13 Python
Python上下文管理器全实例详解
Nov 12 Python
Python定义函数时参数有默认值问题解决
Dec 19 Python
Python3 解决读取中文文件txt编码的问题
Dec 20 Python
python不到50行代码完成了多张excel合并的实现示例
May 28 Python
python初步实现word2vec操作
Jun 09 Python
Python爬虫入门案例之爬取二手房源数据
Oct 16 Python
Python实现日志实时监测的示例详解
Python使用PyYAML库读写yaml文件的方法
Apr 06 #Python
python+pytest接口自动化之token关联登录的实现
Python图像处理库PIL详细使用说明
Apr 06 #Python
Python可变与不可变数据和深拷贝与浅拷贝
Apr 06 #Python
Python 全局空间和局部空间
Apr 06 #Python
Selenium浏览器自动化如何上传文件
Apr 06 #Python
You might like
PHP curl_setopt()函数实例代码与参数分析
2011/06/02 PHP
php启用zlib压缩文件的配置方法
2013/06/12 PHP
discuz免激活同步登入代码修改方法(discuz同步登录)
2013/12/24 PHP
PHP字符串的连接的简单实例
2013/12/30 PHP
PHP抓取网页、解析HTML常用的方法总结
2015/07/01 PHP
使用jQuery jqPlot插件绘制柱状图
2014/12/18 Javascript
JavaScript常用小技巧小结
2014/12/29 Javascript
javascript操作select元素实例分析
2015/03/27 Javascript
JS实现密码框根据焦点的获取与失去控制文字的消失与显示效果
2015/11/26 Javascript
Require.JS中的几种define定义方式示例
2017/06/01 Javascript
vue、react等单页面项目应该这样子部署到服务器
2018/01/03 Javascript
详解基于vue的服务端渲染框架NUXT
2018/06/20 Javascript
Node.js console控制台简单用法分析
2019/01/04 Javascript
Vue简单实现原理详解
2020/05/07 Javascript
微信小程序点击滚动到指定位置的实现
2020/05/22 Javascript
详解Vue的组件中data选项为什么必须是函数
2020/08/17 Javascript
[14:21]VICI vs EG (BO3)
2018/06/07 DOTA
基于Python实现通过微信搜索功能查看谁把你删除了
2016/01/27 Python
Python多线程经典问题之乘客做公交车算法实例
2017/03/22 Python
python负载均衡的简单实现方法
2018/02/04 Python
Python3使用SMTP发送带附件邮件
2020/06/16 Python
应用OpenCV和Python进行SIFT算法的实现详解
2019/08/21 Python
css3和jquery实现自定义checkbox和radiobox组件
2014/04/22 HTML / CSS
详解Html5原生拖拽操作
2018/01/12 HTML / CSS
阿迪达斯德国官方网站:adidas德国
2017/07/12 全球购物
Nike比利时官网:Nike.com (BE)
2019/02/07 全球购物
微型企业创业投资计划书
2014/01/10 职场文书
买房子个人收入证明
2014/01/16 职场文书
电大毕业个人生自我鉴定
2014/03/26 职场文书
考核工作实施方案
2014/03/30 职场文书
房产公证书范本
2014/04/10 职场文书
副主任竞聘演讲稿
2014/08/18 职场文书
群众路线教育实践活动批评与自我批评
2014/09/15 职场文书
小学生安全保证书
2015/05/09 职场文书
Vue的列表之渲染,排序,过滤详解
2022/02/24 Vue.js
利用Java连接Hadoop进行编程
2022/06/28 Java/Android