16 KiB
16 KiB
BEVFusion 项目架构与调用关系分析
项目概述
BEVFusion 是一个用于自动驾驶的多传感器融合框架,基于 MMDetection3D 构建。项目支持:
- 3D目标检测
- BEV(鸟瞰图)地图分割
- 多模态融合(相机 + 激光雷达 + 雷达)
项目目录结构
bevfusion/
├── configs/ # 配置文件(YAML格式)
│ ├── default.yaml # 基础配置
│ └── nuscenes/ # nuScenes数据集相关配置
│ ├── det/ # 检测任务配置
│ └── seg/ # 分割任务配置
├── data/ # 数据集目录
├── mmdet3d/ # 核心代码库
│ ├── apis/ # 训练/测试API
│ ├── core/ # 核心功能(bbox、points等)
│ ├── datasets/ # 数据集加载
│ ├── models/ # 模型定义
│ │ ├── backbones/ # 主干网络
│ │ ├── necks/ # 特征金字塔网络
│ │ ├── heads/ # 检测/分割头
│ │ ├── fusers/ # 多模态融合模块
│ │ ├── fusion_models/ # 融合模型(BEVFusion核心)
│ │ └── vtransforms/ # 视图转换(相机到BEV)
│ ├── ops/ # CUDA算子
│ └── utils/ # 工具函数
├── tools/ # 训练/测试脚本
│ ├── train.py # 训练入口
│ ├── test.py # 测试入口
│ └── visualize.py # 可视化工具
└── pretrained/ # 预训练模型
核心调用流程
1. 训练流程
tools/train.py (训练入口)
├── 加载配置文件 (configs/*.yaml)
├── 初始化分布式训练 (torchpack.distributed)
├── build_dataset() → mmdet3d.datasets.NuScenesDataset
│ └── 数据加载与预处理管道
├── build_model() → mmdet3d.models.BEVFusion
│ └── 构建融合模型(见下方详细结构)
└── train_model() → mmdet3d.apis.train_model
└── 训练循环、验证、保存检查点
2. 测试/推理流程
tools/test.py (测试入口)
├── 加载配置文件和检查点
├── build_dataset() → 测试数据集
├── build_model() → 加载训练好的模型
├── multi_gpu_test() / single_gpu_test()
│ └── 模型前向传播
└── dataset.evaluate() → 评估指标计算
BEVFusion 模型架构详解
整体架构
BEVFusion (mmdet3d/models/fusion_models/bevfusion.py)
├── encoders (多模态编码器)
│ ├── camera (相机分支)
│ │ ├── backbone: 图像特征提取
│ │ ├── neck: 特征金字塔
│ │ └── vtransform: 2D特征 → BEV特征
│ ├── lidar (激光雷达分支)
│ │ ├── voxelize: 点云体素化
│ │ └── backbone: 3D稀疏卷积
│ └── radar (雷达分支 - 可选)
│ ├── voxelize: 雷达点云体素化
│ └── backbone: 特征提取
├── fuser (特征融合)
│ └── ConvFuser / AddFuser: 融合不同模态的BEV特征
├── decoder (BEV解码器)
│ ├── backbone: BEV特征增强
│ └── neck: 多尺度特征融合
└── heads (任务头)
├── object: 3D目标检测 (TransFusion/CenterPoint)
└── map: BEV地图分割
前向传播流程
BEVFusion.forward()
│
├── 1. 特征提取 (extract_camera_features / extract_features)
│ │
│ ├── Camera分支:
│ │ ├── backbone(img) → 提取图像特征
│ │ │ └── ResNet / VoVNet / SwinTransformer
│ │ ├── neck(features) → FPN特征金字塔
│ │ │ └── GeneralizedLSSFPN / FPN
│ │ └── vtransform(features) → 2D → BEV转换
│ │ └── LSS / DepthLSS / AwareBEVDepth
│ │ ├── 预测深度分布
│ │ ├── 投影到3D空间
│ │ └── BEV pooling
│ │
│ ├── LiDAR分支:
│ │ ├── voxelize(points) → 点云体素化
│ │ │ └── Voxelization / DynamicScatter
│ │ └── backbone(voxels) → 3D特征提取
│ │ └── SparseEncoder (稀疏卷积)
│ │ └── VoxelResBackBone8x
│ │
│ └── Radar分支 (可选):
│ └── 类似LiDAR分支处理
│
├── 2. 特征融合 (fuser)
│ └── ConvFuser / AddFuser
│ └── 融合camera_features + lidar_features → unified_bev_features
│
├── 3. BEV解码 (decoder)
│ ├── backbone(unified_bev) → BEV特征增强
│ │ └── SECOND / ResNet
│ └── neck(features) → 多尺度特征
│ └── SECONDFPN
│
└── 4. 任务头 (heads)
│
├── 训练模式:
│ ├── object head → 预测 + 计算损失
│ │ └── TransFusionHead / CenterHead
│ │ ├── heatmap分类
│ │ ├── 中心偏移
│ │ ├── 尺寸回归
│ │ └── 旋转角度
│ └── map head → 分割 + 计算损失
│ └── VanillaSegHead
│
└── 推理模式:
├── object head → 后处理 → 3D检测框
└── map head → 分割结果
关键组件详解
1. Encoders (编码器)
Camera Encoder
作用: 将多视角相机图像转换为统一的BEV特征
流程:
Input: (B, N, C, H, W) - N个相机视图
↓
Backbone (ResNet/SwinTransformer)
↓ 提取图像特征
Neck (FPN)
↓ 多尺度特征融合
VTransform (LSS/BEVDepth)
↓ 2D→BEV转换
├── 预测深度分布
├── 生成3D frustum特征
└── BEV pooling (关键优化)
↓
Output: (B, C', H', W') - BEV特征图
关键文件:
- mmdet3d/models/backbones/resnet.py
- mmdet3d/models/necks/generalized_lss.py
- mmdet3d/models/vtransforms/lss.py
- mmdet3d/ops/bev_pool/ (高效BEV pooling算子)
LiDAR Encoder
作用: 将激光雷达点云转换为BEV特征
流程:
Input: List[Points] - 原始点云
↓
Voxelization (体素化)
↓ 将点云转为规则网格
├── 硬体素化: Voxelization
└── 动态体素化: DynamicScatter
↓
Sparse Backbone (3D稀疏卷积)
↓ 3D特征提取
└── SparseEncoder (VoxelResBackBone8x)
└── 多层稀疏卷积
↓
Output: (B, C', H', W') - BEV特征图
关键文件:
- mmdet3d/ops/voxel/voxelize.py
- mmdet3d/models/backbones/sparse_encoder.py
- mmdet3d/ops/spconv/ (稀疏卷积算子)
2. Fuser (融合器)
作用: 融合不同模态的BEV特征
类型:
├── ConvFuser (卷积融合)
│ └── 使用卷积层融合不同通道数的特征
│ Input: [camera_feat(C1,H,W), lidar_feat(C2,H,W)]
│ Process: Conv → Concat → Conv
│ Output: fused_feat(C_out,H,W)
│
└── AddFuser (简单相加)
└── 直接相加(要求通道数相同)
Output: camera_feat + lidar_feat
关键文件:
- mmdet3d/models/fusers/conv.py
- mmdet3d/models/fusers/add.py
3. Decoder (解码器)
作用: 对融合后的BEV特征进行增强和多尺度处理
流程:
Fused BEV Features
↓
Backbone (SECOND/ResNet)
↓ 特征增强
└── 多层卷积和残差连接
↓
Neck (SECONDFPN)
↓ 多尺度特征金字塔
└── 上采样 + 融合不同层特征
↓
Multi-scale BEV Features
└── 用于检测和分割
关键文件:
- mmdet3d/models/backbones/second.py
- mmdet3d/models/necks/second.py
4. Heads (任务头)
Object Detection Head (TransFusion)
作用: 从BEV特征预测3D目标检测框
流程:
BEV Features
↓
TransFusionHead
├── Heatmap分支 (分类)
│ └── Conv → Sigmoid → 目标中心热图
├── Bbox回归分支
│ ├── Center offset (中心偏移)
│ ├── Size (宽高长)
│ ├── Rotation (旋转角度)
│ └── Velocity (速度 - 可选)
└── Transformer Decoder (可选)
└── Query-based检测优化
训练:
└── 计算损失
├── FocalLoss (heatmap)
├── L1Loss (bbox回归)
└── 其他辅助损失
推理:
└── get_bboxes()
├── 提取热图峰值
├── 解码bbox参数
├── NMS (非极大值抑制)
└── 输出最终检测结果
关键文件:
- mmdet3d/models/heads/bbox/transfusion.py
- mmdet3d/models/heads/bbox/centerpoint.py
Map Segmentation Head
作用: 对BEV特征进行语义分割
流程:
BEV Features
↓
VanillaSegHead
└── Conv layers → Upsample → Conv
└── 输出每个类别的logits
↓
训练: CrossEntropyLoss
推理: Argmax → 分割mask
关键文件:
- mmdet3d/models/heads/segm/vanilla.py
数据流图
训练时数据流
NuScenes Dataset
├── 多视角图像 (6个相机)
├── LiDAR点云
├── Radar点云 (可选)
├── 标注 (3D bbox, 分割mask)
└── 相机/LiDAR标定信息
↓
Data Pipeline (数据增强)
├── LoadMultiViewImageFromFiles
├── LoadPointsFromFile
├── RandomFlip3D
├── GlobalRotScaleTrans
└── Normalize, Pad等
↓
Collate (批处理)
↓
BEVFusion Model
├── forward() → 前向传播
├── loss计算
│ ├── detection loss
│ ├── segmentation loss
│ └── depth loss (如使用BEVDepth)
└── backward() → 反向传播
↓
Optimizer更新参数
推理时数据流
输入数据
├── 图像: (B, N_cam, 3, H, W)
└── 点云: List[Points(N_points, C)]
↓
BEVFusion.forward()
↓
输出
├── 3D检测: boxes_3d, scores_3d, labels_3d
└── 分割: masks_bev
↓
后处理
├── NMS
├── 坐标系转换
└── 可视化
配置系统
配置继承关系
configs/nuscenes/det/transfusion/secfpn/camera+lidar/swint_v0p075/convfuser.yaml
├── 继承: ../default.yaml
│ ├── 继承: ../../default.yaml
│ │ ├── 继承: ../../../default.yaml
│ │ │ └── 继承: configs/default.yaml
│ │ │ └── 基础配置(数据路径、训练参数等)
│ │ └── TransFusion特定配置
│ └── camera+lidar融合配置
└── ConvFuser配置
配置项:
├── model: 模型结构定义
│ ├── encoders: {camera, lidar, radar}
│ ├── fuser: 融合器类型和参数
│ ├── decoder: 解码器配置
│ └── heads: 任务头配置
├── data: 数据集配置
│ ├── train/val/test: 数据集路径和pipeline
│ └── samples_per_gpu, workers_per_gpu
├── optimizer: 优化器配置
├── lr_config: 学习率调度
├── runner: 训练epoch数
└── evaluation: 评估配置
关键算子和优化
1. BEV Pooling (核心优化)
位置: mmdet3d/ops/bev_pool/
作用: 高效地将2D图像特征投影到BEV空间
优化: CUDA实现,相比原始LSS快40x
原理:
对于每个图像特征点:
1. 根据深度分布采样多个深度值
2. 投影到3D空间 (frustum)
3. 转换到LiDAR坐标系
4. 映射到BEV网格
5. 累加特征 (pooling)
2. Sparse Convolution (稀疏卷积)
位置: mmdet3d/ops/spconv/
作用: 对稀疏的体素化点云进行高效卷积
优化: 只计算非空体素,节省计算和内存
关键操作:
- SparseConv3d: 3D稀疏卷积
- SubMConv3d: 子流形稀疏卷积
- SparseInverseConv3d: 稀疏反卷积
3. Voxelization (体素化)
位置: mmdet3d/ops/voxel/
类型:
├── Hard Voxelization (硬体素化)
│ └── 固定每个体素最多容纳K个点
│ └── 超过K个点的取前K个或随机采样
│
└── Dynamic Voxelization (动态体素化)
└── 不限制每个体素点数
└── 使用scatter操作聚合
损失函数
Detection Loss
TransFusion Head:
├── FocalLoss (heatmap)
│ └── 类别分类损失
├── L1Loss (bbox regression)
│ ├── center loss
│ ├── size loss
│ └── rotation loss
└── IoULoss (可选)
└── 3D IoU损失
Segmentation Loss
Segmentation Head:
└── CrossEntropyLoss
└── 像素级分类损失
Depth Loss (如使用BEVDepth)
BEVDepth VTransform:
└── BinaryCrossEntropy / KLDivergence
└── 深度预测监督
评估指标
3D Object Detection (nuScenes)
指标:
├── mAP (mean Average Precision)
│ └── 不同距离和IoU阈值下的AP
├── NDS (nuScenes Detection Score)
│ └── 综合指标: mAP + 其他属性
├── mATE (mean Average Translation Error)
├── mASE (mean Average Scale Error)
├── mAOE (mean Average Orientation Error)
├── mAVE (mean Average Velocity Error)
└── mAAE (mean Average Attribute Error)
BEV Map Segmentation
指标:
└── mIoU (mean Intersection over Union)
└── 各类别IoU的平均值
扩展和自定义
添加新的Backbone
# 1. 在 mmdet3d/models/backbones/ 中实现
@BACKBONES.register_module()
class MyBackbone(nn.Module):
def __init__(self, ...):
...
def forward(self, x):
...
# 2. 在 __init__.py 中导入
# 3. 在配置文件中使用
model:
encoders:
camera:
backbone:
type: MyBackbone
...
添加新的Fuser
# 在 mmdet3d/models/fusers/ 中实现
@FUSERS.register_module()
class MyFuser(nn.Module):
...
添加新的Head
# 在 mmdet3d/models/heads/ 中实现
@HEADS.register_module()
class MyHead(nn.Module):
...
性能优化建议
训练优化
1. 使用混合精度训练 (FP16)
└── 配置: fp16 = dict(loss_scale=512.)
2. 梯度累积
└── 小batch size时模拟大batch
3. 分布式训练
└── torchpack dist-run -np [num_gpus]
4. 数据加载优化
└── workers_per_gpu: 4-8
└── persistent_workers: True
推理优化
1. TensorRT部署
└── 参考: NVIDIA CUDA-BEVFusion
2. 批处理推理
└── samples_per_gpu > 1
3. 模型剪枝和量化
└── INT8量化可达25fps (Jetson Orin)
常见问题
Q1: 如何使用单模态(仅camera或仅lidar)?
# 仅使用camera:
model:
encoders:
camera: {...}
# lidar: null # 注释掉或设为null
fuser: null # 不使用fuser
Q2: 如何添加新的数据集?
# 1. 继承 Custom3DDataset
@DATASETS.register_module()
class MyDataset(Custom3DDataset):
...
# 2. 实现数据加载和评估方法
# 3. 准备数据info文件
# 4. 在配置中使用
Q3: 如何可视化中间特征?
# 在模型forward中添加:
import torch
torch.save(features, 'features.pth')
# 或使用tensorboard:
from torch.utils.tensorboard import SummaryWriter
writer.add_image('bev_features', features)
总结
核心创新点
- 统一BEV表示: 在BEV空间融合多模态特征
- 高效BEV Pooling: CUDA优化,速度提升40x
- 多任务支持: 检测和分割共享backbone
- 模块化设计: 易于扩展和自定义
主要组件调用关系
Entry (train.py/test.py)
↓
BEVFusion Model
├── Camera Encoder → BEV Features
├── LiDAR Encoder → BEV Features
├── Fuser → Unified BEV
├── Decoder → Enhanced BEV
└── Heads → Predictions
推荐学习路径
- 理解BEV表示和视图转换
- 学习稀疏卷积和体素化
- 研究TransFusion检测head
- 深入CUDA算子优化
- 实验不同配置和模态组合
生成时间: 2025-10-16