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的Flask中使用WTForms表单框架的基础教程
Jun 07 Python
Python部署web开发程序的几种方法
May 05 Python
python中使用PIL制作并验证图片验证码
Mar 15 Python
python3 unicode列表转换为中文的实例
Oct 26 Python
python模块之subprocess模块级方法的使用
Mar 26 Python
python 如何去除字符串头尾的多余符号
Nov 19 Python
妙用itchat! python实现久坐提醒功能
Nov 25 Python
Django 限制访问频率的思路详解
Dec 24 Python
Python hashlib模块实例使用详解
Dec 24 Python
Python学习之路安装pycharm的教程详解
Jun 17 Python
Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)
Jan 29 Python
Python爬虫之爬取二手房信息
Apr 27 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
使用XDebug调试及单元测试覆盖率分析
2011/01/27 PHP
微信公众号点击菜单即可打开并登录微站的实现方法
2014/11/14 PHP
Symfony2学习笔记之模板用法详解
2016/03/17 PHP
php+ajax简单实现全选删除的方法
2016/12/06 PHP
PHP简单实现合并2个数字键数组值的方法
2017/05/30 PHP
php记录搜索引擎爬行记录的实现代码
2018/03/02 PHP
PHP Include文件实例讲解
2019/02/15 PHP
JQuery 实现的页面滚动时浮动窗口控件
2009/07/10 Javascript
javascript学习笔记(十四) window对象使用介绍
2012/06/20 Javascript
jQuery qrcode生成二维码的方法
2016/04/03 Javascript
深入理解bootstrap框架之第二章整体架构
2016/10/09 Javascript
学习vue.js表单控件绑定操作
2016/12/05 Javascript
详解JavaScript 中getElementsByName在IE中的注意事项
2017/02/21 Javascript
用jquery获取select标签中选中的option值及文本的示例
2018/01/25 jQuery
浅谈Layui的eleTree树式选择器使用方法
2019/09/25 Javascript
微信小程序实现上传多个文件 超过10个
2020/03/30 Javascript
简单了解Vue + ElementUI后台管理模板
2020/04/07 Javascript
vue中实现弹出层动画效果的示例代码
2020/09/25 Javascript
如何利用JS将手机号中间四位变成*号
2020/09/29 Javascript
[05:40]DOTA2荣耀之路6:Wings最后进攻
2018/05/30 DOTA
python 图像平移和旋转的实例
2019/01/10 Python
Python中时间datetime的处理与转换用法总结
2019/02/18 Python
Python字符串通过'+'和join函数拼接新字符串的性能测试比较
2019/03/05 Python
浅析pip安装第三方库及pycharm中导入第三方库的问题
2020/03/10 Python
python实现在线翻译
2020/06/18 Python
python脚本第一行如何写
2020/08/30 Python
pip 20.3 新版本发布!即将抛弃 Python 2.x(推荐)
2020/12/16 Python
乌克兰第一的珠宝网上商店:Gold.ua
2019/11/29 全球购物
C/C++程序员常见面试题一
2012/12/08 面试题
这段代码难道不该打印出56吗
2013/02/27 面试题
会计学生自我鉴定
2014/02/06 职场文书
可口可乐广告词
2014/03/20 职场文书
党的群众路线教育实践活动宣传标语口号
2014/06/06 职场文书
交通安全主题班会
2015/08/12 职场文书
学生会部长竞选稿
2015/11/19 职场文书
JS数组的常用方法整理
2021/03/31 Javascript