资讯动态

PV-RCNN 点-体素特征集抽象:在 mmdetection3d 中复现与配置 KITTI 3D 目标检测

发布时间:2026/10/8 19:16:05 来源:尧图企业网站定制
人工智能计算机视觉深度学习自动驾驶【免费下载链接】mmdetection3dOpenMMLabs next-generation platform for general 3D object detection.项目地址https://gitcode.com/gh_mirrors/mm/mmdetection3d点击查看免费下载导读PV-RCNNPoint-Voxel RCNN是 3D 目标检测领域的代表性两阶段算法其核心贡献在于将体素表征的高效计算与点云表征的精细感受野统一到同一框架中第一阶段用稀疏 3D 卷积在体素空间高效提取多尺度特征并生成 3D 候选框第二阶段通过点-体素特征集抽象Point-Voxel Feature Set Abstraction把体素特征反哺到原始点云的关键点上进而对候选框做精细化分类与回归。本文以 mmdetection3d 仓库中 PV-RCNN 的官方实现为对象逐层解读 configs/pv_rcnn/pv_rcnn_8xb2-80e_kitti-3d-3class.py 这一完整配置从数据增强管线、体素化与稀疏编码器到VoxelSetAbstraction点特征融合、RPN 与 RoI Head 的损失配置再到 KITTI 上的复现结果与训练/测试/推理命令。读完本文你将能够从源码级理解 PV-RCNN 在 mmdetection3d 中的完整数据流并能在自己的 KITTI 数据上直接复现、调参或改造。一、算法背景为什么需要点-体素融合1.1 问题动机LiDAR 点云是自动驾驶与机器人感知中最主要的 3D 场景信息来源但原始点云具有稀疏、非规则、分布不均的特点直接在其上做特征学习存在两大矛盾体素化方案的矛盾将点云离散为规则体素后可以使用高效的 3D 稀疏卷积如 SECOND 的 SparseConv与 BEV 特征图计算效率高、适合并行但体素化本身会造成信息损失且难以感知点级别的精细结构纯点云方案的矛盾PointNet 这类直接处理原始点的网络保留了几何细节但全场景的邻域搜索与采样开销大难以在远距离、大场景如自动驾驶的 70m 感知范围中高效工作。PV-RCNN 论文提出的方案是分治 融合先用体素分支高效编码全场景上下文再把体素特征投影回一组稀疏的关键点上让后续的候选框细化refinement在富含上下文信息的点特征上进行。1.2 核心组件Voxel Set AbstractionVSAVSA 是 PV-RCNN 区别于普通两阶段 3D 检测器的核心模块。它先使用FPS最远点采样从原始点云中采样固定数量的关键点本配置为 2048 个然后让每个关键点通过多组Set Abstraction模块同时从三类来源聚合特征原始点云关键点邻域内的原始点特征rawpoints_sa_cfgs多尺度体素特征稀疏编码器中间层的多尺度体素中心特征voxel_sa_cfgs_list对应 4 个尺度scale_factor分别为 1/2/4/8BEV 特征图通过双线性插值从 BEV 特征图采样bev_feat_channel256bev_scale_factor8。三类特征拼接后送入一个1x1卷积融合层压缩为统一的点特征fused_out_channel128供后续 RoI 细化使用。该模块在仓库中的实现见 mmdet3d/models/middle_encoders/voxel_set_abstraction.py 的VoxelSetAbstraction类从源码结构看其forward依次执行sample_key_points的 FPS 采样、interpolate_from_bev_features的 BEV 双线性插值以及rawpoints_sa_layer与voxel_sa_layers两组 SA 聚合最终经point_feature_fusion_layer融合输出。二、mmdetection3d 中的整体实现PointVoxelRCNN在 mmdetection3d 中PV-RCNN 的检测器类名为PointVoxelRCNN继承自TwoStage3DDetector源码位于 mmdet3d/models/detectors/pv_rcnn.py。与常规两阶段检测器不同它的构造参数额外包含三个专用模块构造参数配置中的类型作用voxel_encoderHardSimpleVFE体素内点特征编码简单 VFEmiddle_encoderSparseEncoder稀疏 3D 卷积编码器输出多尺度特征与 BEV 特征points_encoderVoxelSetAbstraction点-体素特征集抽象产出关键点特征从前向流程看pv_rcnn.py 的extract_feat/extract_points_feat/predict/loss数据流可概括为体素化与点特征编码Det3DDataPreprocessorvoxelTrue将原始点云转为 voxels第一阶段RPNHardSimpleVFE→SparseEncoderreturn_middle_featsTrue同时输出多尺度稀疏特征multi_scale_3d_feats与 BEV 特征spatial_feats→SECOND骨干 →SECONDFPN颈部 →PartA2RPNHead生成 3D 候选框点特征提取VoxelSetAbstraction采样 2048 个关键点聚合原始点、多尺度体素与 BEV 三类特征输出keypoints/keypoint_features/fusion_keypoint_features第二阶段RoI HeadPVRCNNRoiHead先由ForegroundSegmentationHead做前景语义分割再用Batch3DRoIGridExtractor在每个候选框内生成6x6x6网格点并聚合关键点特征最后由PVRCNNBBoxHead完成分类与回归。原始点云 ──体素化── HardSimpleVFE ── SparseEncoder ── SECOND SECONDFPN ── PartA2RPNHead ── 3D 候选框 │ │ │ │ └──── FPS 采样 2048 关键点 ── 多尺度体素特征 / BEV 特征 / 原始点特征VoxelSetAbstraction│ │ PVRCNNRoiHead前景分割 6x6x6 网格 RoI 特征 分类回归──┘2.1 体素编码与稀疏中间编码器配置中voxel_size [0.05, 0.05, 0.1]、point_cloud_range [0, -40, -3, 70.4, 40, 1]即感知范围覆盖前方 0~70.4m、横向 -40~40m、高度 -3~1m体素分辨率为 5cm x 5cm x 10cm因此稀疏特征空间的形状为[41, 1600, 1408]sparse_shape。max_num_points5每个体素最多容纳 5 个点max_points_per_voxelmax_voxels(16000, 40000)训练/测试阶段分别允许的最大非空体素数用于显存控制HardSimpleVFE将每个体素内最多 5 个点的 4 维特征x, y, z, intensity做逐点 MLP 后最大池化得到体素级特征SparseEncoder的return_middle_featsTrue是 PV-RCNN 的关键开关它让稀疏编码器把 4 个下采样阶段的中间稀疏特征一并返回multi_scale_3d_feats供 VSA 模块跨尺度聚合。各阶段的encoder_paddings控制 3D 稀疏卷积的 padding其中((1, 1, 1), 0, 0)表示仅在 z 维度 pad 1 个格子体素尺寸在 z 方向为 0.1m用于将边界外扩。2.2 第二阶段PVRCNNRoiHead 三件套RoI Head 定义于 mmdet3d/models/roi_heads/pv_rcnn_roi_head.py 的PVRCNNRoiHead由三个子模块组成1前景语义分割头ForegroundSegmentationHeadmmdet3d/models/roi_heads/mask_heads/foreground_segmentation_head.py对 2048 个关键点做二分类前景/背景预测in_channels640与 VSA 融合前特征通道数一致其 sigmoid 输出在后续作为前景置信门控fusion_keypoint_features * seg_preds.sigmoid().max(...)即只有被判为前景的关键点特征才参与 RoI 网格聚合从而抑制背景噪声见 pv_rcnn_roi_head.py 的_bbox_forward与predict。分割损失使用mmdet.FocalLossreductionsum且activatedTrue。2RoI 网格特征提取器Batch3DRoIGridExtractormmdet3d/models/roi_heads/roi_extractors/batch_roigridpoint_extractor.py对每个候选框在其内部生成6x6x6 216个均匀网格点grid_size6用一组StackedSAModuleMSGradius(0.8, 1.6)双半径sample_nums(16, 16)pool_modmax从关键点特征中聚合出每个网格点的特征最终输出(BxN, 6, 6, 6, C)形状的体素化 RoI 特征。3细化头PVRCNNBBoxHeadmmdet3d/models/roi_heads/bbox_heads/pv_rcnn_bbox_head.py输入为in_channels128 * 6^3网格展开经shared_fc_channels(256, 256)共享全连接层后分出分类支路cls_channels(256, 256)与回归支路reg_channels(256, 256)dropout_ratio0.3防止过拟合。关键设置class_agnosticTrue表示类别无关的细化分类分数由 RPN 的labels_3d携带回归用DeltaXYZWLHRBBoxCoder编码并额外启用with_corner_lossTrue计算 8 个角点的 Huber 损失get_corner_loss_lidar以增强框角点的几何约束。三、完整配置逐段拆解pv_rcnn_8xb2-80e_kitti-3d-3class.py3.1 基础继承该配置继承了三份基础配置相对路径均从仓库根目录出发_base_ [ ../_base_/datasets/kitti-3d-3class.py, # KITTI 3 类Pedestrian/Cyclist/Car数据配置 ../_base_/schedules/cyclic-40e.py, # 余弦退火 动量余弦的循环调度 ../_base_/default_runtime.py # 日志、checkpoint、hook 等运行时默认设置 ]注意模型名为pv_rcnn_8xb2-80e_kitti-3d-3class其中的 80e 源于cyclic-40e.py的调度配合RepeatDataset的重复机制train_cfg中max_epochs40基础上再循环放大README 中给出的训练显存 5.4GB、mAP 72.28 即按该设置复现。此外配置将class_names定义为[Pedestrian, Cyclist, Car]并通过metainfo dict(CLASSESclass_names)注入。3.2 数据管线训练与测试训练管线train_pipeline包含以下依次执行的数据变换全部定义于 mmdet3d/datasets/transforms 中变换关键参数作用LoadPointsFromFilecoord_typeLIDAR,load_dim4,use_dim4读取 LiDAR 坐标点云保留 x/y/z/intensity 4 维LoadAnnotations3Dwith_bbox_3dTrue, with_label_3dTrue加载 3D 框与类别标签ObjectSampledb_sampler,use_ground_planeTrue基于 GT 数据库kitti_dbinfos_train.pkl的点云增强采样RandomFlip3Dflip_ratio_bev_horizontal0.550% 概率水平翻转GlobalRotScaleTransrot_range[-0.7854, 0.7854](±45°),scale_ratio_range[0.95, 1.05]全局旋转 缩放PointsRangeFilterpoint_cloud_range裁剪点云到感知范围ObjectRangeFilterpoint_cloud_range剔除范围外的 GT 框PointShuffle-打乱点顺序Pack3DDetInputskeys[points, gt_bboxes_3d, gt_labels_3d]打包模型输入其中db_sampler的sample_groupsdict(Car15, Pedestrian10, Cyclist10)控制每帧最多从数据库采样的各类别数量filter_by_min_points则要求 GT 框内至少包含 5 个点才参与采样。测试管线test_pipeline相对简洁仅做MultiScaleFlipAug3D包裹的恒等变换rot_range[0,0]、scale_ratio_range[1,1]、flipFalse保证测试时不做随机增强最后以Pack3DDetInputs打包points。3.3 模型结构配置模型model字典的组装顺序与 2.1~2.2 节描述一一对应核心字段及含义如下数据预处理器data_preprocessordict( typeDet3DDataPreprocessor, voxelTrue, voxel_layerdict( max_num_points5, # 每个体素最大点数 point_cloud_rangepoint_cloud_range, voxel_sizevoxel_size, max_voxels(16000, 40000))) # 训练/测试最大非空体素数体素编码与稀疏编码器voxel_encoderdict(typeHardSimpleVFE), middle_encoderdict( typeSparseEncoder, in_channels4, sparse_shape[41, 1600, 1408], order(conv, norm, act), encoder_paddings((0, 0, 0), ((1, 1, 1), 0, 0), ((1, 1, 1), 0, 0), ((0, 1, 1), 0, 0)), return_middle_featsTrue) # 关键返回多尺度中间稀疏特征供 VSA 使用点-体素特征集抽象VSAnum_keypoints2048、fused_out_channel128。四组voxel_sa_cfgs_list的StackedSAModuleMSG分别对应尺度因子 1/2/4/8半径随尺度放大(0.4, 0.8) → (0.8, 1.2) → (1.2, 2.4) → (2.4, 4.8)mlp_channels的输入通道数与前一级稀疏特征通道匹配16/32/64/64。rawpoints_sa_cfgs用in_channels1从原始点仅坐标聚合特征。BEV 侧bev_feat_channel256, bev_scale_factor8对应 SECOND 骨干输出的 BEV 特征图分辨率。骨干与颈部backbonedict(typeSECOND, in_channels256, layer_nums[5, 5], layer_strides[1, 2], out_channels[128, 256]), neckdict(typeSECONDFPN, in_channels[128, 256], upsample_strides[1, 2], out_channels[256, 256]),RPN 头PartA2RPNHeadin_channels512为 FPN 输出的两路 256 通道拼接。anchor_generator使用Anchor3DRangeGenerator为三个类别分别定义锚框rangesPedestrian/Cyclist 的中心 z 为 -0.6Car 为 -1.78sizes[0.8, 0.6, 1.73]Pedestrian、[1.76, 0.6, 1.73]Cyclist、[3.9, 1.6, 1.56]Carrotations[0, 1.57]每个位置两种朝向0 与 π/2。损失配置mmdet.FocalLossgamma2.0, alpha0.25权重 1.0做分类mmdet.SmoothL1Lossbeta1/9权重 2.0做框回归mmdet.CrossEntropyLoss权重 0.2做方向分类use_direction_classifierTrue, dir_offset0.78539。assigner_per_sizeTrue与assign_per_classTrue意味着每个类别有独立的正负样本分配器。RoI Head语义分割头in_channels640VSA 聚合前的特征通道原始点 32 四尺度体素 4x(3232)256… 由VoxelSetAbstraction累加得到加extra_width0.1GT 框外扩宽度用于生成前景分割目标网格提取器grid_size6细化头in_channels128、grid_size6、class_agnosticTrueloss_bbox与loss_cls均使用reductionsum。3.4 训练与测试配置分配器、采样器与 NMSRPN 训练train_cfg.rpn三个类别各自独立使用Max3DIoUAssignerBboxOverlapsNearest3D计算 IoUCar 的阈值更严格pos_iou_thr0.6, neg_iou_thr0.45Pedestrian/Cyclist 为0.5/0.35min_pos_iou与各自 neg 阈值一致。rpn_proposal阶段nms_pre9000 → nms_post512 → max_num512nms_thr0.8使用旋转 NMSuse_rotate_nmsTrue。RoI 训练train_cfg.rcnn三个类别的分配器阈值统一pos_iou_thr0.55, neg_iou_thr0.55IoU 计算改用BboxOverlaps3D且coordinatelidar采样器为IoUNegPiecewiseSampler每 batch 采样num128个 RoIpos_fraction0.5负样本按 IoU 分两段neg_piece_fractions[0.8, 0.2]对应阈值[0.55, 0.1]return_iouTrue使分类目标可以采用软标签——见 pv_rcnn_bbox_head.py 的_get_target_single当 IoU 处于cls_pos_thr0.75与cls_neg_thr0.25之间时标签被设置为iou * 2 - 0.5的连续值而非 0/1。测试test_cfgRPN 侧nms_pre1024 → nms_post100 → max_num100、nms_thr0.7RoI 侧use_rotate_nmsTrue, use_raw_scoreTrue, nms_thr0.1, score_thr0.1。3.5 优化器与学习率调度配置覆盖了基础调度中的lr 0.001优化器沿用cyclic-40e.py的AdamWbetas(0.95, 0.99), weight_decay0.01梯度裁剪max_norm10。调度器为两段余弦退火 动量余弦见 configs/base/schedules/cyclic-40e.py0~15 epoch学习率由 0 升温至lr*10 0.01CosineAnnealingLR,T_max15,eta_minlr*10动量由 0 升温至0.85/0.9515~40 epoch学习率由lr*10余弦退火至lr*1e-4动量趋向 1。这种先热身后冷却的循环策略是 KITTI 数据集上 SECOND 系列模型的标准做法配合RepeatDataset可等效实现 80 epoch 的训练。3.6 Dataloader 与评估train_dataloader dict(batch_size2, num_workers2, datasetdict(datasetdict(pipelinetrain_pipeline, metainfometainfo))) test_dataloader dict(datasetdict(pipelinetest_pipeline, metainfometainfo)) eval_dataloader dict(datasetdict(pipelinetest_pipeline, metainfometainfo))外层dict(dataset...)即RepeatDataset包装metainfo将类别名注入每个 data samplebatch_size2对应 README 中 5.4GB 显存占用8 张 A100 GPU 的分布式训练环境下单卡 2 个样本。四、KITTI 上的复现结果4.1 总览README 给出的官方复现结果如下该表同时登记于 configs/pv_rcnn/metafile.ymlBackboneClassLr schdMem (GB)mAPSECFPN3 Classcyclic 80e5.472.28说明mAP 为 3 类在moderate难度下的AP11结果KITTI 官方 11 点插值 AP。4.2 分难度分类别精度AP11, 3D类别EasyModerateHardCar89.2083.7278.79Pedestrian66.6459.8455.33Cyclist87.2573.2769.61从结果可以看出Car 与 Cyclist 在三个难度上表现均衡且精度较高Pedestrian 相对偏低小目标、形状多变这与 KITTI 3D 检测的整体难度分布一致。评估器为 mmdet3d/evaluation/metrics/kitti_metric.py 对应的 KITTI 官方评测协议。五、训练、测试与推理实操以下命令均基于仓库自带的 tools/train.py、tools/test.py 与 demo/pcd_demo.py先按 docs/en/user_guides/dataset_prepare.md 准备 KITTI 数据并生成kitti_infos_train.pkl、kitti_dbinfos_train.pkl。单机单卡训练python tools/train.py configs/pv_rcnn/pv_rcnn_8xb2-80e_kitti-3d-3class.py单机多卡分布式训练bash tools/dist_train.sh configs/pv_rcnn/pv_rcnn_8xb2-80e_kitti-3d-3class.py 8测试评估python tools/test.py configs/pv_rcnn/pv_rcnn_8xb2-80e_kitti-3d-3class.py \ checkpoint.pth --cfg-options --eval kitti_map点云可视化推理python demo/pcd_demo.py point_cloud.bin \ configs/pv_rcnn/pv_rcnn_8xb2-80e_kitti-3d-3class.py checkpoint.pth需要说明由于训练显存约 5.4GB/卡单卡如 24GB 显存的消费级/专业卡即可完整训练该模型分布式脚本中的 GPU 数量应与train_dataloader的batch_size配合考虑且auto_scale_lr默认关闭。六、测试验证与实现要点仓库针对该实现提供了单元测试 tests/test_models/test_detectors/test_pvrcnn.py断言mmdet3d.models中存在PointVoxelRCNN模块直接从pv_rcnn/pv_rcnn_8xb2-80e_kitti-3d-3class.py读取配置并用MODELS.build构建模型get_detector_cfg说明该配置是开箱即用、可被配置系统完整解析的在 CUDA 环境下执行modepredict与modeloss两种前向验证输出包含bboxes_3d/scores_3d/labels_3d且六项损失loss_rpn_cls、loss_rpn_bbox、loss_rpn_dir、loss_semantic、loss_bbox、loss_cls、loss_corner都能正确计算——这与 pv_rcnn.py 中loss()将 RPN 损失与 RoI 损失合并返回的实现相互印证。从实现要点上值得注意的工程细节还包括显存优化max_voxels(16000, 40000)与num_keypoints2048是平衡精度与内存的关键旋钮调大num_keypoints会提升 RoI 特征覆盖但增加 VSA 计算量return_middle_feats去掉该开关将导致VoxelSetAbstraction无法拿到多尺度体素特征VSA 模块会退化为仅聚合原始点与 BEV 特征前景门控RoI 特征在送入网格提取器前会乘以前景分割的 sigmoid 分数这是 PV-RCNN 抑制背景关键点噪声、提升细粒度回归精度的核心机制见 pv_rcnn_roi_head.py 的_bbox_forward。七、扩展阅读配置文件的模型基础定义可对照 configs/base/models 中的parta2.py、second_hv_secfpn_kitti.py等基础模板理解其继承关系与 PV-RCNN 结构相近的两阶段模型如 Part-A2、PointRCNN分别位于 mmdet3d/models/detectors/parta2.py 与 mmdet3d/models/detectors/point_rcnn.py可对比其extract_feat的差异理解不同融合策略数据准备、训练测试与模型库索引可参考 docs/en/user_guides/train_test.md、docs/en/user_guides/dataset_prepare.md 与 configs/pv_rcnn/metafile.yml。引用若在研究中引用 PV-RCNN请使用官方 README 提供的 BibTeXarticle{ShaoshuaiShi2020PVRCNNPF, title{PV-RCNN: Point-Voxel Feature Set Abstraction for 3D Object Detection}, author{Shaoshuai Shi and Chaoxu Guo and Li Jiang and Zhe Wang and Jianping Shi and Xiaogang Wang and Hongsheng Li}, journal{computer vision and pattern recognition}, year{2020} }赞分享人工智能计算机视觉深度学习自动驾驶【免费下载链接】mmdetection3dOpenMMLabs next-generation platform for general 3D object detection.项目地址https://gitcode.com/gh_mirrors/mm/mmdetection3d点击查看免费下载相关推荐MMDetection3D 中的 PointRCNN两阶段纯点云 3D 目标检测原理、配置解析与 KITTI 实战MMDetection3D 中的 PointRCNN两阶段纯点云 3D 目标检测原理、配置解析与 KITTI 实战 PointRCNN 是首个直接从原始点云进人工智能计算机视觉深度学习自动驾驶SMOKE 单目 3D 目标检测算法在 mmdetection3d 中的实现与 KITTI 实战指南SMOKE 单目 3D 目标检测算法在 mmdetection3d 中的实现与 KITTI 实战指南 本文基于 mmdetection3d 仓库中 config人工智能计算机视觉深度学习自动驾驶Redis 生产环境部署方案实战doocs/advanced-java 中的集群架构、容量规划与高可用设计Redis 生产环境部署方案实战doocs/advanced java 中的集群架构、容量规划与高可用设计 生产环境中的 Redis 到底该怎么部署本篇文章人工智能计算机视觉深度学习自动驾驶上一篇WebAssembly模块签名验证终极指南确保代码安全运行的完整教程下一篇Structurae排序结构详解BinaryHeap与SortedArray使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑