mmdetection3d 中 Group-Free 3D 检测器全解析:基于 Transformer 的无分组点云 3D 目标检测

发布时间:2026/10/8 1:29:53
mmdetection3d 中 Group-Free 3D 检测器全解析:基于 Transformer 的无分组点云 3D 目标检测 人工智能计算机视觉深度学习自动驾驶【免费下载链接】mmdetection3dOpenMMLabs next-generation platform for general 3D object detection.项目地址https://gitcode.com/gh_mirrors/mm/mmdetection3d点击查看免费下载Group-Free 3D论文题目Group-Free 3D Object Detection via TransformersarXiv:2104.00678 为主干结合 mmdetection3d 仓库中的完整配置文件、检测器与检测头源码系统地讲解其原理、配置结构、4 套官方 ScanNet 实验配置的差异以及训练、测试与结果复现的全流程。读完本文你将能够理解无分组注意力检测头的内部工作机制读懂并修改 L6/L12、O256/O512、w2x 等配置关键参数独立在 ScanNet V2 上训练、评估并复现官方指标。一、从“分组”到“无分组”Group-Free 3D 的核心动机1.1 传统点云检测方法的痛点在 Group-Free 3D 之前从原始点云直接检测 3D 物体的主流范式是两段式点分组point grouping通过手工设计的方案例如基于投票中心、基于聚类或基于候选框内的局部区域把散乱点云中的点划归到某个物体候选局部特征提取对每组点使用 PointNet 类网络聚合出物体特征再送入后续的回归/分类头。正如论文 Abstract 中指出的这种范式存在一个天然缺陷手工分组方案给出的点分配往往不准确一旦点被分到错误的候选后续基于局部点的特征提取就会引入噪声直接拉低检测性能。此外手工分组如 KNN 或球查询在点云密度不均、物体遮挡严重的室内场景中稳定性差。1.2 Group-Free 3D 的解决思路Group-Free 3D 提出一种简单而有效的方法放弃局部点分组让每个物体候选的特征由整个点云中所有点的特征共同计算得到。具体实现依赖 Transformer 中的注意力机制——每个点对某个候选的“贡献权重”是在网络训练中自动学习的而不是手工指定的。在此基础上论文进一步提出改进的注意力堆叠方案improved attention stacking scheme把不同阶段解码器输出的物体特征进行融合从而生成更准确的检测结果。整个方法几乎不需要任何额外的技巧“with few bells and whistles”就在 ScanNet V2 和 SUN RGB-D 两个广泛使用的室内 3D 检测基准上达到了当时领先state-of-the-art的水平。在 mmdetection3d 中该算法的实现路径为检测器mmdet3d/models/detectors/groupfree3dnet.py 中的GroupFree3DNet检测头mmdet3d/models/dense_heads/groupfree3d_head.py 中的GroupFree3DHead约 1100 行内含PointsObjClsModule、GeneralSamplingModule等子模块边界框编解码器mmdet3d/models/task_modules/coders/groupfree3d_bbox_coder.py 中的GroupFree3DBBoxCoder。二、算法流程与网络结构拆解2.1 总体流程从原始点云到 3D 框一个样本在GroupFree3DNet中的前向流程可以概括为以下 5 步点云预处理Det3DDataPreprocessor对原始点云做归一化与整理见 configs/base/models/groupfree3d.py 中data_preprocessor配置骨干特征提取PointNet2SASSGPointNet SSG 变体对全场景点云做多尺度下采样与特征提取得到一组种子点特征seed features初始候选采样GroupFree3DHead内的PointsObjClsModule先用一个小 MLP 预测每个种子点的 objectness 分数GeneralSamplingModule依据num_proposal如 256 或 512采样出初始物体候选即 Transformer 解码器的 queryTransformer 解码堆叠num_decoder_layers如 6 或 12层 Transformer 解码层每个候选通过自注意力 交叉注意力不断从全部种子点特征中聚合信息、精化自身预测与后处理pred_layer_cfg指定的预测层对每层/末几层解码输出做分类与回归中心点、尺寸、方向、语义最后按test_cfg做采样、NMS 与分数过滤得到最终 3D 框。2.2 无分组注意力的关键模块从 mmdet3d/models/dense_heads/groupfree3d_head.py 源码可以看到两个核心模块PointsObjClsModule第 28 行起输入种子点特征(B, C, N)通过 3 层 1D 卷积Conv1dBN1d ReLU最后一层不加 BN/激活输出每个种子点的 objectness logits(B, 1, N)。它负责为后续候选采样提供“哪些种子点更像物体中心”的置信度。GeneralSamplingModule第 85 行起根据给定索引sample_inds用gather_points从全场景特征中采样出(B, M, 3)的坐标与(B, C, M)的特征作为解码器 query 的初始化M 即num_proposal。Transformer 解码层通过transformerlayers配置为BaseTransformerLayer其operation_order为(self_attn, norm, cross_attn, norm, ffn, norm)自注意力让候选之间互相通信、避免重复框交叉注意力让每个候选从全部种子点特征中加权聚合信息——这正是“每个点的贡献由网络自动学习”的落地实现。2.3 训练与推理的区别训练train_cfg中sample_modekpskeypoint sampling配合sampling_objectness_loss监督初始采样解码器每层输出都有监督多阶段监督loss 名称在测试用例中可看到见 tests/test_models/test_detectors/test_groupfree3d.pysampling_objectness_loss、proposal.objectness_loss、s0.objectness_loss、s1.size_res_loss、s4.size_class_loss等。推理test_cfg中prediction_stageslast_three配置文件中或last基础配置中即只取最后 1 层或最后 3 层解码输出做预测然后经过nms_thr0.25的 3D NMS、score_thr0.0的分数过滤以及per_class_proposalTrue的逐类别后处理。三、官方配置文件详解四套 ScanNet 实验mmdetection3d 在 configs/groupfree3d/ 目录下提供了 4 个 ScanNet 训练配置它们的文件名清晰编码了关键超参L解码器层数num_decoder_layersO候选数num_proposalw2x骨干宽度 2 倍配置文件Backbone解码器层数 L候选数 O骨干宽度显存 (GB)AP0.25AP0.5groupfree3d_head-L6-O256_4xb8_scannet-seg.pyPointNet62561x6.766.1748.47groupfree3d_head-L12-O256_4xb8_scannet-seg.pyPointNet122561x9.466.5748.21groupfree3d_w2x-head-L12-O256_4xb8_scannet-seg.pyPointNetw2x122562x13.368.2051.02groupfree3d_w2x-head-L12-O512_4xb8_scannet-seg.pyPointNetw2x125122x18.868.2252.61上表数据来自 configs/groupfree3d/README.md 与 configs/groupfree3d/metafile.yml后者同时记录了 4x V100 GPU 的训练资源与 AdamW 优化器。Notes官方说明命名规则L6-O256表示num_layers6、num_proposals256w2x表示骨干网络权重为原始的两倍。表中汇报的是每次训练过程中验证集上的最佳结果AP0.50带*的数值是论文中的评估方法每个设置训练 5 次、每次训练测试 5 次对 25 次试验取平均以消除算法随机性。官方默认使用 4 张 GPU 训练与原论文一致。3.1 四个配置文件的继承结构四个配置文件都基于同样的四个基础配置只通过增量覆盖实现差异_base_ [ ../_base_/datasets/scannet-3d.py, ../_base_/models/groupfree3d.py, ../_base_/schedules/schedule-3x.py, ../_base_/default_runtime.py ]差异点分别在于L6-O256groupfree3d_head-L6-O256_4xb8_scannet-seg.py不覆盖num_decoder_layers与num_proposal直接沿用基础配置的num_decoder_layers6、num_proposal256L12-O256groupfree3d_head-L12-O256_4xb8_scannet-seg.py仅覆盖bbox_head.num_decoder_layers12w2x-L12-O256groupfree3d_w2x-head-L12-O256_4xb8_scannet-seg.py覆盖 backbonePointNet2SASSG的sa_channels由(64,64,128)/(128,128,256)/(128,128,256)/(128,128,256)加宽为(128,128,256)/(256,256,512)/(256,256,512)/(256,256,512)fp_channels由(256,256)/(256,288)加宽为(512,512)/(512,288)并设置num_decoder_layers12w2x-L12-O512groupfree3d_w2x-head-L12-O512_4xb8_scannet-seg.py在 w2x 骨干基础上再覆盖bbox_head.num_proposal512。可见从 L6-O256 到 w2x-L12-O512是一个“解码器加深 → 骨干加宽 → 候选增多”的逐步升级链路显存占用也从 6.7 GB 一路升到 18.8 GBAP0.5 从 48.47 提升到 52.61。3.2 基础模型配置逐项解读configs/base/models/groupfree3d.py 定义了完整的GroupFree3DNet骨架以下是关键字段的解读BackbonePointNet2SASSGbackbonedict( typePointNet2SASSG, in_channels3, num_points(2048, 1024, 512, 256), radius(0.2, 0.4, 0.8, 1.2), num_samples(64, 32, 16, 16), sa_channels((64, 64, 128), (128, 128, 256), (128, 128, 256), (128, 128, 256)), fp_channels((256, 256), (256, 288)), norm_cfgdict(typeBN2d), sa_cfgdict( typePointSAModule, pool_modmax, use_xyzTrue, normalize_xyzTrue)),num_points4 个 Set Abstraction 层逐步把点集从 2048 下采样到 1024 → 512 → 256最后一层得到 256 个种子点radius/num_samples每层球查询的邻域半径与采样点数64/32/16/16半径随下采样逐步增大sa_channels各层 SA 的 MLP 通道数最终输出的特征维度为 288fp_channels上采样融合后到达第 2 层输出即bbox_head.in_channels288的来源。检测头GroupFree3DHeadbbox_headdict( typeGroupFree3DHead, in_channels288, num_decoder_layers6, num_proposal256, transformerlayersdict( typeBaseTransformerLayer, attn_cfgsdict( typeGroupFree3DMHA, embed_dims288, num_heads8, attn_drop0.1, dropout_layerdict(typeDropout, drop_prob0.1)), ffn_cfgsdict( embed_dims288, feedforward_channels2048, ffn_drop0.1, act_cfgdict(typeReLU, inplaceTrue)), operation_order(self_attn, norm, cross_attn, norm, ffn, norm)), pred_layer_cfgdict( in_channels288, shared_conv_channels(288, 288), biasTrue), ...in_channels288与骨干输出特征维度对齐num_decoder_layers6默认 6 层 Transformer 解码器L12 配置覆盖为 12num_proposal256初始物体候选数量O512 配置覆盖为 512transformerlayers解码层的注意力配置GroupFree3DMHA多头注意力 8 头、embed_dims 288FFN 隐层 2048dropout 均为 0.1pred_layer_cfg分类与回归预测头共享卷积通道(288, 288)。损失函数配置完整保留便于对照基础配置与 4 个实验配置中一致的损失设置如下sampling_objectness_lossdict( # 初始采样 objectnessFocal Loss typemmdet.FocalLoss, use_sigmoidTrue, gamma2.0, alpha0.25, loss_weight8.0), objectness_lossdict( # 每层解码 objectnessFocal Loss typemmdet.FocalLoss, use_sigmoidTrue, gamma2.0, alpha0.25, loss_weight1.0), center_lossdict( # 中心点 SmoothL1 typemmdet.SmoothL1Loss, beta0.04, reductionsum, loss_weight10.0), dir_class_lossdict( # 方向分类 typemmdet.CrossEntropyLoss, reductionsum, loss_weight1.0), dir_res_lossdict( # 方向残差回归 typemmdet.SmoothL1Loss, reductionsum, loss_weight10.0), size_class_lossdict( # 尺寸类别 typemmdet.CrossEntropyLoss, reductionsum, loss_weight1.0), size_res_lossdict( # 尺寸残差回归 typemmdet.SmoothL1Loss, beta1.0 / 9.0, reductionsum, loss_weight10.0 / 9.0), semantic_lossdict( # 语义分类 typemmdet.CrossEntropyLoss, reductionsum, loss_weight1.0),值得注意的是实验配置中对size_res_loss的beta从基础配置的1.0调整为1.0/9.0并显式给出center_loss的beta0.04——这是 ScanNet 上微调后的训练细节。3.3 bbox_coder类别感知的尺寸回归configs/base/models/groupfree3d.py 与 4 个实验配置都通过bbox_coder指定了编解码方式bbox_coderdict( typeGroupFree3DBBoxCoder, num_sizes18, num_dir_bins1, with_rotFalse, size_cls_agnosticFalse, mean_sizes[[0.76966727, 0.8116021, 0.92573744], ...])num_sizes18ScanNet 的 18 个物体类别cabinet、bed、chair、sofa、table、door、window、bookshelf、picture、counter、desk、curtain、refrigerator、showercurtrain、toilet、sink、bathtub、garbagebin每个类别有一个预设的平均尺寸mean_sizes18 个[长, 宽, 高]平均尺寸列表作为尺寸残差回归的锚点size_cls_agnosticFalse尺寸预测是类别感知的先分类再回归残差with_rotFalse、num_dir_bins1ScanNet 场景中物体基本轴对齐因此不预测旋转方向 bin 只有 1 个。该编码器继承自PartialBinBasedBBoxCoder见 groupfree3d_bbox_coder.py即“类别 残差”的混合编码方式与 VoteNet 等室内检测器一脉相承。四、ScanNet 数据配置与数据流水线4.1 数据集与类别所有 4 个配置都使用ScanNetDataset数据根目录为data/scannet/训练与验证各自使用scannet_infos_train.pkl、scannet_infos_val.pkldataset_type ScanNetDataset data_root ./data/scannet/ class_names (cabinet, bed, chair, sofa, table, door, window, bookshelf, picture, counter, desk, curtain, refrigerator, showercurtrain, toilet, sink, bathtub, garbagebin) metainfo dict(classesclass_names)与基础数据集配置 configs/base/datasets/scannet-3d.py 相比实验配置做了两处关键调整LoadPointsFromFile中去掉了shift_heightTrue不额外引入高度偏移特征PointSample的采样点数从 40000 提高到50000。其余保持一致的要点包括coord_typeDEPTH、load_dim6、use_dim[0, 1, 2]深度相机坐标系原始 6 维只取 xyzbox_type_3dDepth使用 Depth 类型 3D 框与 KITTI/NuScenes 的 LiDAR 坐标系区分配置注释中已说明训练数据通过RepeatDataset重复 5 次配合 80 epoch 的schedule-3x详见下文。4.2 训练与测试流水线训练流水线groupfree3d_head-L6-O256_4xb8_scannet-seg.pytrain_pipeline [ dict(typeLoadPointsFromFile, coord_typeDEPTH, load_dim6, use_dim[0, 1, 2], backend_argsbackend_args), dict(typeLoadAnnotations3D, with_bbox_3dTrue, with_label_3dTrue, with_mask_3dTrue, with_seg_3dTrue, backend_argsbackend_args), dict(typeGlobalAlignment, rotation_axis2), dict(typePointSegClassMapping), dict(typePointSample, num_points50000), dict(typeRandomFlip3D, sync_2dFalse, flip_ratio_bev_horizontal0.5, flip_ratio_bev_vertical0.5), dict(typeGlobalRotScaleTrans, rot_range[-0.087266, 0.087266], scale_ratio_range[1.0, 1.0]), dict(typePack3DDetInputs, keys[points, gt_bboxes_3d, gt_labels_3d, pts_semantic_mask, pts_instance_mask]) ]GlobalAlignment把整个场景旋转到统一轴向上rotation_axis2绕 z 轴PointSegClassMapping把 ScanNet 的语义标签映射到 18 类索引-1 视为忽略类RandomFlip3DBEV 平面水平/垂直各 50% 概率翻转GlobalRotScaleTrans绕 z 轴 ±5°约 ±0.087266 rad随机旋转尺度不变scale_ratio_range[1.0, 1.0]LoadAnnotations3D同时加载 3D 框、标签、语义 mask 与实例 mask——Group-Free 3D 训练需要语义/实例分割标签来监督初始候选采样与多阶段解码。测试流水线使用MultiScaleFlipAug3DflipFalse单尺度单方向内部包含恒等GlobalRotScaleTrans、RandomFlip3D与PointSample(num_points50000)最终Pack3DDetInputs(keys[points])打包。DataLoader 与评估训练batch_size8、4 个 worker、DefaultSampler(shuffleTrue)验证/测试batch_size1、1 个 worker、不 shuffle评估器为IndoorMetric室内数据集专用指标验证与测试共用测试用例tests/test_models/test_detectors/test_groupfree3d.py使用get_detector_cfg(groupfree3d/groupfree3d_head-L6-O256_4xb8_scannet-seg.py)构建模型并校验pred_instances_3d中包含bboxes_3d、scores_3d、labels_3d同时断言多阶段损失均大于 0可作为理解数据格式与损失组成的参考。五、优化器、学习率与训练调度4 个实验配置共享同一套优化与调度设置# optimizer lr 0.006 optim_wrapper dict( typeOptimWrapper, optimizerdict(typeAdamW, lrlr, weight_decay0.0005), clip_graddict(max_norm0.1, norm_type2), paramwise_cfgdict( custom_keys{ bbox_head.decoder_layers: dict(lr_mult0.1, decay_mult1.0), bbox_head.decoder_self_posembeds: dict(lr_mult0.1, decay_mult1.0), bbox_head.decoder_cross_posembeds: dict(lr_mult0.1, decay_mult1.0), bbox_head.decoder_query_proj: dict(lr_mult0.1, decay_mult1.0), bbox_head.decoder_key_proj: dict(lr_mult0.1, decay_mult1.0), })) # learning rate param_scheduler [ dict(typeMultiStepLR, begin0, end80, by_epochTrue, milestones[56, 68], gamma0.1) ] # training schedule for 1x train_cfg dict(typeEpochBasedTrainLoop, max_epochs80, val_interval1) val_cfg dict(typeValLoop) test_cfg dict(typeTestLoop) default_hooks dict( checkpointdict(typeCheckpointHook, interval1, max_keep_ckpts10))优化器AdamWlr0.006weight_decay0.0005并做梯度裁剪max_norm0.1参数分组解码器相关参数decoder_layers、自/交叉位置编码、query/key 投影的学习率降为其他参数的 1/10lr_mult0.1——这是 Transformer 检测头常见的“小学习率”技巧用于稳定训练调度器MultiStepLR在 epoch 56 和 68 处各衰减 0.1循环EpochBasedTrainLoop共 80 epoch每 epoch 验证一次配合数据集RepeatDataset(times5)即每个真实 epoch 内迭代 5 遍数据对应schedule-3x见 configs/base/schedules/schedule-3x.py的语义checkpoint每 epoch 保存一次最多保留 10 个。六、训练、测试与结果复现6.1 训练数据准备完成后ScanNet 数据需按 docs/en/advanced_guides/datasets/scannet.md 中的说明转换出scannet_infos_train.pkl与scannet_infos_val.pkl即可使用 mmdetection3d 的训练脚本启动# 单卡训练会因 batch_size8 需较大显存 python tools/train.py configs/groupfree3d/groupfree3d_head-L6-O256_4xb8_scannet-seg.py # 4 卡分布式训练与官方结果一致README Notes 中说明默认 4 GPU bash tools/dist_train.sh configs/groupfree3d/groupfree3d_head-L6-O256_4xb8_scannet-seg.py 4训练脚本为 tools/train.py分布式入口为 tools/dist_train.sh。6.2 测试与推理使用官方提供的预训练权重测试或使用自训练权重python tools/test.py configs/groupfree3d/groupfree3d_w2x-head-L12-O512_4xb8_scannet-seg.py \ ${CHECKPOINT_FILE} --show-dir ${SHOW_DIR}测试脚本为 tools/test.py。4 套实验的官方权重下载地址记录在 configs/groupfree3d/README.md 的结果表中L6-O256、L12-O256、w2x-L12-O256、w2x-L12-O512 各有一条model与log链接对应关系也同步维护在 configs/groupfree3d/metafile.yml 中。验证时使用IndoorMetric以 AP0.25 与 AP0.5 为指标评测实现见 mmdet3d/evaluation/metrics/indoor_metric.py。6.3 结果解读与复现注意事项表中最优配置为w2x-L12-O512AP0.25 68.22、AP0.5 52.61代价是 18.8 GB 训练显存带*的数值对应论文中“5 次训练 × 5 次测试取平均”的评估协议用于消除随机性直接复现时应以括号外单次最佳结果为准从实验配置看解码器层数6→12、骨干宽度1x→w2x、候选数256→512是三个正交的增益来源可按显存预算自由组合复现时注意配置中randomness dict(seed4)固定了随机种子仅 L6-O256 配置显式声明其余配置未显式指定继承默认行为。七、如何改造为自己的数据集借鉴 configs/groupfree3d/ 中的结构迁移到其他室内数据集如 SUN RGB-D时一般只需修改metainfo/class_names替换为目标数据集的类别列表bbox_coder.mean_sizes提供新类别各自的平均尺寸可在数据统计阶段计算并同步修改num_sizesnum_dir_bins与with_rot若目标场景存在任意朝向的物体需要增大方向 bin 数并开启旋转预测数据流水线coord_type、box_type_3d、PointSample采样点数需与数据采集设备深度相机 vs LiDAR匹配。需要注意Group-Free 3D 的训练强依赖语义/实例分割标签LoadAnnotations3D中with_mask_3dTrue、with_seg_3dTrue因此目标数据集必须能提供这两类监督这也是它主要被应用于室内场景ScanNet、SUN RGB-D的原因。八、与仓库中其他室内检测器的定位在 mmdetection3d 中Group-Free 3D 与 VoteNet、H3DNet、ImVoteNet 等室内检测器同属SingleStage3DDetector家族mmdet3d/models/detectors/groupfree3dnet.py 直接继承SingleStage3DDetector。它们的本质区别在于候选如何获得物体特征VoteNet 系通过投票把种子点收敛到物体中心再以局部聚类/分组取特征存在 1.1 节所述的手工分组误差Group-Free 3D候选直接通过交叉注意力从全场景种子点特征中加权聚合点贡献由网络学习从原理上规避了分组误差同时利用多阶段解码特征融合提升精度。这一“无分组”设计正是 Group-Free 3D 在 ScanNet V2 与 SUN RGB-D 上取得当时领先性能的核心原因也是它作为 Transformer 架构在 3D 检测领域早期代表作的价值所在。参考资源官方 README 与结果表configs/groupfree3d/README.md模型元信息与权重索引configs/groupfree3d/metafile.yml基础模型配置configs/base/models/groupfree3d.py基础数据集配置configs/base/datasets/scannet-3d.py检测器源码mmdet3d/models/detectors/groupfree3dnet.py检测头源码mmdet3d/models/dense_heads/groupfree3d_head.pyBBox 编解码器mmdet3d/models/task_modules/coders/groupfree3d_bbox_coder.py单元测试tests/test_models/test_detectors/test_groupfree3d.py赞分享人工智能计算机视觉深度学习自动驾驶【免费下载链接】mmdetection3dOpenMMLabs next-generation platform for general 3D object detection.项目地址https://gitcode.com/gh_mirrors/mm/mmdetection3d点击查看免费下载相关推荐mmdetection3d 中的 SSN 实现解析Shape-aware 分组检测头与 PointPillars 多类别 3D 目标检测实战mmdetection3d 中的 SSN 实现解析Shape aware 分组检测头与 PointPillars 多类别 3D 目标检测实战 SSNShap人工智能计算机视觉深度学习自动驾驶MMDetection3D 中的 PointRCNN两阶段纯点云 3D 目标检测原理、配置解析与 KITTI 实战MMDetection3D 中的 PointRCNN两阶段纯点云 3D 目标检测原理、配置解析与 KITTI 实战 PointRCNN 是首个直接从原始点云进人工智能计算机视觉深度学习自动驾驶mmdetection3d中的SMOKE单阶段monocular 3D检测mmdetection3d中的SMOKE单阶段monocular 3D检测 引言单目3D检测的挑战与解决方案 在自动驾驶Autonomous Drivin人工智能计算机视觉深度学习自动驾驶上一篇10分钟上手Nuka Carousel面向初学者的完整快速开始教程下一篇x-transformers中的位置编码技术从绝对位置到相对位置的进化指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考