OpenCV 模板与多个对象匹配方法详解(继OpenCV 模板匹配方法详解)

发布于:2025-04-21 ⋅ 阅读:(70) ⋅ 点赞:(0)

前言

上文《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 关键细节

  1. 坐标顺序

    • OpenCV 使用 (x, y) 坐标,其中:
      • x 是水平方向(列索引,从左到右递增)
      • y 是垂直方向(行索引,从上到下递增)
  2. 颜色格式

    • (0, 0, 255)BGR 格式(不是 RGB),所以这里表示红色。
    • 常见颜色示例:
      • 红色:(0, 0, 255)
      • 绿色:(0, 255, 0)
      • 蓝色:(255, 0, 0)
  3. 矩形尺寸

    • w 和 h通常是模板图像的宽度和高度(通过 template.shape[:2] 获取)。
    • 如果 w 或 h 超出图像边界,OpenCV 会报错。

7.4 常见问题

  1. 为什么矩形颜色不对?

    • 检查颜色是否是 BGR 格式,例如红色应为 (0, 0, 255),而非 RGB 的 (255, 0, 0)。
  2. 如何调整矩形样式?

    • 修改参数:
      • 边框粗细:2 表示更粗的边框,-1 表示填充矩形。
      • 颜色:(255, 0, 0) 是蓝色,(0, 255, 0) 是绿色。

8.运行结果

在这里插入图片描述

9. 总结

到这里本篇博客就结束啦,感谢大家的阅读!最近一直在坚持每天写博客,当作是一个叙说心得的地方,在这个过程中自己通过不断的回顾之前所学习的内容,发现很多细节地方之前都没有注意到,通过再一次的回顾,增添了很多收获,这真的就是“温故而知新”这句话现实化了。最后,希望大家能一直朝着自己理想的方向努力。越努力,越幸运!!!


网站公告

今日签到

点亮在社区的每一天
去签到