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 thread 并发且顺序运行示例
Apr 09 Python
python操作ie登陆土豆网的方法
May 09 Python
实例讲解Python中函数的调用与定义
Mar 14 Python
Pandas GroupBy对象 索引与迭代方法
Nov 16 Python
python BlockingScheduler定时任务及其他方式的实现
Sep 19 Python
Python 中判断列表是否为空的方法
Nov 24 Python
带你彻底搞懂python操作mysql数据库(cursor游标讲解)
Jan 06 Python
python连接PostgreSQL过程解析
Feb 09 Python
解决Python logging模块无法正常输出日志的问题
Feb 21 Python
django序列化时使用外键的真实值操作
Jul 15 Python
零基础学python应该从哪里入手
Aug 11 Python
浅谈pytorch中stack和cat的及to_tensor的坑
May 20 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使用imagick模块实现图片缩放、裁剪、压缩示例
2014/04/17 PHP
PHP实现HTML生成PDF文件的方法
2014/11/07 PHP
smarty表格换行实例
2014/12/15 PHP
Yii实现文章列表置顶功能示例
2016/10/18 PHP
数据结构之利用PHP实现二分搜索树
2020/10/25 PHP
一个可以兼容IE FF的加为首页与加入收藏实现代码
2009/11/02 Javascript
jQuery文本框(input textare)事件绑定方法教程
2013/04/24 Javascript
javascript 3d 逐侦产品展示(核心精简)
2014/03/26 Javascript
Node.js中使用计时器定时执行函数详解
2014/08/15 Javascript
node.js中的fs.chmodSync方法使用说明
2014/12/18 Javascript
jQuery中:last选择器用法实例
2014/12/30 Javascript
分享一则JavaScript滚动条插件源码
2015/03/03 Javascript
浅谈js对象的创建和对6种继承模式的理解和遐想
2016/10/16 Javascript
JS根据生日月份和日期计算星座的简单实现方法
2016/11/24 Javascript
详解前端路由实现与react-router使用姿势
2017/08/07 Javascript
vue实现模态框的通用写法推荐
2018/02/26 Javascript
详解PHP后期静态绑定分析与应用
2018/03/21 Javascript
webpack4 处理CSS的方法示例
2018/09/03 Javascript
Vue开发之封装上传文件组件与用法示例
2019/04/25 Javascript
vue安装遇到的5个报错及解决方法
2019/06/12 Javascript
nuxt.js 在middleware(中间件)中实现路由鉴权操作
2020/11/06 Javascript
vue实现lodop打印功能的示例
2020/11/11 Javascript
Python 爬虫之超链接 url中含有中文出错及解决办法
2017/08/03 Python
python中format()函数的简单使用教程
2018/03/14 Python
Python使用qrcode二维码库生成二维码方法详解
2020/02/17 Python
Pycharm激活码激活两种快速方式(附最新激活码和插件)
2020/03/12 Python
Django-simple-captcha验证码包使用方法详解
2020/11/28 Python
HTML5 Canvas标签使用收录
2009/07/07 HTML / CSS
AE美国鹰日本官方网站: American Eagle Outfitters
2016/12/10 全球购物
英国家电购物网站:Sonic Direct
2019/03/26 全球购物
2014年党员公开承诺书范文
2014/03/28 职场文书
建筑工程专业大学生求职信
2014/04/23 职场文书
献爱心活动总结
2014/05/07 职场文书
实习介绍信范文
2015/05/05 职场文书
2016七夕情人节寄语
2015/12/04 职场文书
使用vue判断当前环境是安卓还是IOS
2022/04/12 Vue.js