MMDetection3D 动态体素化(Dynamic Voxelization)原理与 KITTI 实战配置全解析
人工智能计算机视觉深度学习自动驾驶【免费下载链接】mmdetection3dOpenMMLabs next-generation platform for general 3D object detection.项目地址https://gitcode.com/gh_mirrors/mm/mmdetection3d点击查看免费下载动态体素化Dynamic Voxelization是 OpenMMLab 的 mmdetection3d 仓库中一项重要的点云预处理技术源自论文End-to-End Multi-View Fusion for 3D Object Detection in LiDAR Point CloudsYin Zhou 等人2019。本文以 configs/dynamic_voxelization/README.md 为主线结合仓库内 DynamicVoxelNet 检测器、体素化算子 与三个 KITTI 实战配置讲清动态体素化的动机、核心算子原理、配置写法与复现方法。读完本文你将能理解它与硬体素化的差异并直接基于 KITTI 配置训练/测试 DV-SECOND 与 DV-PointPillars 模型。一、为什么要做动态体素化论文动机与四大优势传统 3D 检测通常将点云在鸟瞰图BEV下进行体素化物体在该视角下保持物理尺寸、天然可分。但 BEV 点云稀疏、点密度差异极大导致远距离或小目标行人、交通标志等难以检测而透视视图能提供密集观测更有利于此类目标的特征编码。MVFMulti-View Fusion算法试图协同两种视图引入动态体素化作为跨视图特征融合的基础。原 README 的 Abstract 总结了动态体素化相对既有体素化方法的四大优点无需预先分配固定大小的张量传统方法要按max_points × max_voxels预留连续显存动态方法按实际点数分配克服随机点/体素丢弃带来的信息损失硬体素化在点数超出上限或体素数超出上限时会截断点/体素动态体素化不设固定上限产生确定性的体素嵌入与更稳定的检测结果不再依赖随机截断训练与推理结果可复现建立点与体素的双向关系既知道点属于哪个体素也能反查体素包含哪些点为跨视图特征融合提供了天然基础。MVF 基于该机制让每个点学习融合不同视图的上下文信息且整体框架在点云上操作可自然扩展到其他基于 LiDAR 点云的方法。二、仓库实现概览与文件索引本仓库对动态体素化的实现贯穿数据预处理、检测器与体素编码器三层层次文件关键组件数据预处理mmdet3d/models/data_preprocessors/voxelize.py_Voxelization、DynamicScatter3D、dynamic_scatter_3d数据预处理mmdet3d/models/data_preprocessors/data_preprocessor.pyDet3DDataPreprocessorvoxel_typehard/dynamic检测器mmdet3d/models/detectors/dynamic_voxelnet.pyDynamicVoxelNet体素编码器mmdet3d/models/voxel_encoders/voxel_encoder.pyDynamicSimpleVFE、DynamicVFE体素编码器mmdet3d/models/voxel_encoders/pillar_encoder.pyDynamicPillarFeatureNet入口配置位于 configs/dynamic_voxelization/ 目录模型元数据记录在 configs/dynamic_voxelization/metafile.yml。三、硬体素化 vs 动态体素化核心差异动态体素化的切换核心在数据预处理器的voxel_type参数。查看 data_preprocessor.py 可知Det3DDataPreprocessor支持voxel_typehard默认与voxel_typedynamic两种模式。以 SECOND 的基准配置 configs/base/models/second_hv_secfpn_kitti.py 为例硬体素化的典型设置为data_preprocessordict( typeDet3DDataPreprocessor, voxelTrue, voxel_layerdict( max_num_points5, # 每个体素最多 5 个点超出即截断 point_cloud_range[0, -40, -3, 70.4, 40, 1], voxel_size[0.05, 0.05, 0.1], max_voxels(16000, 40000))), # 训练/测试时体素数量上限超出即丢弃 voxel_encoderdict(typeHardSimpleVFE),而动态体素化配置则将max_num_points与max_voxels置为-1。从 voxelize.py 中_Voxelization.forward的实现可以确认这一约定当max_points -1或max_voxels -1时算子只调用dynamic_voxelize_forward计算每个点的体素坐标coors不再分配[M, max_points, n_dim]的固定张量否则走hard_voxelize_forward的截断路径。两种模式对比维度硬体素化动态体素化每体素点数上限固定如 5/32/35无限制max_num_points-1体素数量上限固定如(16000, 40000)无限制max_voxels(-1, -1)内存分配预先分配固定大张量按需计算坐标随后的 scatter 按实际体素数分配点→体素关系单向截断后无法反查双向point2voxel_map可反查结果确定性随机截断可能引入抖动确定性嵌入、结果稳定四、KITTI 实战配置逐行解析仓库提供了三个动态体素化 KITTI 配置对应 README 结果表second_dv_secfpn_8xb6-80e_kitti-3d-car.pyDV-SECONDCar 单类second_dv_secfpn_8xb2-cosine-80e_kitti-3d-3class.pyDV-SECOND3 类pointpillars_dv_secfpn_8xb6-160e_kitti-3d-car.pyDV-PointPillarsCar 单类三个配置都只重写模型头部的体素化 体素编码器部分其余middle encoder、SECOND backbone、SECONDFPN neck、Anchor3DHead 等继承自对应基准配置改动极小这正是动态体素化即插即用的体现。4.1 DV-SECONDCar 单类80 epoch_base_ ../second/second_hv_secfpn_8xb6-80e_kitti-3d-car.py point_cloud_range [0, -40, -3, 70.4, 40, 1] voxel_size [0.05, 0.05, 0.1] model dict( typeDynamicVoxelNet, data_preprocessordict( voxel_typedynamic, # 关键开关切换到动态体素化 voxel_layerdict( _delete_True, # 删除基类里的硬体素化 voxel_layer max_num_points-1, # 每体素点数不设上限 point_cloud_rangepoint_cloud_range, voxel_sizevoxel_size, max_voxels(-1, -1))), # 体素数量不设上限 voxel_encoderdict( _delete_True, # 用动态 VFE 替换 HardSimpleVFE typeDynamicSimpleVFE, voxel_sizevoxel_size, point_cloud_rangepoint_cloud_range))要点说明_delete_TrueMMEngine 配置继承语法用于删除_base_中继承来的voxel_layer与voxel_encoder配置项避免与动态版本冲突voxel_typedynamic对应 Det3DDataPreprocessor 的voxel_type参数DynamicSimpleVFE见 voxel_encoder.py内部持有一个DynamicScatter对点数不固定N个点的输入按体素坐标做平均聚合输出[M, C]的体素特征与[M, 3]的体素坐标与HardSimpleVFE接收(N, M, C)稠密张量的接口完全不同继承的middle_encoderdict(typeSparseEncoder, in_channels4, sparse_shape[41, 1600, 1408])保持 4 通道输入、[0.05, 0.05, 0.1]对应的稀疏形状。4.2 DV-SECONDKITTI 3 类cosine 80 epoch该配置通过组合基类实现_base_ [ ../_base_/models/second_hv_secfpn_kitti.py, ../_base_/datasets/kitti-3d-3class.py, ../_base_/schedules/cosine.py, ../_base_/default_runtime.py ] point_cloud_range [0, -40, -3, 70.4, 40, 1] voxel_size [0.05, 0.05, 0.1] model dict( typeDynamicVoxelNet, data_preprocessordict( voxel_typedynamic, voxel_layerdict( _delete_True, max_num_points-1, point_cloud_rangepoint_cloud_range, voxel_sizevoxel_size, max_voxels(-1, -1))), voxel_encoderdict( _delete_True, typeDynamicSimpleVFE, voxel_sizevoxel_size, point_cloud_rangepoint_cloud_range))与 4.1 的唯一结构区别在于调度器使用_base_/schedules/cosine.pycosine 学习率衰减数据集为 configs/base/datasets/kitti-3d-3class.pyCar/Pedestrian/Cyclist 三类bbox_head 使用 3 类 anchor见 second_hv_secfpn_kitti.py 中的num_classes3与三组 anchor ranges/sizes。4.3 DV-PointPillarsCar 单类160 epoch_base_ ../pointpillars/pointpillars_hv_secfpn_8xb6-160e_kitti-3d-car.py voxel_size [0.16, 0.16, 4] # 柱体pillar尺寸z 方向覆盖整个高度 point_cloud_range [0, -39.68, -3, 69.12, 39.68, 1] model dict( typeDynamicVoxelNet, data_preprocessordict( voxel_typedynamic, voxel_layerdict( max_num_points-1, point_cloud_rangepoint_cloud_range, voxel_sizevoxel_size, max_voxels(-1, -1))), voxel_encoderdict( typeDynamicPillarFeatureNet, in_channels4, # x, y, z, r 四维输入 feat_channels[64], # 单层 PFNLayer输出 64 维 with_distanceFalse, voxel_sizevoxel_size, point_cloud_rangepoint_cloud_range))要点说明PointPillars 使用柱状体素voxel_size[0.16, 0.16, 4]z 方向 4m 覆盖整列DynamicPillarFeatureNet定义于 pillar_encoder.py继承自PillarFeatureNet核心差异是用DynamicScatter处理点数不固定的体素pfn_scatter按modemax/avg聚合点特征得到体素特征cluster_scatter用于计算点到聚类中心的偏移该配置未使用_delete_因为基类 pointpillars_hv_secfpn_8xb6-160e_kitti-3d-car.py 中对应配置项被整体覆盖两种写法均可注意区分。五、源码级原理DynamicVoxelNet 与 scatter 算子5.1 检测器DynamicVoxelNetDynamicVoxelNet定义在 dynamic_voxelnet.py继承自VoxelNet仅重写了extract_featdef extract_feat(self, batch_inputs_dict: dict) - Tuple[Tensor]: voxel_dict batch_inputs_dict[voxels] voxel_features, feature_coors self.voxel_encoder( voxel_dict[voxels], voxel_dict[coors]) batch_size voxel_dict[coors][-1, 0].item() 1 x self.middle_encoder(voxel_features, feature_coors, batch_size) x self.backbone(x) if self.with_neck: x self.neck(x) return x与前向过程对应的数据流为点云 →Det3DDataPreprocessor动态体素化得到voxels点特征与coors每个点的体素坐标→DynamicSimpleVFE/DynamicPillarFeatureNetscatter 成体素特征 →SparseEncodermiddle encoder→SECONDbackbone →SECONDFPNneck →Anchor3DHead输出检测框。5.2 体素化算子与 scatter 算子voxelize.py 是动态体素化的算子层通过 mmcv 的 ext_loader 加载了四个 CUDA 扩展ext_module ext_loader.load_ext(_ext, [ dynamic_voxelize_forward, hard_voxelize_forward, dynamic_point_to_voxel_forward, dynamic_point_to_voxel_backward ])dynamic_voxelize_forward对每个点计算其体素坐标coors输出形状[N, 3]不产生体素张量voxelize.pydynamic_point_to_voxel_forward将[N, C]点特征按坐标归约reduce_type支持max/sum/mean为[M, C]体素特征同时返回point2voxel_map与voxel_points_countvoxelize.pydynamic_point_to_voxel_backward配套的反向传播算子将体素梯度按point2voxel_map散射回每个点保证整个流程可端到端训练voxelize.py。值得注意的是_DynamicScatter注释明确说明与 mmcv 实现不同这里允许返回point2voxel_map这正是论文点与体素双向关系这一优点的代码级落地有了point2voxel_map下游模块如多视图融合层可以把体素级特征再映射回点级实现逐点融合。DynamicScatter3D模块在coors.size(-1) 3时走单样本路径否则按 batch 逐样本 scatter 后拼接voxelize.py。5.3 支持融合与点级输出的 DynamicVFE除DynamicSimpleVFE外仓库还提供功能更完整的DynamicVFEvoxel_encoder.py其构造函数包含fusion_layer用于多模态检测器的跨视图融合层配置、with_voxel_center、with_cluster_center、return_point_feats是否返回逐点特征等参数mode参数控制池化方式max/avg。这一设计直接呼应论文中每个点学习融合不同视图上下文信息的目标是 MVF 算法落地更完整形态的编码器可作为在动态体素化基础上扩展多模态融合的参考入口。六、训练、测试与复现方法配置就绪后按仓库通用流程执行。训练# 单机多卡分布式训练8x V100 与 metafile 记录的资源一致 bash tools/dist_train.sh configs/dynamic_voxelization/second_dv_secfpn_8xb6-80e_kitti-3d-car.py 8 # 或单卡训练 python tools/train.py configs/dynamic_voxelization/second_dv_secfpn_8xb6-80e_kitti-3d-car.py测试python tools/test.py configs/dynamic_voxelization/second_dv_secfpn_8xb6-80e_kitti-3d-car.py \ checkpoint路径 --eval bbox前提说明需要先按 docs/zh_cn/user_guides/dataset_prepare.md英文版见 docs/en/user_guides/dataset_prepare.md准备 KITTI 数据集并生成 pkl 信息文件_base_中的 KITTI 数据配置configs/base/datasets/kitti-3d-car.py、configs/base/datasets/kitti-3d-3class.py指定了数据路径、测试模式与评估指标请按实际数据目录调整。七、KITTI 上的复现结果下表完整收录 README 与 metafile.yml 中登记的结果与配置对应关系模型配置类别学习率调度显存GBmAPSECONDDVsecond_dv_secfpn_8xb6-80e_kitti-3d-car.pyCarcyclic 80e5.578.83SECONDDVsecond_dv_secfpn_8xb2-cosine-80e_kitti-3d-3class.py3 Classcosine 80e5.565.27PointPillarsDVpointpillars_dv_secfpn_8xb6-160e_kitti-3d-car.pyCarcyclic 80e4.777.76几点说明权重下载地址与训练日志链接记录在 metafile.yml 及仓库根目录的 model-index.yml 中对应Weights字段需要权重时请前往该元数据文件核对获取原 README 结果表中 PointPillars 行的 Lr schd 标注为 cyclic 80e但其配置文件名与继承基类均为 160 epoch见 pointpillars_hv_secfpn_8xb6-160e_kitti-3d-car.py复现时以配置文件实际 epoch 数为准模型目录内各模型同样在 model-index.yml 中有结构化登记供模型库工具自动检索。八、总结与引用动态体素化在本仓库中被实现为一条完整的预处理算子 → 检测器 → 体素编码器链路核心改动集中在数据预处理器voxel_typedynamic与两类动态编码器DynamicSimpleVFE/DynamicPillarFeatureNet对 SECOND、PointPillars 等主流框架均可低侵入替换。其免预分配、无损点云、确定性输出、点体素双向映射四大特性使其尤其适合远距离/小目标场景以及需要逐点跨视图特征融合的多模态方法。若在论文中使用本工作可引用原文献article{zhou2019endtoend, title{End-to-End Multi-View Fusion for 3D Object Detection in LiDAR Point Clouds}, author{Yin Zhou and Pei Sun and Yu Zhang and Dragomir Anguelov and Jiyang Gao and Tom Ouyang and James Guo and Jiquan Ngiam and Vijay Vasudevan}, year{2019}, eprint{1910.06528}, archivePrefix{arXiv}, primaryClass{cs.CV} }赞分享人工智能计算机视觉深度学习自动驾驶【免费下载链接】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 是首个直接从原始点云进人工智能计算机视觉深度学习自动驾驶Redis 生产环境部署方案实战doocs/advanced-java 中的集群架构、容量规划与高可用设计Redis 生产环境部署方案实战doocs/advanced java 中的集群架构、容量规划与高可用设计 生产环境中的 Redis 到底该怎么部署本篇文章人工智能计算机视觉深度学习自动驾驶Front-End-Checklist 无障碍指南为 ARIA command 元素提供可访问名称Accessible NamesFront End Checklist 无障碍指南为 ARIA command 元素提供可访问名称Accessible Names 本文基于 Front人工智能计算机视觉深度学习自动驾驶上一篇深入解析 MLflow 仓库 upload-media Skill本地媒体一键上传 GitHub user-attachments 并嵌入 PR 评论下一篇ToolJet 在 AWS EKS 上的 Kubernetes 部署实战从 Deployment、AWS Load Balancer 到 PostgREST 与 LTS 升级创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考