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

 更新时间:2022年04月06日 17:49:09   作者:侯小啾  
提供一个模板图像,一个目标图像,且满足模板图像是目标图像的一部分,从目标图像中寻找特定的模板图像的过程,即为模板匹配。本文将详细讲解如何利用Python OpenCV实现图像模板匹配,需要的可以参考一下

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):

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

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)

取出的模板素材如下:

电灯

虎牢关牌匾

青龙刀

关云长

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()

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

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

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

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

翻转产生素材(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)        

然后使用模板 关云长 (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中的关云长与模板更为匹配。

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)      

多目标匹配

多目标匹配即对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()

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

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迅速掌握语音识别之知识储备篇

    Python迅速掌握语音识别之知识储备篇

    语音识别是一门交叉学科。近二十年来,语音识别技术取得显著进步,开始从实验室走向市场。人们预计,未来10年内,语音识别技术将进入工业、家电、通信、汽车电子、医疗、家庭服务、消费电子产品等各个领域
    2021-11-11
  • python机器学习之线性回归详解

    python机器学习之线性回归详解

    这篇文章主要介绍了python机器学习之线性回归详解,文中有非常详细的代码示例,对正在学习python的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-04-04
  • python set()去重的底层原理及实例

    python set()去重的底层原理及实例

    python中集合set是一个无序不重复元素的集,基本功能包括关系测试和消除重复元素,还可以计算交集、差集、并集等,它与列表(list)的行为类似,这篇文章主要介绍了python set()去重的底层原理,需要的朋友可以参考下
    2022-01-01
  • Python删除列表中多个元素的四种方法总结

    Python删除列表中多个元素的四种方法总结

    这篇文章主要给大家介绍了关于Python删除列表中多个元素的四种方法,在Python中想要删除列表的某个元素,可以使用本文介绍的方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • 详解Python3.6的py文件打包生成exe

    详解Python3.6的py文件打包生成exe

    这篇文章给大家分享了Python3.6的py文件打包生成exe的方法步骤以及相关知识点,有需要的朋友可以参考学习下。
    2018-07-07
  • python使用numpy读取、保存txt数据的实例

    python使用numpy读取、保存txt数据的实例

    今天小编就为大家分享一篇python使用numpy读取、保存txt数据的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • Python操作json的方法实例分析

    Python操作json的方法实例分析

    这篇文章主要介绍了Python操作json的方法,结合实例形式简单分析了Python针对json数据使用解码loads()和编码dumps()相关操作技巧,需要的朋友可以参考下
    2018-12-12
  • Python区块链创建Genesis Block教程

    Python区块链创建Genesis Block教程

    这篇文章主要为大家介绍了Python区块链创建Genesis Block教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Python3.8如何解决No module named 'numpy'报错问题

    Python3.8如何解决No module named 'numpy&apos

    这篇文章主要介绍了Python3.8如何解决No module named 'numpy'报错问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • python装饰器初探(推荐)

    python装饰器初探(推荐)

    下面小编就为大家带来一篇python装饰器初探(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07

最新评论