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

目录
  • 1.什么是模板匹配及模板匹配方法matchTemplate()
    • 介绍
    • 素材准备
  • 2.单模板匹配
    • 2.1 单目标匹配
    • 2.2 多目标匹配
  • 3.多模板匹配

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图像模板匹配的资料请关注我们其它相关文章!

(0)

相关推荐

  • python计算机视觉opencv图像金字塔轮廓及模板匹配

    目录 1.图像金字塔 ①高斯金字塔 ②拉普拉斯金字塔 2.图像轮廓 ①寻找轮廓 ②轮廓特征 ③轮廓绘制 3.模板匹配 ①模板匹配 ②匹配框线绘制 ③多对象匹配 4.直方图统计 ①直方图绘制 ②直方图统计 ③直方图的mask操作 ④直方图均衡化 5.傅里叶变换 1.图像金字塔 ①高斯金字塔 向下采样,数据会越来越少,减少的方式是:将偶数行和列删除 向上采样,数据会越来越多,将图像在每个方向上扩大为原来的两倍,新增的行和列用0来填充.使用先前同样的内核与放大后的图像卷积,获得近似值. 上采样之后,图

  • Python+Opencv实现图像匹配功能(模板匹配)

    本文实例为大家分享了Python+Opencv实现图像匹配功能的具体代码,供大家参考,具体内容如下 1.原理 简单来说,模板匹配就是拿一个模板(图片)在目标图片上依次滑动,每次计算模板与模板下方的子图的相似度,最后就计算出了非常多的相似度: 如果只是单个目标的匹配,那只需要取相似度最大值所在的位置就可以得出匹配位置: 如果要匹配多个目标,那就设定一个阈值,就是说,只要相似度大于比如0.8,就认为是要匹配的目标. 1.1 相似度度量指标 差值平方和匹配 CV_TM_SQDIFF 标准化差值平方和匹

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

    目录 1.什么是模板匹配及模板匹配方法matchTemplate() 介绍 素材准备 2.单模板匹配 2.1 单目标匹配 2.2 多目标匹配 3.多模板匹配 1.什么是模板匹配及模板匹配方法matchTemplate() 介绍 提供一个模板图像,一个目标图像,且满足模板图像是目标图像的一部分,从目标图像中寻找特定的模板图像的过程,即为模板匹配.OpenCV提供了matchTemplate()方法帮助我们实现模板匹配. 该方法语法如下: cv2.matchTemplate(image, templ

  • Python+Opencv实现图像模板匹配详解

    目录 引言 一.匹配方法 二.匹配单个对象 三.匹配多个对象 引言 什么是模板匹配呢? 看到这里大家是否会觉得很熟悉的感觉涌上心头!在人脸识别是不是也会看见 等等. 模板匹配可以看作是对象检测的一种非常基本的形式.使用模板匹配,我们可以使用包含要检测对象的“模板”来检测输入图像中的对象. 一.匹配方法 cv2.matchTemplate(img, templ, method) 参数:(img: 原始图像.temple: 模板图像.method: 匹配度计算方法) 方法如下: cv2.TM_SQD

  • Python+OpenCV实现图像识别替换功能详解

    OpenCV-Python是一个Python库,旨在解决计算机视觉问题. OpenCV是一个开源的计算机视觉库,1999年由英特尔的Gary Bradski启动.Bradski在访学过程中注意到,在很多优秀大学的实验室中,都有非常完备的内部公开的计算机视觉接口.这些接口从一届学生传到另一届学生,对于刚入门的新人来说,使用这些接口比重复造轮子方便多了.这些接口可以让他们在之前的基础上更有效地开展工作.OpenCV正是基于为计算机视觉提供通用接口这一目标而被策划的. 安装opencv pip3 in

  • Python+Opencv实战之人脸追踪详解

    目录 前言 人脸追踪技术简介 使用基于 dlib DCF 的跟踪器进行人脸跟踪 使用基于 dlib DCF 的跟踪器进行对象跟踪 小结 前言 人脸处理是人工智能中的一个热门话题,人脸处理可以使用计算机视觉算法从人脸中自动提取大量信息,例如身份.意图和情感:而目标跟踪试图估计目标在整个视频序列中的轨迹,其中只有目标的初始位置是已知的,将这两者进行结合将产生许多有趣的应用.由于外观变化.遮挡.快速运动.运动模糊和比例变化等多种因素,人脸追踪非常具有挑战性. 人脸追踪技术简介 基于判别相关滤波器 (d

  • Python OpenCV使用dlib进行多目标跟踪详解

    目录 1.使用dlib进行多目标跟踪 2.项目结构 3.dlib多对象跟踪的简单“朴素”方法 4.快速.高效的dlib多对象跟踪实现 5.完整代码 6.改进和建议 在本教程中,您将学习如何使用 dlib 库在实时视频中有效地跟踪多个对象. 我们当然可以使用 dlib 跟踪多个对象:但是,为了获得可能的最佳性能,我们需要利用多处理并将对象跟踪器分布在处理器的多个内核上. 正确利用多处理使我们能够将 dlib 多对象跟踪每秒帧数 (FPS) 提高 45% 以上! 1.使用 dlib 进行多目标跟踪

  • Python OpenCV之常用滤波器使用详解

    目录 1. 滤波器 1.1 什么是滤波器 1.2 关于滤波核 1.3 素材选择 2.均值滤波器 cv2.blur() 2.1 语法简介 2.2 代码示例 3. 中值滤波器 cv2.medianBlur() 代码示例 4. 高斯滤波器 cv2.GaussianBlur() 5. 双边滤波器 cv2.bilateralFilter() 1. 滤波器 1.1 什么是滤波器 滤波器是对图像做平滑处理 的一种常用工具. 平滑处理即在尽可能地保留原图像信息的情况下,对像素值进行微调,使邻近的像素值之间,值的

  • Python OpenCV实现图形检测示例详解

    目录 1. 轮廓识别与描绘 1.1 cv2.findComtours()方法 1.2 cv2.drawContours() 方法 1.3 代码示例 2. 轮廓拟合 2.1 矩形包围框拟合 - cv2.boundingRect() 2.2圆形包围框拟合 - cv2.minEnclosingCircle() 3. 凸包 绘制 4. Canny边缘检测 - cv2.Canny() 4.1 cv2.Canny() 用法简介 4.2 代码示例 5. 霍夫变换 5.1 概述 5.2 cv2.HoughLin

  • Python+OpenCV读写视频的方法详解

    目录 读视频,提取帧 接口函数:cv2.VideoCapture() 获取视频信息 使用set(cv2.CAP_PROP_POS_FRAMES)读取指定帧 读取函数(重点) 将图像写为视频 示例 fourcc 读视频,提取帧 接口函数:cv2.VideoCapture() 通过video_capture = cv2.VideoCapture(video_path)可以获取读取视频的句柄.而后再通过flag, frame = video_capture.read()可以读取当前帧,flag表示读取

  • Python Numpy,mask图像的生成详解

    什么是掩膜(mask) 在numpy中,有一个模块叫做ma,这个模块几乎复制了numpy里面的所有函数,当然底层里面都换成了对自己定义的新的数据类型MaskedArray的操作. 我们来看最基本的array定义. An array class with possibly masked values. Masked values of True exclude the corresponding element from any computation. MaskedArray是一个可能带有掩膜信

  • C++ OpenCV实现图像双三次插值算法详解

    目录 前言 一.图像双三次插值算法原理 二.C++ OpenCV代码 1.计算权重矩阵 2.遍历插值 3. 测试及结果 前言 近期在学习一些传统的图像处理算法,比如传统的图像插值算法等.传统的图像插值算法包括邻近插值法.双线性插值法和双三次插值法,其中邻近插值法和双线性插值法在网上都有很详细的介绍以及用c++编写的代码.但是,网上关于双三次插值法的原理介绍虽然很多,也有对应的代码,但是大多都不是很详细.因此基于自己对原理的理解,自己编写了图像双三次插值算法的c++ opencv代码,在这里记录一

随机推荐