openCV——模板匹配

单模板匹配

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline 
def cvshow(name, ndarray):
    img = cv2.imshow(name, ndarray)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

模板匹配是指在当前图像 A 内寻找与图像 B 最相似的部分,一般将图像 A 称为输入图像,
将图像 B 称为模板图像。模板匹配的操作方法是将模板图像 B 在图像 A 上滑动,遍历所有像
素以完成匹配。

API

result = cv2.matchTemplate(image, templ, method[, mask ] )

  • image 为原始图像,必须是 8 位或者 32 位的浮点型图像。
  • templ 为模板图像。它的尺寸必须小于或等于原始图像,并且与原始图像具有同样的类型。
  • method 为匹配方法。有六种方法,如下图
  • mask 为模板图像掩模。它必须和模板图像 templ 具有相同的类型和大小。通常情况下该值使用默认值即可。当前,该参数仅支持 TM_SQDIFF 和 TM_CCORR_NORMED 两个值。
  • 返回值 result 是由每个位置的比较结果组合所构成的一个结果集,类型是单通道 32 位浮点型。如果输入图像(原始图像)尺寸是 WH,模板的尺寸是 wh,则返回值的大小为(W-w+1)*(H-h+1)。

在这里插入图片描述

下图是计算公式:
在这里插入图片描述

method 的值为 cv2.TM_SQDIFF 和 cv2.TM_SQDIFF_NORMED 时,result 值为 0 表示匹配度最好,值越大,表示匹配度越差;
method 的值为 cv2.TM_CCORR、cv2.TM_CCORR_NORMED、cv2.TM_CCOEFF和cv2.TM_CCOEFF_NORMED 时,result 的值越小表示匹配度越差,值越大表示匹配度越好

在查找最佳匹配时,首先要确定使用的是何种 method,然后再确定到底是查找最大值,还是查找最小值。查找最值(极值)与最值所在的位置,可以使用 cv2.minMaxLoc()函数实现。

minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc( src [, mask] )

  • src 为单通道数组。
  • minVal 为返回的最小值,如果没有最小值,则可以是 NULL(空值)。
  • maxVal 为返回的最大值,如果没有最小值,则可以是 NULL。
  • minLoc 为最大值的位置,如果没有最大值,则可以是 NULL。
  • maxLoc 为最大值的位置,如果没有最大值,则可以是 NULL。
  • mask 为用来选取掩模的子集,可选项。
lena = cv2.imread("lena.jpg")
template = cv2.imread("template.png")
# 模板匹配
res = cv2.matchTemplate(lena, template, cv2.TM_CCOEFF_NORMED)
# 相关系数则是值越大越匹配
minVal, maxVal, minLoc, maxloc = cv2.minMaxLoc(res)
img = cv2.rectangle(lena, (maxloc[0], maxloc[1]), (maxloc[0]+template.shape[1], maxloc[1]+template.shape[0]), (255, 0, 0), 2)
cvshow("lena", img)

Img = cv.rectangle( img, pt1, pt2, color[, thickness])

  • img 表示要标记的目标图像
  • pt1 是矩形的顶点
  • pt2 是 pt1 的对角顶点
  • color 是要绘制矩形的颜色或灰度级(灰度图像)
  • thickness 是矩形边线的宽度

多模板匹配

有些情况下,要搜索的模板图像很可能在输入图像内出现了多次,这时就需要想匹配多个结果,使用函数 cv2.minMaxLoc()是无法实现的,需要利用np.where()进行处理。要找出多个匹配结果。

a = np.arange(12).reshape(3, 4)
b = np.where(a>2)
print(a)
print(b)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
(array([0, 1, 1, 1, 1, 2, 2, 2, 2], dtype=int64), array([3, 0, 1, 2, 3, 0, 1, 2, 3], dtype=int64))

可以看出,np.where()返回值为一个元组,每个元素为一个array,array中的元素代表索引。因为a为二维矩阵,所以返回两个数组,一个代表行索引,一个代表列索引,行列索引一一匹配成一个坐标

函数 zip()用可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表

# 将原始图像扩充为4份进行多模板匹配
lena = cv2.imread("lena.jpg")
mid = np.hstack((lena, lena))
res = np.vstack((mid, mid))
cvshow("res", res)
# 读入模板
template = cv2.imread("template.png")
# 模板匹配
result = cv2.matchTemplate(res, template, cv2.TM_CCOEFF_NORMED)

width, height = template.shape[1], template.shape[0]

# 阈值筛选
filter = np.where(result>0.95)
# 打包行列索引对并遍历
for item in zip(*filter[::-1]):  #filter[::-1]表示行列数组互换位置,原来是第一个数组为行索引,第二个数组为列索引,但是列索引才表示x,行索引表示y
    print(item)
    cv2.rectangle(res, (item[0], item[1]), (item[0]+width, item[1]+height), (0, 255, 0), 1)
cvshow("res", res)
(127, 111)
(390, 111)
(127, 374)
(390, 374)

其实按这个道理来说,应该会有很多区域可以匹配成功,但是每个图象里怎么就一个框呢?其实是都画出来了,尤其是最相似的区域里有很多框,只不过都重合在一起了,框的线条粗细才1,可以把阈值调低看框是不是会变很粗


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenCV模板匹配是基于OpenCV库中的模板匹配技术而发展出来的一种方法,可以同时匹配多个模板并识别它们在图像中的位置。这种技术被广泛应用于机器人视觉领域、物体识别和追踪等方面,可以增强图像处理系统对目标的检测和识别能力。 与传统的模板匹配技术相比,多模板匹配更加灵活和高效。它可以一次性加载多个模板,并对它们在图像中出现的次数和位置进行统计。采用该技术进行图像处理时,可以更加精确地识别和分析图像中的目标对象,提高图像处理的准确性和效率。 OpenCV模板匹配的实现原理是基于图像的卷积运算。首先,将多个模板分别加载到内存中,然后在待处理的图像上进行滑动窗口搜索。对于每一个滑动窗口,将其与所有模板进行卷积运算,得到一组匹配度的值,然后从中选取最大值作为匹配结果。最后,将所有匹配结果按照匹配度从大到小进行排序,即可得到多个模板在图像中的位置信息。 总的来说,OpenCV模板匹配是一种强大的图像处理技术,可以快速高效地匹配多个目标,并准确地标记出目标的位置。它在机器视觉、自动化生产线、机器人应用等领域都具有广泛的应用前景。 ### 回答2: OpenCV模板匹配是一种用于在图像中查找多个模板位置的技术。该技术使用多个模板图像,从待匹配图像中找到它们的精确位置。 在多模板匹配中,需要先准备好多个模板图像。然后使用OpenCV中的模板匹配功能分别对每个模板图像进行匹配。常用的匹配算法有两种:SAD匹配和SSD匹配。 在SAD匹配中,对于每个像素位置,计算模板中的像素值与待匹配图像中的像素值之间的差值的绝对值之和。其中,差值越小说明匹配度越高。 在SSD匹配中,对于每个像素位置,计算模板中的像素值与待匹配图像中的像素值之间的差值的平方和。其中,差值越小说明匹配度越高。 无论使用哪种算法,最终得到一个匹配矩阵。匹配矩阵中的每个元素代表着待匹配图像中对应位置与模板图像匹配的程度。最后,可以通过设置一个阈值来确定哪些匹配位置是有效的。 需要注意的是,多模板匹配需要足够的计算资源和时间,因为要对多个模板进行匹配。同时,如果模板之间相似度较高,可能会出现匹配位置重叠或匹配不准确的情况。因此,在应用中需要进行适当的优化和调节。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值