文章目录
- 前言
- 1.导入库
- 2.图片预处理
- 3.输出模板图片的宽和高
- 4.模板匹配
- 5.获取匹配结果中所有符合阈值的点的坐标
- 5.1 threshold = 0.9:
- 5.2 loc = np.where(res >= threshold):
- 6.遍历所有匹配点
- 6.1 loc 的结构回顾
- 6.2 loc[::-1] 的作用
- 6.2.1 为什么需要反转?
- 6.3 zip(*loc[::-1]) 的作用
- 7.画出模板匹配矩形框
- 7.1 功能
- 7.2 参数详解
- 7.3 关键细节
- 7.4 常见问题
- 8.运行结果
- 9. 总结
前言
上文《OpenCV 模板匹配方法详解》我们详细介绍了模板匹配这一方法,本文我们来介绍一下模板与多个对象匹配的方法。
其中有很多的函数需要我们来详细介绍,接下来我们直接看代码讲解:
1.导入库
import cv2
import numpy as np
- 导入opencv库和numpy库
2.图片预处理
img_rgb = cv2.imread("image.jpg")
img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
template = cv2.imread("tem.jpg",0)
- 导入图片,并转化为灰度图
- 导入的图片如下图所示,左图为匹配图片,右图为模板图片
3.输出模板图片的宽和高
h,w = template.shape[:2]
- template.shape:假设 template 是一个 NumPy 数组(通常是图像数据),.shape 属性会返回数组的维度信息。
- 对于图像:通常返回 (高度, 宽度, 通道数),如果是灰度图则只有 (高度, 宽度)
- [:2]:切片操作,取前两个元素
- 例如对于彩色图像 (480, 640, 3),取前两个值得到 (480, 640)
- h, w = …:元组解包
- 将前两个值分别赋值给变量 h (height/高度) 和 w (width/宽度)
所以这行代码的作用是:获取模板图像的高度和宽度,分别存入变量 h 和 w 中。
4.模板匹配
# 使用模板匹配方法 cv2.matchTemplate 进行模板匹配
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
功能:
- 模板匹配:在 img_gray(灰度图像)中滑动 template(模板图像),计算每个位置的 相似度,并返回一个 相似度矩阵 res。
- 匹配方法:cv2.TM_CCOEFF_NORMED 是 归一化相关系数匹配,取值范围 [-1, 1],越接近 1 表示匹配度越高。
返回值 res:
- res 是一个 二维浮点型数组,大小 = (img_h - template_h + 1, img_w - template_w +1)(因为模板不能超出原图边界)
- 每个 res[y, x] 表示模板在 (x, y) 处的匹配得分。
5.获取匹配结果中所有符合阈值的点的坐标
# 设定匹配阈值
threshold = 0.9
# 获取匹配结果中所有符合阈值的点的坐标
loc = np.where(res >= threshold) #(符合条件的行,符合条件的列)
5.1 threshold = 0.9:
功能:
- 设定一个 匹配阈值,只有 res 中 ≥ 0.9 的点才被认为是有效匹配。
调整建议:
- 阈值越高(如 0.95),匹配越严格,漏检率可能增加。
- 阈值越低(如 0.8),匹配越宽松,但可能误检。
5.2 loc = np.where(res >= threshold):
功能:
- 查找所有匹配度 ≥ threshold 的坐标,返回它们的 行列索引。
- loc 是一个 元组,包含两个数组:
-
loc[0]:所有匹配点的 Y 坐标(行索引)
-
loc[1]:所有匹配点的 X 坐标(列索引
示例
假设 res 如下:
res = [[0.1, 0.3, 0.7],[0.8, 0.95, 0.6], # (1,1) = 0.95 ≥ 0.9[0.4, 0.9, 0.2] # (2,1) = 0.9 ≥ 0.9
]
执行 loc = np.where(res >= 0.9) 后:
loc = (array([1, 2]), array([1, 1])) # 匹配点:(Y=1,X=1), (Y=2,X=1)
注意:loc 是一个元组,格式为 (y_coords, x_coords),所以先返回的是Y值,再返回的是X值!!!
6.遍历所有匹配点
for pt in zip(*loc[::-1]):
这段代码 for pt in zip(*loc[::-1]): 是 模板匹配后处理 的关键部分,用于遍历所有匹配到的目标位置,并调整坐标顺序以适应 OpenCV 的绘图要求。下面详细解析它的作用:
6.1 loc 的结构回顾
在之前的代码中:
loc = np.where(res >= threshold)
- loc 是一个元组,格式为 (y_coords, x_coords),所以先返回的是Y值,再返回的是X值
6.2 loc[::-1] 的作用
loc[::-1] 的作用loc[::-1] 对元组进行 反向切片,将 (y_coords, x_coords) 变成 (x_coords, y_coords)。
例如:
loc = (array([1, 2]), array([3, 4]))
loc[::-1] = (array([3, 4]), array([1, 2]))
# 现在顺序是 (x, y)
6.2.1 为什么需要反转?
- OpenCV 的坐标系统使用 (x, y)(列在前,行在后),而 np.where() 返回的是 (y, x),因此需要交换顺序。
6.3 zip(*loc[::-1]) 的作用
- *loc[::-1] 解包 元组,相当于
zip(array([3, 4]), array([1, 2]))
- zip() 将两个数组按元素配对,生成可迭代的 (x, y) 坐标对
for pt in zip(*loc[::-1]):print(pt) # 输出:(3, 1), (4, 2)
最终效果:
遍历所有匹配点,每次循环的 pt 是一个 (x, y) 坐标元组,可以直接用于 OpenCV 绘图函数(如 cv2.rectangle())。
7.画出模板匹配矩形框
cv2.rectangle(img_rgb,pt,(pt[0] + w,pt[1] + h),(0,0,255),1)
这段代码 cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1) 是 OpenCV 中用于在图像上绘制矩形的函数,具体含义如下:
7.1 功能
在图像 img_rgb 上,以 pt 为左上角起点,绘制一个 宽度为 w、高度为 h 的红色矩形框,边框粗细为 1 像素。
7.2 参数详解
参数 | 含义 | 示例 |
---|---|---|
img_rgb | 要绘制矩形的目标图像(RGB 格式) | 从 cv2.imread()读取的图像 |
pt | 矩形的 左上角坐标 (x, y) | (50, 100) 表示从图像的第 50 列、第 100 行开始 |
(pt[0] + w, pt[1] + h) | 矩形的 右下角坐标 | 如果 pt=(50,100),w=30,h=20,则右下角是 (80, 120) |
(0, 0, 255) | 矩形颜色(BGR 格式) | (0,0,255)表示纯红色 |
1 | 矩形边框的粗细(像素) | 1 表示 1 像素宽,-1表示填充矩形 |
7.3 关键细节
-
坐标顺序
- OpenCV 使用 (x, y) 坐标,其中:
- x 是水平方向(列索引,从左到右递增)
- y 是垂直方向(行索引,从上到下递增)
- OpenCV 使用 (x, y) 坐标,其中:
-
颜色格式
- (0, 0, 255) 是 BGR 格式(不是 RGB),所以这里表示红色。
- 常见颜色示例:
- 红色:(0, 0, 255)
- 绿色:(0, 255, 0)
- 蓝色:(255, 0, 0)
-
矩形尺寸
- w 和 h通常是模板图像的宽度和高度(通过 template.shape[:2] 获取)。
- 如果 w 或 h 超出图像边界,OpenCV 会报错。
7.4 常见问题
-
为什么矩形颜色不对?
- 检查颜色是否是 BGR 格式,例如红色应为 (0, 0, 255),而非 RGB 的 (255, 0, 0)。
-
如何调整矩形样式?
- 修改参数:
- 边框粗细:2 表示更粗的边框,-1 表示填充矩形。
- 颜色:(255, 0, 0) 是蓝色,(0, 255, 0) 是绿色。
- 修改参数:
8.运行结果
9. 总结
到这里本篇博客就结束啦,感谢大家的阅读!最近一直在坚持每天写博客,当作是一个叙说心得的地方,在这个过程中自己通过不断的回顾之前所学习的内容,发现很多细节地方之前都没有注意到,通过再一次的回顾,增添了很多收获,这真的就是“温故而知新”这句话现实化了。最后,希望大家能一直朝着自己理想的方向努力。越努力,越幸运!!!