855 字
4 分钟
OpenCV:模板匹配

1. 介绍#

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

模板匹配

2. 单目标匹配#

2.1 使用方法#

  • 通过函数cv2.matchTemplate()实现模板匹配
  • 函数原型ret = cv2.matchTemplate( image, template, method, mask )
  • 参数说明
    • image原始图像,必须是8位或者32位浮点型图像
    • template模板图像尺寸必须小于或等于原始图像,并且与原始图像具有同样的类型。
    • method匹配方法
    • mask:模板图像掩模
    • ret:由每个位置的比较结果组合所构成的一个结果集,类型是单通道、32位浮点型
      • 如果输入图像尺寸是 W * H,模板的尺寸是 w * h, 则返回值的大小为(W - w + 1) * (H - h + 1)。
参数值说明
cv2.TM_SQDIFF0以方差为依据进行匹配。若完全匹配,则结果为零;若不匹配,则会得到一个很大的值
cv2.TM_SQDIFF_NORMED1以标准(归一化)方差为依据进行匹配。
cv2.TM_CCORR2相关匹配。将模板图像与输入图像相乘,如果乘积较大,表示匹配程度较高;如果乘积为 0,则表示匹配效果最差
cv2.TM_CCORR_NORMED3以标准(归一化)相关为依据进行匹配。
cv2.TM_CCOEFF4相关系数匹配。将模板图像与其均值的相对值,和输入图像与其均值的相关值进行匹配。1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性。
cv2.TM_CCOEFF_NORMED5以标准(归一化)相关系数为依据进行匹配。
提醒

查找最佳匹配时,首先要确定使用的是何种方法,然后再确定到底是查找最大值,还是查找最小值

2.2 示例#

最小值方案:cv2.TM_SQDIFF#

import cv2
img = cv2.imread('rice.png')
template = cv2.imread('template.png')
th, tw, tc = template.shape
rv = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(rv)
topLeft = minLoc
bottomRight = (topLeft[0] + tw, topLeft[1] + th)
# print(topLeft)
cv2.rectangle(img, topLeft, bottomRight, [0, 0, 255], 2)
cv2.imwrite("detect_TM_SQDIFF.png", img)
原图目标位置匹配

最大值方案:cv2.TM_CCOEFF#

import cv2
img = cv2.imread('rice.png')
template = cv2.imread('template.png')
th, tw, tc = template.shape
rv = cv2.matchTemplate(img, template, cv2.TM_CCOEFF)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(rv)
topLeft = maxLoc
bottomRight = (topLeft[0] + tw, topLeft[1] + th)
# print(topLeft)
cv2.rectangle(img, topLeft, bottomRight, [0, 255, 255], 2)
cv2.imwrite("detect_TM_CCOEFF.png", img)
原图目标位置匹配

3. 多目标匹配#

  • 单目标匹配模板图像在整个输入图像内仅出现了一次
  • 多目标匹配模板图像很可能在输入图像内出现多次,需要找出多个匹配结果。

3.1 使用方法#

  • 通过函数np.where()获取满足条件的模板匹配位置的集合
  • 通过函数zip()将对象中对应的元素打包成坐标元组
  • 行列互换:函数cv2.matchTemplate()输出值的形式为 (行号,列号) ,在使用函数np.where()过滤信息后,需要进行行列互换操作——[::-1],将形式转换为 (列号,行号) 以便绘图需要。

3.2 示例#

import cv2
import numpy as np
img = cv2.imread('rices.png')
template = cv2.imread('template.png')
th, tw, tc = template.shape
rv = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.975
loc = np.where( rv >= threshold )
for pt in zip(*loc[::-1]):
# print(pt)
cv2.rectangle(img, pt, (pt[0] + tw, pt[1] + th), [0, 255, 0], 1)
cv2.imwrite("detect_TM_CCOEFF_NORMED.png", img)
原图目标位置匹配
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00