You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从3D长方体顶点(8×3矩阵)计算目标检测边界框的中心、尺寸与偏航角

从3D长方体顶点计算中心、尺寸与偏航角

嘿,我来帮你拆解这三个计算步骤,都是3D目标检测里常用的操作,咱们一步步来:

1. 计算边界框中心坐标

这个是最直观的,不管长方体有没有旋转,它的几何中心就是所有顶点的算术平均值,或者更高效的方式——取每个坐标轴上极值的中点:

  • 遍历8个顶点,找出x坐标的最小值x_min和最大值x_max,同理得到y_min/y_maxz_min/z_max
  • 中心坐标(cx, cy, cz) = ((x_min+x_max)/2, (y_min+y_max)/2, (z_min+z_max)/2)

两种方法结果完全一致,选哪个都可以,后者不用遍历所有8个点求和,计算更快一点。

2. 计算边界框的真实尺寸(长宽高)

你提到的“对应顶点对的欧氏距离”思路是对的,但因为只有偏航旋转(绕y轴),长方体的三个边方向里,y轴方向是和世界坐标系对齐的,所以可以简化步骤:

  1. 随便选一个顶点P0,计算它到其他7个顶点的向量,找出距离最短的三个向量(这三个就是和P0共享边的相邻顶点对应的边向量)
  2. 这三个边向量里,有一个是沿y轴方向的(x、z分量接近0,因为偏航不影响y轴),它的长度就是长方体的高度h
  3. 剩下两个向量是长方体的宽度和长度方向(经过偏航旋转后的x'、z'轴),它们的长度就是宽度w长度l

给你一段伪代码参考(用numpy实现):

import numpy as np

# 假设vertices是8×3的顶点坐标矩阵
vertices = np.array([[x1,y1,z1], [x2,y2,z2], ..., [x8,y8,z8]])
p0 = vertices[0]
# 计算所有顶点到p0的向量
vecs = vertices - p0
# 计算向量长度,排序后取前三个非零的(排除自身)
lengths = np.linalg.norm(vecs, axis=1)
adjacent_idx = np.argsort(lengths)[1:4]
v1, v2, v3 = vecs[adjacent_idx]

# 找出沿y轴的向量(x-z平面模长接近0)
def is_y_axis_vec(vec):
    return np.linalg.norm(vec[[0,2]]) < 1e-6  # 浮点误差阈值

if is_y_axis_vec(v1):
    height = np.linalg.norm(v1)
    w_vec, l_vec = v2, v3
elif is_y_axis_vec(v2):
    height = np.linalg.norm(v2)
    w_vec, l_vec = v1, v3
else:
    height = np.linalg.norm(v3)
    w_vec, l_vec = v1, v2

width = np.linalg.norm(w_vec)
length = np.linalg.norm(l_vec)
# 最终尺寸可以按你需要的顺序输出,比如(width, height, length)

3. 计算偏航角(绕y轴的旋转角度)

因为只有偏航旋转,我们只需要看长方体在x-z平面的朝向即可:

  1. 从上面得到的宽度/长度向量里,取一个x-z平面的向量(比如w_vec的x和z分量组成的二维向量(wx, wz)
  2. atan2函数计算这个向量与世界参考轴(通常是z轴,对应前进方向)的夹角,这就是偏航角
  3. 注意atan2的参数顺序:如果参考轴是z轴,就用atan2(wx, wz),返回的是弧度值,转成角度的话乘以180/np.pi

伪代码示例:

# 提取x-z平面的向量分量
xz_vec = w_vec[[0, 2]]
# 计算偏航角(弧度),范围[-π, π]
yaw_rad = np.arctan2(xz_vec[0], xz_vec[1])
# 转成角度,范围[-180°, 180°]
yaw_deg = np.rad2deg(yaw_rad)
# 如果需要转成[0°, 360°]范围:
yaw_deg_360 = yaw_deg if yaw_deg >=0 else yaw_deg + 360

这里要注意不同3D检测框架的坐标系定义:如果你的框架用x轴作为前进方向,那就要调整atan2的参数为atan2(xz_vec[1], xz_vec[0]),可以根据实际情况验证调整。


内容的提问来源于stack exchange,提问作者John.Ludlum

火山引擎 最新活动