参考:带你玩转 3D 检测和分割 (二):核心组件分析之坐标系和 Box - 知乎
激光雷达坐标系通常定义如下左图所示,其中指向前方,指向左方,指向上方。
相机坐标系通常定义如上右图所示,其中指向右方,指向下方,指向前方。
一般来说,对于自动驾驶目标检测任务而言,一个3D边界框可以由7个参数决定:位置、尺寸以及朝向角/偏航角/旋转角。
一般将与物体朝向平行的棱的长度记为边界框长度,竖直方向棱的长度记为边界框高度,余下一组棱的长度记为边界框宽度,如下左图所示。
将边界框绕高度轴(对于激光雷达坐标系,高度轴为轴;对于相机坐标系,高度轴为轴)旋转到朝向与轴正方向相同时,边界框与坐标轴平行的3组棱对应的长度分别记为。
对于激光雷达坐标系下的边界框,其即为(如上中图所示);则对于相机坐标系下的边界框,其即(如上右图所示)。
朝向角为边界框绕高度轴的旋转角度(从轴正向与边界框朝向之间的角度),其正负按照右手螺旋定则确定。
从激光雷达坐标系到相机坐标系:
角度的变换是由于两个坐标系中,的基准轴轴并不是同一个(相差90度),且由于相机坐标系高度轴正方向向下, 故角度增大的方向从上向下看是顺时针,与激光雷达坐标系中相反。
注意:上述旋转角的变换的前提条件是,相机坐标系轴与激光雷达坐标系轴朝向相同(多数情况下均符合此条件)。
后续内容是MMDetection3D的相关概念、函数和数据类型的介绍。若只是想了解3D目标检测的坐标系和边界框,则无需继续往下看。
在MMDetection3D一些边界框相关的函数中(如2.3节的函数),存在origin参数,这个origin表示边界框位置坐标对应的那个点在边界框中的相对位置。
具体来说,在坐标系下先旋转3D边界框到朝向角为0,然后将其缩放为单位正方体,并平移到第一象限,使其一个角点位于坐标系原点,与角点相邻的三条棱分别与三个坐标轴重合。此时边界框位置坐标也相应地被变换到某处,其变换后的坐标即为origin。
举例来说,一般的数据集会使用边界框底面中心坐标作为边界框的位置坐标,则在激光雷达坐标系下,origin应设为(0.5,0.5,0),如下左图所示:
而在相机坐标系下,origin应设为(0.5,1,0.5),如上右图所示。
mmdet3d/core/bbox/box_np_ops.py中有很多与边界框相关的函数,这些函数通常会在数据准备的相关代码中看到。
目的是去除图像视锥外的点云,仅保留能投影到图像范围内的那些点。
目的是将相机坐标系下的边界框参数变换为激光雷达坐标系下的参数。
该函数的原理见1.3节。
注意:该函数默认相机坐标系轴和激光雷达坐标系轴同向;若坐标系不完全对齐(如View-of-Delft数据集),若输入该函数的旋转角定义为绕激光雷达轴的旋转角(朝向激光雷达轴时角度为0),则也可使用该函数。
目的是统计各点是否落在每个边界框内。
目的是将边界框的位置、尺寸、朝向角参数转换为边界框的8个角点坐标。
注意:所有边界框参数、origin以及旋转轴应对应同一坐标系。
目的是将相机坐标系下的点云坐标转换到图像坐标系下。
目的是将相机坐标系下的点云坐标转换到图像坐标系下。
图像坐标系下的点云(若输出包含深度信息则为,前两维为像素坐标,最一维为深度;否则输出为,为像素坐标)。
注:上述维度中的 “ ” 代表任意多个维度,如可以为或等。
mmdet3d提供了定义好的边界框数据类型LiDARPoints(位于mmdet3d/core/points/lidar_points.py下)和CameraPoints(位于mmdet3d/core/points/camera_points.py下),分别是激光雷达坐标系下的点云以及相机坐标系下的点云数据类型。一些方法已经内置于数据结构中,可直接调用。
以LiDARPoints为例,首先需要创建该类的实例:
# 设pts为(N,C)的Tensor,表示N个C维的点(C>=3),其中前三个维度分别是x,y,z坐标
pts = LiDARPoints(pts, points_dim=C)
然后可以直接调用flip/rotate等数据增广方法以及坐标变换方法。
mmdet3d提供了定义好的边界框数据类型LiDARInstance3DBoxes(位于mmdet3d/core/bbox/structure/lidar_box3d.py下)以及CameraInstance3DBoxes(位于mmdet3d/core/bbox/structure/cam_box3d.py下),分别是激光雷达坐标系下的3D边界框以及相机坐标系下的3D边界框数据类型,许多方法已经内置于数据结构中,可直接调用。
以LiDARInstance3DBoxes类为例,首先需要创建该类的实例:
# 设bboxes为大小(M,7)的Tensor,其中M为边界框数量,7代表x,y,z坐标,x,y,z尺寸以及朝向角,若有速度等其它参数,需放置在最后
bboxes = LiDARInstance3DBoxes(bboxes)
# 另有三项输入box_dim(每个边界框的参数数量),with_yaw(包含朝向角为True)和origin(含义见前文介绍,指示3D坐标在边界框中的相对位置)
# 可使用默认值box_dim=7, with_yaw=True, origin=(0.5, 0.5, 0),
注意:对于边界框的朝向角,LiDARInstance3DBoxes是绕激光雷达坐标系轴定义的,而CameraInstance3DBoxes是绕相机坐标系轴定义的。
然后可以直接调用如下方法(没有全部介绍):
调用上述方法的代码如下(以gravity_center为例):
bboxes_centers = bboxes.gravity_center