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 过滤字符串的技巧,map与itertools.imap
Sep 06 Python
Python中用Ctrl+C终止多线程程序的问题解决
Mar 30 Python
Python读写Redis数据库操作示例
Mar 18 Python
Python中使用MELIAE分析程序内存占用实例
Feb 18 Python
python3中bytes和string之间的互相转换
Feb 09 Python
Python实现的简单模板引擎功能示例
Sep 02 Python
python版大富翁源代码分享
Nov 19 Python
Python小游戏之300行代码实现俄罗斯方块
Jan 04 Python
pymysql 开启调试模式的实现
Sep 24 Python
python getpass实现密文实例详解
Sep 24 Python
Pytorch Tensor的统计属性实例讲解
Dec 30 Python
Python __slots__的使用方法
Nov 15 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实现的返回数据格式化类实例
2014/09/22 PHP
phpstorm配置Xdebug进行调试PHP教程
2014/12/01 PHP
在Ubuntu 18.04上安装PHP 7.3 7.2和7.0的方法
2019/04/09 PHP
PHP safe_mode开启对于PHP系统函数有什么影响
2020/11/10 PHP
PHP常用字符串输出方法分析(echo,print,printf及sprintf)
2021/03/09 PHP
javascript轻松实现当鼠标移开时已弹出子菜单自动消失
2013/12/29 Javascript
jquery控制页面部分刷新的方法
2015/06/24 Javascript
JS实现的鼠标跟随代码(卡通手型点击效果)
2015/10/26 Javascript
一道关于JavaScript变量作用域的面试题
2016/03/08 Javascript
JS文件上传神器bootstrap fileinput详解
2021/01/28 Javascript
浅谈js中同名函数和同名变量的执行问题
2017/02/12 Javascript
jQuery ajax实现省市县三级联动
2021/03/07 Javascript
Node调用Java的示例代码
2017/09/20 Javascript
AngularJS使用ng-repeat遍历二维数组元素的方法详解
2017/11/11 Javascript
JavaScript的Object.defineProperty详解
2018/07/09 Javascript
使用JavaScript获取Django模板指定键值数据
2020/05/27 Javascript
jquery实现拖拽小方块效果
2020/12/10 jQuery
Python Tkinter GUI编程入门介绍
2015/03/10 Python
Python OpenCV 使用滑动条来调整函数参数的方法
2019/07/08 Python
python用win32gui遍历窗口并设置窗口位置的方法
2019/07/26 Python
python正则表达式匹配IP代码实例
2019/12/28 Python
python批量生成条形码的示例
2020/10/10 Python
canvas环形倒计时组件的示例代码
2018/06/14 HTML / CSS
Mavi牛仔裤美国官网:土耳其著名牛仔品牌
2016/09/24 全球购物
VICHY薇姿美国官方网站:欧洲药房第一的抗衰老品牌
2017/11/22 全球购物
数学专业毕业生自荐信
2013/11/10 职场文书
学校大课间活动方案
2014/01/30 职场文书
四议两公开实施方案
2014/03/28 职场文书
同学聚会策划方案
2014/06/06 职场文书
法人委托书
2014/07/31 职场文书
2015新年寄语大全
2014/12/08 职场文书
2015年乡镇妇联工作总结
2015/05/19 职场文书
2016年心理学教育培训学习心得体会
2016/01/12 职场文书
高中地理教学反思
2016/02/19 职场文书
简单实现一个手持弹幕功能+文字抖动特效
2021/03/31 HTML / CSS
win10键盘驱动怎么修复?Win10键盘驱动修复小技巧
2022/04/06 数码科技