一、 概念
模板匹配就是用模板图(通常是一个小图)在目标图像(通常是一个比模板图大的图片)中不断的滑动 比较,通过某种比较方法来判断是否匹配成功。
二、应用场景
1. 目标检测与识别:在计算机视觉领域,模板匹配常用于目标检测与识别。 通过提前准备好的模板图像,可以在输入图像或视频流中识别出具有相似 特征的目标物体,从而实现目标检测与识别。
2. 视频分析与目标跟踪:在视频分析中,模板匹配可用于实现目标物体的跟 踪与追踪。借助模板匹配算法,可以在视频序列中追踪目标物体的运动轨 迹,实现目标跟踪功能。
三、匹配方法
3.1、平方差匹配TM_SQDIFF
以模板图与目标图所对应的像素值使用平方差公式来计算,其结果越小,代表匹配程度越高。
3.2、归一化平方差匹配TM_SQDIFF_NORMED
与平方差匹配类似,只不过需要将值统一到0到1,计算结果越小,代表匹配程度越高
3.3、相关匹配TM_CCORR
使用对应像素的乘积进行匹配,乘积的结果越大其匹配程度越高
3.4、归一化相关匹配TM_CCORR_NORMED
与相关匹配类似,只不过是将其值统一到0到1之间,值越大,代表匹配程度越高
3.5、相关系数匹配TM_CCOEFF
需要先计算模板与目标图像的均值,然后通过每个像素与均值之间的差的乘积再求和来表示其匹配程 度,1表示完美的匹配,-1表示最差的匹配
3.6、归一化相关系数匹配TM_CCOEFF_NORMED
也是将相关系数匹配的结果统一到0到1之间,值越接近1代表匹配程度越高
四、绘制轮廓
导入模块
import cv2
import numpy as np
输入图像
img = cv2.imread('mali.png')
img_template = cv2.imread('jinbi.png')
灰度化
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_template_gray = cv2.cvtColor(img_template, cv2.COLOR_BGR2GRAY)
模板匹配
res = cv2.matchTemplate(img_gray, img_template_gray, cv2.TM_CCOEFF_NORMED)
筛选数据
threshold = 0.73
location = np.where(res > threshold)
绘制轮廓
for i in zip(*location[::-1]):
right_bottom = (i[0] + w, i[1] + h)
cv2.rectangle(img, i, right_bottom, (0, 0, 255))
输出图像
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
完整代码
import cv2
import numpy as np
# 读取原始图像
img = cv2.imread('mali.png')
# 读取模板图像
img_template = cv2.imread('jinbi.png')
# 将原始图像转换为灰度图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 将模板图像转换为灰度图像
img_template_gray = cv2.cvtColor(img_template, cv2.COLOR_BGR2GRAY)
# 获取模板灰度图像的高度(h)和宽度(w)
h, w = img_template_gray.shape
# 在原始灰度图像中执行模板匹配
res = cv2.matchTemplate(img_gray, img_template_gray, cv2.TM_CCOEFF_NORMED)
# 设置匹配的阈值,只有大于该值的匹配才会被考虑
threshold = 0.73
# 找到所有匹配结果的位置
location = np.where(res > threshold)
# 在每个匹配位置绘制矩形框
for i in zip(*location[::-1]): # 反转位置元组(从列开始)
right_bottom = (i[0] + w, i[1] + h) # 计算矩形的右下角坐标
cv2.rectangle(img, i, right_bottom, (0, 0, 255), thickness=2) # 绘制红色矩形框
# 显示带有矩形框的图像
cv2.imshow('img', img)
# 等待用户按键
cv2.waitKey(0)
# 关闭所有OpenCV窗口
cv2.destroyAllWindows()
疑难解读
np.where(res > threshold)
np.where 返回的是一个包含多维数组索引的元组。对于二维图像(如模板匹配的结果),返回的 location 是一个元组,包含两个数组:一个是所有行坐标,一个是所有列坐标。
zip(*location[::-1])
location[::-1]:
这个操作是用来反转元组的顺序。元组的格式是 (行数组, 列数组),反转之后会成为 (列数组, 行数组),这样做是为了确保接下来的 zip 操作可以正确地将坐标组合成元组。zip(*location[::-1]):
zip 函数用于将多个可迭代对象的元素组合成元组。在这里,* 运算符用于解包 location[::-1],把反转后的元组传入到 zip 函数中。
五、库函数
5.1、matchTemplate()
cv.matchTemplate( image, templ, method[, result[, mask]] ) -> result
方法 | 描述 |
---|---|
image | 运行搜索的图像。它必须是 8 位或 32 位浮点。 |
templ | 搜索到的模板。它必须不大于源图像,并且具有相同的数据类型。 |
result | 比较结果的映射。它必须是单通道 32 位浮点 |
method | 指定比较方法的参数,请参阅 TemplateMatchModes |
mask | 可选掩码。它的大小必须与 templ 相同。它必须具有与模板相同的通道数,或者只有一个通道,然后用于所有模板和图像通道。如果数据类型为 CV_8U,则掩码将被解释为二进制掩码,这意味着仅使用 mask 为非零的元素,并且这些元素保持不变,与实际掩码值无关(权重等于 1)。对于数据 tpye CV_32F,掩码值用作权重。确切的公式记录在 TemplateMatchModes 中。 |
5.2、np.where()
numpy.where 是 NumPy 库中的一个非常有用的函数,它可以根据指定的条件返回 满足该条件的元素的索引。
当 numpy.where 接受一个条件作为参数时,它会返回一个元组,其中包含满足该条 件的元素的索引。
numpy.where(condition)
函数 | 说明 |
---|---|
condition | 一个布尔数组或条件表达式。 |
返回值 |
---|
一个元组,其中包含满足条件的元素的索引。 |
详情查看