本页提供了有关在 MMDetection3D 中使用 nuScenes 数据集的具体教程。
您可以在这里下载 nuScenes 3D 检测数据并解压缩所有 zip 文件。
像准备数据集的一般方法一样,建议将数据集根目录软链接到 $MMDETECTION3D/data
。
在我们处理之前,文件夹结构应按如下方式组织。
mmdetection3d
├── mmdet3d
├── tools
├── configs
├── data
│ ├── nuscenes
│ │ ├── maps
│ │ ├── samples
│ │ ├── sweeps
│ │ ├── v1.0-test
| | ├── v1.0-trainval
我们通常需要通过特定样式来使用 .pkl 或 .json 文件组织有用的数据信息,例如用于组织图像及其标注的 coco 样式。
要为 nuScenes 准备这些文件,请运行以下命令:
python tools/create_data.py nuscenes --root-path ./data/nuscenes --out-dir ./data/nuscenes --extra-tag nuscenes
处理后的文件夹结构应该如下
mmdetection3d
├── mmdet3d
├── tools
├── configs
├── data
│ ├── nuscenes
│ │ ├── maps
│ │ ├── samples
│ │ ├── sweeps
│ │ ├── v1.0-test
| | ├── v1.0-trainval
│ │ ├── nuscenes_database
│ │ ├── nuscenes_infos_train.pkl
│ │ ├── nuscenes_infos_trainval.pkl
│ │ ├── nuscenes_infos_val.pkl
│ │ ├── nuscenes_infos_test.pkl
│ │ ├── nuscenes_dbinfos_train.pkl
│ │ ├── nuscenes_infos_train_mono3d.coco.json
│ │ ├── nuscenes_infos_trainval_mono3d.coco.json
│ │ ├── nuscenes_infos_val_mono3d.coco.json
│ │ ├── nuscenes_infos_test_mono3d.coco.json
这里,.pkl 文件一般用于涉及点云的方法,coco 风格的 .json 文件更适合基于图像的方法,例如基于图像的 2D 和 3D 检测。
接下来,我们将详细说明这些信息文件中记录的细节。
nuscenes_database/xxxxx.bin
:训练数据集的每个 3D 包围框中包含的点云数据。nuscenes_infos_train.pkl
:训练数据集信息,每帧信息有两个键值: metadata
和 infos
。 metadata
包含数据集本身的基本信息,例如 {'version': 'v1.0-trainval'}
,而 infos
包含详细信息如下:
sweeps
是指没有标注的中间帧,而 samples
是指那些带有标注的关键帧)。
'CAM_FRONT'
, 'CAM_FRONT_RIGHT'
, 'CAM_FRONT_LEFT'
, 'CAM_BACK'
, 'CAM_BACK_LEFT'
, 'CAM_BACK_RIGHT'
。nuscenes_infos_train_mono3d.coco.json
:训练数据集 coco 风格的信息。该文件将基于图像的数据组织为三类(键值):'categories'
, 'images'
, 'annotations'
。
'id'
和 'name'
。i
。这里我们只解释训练信息文件中记录的数据。这同样适用于验证和测试集。
获取 nuscenes_infos_xxx.pkl
和 nuscenes_infos_xxx_mono3d.coco.json
的核心函数分别为 _fill_trainval_infos 和 get_2d_boxes。更多细节请参考 nuscenes_converter.py。
nuScenes 上基于 LiDAR 的 3D 检测(包括多模态方法)的典型训练流程如下。
train_pipeline = [
dict(
type='LoadPointsFromFile',
coord_type='LIDAR',
load_dim=5,
use_dim=5,
file_client_args=file_client_args),
dict(
type='LoadPointsFromMultiSweeps',
sweeps_num=10,
file_client_args=file_client_args),
dict(type='LoadAnnotations3D', with_bbox_3d=True, with_label_3d=True),
dict(
type='GlobalRotScaleTrans',
rot_range=[-0.3925, 0.3925],
scale_ratio_range=[0.95, 1.05],
translation_std=[0, 0, 0]),
dict(type='RandomFlip3D', flip_ratio_bev_horizontal=0.5),
dict(type='PointsRangeFilter', point_cloud_range=point_cloud_range),
dict(type='ObjectRangeFilter', point_cloud_range=point_cloud_range),
dict(type='ObjectNameFilter', classes=class_names),
dict(type='PointShuffle'),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(type='Collect3D', keys=['points', 'gt_bboxes_3d', 'gt_labels_3d'])
]
与一般情况相比,nuScenes 有一个特定的 'LoadPointsFromMultiSweeps'
流水线来从连续帧加载点云。这是此设置中使用的常见做法。
更多细节请参考 nuScenes 原始论文。
'LoadPointsFromMultiSweeps'
中的默认 use_dim
是 [0, 1, 2, 4]
,其中前 3 个维度是指点坐标,最后一个是指时间戳差异。
由于在拼接来自不同帧的点时使用点云的强度信息会产生噪声,因此默认情况下不使用点云的强度信息。
nuScenes 上基于图像的 3D 检测的典型训练流水线如下。
train_pipeline = [
dict(type='LoadImageFromFileMono3D'),
dict(
type='LoadAnnotations3D',
with_bbox=True,
with_label=True,
with_attr_label=True,
with_bbox_3d=True,
with_label_3d=True,
with_bbox_depth=True),
dict(type='Resize', img_scale=(1600, 900), keep_ratio=True),
dict(type='RandomFlip3D', flip_ratio_bev_horizontal=0.5),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle3D', class_names=class_names),
dict(
type='Collect3D',
keys=[
'img', 'gt_bboxes', 'gt_labels', 'attr_labels', 'gt_bboxes_3d',
'gt_labels_3d', 'centers2d', 'depths'
]),
]
它遵循 2D 检测的一般流水线,但在一些细节上有所不同:
RandomFlip3D
。使用 8 个 GPU 以及 nuScenes 指标评估的 PointPillars 的示例如下
bash ./tools/dist_test.sh configs/pointpillars/hv_pointpillars_fpn_sbn-all_4x8_2x_nus-3d.py checkpoints/hv_pointpillars_fpn_sbn-all_4x8_2x_nus-3d_20200620_230405-2fa62f3d.pth 8 --eval bbox
NuScenes 提出了一个综合指标,即 nuScenes 检测分数(NDS),以评估不同的方法并设置基准测试。
它由平均精度(mAP)、平均平移误差(ATE)、平均尺度误差(ASE)、平均方向误差(AOE)、平均速度误差(AVE)和**平均属性误差(AAE)**组成。
更多细节请参考其官方网站。
我们也采用这种方法对 nuScenes 进行评估。打印的评估结果示例如下:
mAP: 0.3197
mATE: 0.7595
mASE: 0.2700
mAOE: 0.4918
mAVE: 1.3307
mAAE: 0.1724
NDS: 0.3905
Eval time: 170.8s
Per-class results:
Object Class AP ATE ASE AOE AVE AAE
car 0.503 0.577 0.152 0.111 2.096 0.136
truck 0.223 0.857 0.224 0.220 1.389 0.179
bus 0.294 0.855 0.204 0.190 2.689 0.283
trailer 0.081 1.094 0.243 0.553 0.742 0.167
construction_vehicle 0.058 1.017 0.450 1.019 0.137 0.341
pedestrian 0.392 0.687 0.284 0.694 0.876 0.158
motorcycle 0.317 0.737 0.265 0.580 2.033 0.104
bicycle 0.308 0.704 0.299 0.892 0.683 0.010
traffic_cone 0.555 0.486 0.309 nan nan nan
barrier 0.466 0.581 0.269 0.169 nan nan
使用 8 个 GPU 在 nuScenes 上测试 PointPillars 并生成对排行榜的提交的示例如下
./tools/dist_test.sh configs/pointpillars/hv_pointpillars_fpn_sbn-all_4x8_2x_nus-3d.py work_dirs/hv_pointpillars_secfpn_6x8_160e_kitti-3d-3class/latest.pth 8 --out work_dirs/pp-nus/results_eval.pkl --format-only --eval-options 'jsonfile_prefix=work_dirs/pp-nus/results_eval'
请注意,在这里测试信息应更改为测试集而不是验证集。
生成 work_dirs/pp-nus/results_eval.json
后,您可以压缩并提交给 nuScenes 基准测试。更多信息请参考 nuScenes 官方网站。
我们还可以使用我们开发的可视化工具将预测结果可视化。更多细节请参考可视化文档。
NuScenesBox
和我们的 CameraInstanceBoxes
之间的转换。总的来说,NuScenesBox
和我们的 CameraInstanceBoxes
的主要区别主要体现在转向角(yaw)定义上。 NuScenesBox
定义了一个四元数或三个欧拉角的旋转,而我们的由于实际情况只定义了一个转向角(yaw),它需要我们在预处理和后处理中手动添加一些额外的旋转,例如这里。
另外,请注意,角点和位置的定义在 NuScenesBox
中是分离的。例如,在单目 3D 检测中,框位置的定义在其相机坐标中(有关汽车设置,请参阅其官方插图),即与我们的一致。相比之下,它的角点是通过惯例 定义的,“x 向前, y 向左, z 向上”。它导致了与我们的 CameraInstanceBoxes
不同的维度和旋转定义理念。一个移除相似冲突的例子是 PR #744。同样的问题也存在于 LiDAR 系统中。为了解决它们,我们通常会在预处理和后处理中添加一些转换,以保证在整个训练和推理过程中框都在我们的坐标系系统里。