bev-project/project/docs/BEVFUSION_ARCHITECTURE.md

618 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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地图分割
```
### 前向传播流程
```python
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
```python
# 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
```python
# 在 mmdet3d/models/fusers/ 中实现
@FUSERS.register_module()
class MyFuser(nn.Module):
...
```
### 添加新的Head
```python
# 在 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)?
```yaml
# 仅使用camera:
model:
encoders:
camera: {...}
# lidar: null # 注释掉或设为null
fuser: null # 不使用fuser
```
### Q2: 如何添加新的数据集?
```python
# 1. 继承 Custom3DDataset
@DATASETS.register_module()
class MyDataset(Custom3DDataset):
...
# 2. 实现数据加载和评估方法
# 3. 准备数据info文件
# 4. 在配置中使用
```
### Q3: 如何可视化中间特征?
```python
# 在模型forward中添加:
import torch
torch.save(features, 'features.pth')
# 或使用tensorboard:
from torch.utils.tensorboard import SummaryWriter
writer.add_image('bev_features', features)
```
## 总结
### 核心创新点
1. **统一BEV表示**: 在BEV空间融合多模态特征
2. **高效BEV Pooling**: CUDA优化速度提升40x
3. **多任务支持**: 检测和分割共享backbone
4. **模块化设计**: 易于扩展和自定义
### 主要组件调用关系
```
Entry (train.py/test.py)
BEVFusion Model
├── Camera Encoder → BEV Features
├── LiDAR Encoder → BEV Features
├── Fuser → Unified BEV
├── Decoder → Enhanced BEV
└── Heads → Predictions
```
### 推荐学习路径
1. 理解BEV表示和视图转换
2. 学习稀疏卷积和体素化
3. 研究TransFusion检测head
4. 深入CUDA算子优化
5. 实验不同配置和模态组合
---
生成时间: 2025-10-16