- 人工智能
- 计算机视觉
- 深度学习
- 自动驾驶
【免费下载链接】mmdetection3d
OpenMMLab's next-generation platform for general 3D object detection.
本文是 MMDetection3D 中 LiDAR-based 3D 检测(点云 3D 目标检测)任务的完整实战指南。我们将以 PointPillars 模型在 KITTI 数据集上的标准流程为主线,逐步讲解数据准备、分布式训练、定量评估、在线测试提交与可视化验证的完整链路。读完本文,你将能够独立完成一个点云 3D 检测模型的从数据到部署评估的全流程,并理解背后各环节的源码实现原理。
LiDAR 3D 检测任务概述
LiDAR-based 3D detection 是 MMDetection3D 支持的最基础任务之一。该任务要求模型以激光雷达采集的任意数量点云(每个点通常携带 x、y、z 坐标与反射强度等特征)作为输入,为每个感兴趣目标预测 3D 边界框(位置、尺寸、朝向)与类别标签。
从仓库代码结构看,该任务的核心实现覆盖了 检测器(detectors)、点云骨干网络(backbones)、3D 密集检测头(dense_heads) 与 3D 边界框数据结构(structures/bbox_3d) 等多个模块。PointPillars 是最具代表性的入门模型之一,其配置位于 PointPillars 配置目录,对应的 KITTI 三类别(Pedestrian / Cyclist / Car)完整配置为 pointpillars_hv_secfpn_8xb6-160e_kitti-3d-3class.py,下文所有实操均以该配置为例展开。
数据准备:从原始 KITTI 数据到标准目录与信息文件
第一步:下载原始数据并组织目录
首先需要下载 KITTI 3D 检测原始数据(包括velodyne点云、calib标定文件、image_2图像与label_2标注),并按 数据准备文档 中给出的标准方式重组目录。注意:KITTI 数据集还需要额外的.txt分割文件(ImageSets),用于划分 train / val / test 子集。
数据分割文件的准备方式如下(详见 数据准备文档):
mkdir ./data/kitti/ && mkdir ./data/kitti/ImageSets # 下载 4 个分割文件(test / train / val / trainval) wget -c ... -O ./data/kitti/ImageSets/test.txt wget -c ... -O ./data/kitti/ImageSets/train.txt wget -c ... -O ./data/kitti/ImageSets/val.txt wget -c ... -O ./data/kitti/ImageSets/trainval.txt此外,也可以使用mim download mmdet3d --dataset kitti一键下载并预处理数据(需要先安装 OpenDataLab CLI 并登录)。
第二步:用 create_data.py 生成数据信息文件
由于不同数据集的原始数据组织方式差异较大,MMDetection3D 通常需要用一个.pkl文件统一收集有用的数据信息。原始数据就绪后,需要运行 tools/create_data.py 中对应数据集的脚本生成 data infos。对 KITTI 而言,命令为:
python tools/create_data.py kitti --root-path ./data/kitti --out-dir ./data/kitti --extra-tag kitti从 tools/create_data.py 的源码可以看到,kitti_data_prep内部依次完成四件事:
- 调用
kitti.create_kitti_info_file依据 ImageSets 分割生成 train / val / trainval / test 四份 infos pkl; - 调用
kitti.create_reduced_point_cloud生成velodyne_reduced(采样降密后的点云,KITTI 官方评估仅使用降密点云的前 100 行左右的点); - 调用
update_pkl_infos将 infos 升级为 v2 格式(兼容 MMDetection3D 新版数据结构); - 调用
create_groundtruth_database构建 GT 数据库(用于训练期的ObjectSample数据增强)。
命令中三个参数的含义为:--root-path指定原始数据根目录,--out-dir指定 pkl 输出目录,--extra-tag指定 infos 文件名的前缀(此处为kitti)。若环境使用 slurm 调度,可改用sh tools/create_data.sh <partition> kitti。
第三步:核对生成后的目录结构
命令执行完毕后,data/kitti下应包含如下结构(与 数据准备文档 描述一致):
mmdetection3d ├── mmdet3d ├── tools ├── configs ├── data │ ├── kitti │ │ ├── ImageSets │ │ ├── testing │ │ │ ├── calib │ │ │ ├── image_2 │ │ │ ├── velodyne │ │ │ ├── velodyne_reduced │ │ ├── training │ │ │ ├── calib │ │ │ ├── image_2 │ │ │ ├── label_2 │ │ │ ├── velodyne │ │ │ ├── velodyne_reduced │ │ ├── kitti_gt_database │ │ ├── kitti_infos_train.pkl │ │ ├── kitti_infos_trainval.pkl │ │ ├── kitti_infos_val.pkl │ │ ├── kitti_infos_test.pkl │ │ ├── kitti_dbinfos_train.pkl其中kitti_infos_*.pkl记录每帧数据的点云路径、标定参数、图像信息与 3D/2D 标注,训练时由 KittiDataset 加载;kitti_gt_database与kitti_dbinfos_train.pkl则用于训练期的 GT 采样增强(对应配置中的db_sampler)。如果你不需要重新生成、也可以直接下载仓库提供的现成标注文件放置到data/kitti/;但若要使用ObjectSample增强,仍需额外执行--only-gt-database模式生成 GT 数据库:
python tools/create_data.py kitti --root-path ./data/kitti --out-dir ./data/kitti --extra-tag kitti --only-gt-database训练:以 PointPillars 配置启动分布式训练
单机多卡启动命令
数据就绪后,即可用仓库提供的配置训练 PointPillars。不同 GPU 规模的训练方式可参考 训练与测试教程。假设我们在单机 8 卡上进行分布式训练:
./tools/dist_train.sh configs/pointpillars/pointpillars_hv_secfpn_8xb6-160e_kitti-3d-3class.py 8dist_train.sh 内部通过python -m torch.distributed.launch启动 tools/train.py,支持通过环境变量NNODES、NODE_RANK、PORT、MASTER_ADDR扩展多机训练。
理解配置:8xb6、学习率与自动缩放
配置名中的8xb6表示训练使用8 张 GPU、每张 GPU 上 6 个样本(batch size = 6)。如果你的自定义设置与此不同,通常需要相应调整学习率——基本经验规则可参考论文《Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour》(arXiv:1706.02677)。MMDetection3D 已支持--auto-scale-lr参数自动缩放学习率:从 tools/train.py 的源码可以看到,该参数会读取配置中的auto_scale_lr.enable与auto_scale_lr.base_batch_size字段并据此自动推算新的学习率。
以当前配置 pointpillars_hv_secfpn_8xb6-160e_kitti-3d-3class.py 为例,其关键训练设置包括:
- 学习率与调度:
lr = 0.001,epoch_num = 80,采用两段式CosineAnnealingLR(前 40% epoch 以eta_min = lr * 10退火,后 60% 退火到lr * 1e-4),并配套CosineAnnealingMomentum; - epoch 数:虽然
train_cfg = dict(by_epoch=True, max_epochs=80),但训练数据加载器外层套了RepeatDataset(times=2),因此实际训练 160 epochs(这正是配置名中160e的来源); - 验证间隔:
train_cfg = dict(by_epoch=True, max_epochs=epoch_num, val_interval=2),即每 2 个 epoch 在验证集上评估一次; - 梯度裁剪:
optim_wrapper = dict(optimizer=dict(lr=lr), clip_grad=dict(max_norm=35, norm_type=2)),注释说明对 PointPillars 而言max_norm=35略优于 10; - 类别与点云范围:
class_names = ['Pedestrian', 'Cyclist', 'Car'],point_cloud_range = [0, -39.68, -3, 69.12, 39.68, 1](x/y/z 的前后边界)。
数据增强管线(train_pipeline)
训练管线定义在同一配置中,依次执行:
LoadPointsFromFile:加载 LiDAR 点云,load_dim=4, use_dim=4(x, y, z, intensity);LoadAnnotations3D:加载 3D 框与标签;ObjectSample:基于db_sampler从kitti_dbinfos_train.pkl中采样 GT 点云做增强,其中sample_groups=dict(Car=15, Pedestrian=15, Cyclist=15)表示每个类别的采样目标数量(注意:PointPillars 的 KITTI 配置在基类 kitti-3d-3class.py 基础上调整了各类别的采样策略);RandomFlip3D:BEV 水平翻转概率 0.5;GlobalRotScaleTrans:全局旋转 ±45°、缩放 0.95~1.05;PointsRangeFilter/ObjectRangeFilter:过滤超出point_cloud_range的点与框;PointShuffle:打乱点序;Pack3DDetInputs:打包为模型输入。
模型结构速览
PointPillars 的模型定义见 pointpillars_hv_secfpn_kitti.py,主干为VoxelNet架构:
- 体素化:
voxel_size = [0.16, 0.16, 4](x/y 方向 0.16m、z 方向 4m),max_points_per_voxel=32,max_voxels=(16000, 40000)(训练/测试上限); - 体素编码器:
PillarFeatureNet(pillar 特征提取,输入 4 通道,输出 64 维特征); - 中间编码器:
PointPillarsScatter,将 pillar 特征散射回伪图像,输出尺寸[496, 432]; - 骨干网络:
SECOND(3 层下采样,通道 64→128→256); - 颈部:
SECONDFPN(上采样融合,输出 128 维); - 检测头:
Anchor3DHead,使用三类 anchor(Pedestrian 尺寸[0.8, 0.6, 1.73]、Cyclist[1.76, 0.6, 1.73]、Car[3.9, 1.6, 1.56],旋转角 0 与 1.57),并针对每个类别配置不同的Max3DIoUAssigner正负样本阈值(Car 的pos_iou_thr=0.6,Pedestrian/Cyclist 为 0.5);测试阶段使用use_rotate_nms=True、nms_thr=0.01、score_thr=0.1、max_num=50。
定量评估:理解 KITTI 官方评估协议
训练期间的定期评估
训练过程中,模型检查点会根据配置中的train_cfg = dict(val_interval=xxx)定期在验证集上评估。MMDetection3D 对不同的数据集支持各自的官方评估协议。对 KITTI 而言,评估协议为:对 3 个类别分别计算 mAP(mean Average Precision),IoU 阈值分别为 0.5 / 0.7,且按 easy / moderate / hard 三档难度分别报告。
评估核心由 KittiMetric 实现,它注册为type='KittiMetric',其关键构造参数包括:
ann_file:验证/测试集标注 pkl 路径;metric:评估指标,默认'bbox',允许取值为bbox、img_bbox、mAP、LET_mAP;pcd_limit_range:点云范围过滤阈值,用于剔除无效预测框,默认[0, -40, -3, 70.4, 40, 0.0];pklfile_prefix:结果 pkl 的保存前缀;format_only:仅格式化结果不计算指标(用于提交);submission_prefix:提交文件的保存目录前缀;default_cam_key:默认相机(KITTI 为'CAM2'),用于 LiDAR 到相机的坐标转换与 2D 框投影。
在kitti_evaluate中,对 3D 预测默认计算bbox / bev / 3d三类 AP(2D 框、BEV 鸟瞰框、3D 框),评估结果会打印在命令行,形如:
Car AP@0.70, 0.70, 0.70: bbox AP:98.1839, 89.7606, 88.7837 bev AP:89.6905, 87.4570, 85.4865 3d AP:87.4561, 76.7569, 74.1302 aos AP:97.70, 88.73, 87.34 Car AP@0.70, 0.50, 0.50: bbox AP:98.1839, 89.7606, 88.7837 bev AP:98.4400, 90.1218, 89.6270 3d AP:98.3329, 90.0209, 89.4035 aos AP:97.70, 88.73, 87.34其中AP@0.70, 0.70, 0.70行对应 easy / moderate / hard 三档难度在 IoU 0.7 下的 Car AP,第二行AP@0.70, 0.50, 0.50对应 BEV / 3D 评估放宽到 IoU 0.5 的 Car 指标;aos为朝向相似度指标。
训练完成后的独立评估
训练结束后,也可以单独评估某个检查点,直接运行:
./tools/dist_test.sh configs/pointpillars/pointpillars_hv_secfpn_8xb6-160e_kitti-3d-3class.py work_dirs/pointpillars/latest.pth 8dist_test.sh的用法为dist_test.sh <config> <checkpoint> <gpus>,其内部同样基于torch.distributed.launch启动 tools/test.py。注意默认配置中验证集与测试集都指向kitti_infos_val.pkl(见 kitti-3d-3class.py),因此上述命令评估的是验证集指标。
测试与在线提交:生成 KITTI 官方格式的预测结果
如果你只想做纯推理,或将模型性能提交到 KITTI 在线评估服务器(需要模型在测试集上预测),则需要为对应的评估器指定submission_prefix。例如在配置中加入:
test_evaluator = dict( type='KittiMetric', ann_file=data_root + 'kitti_infos_test.pkl', format_only=True, pklfile_prefix='results/kitti-3class/kitti_results', submission_prefix='results/kitti-3class/kitti_results')配置要点:
format_only=True:只格式化输出、不执行本地评估。从 kitti_metric.py 的源码可以看到,format_only=True时强制要求submission_prefix非空,否则结果会被保存到临时目录并在结束时被清理;ann_file必须指向测试集:请确保配置中的data_prefix与ann_file与测试集对应(参考 kitti-3d-3class.py 中test_dataloader的写法),即ann_file='kitti_infos_test.pkl'、data_prefix=dict(pts='testing/velodyne_reduced'),而不是验证集;- 生成的文件格式:从 bbox2result_kitti 可以看到,每个测试样本会输出一个
{sample_idx:06d}.txt文本文件,每行包含类别名、alpha、2D bbox、尺寸、位置、rotation_y与置信度,该格式与 KITTI 官方提交要求一致。
生成结果后,将结果文件夹压缩并上传到 KITTI 评估服务器即可获得官方打分。
定性验证:可视化检测结果与数据集
MMDetection3D 提供了丰富的可视化工具,便于直观感受训练模型的检测效果,共三条途径:
方式一:评估时在线可视化(--show)
在运行 tools/test.py 时添加--show选项,即可在评估过程中实时可视化预测结果。从 tools/test.py 的源码可以看到,--show会激活default_hooks中的VisualizationHook,并联动以下参数:
--show-dir:指定保存可视化结果的目录;--task:可视化任务类型,LiDAR 3D 检测对应lidar_det;--score-thr:框分数阈值(默认 0.1);--wait-time:每帧显示间隔(默认 2 秒)。
方式二:离线可视化(visualize_results.py)
也可以先保存预测结果,再使用 tools/misc/visualize_results.py 做离线可视化:
python tools/misc/visualize_results.py <config> --result <结果.pkl> --show-dir <输出目录>该脚本加载指定 pkl 结果,通过数据集的show方法逐帧绘制(--result必须是.pkl文件,且测试配置中需设置test_mode=True)。
方式三:无需推理的数据集浏览(browse_dataset.py)
仓库还提供了 tools/misc/browse_dataset.py 脚本,无需任何模型推理即可直接可视化数据集本身(点云、GT 框与标注),常用参数包括:
--output-dir:无显示界面时保存可视化结果;--task:任务类型(如lidar_det);--aug:可视化增强后的数据(走训练管线)而非原始数据;--show-interval:显示间隔(秒)。
更完整的可视化用法可参考 可视化文档。
小结
本文以 PointPillars + KITTI 三类别检测为完整示例,走通了 LiDAR 3D 检测的标准工作流:数据准备(ImageSets 分割 +create_data.py生成 infos 与 GT 数据库)→ 分布式训练(dist_train.sh+ 8xb6 配置解读)→ 定量评估(KittiMetric 与 mAP/IoU 协议)→ 测试提交(format_only+submission_prefix生成官方格式结果)→ 定性验证(三类可视化工具)。
对读者而言,理解这套流程后可以轻松迁移到仓库中其他 LiDAR 检测模型(如 SECOND、CenterPoint、PartA2、PV-RCNN、SASSD 等,见 configs 目录),因为它们在数据准备、评估与可视化环节共享同一套基础设施;不同之处仅在于各自配置中的模型结构、数据增强管线与训练调度策略。更多数据集(nuScenes、Waymo、Lyft 等)的 LiDAR 检测配置也可在 configs/base/datasets 中找到对应基类,按本文流程举一反三即可。
- 人工智能
- 计算机视觉
- 深度学习
- 自动驾驶
【免费下载链接】mmdetection3d
OpenMMLab's next-generation platform for general 3D object detection.
相关推荐
MMDetection3D 视觉 3D 检测实战指南:以 FCOS3D 单目模型跑通 nuScenes 数据准备、训练、评估与可视化全流程
MMDetection3D 视觉 3D 检测实战指南:以 FCOS3D 单目模型跑通 nuScenes 数据准备、训练、评估与可视化全流程 本文基于 MMDet
人工智能计算机视觉深度学习自动驾驶MMDetection3D 室内 3D 检测实战:SUN RGB-D 数据集准备、训练流水线与评估全指南
MMDetection3D 室内 3D 检测实战:SUN RGB D 数据集准备、训练流水线与评估全指南 导读 SUN RGB D 是室内场景 3D 目标检测领
人工智能计算机视觉深度学习自动驾驶MMDetection3D 中 KITTI 数据集的完整使用指南:数据准备、训练 Pipeline 与评测提交
MMDetection3D 中 KITTI 数据集的完整使用指南:数据准备、训练 Pipeline 与评测提交 KITTI 是自动驾驶领域最经典的 3D 目标检
人工智能计算机视觉深度学习自动驾驶
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考