# BEV特征尺度详解 - Phase 4A Stage 1配置 ## 📋 目录 1. [BEV特征生成流程](#bev特征生成流程) 2. [多尺度处理细节](#多尺度处理细节) 3. [任务头输入分析](#任务头输入分析) 4. [关键问题解答](#关键问题解答) --- ## 🔄 BEV特征生成流程 ### 阶段1: 多模态编码 → 单尺度BEV #### **Camera分支** (多尺度图像 → 单尺度BEV) ``` 输入图像 (6×3×256×704) ↓ [SwinTransformer Backbone] ├─ out_indices: [1, 2, 3] # 输出3个尺度 ├─ Stage 1: (B, 192, H/4, W/4) ├─ Stage 2: (B, 384, H/8, W/8) └─ Stage 3: (B, 768, H/16, W/16) ↓ [GeneralizedLSSFPN Neck] ├─ 将3个尺度融合到统一通道 └─ 输出: 3个尺度×256通道 ↓ [DepthLSSTransform] ├─ 3D几何变换 (Lift-Splat-Shoot) ├─ xbound: [-54.0, 54.0, 0.2] # Stage 1: 0.2m分辨率 ├─ ybound: [-54.0, 54.0, 0.2] ├─ downsample: 2 └─ 输出: **单个BEV特征** (B, 80, 360, 360) ^^^^^^^^^^^^^^^^ 关键:多尺度图像特征被投影到单一BEV平面 ``` #### **LiDAR分支** (3D点云 → 单尺度BEV) ``` 点云输入 ↓ [Voxelization] └─ Voxel Size: [0.075, 0.075, 0.2] ↓ [SparseEncoder Backbone] ├─ 多尺度稀疏卷积 ├─ encoder_channels: [[16,16,32], [32,32,64], [64,64,128], [128,128]] └─ 输出: **单个BEV特征** (B, 256, 360, 360) ^^^^^^^^^^^^^^^^ 关键:3D稀疏特征被压缩到2D BEV ``` #### **融合阶段** (多模态 → 统一BEV) ``` Camera BEV (B, 80, 360, 360) ┐ ├─→ [ConvFuser] → (B, 256, 360, 360) LiDAR BEV (B, 256, 360, 360) ┘ ^^^^^^^^^^^^^^ 统一的单尺度BEV特征 ``` **重要结论1️⃣**: > **从骨干网络多尺度形成的BEV是【单个尺度】** > 虽然Camera和LiDAR编码器内部使用多尺度特征提取,但最终输出的BEV特征是统一的单一尺度 (360×360 @ 0.2m分辨率)。 --- ### 阶段2: Decoder处理 → 多尺度再生成 #### **SECOND Backbone** (单尺度输入 → 多尺度输出) ```yaml 配置: in_channels: 256 # 输入单尺度BEV out_channels: [128, 256] # 输出2个尺度 layer_nums: [5, 5] layer_strides: [1, 2] # 第1层stride=1,第2层stride=2 ``` ``` 融合BEV (B, 256, 360, 360) ↓ [Block 1: stride=1] ├─ 5层卷积 └─ 输出: (B, 128, 360, 360) ← Scale 1 (原分辨率) ↓ [Block 2: stride=2] ├─ 5层卷积 + 下采样 └─ 输出: (B, 256, 180, 180) ← Scale 2 (1/2分辨率) ``` #### **SECONDFPN Neck** (多尺度融合 → 单尺度输出) ```yaml 配置: in_channels: [128, 256] # 输入2个尺度 out_channels: [256, 256] # 每个尺度输出256通道 upsample_strides: [1, 2] # Scale1不变,Scale2上采样2倍 ``` ``` Scale 1: (B, 128, 360, 360) → Conv → (B, 256, 360, 360) ↓ Scale 2: (B, 256, 180, 180) → Deconv(×2) → (B, 256, 360, 360) ↓ Concat ↓ 最终输出: (B, 512, 360, 360) ^^^^^^^^^^^^^^^^^^^^ 单尺度BEV特征 (通道拼接) ``` **重要结论2️⃣**: > **Decoder输出【单个尺度】的BEV特征** > SECONDFPN将多尺度特征上采样到统一分辨率后concat,输出512通道的单尺度BEV。 --- ## 🎯 任务头输入分析 ### **3D检测头 (TransFusionHead)** ```python # bevfusion.py L346 pred_dict = head(x, metas) # x是单个tensor # 配置 heads: object: type: TransFusionHead in_channels: 512 # ← 接收512通道的单尺度BEV ``` **输入**: `(B, 512, 360, 360)` - **单个尺度**的BEV特征 **处理流程**: ``` (B, 512, 360, 360) ↓ [Heatmap Branch] └─ 生成检测热图 (B, num_classes, H, W) ↓ [Transformer Decoder] ├─ Query-based检测 └─ 精细化Bbox预测 ``` --- ### **BEV分割头 (EnhancedBEVSegmentationHead)** ```python # bevfusion.py L349 losses = head(x, gt_masks_bev) # x是单个tensor # 配置 heads: map: type: EnhancedBEVSegmentationHead in_channels: 512 # ← 接收512通道的单尺度BEV decoder_channels: [256, 256, 128, 128] # 内部4层decoder grid_transform: input_scope: [[-54.0, 54.0, 0.75], [-54.0, 54.0, 0.75]] # 360×360 output_scope: [[-50, 50, 0.167], [-50, 50, 0.167]] # 600×600 ``` **输入**: `(B, 512, 360, 360)` - **单个尺度**的BEV特征 **处理流程**: ``` (B, 512, 360, 360) ↓ [Grid Transform] # 双线性插值 └─ 从360×360上采样到384×384 (padding到540×540范围) ↓ [ASPP多尺度特征提取] ├─ 1×1卷积 ├─ 3×3空洞卷积 (rate=6) ├─ 3×3空洞卷积 (rate=12) └─ 3×3空洞卷积 (rate=18) ↓ [注意力机制] ├─ Channel Attention (SE) └─ Spatial Attention ↓ [4层Decoder上采样] ├─ Layer 1: 256通道 → 上采样 ├─ Layer 2: 256通道 → 上采样 ├─ Layer 3: 128通道 → 上采样 └─ Layer 4: 128通道 → 上采样到600×600 ↓ [Per-class分类器] └─ 输出: (B, 6, 600, 600) # 6个类别的分割结果 ``` **重要结论3️⃣**: > **检测头和分割头都接收【单个尺度】的BEV特征** > 两个任务头共享同一个512通道的BEV特征 (360×360),然后各自进行任务特定的处理。 --- ## ❓ 关键问题解答 ### Q1: 从骨干多尺度形成的BEV是一个尺度还是多个? **答案:单个尺度 (360×360)** **详细解释**: 1. **Camera编码器内部**使用多尺度特征 (SwinTransformer的3个输出) 2. **LiDAR编码器内部**使用多尺度稀疏卷积 3. 但**最终投影到BEV空间时**,都被统一到单一分辨率: - Camera: 通过DepthLSSTransform投影 → 360×360 @ 0.2m - LiDAR: 通过Voxelize+压缩 → 360×360 @ 0.2m 4. **融合后**仍是单尺度:256通道 × 360×360 **原因**: - BEV空间的物理分辨率是统一的 (xbound/ybound定义) - 多模态融合需要空间对齐,必须是同一尺度 --- ### Q2: 3D检测头和分割头的输入是单个BEV尺寸还是多个? **答案:单个尺寸 (512×360×360)** **详细解释**: 1. **输入统一**:两个头都接收decoder输出的同一个tensor ```python x = self.decoder["neck"](x) # (B, 512, 360, 360) # 检测头 pred_dict = self.heads["object"](x, metas) # 分割头 losses = self.heads["map"](x, gt_masks_bev) ``` 2. **内部处理不同**: - **检测头**:保持360×360,在这个尺度上做heatmap和transformer - **分割头**:上采样到600×600 (通过grid_transform) 3. **为什么不直接输入多尺度?** - 架构设计简洁:统一的BEV特征更易于多任务学习 - 计算效率:避免多尺度特征的重复计算 - 特征共享:两个任务共享前面提取的高层语义 --- ## 📐 尺度变化全流程总结 ``` 阶段 | 特征尺度数 | 具体尺寸 | 说明 ------------------|-----------|--------------------------|------------------- Camera Backbone | 3个尺度 | H/4, H/8, H/16 | 多尺度图像特征 LiDAR Backbone | 1个尺度 | 1440×1440×41 (3D) | 稀疏体素特征 BEV投影 | 1个尺度 | 360×360 @ 0.2m | ★统一到BEV平面 Fuser融合 | 1个尺度 | 256×360×360 | ★多模态统一 Decoder Backbone | 2个尺度 | 360×360, 180×180 | 短暂的多尺度 Decoder Neck | 1个尺度 | 512×360×360 | ★上采样+concat 检测头输入 | 1个尺度 | 512×360×360 | ★共享BEV特征 分割头输入 | 1个尺度 | 512×360×360 | ★共享BEV特征 分割头输出 | 1个尺度 | 6×600×600 | 上采样到GT分辨率 ``` **核心要点**: 1. ✅ **BEV空间是单尺度的**:由xbound/ybound统一定义 2. ✅ **多尺度只存在于Decoder内部**:SECOND backbone输出2个尺度,但SECONDFPN立即融合回单尺度 3. ✅ **任务头共享单一BEV特征**:都是512×360×360 4. ✅ **分割头内部有多尺度decoder**:4层逐步上采样到600×600 --- ## 🎯 Phase 4A配置验证 ### **当前训练配置摘要** ```yaml # Camera BEV生成 vtransform: xbound: [-54.0, 54.0, 0.2] # 360×360 ybound: [-54.0, 54.0, 0.2] downsample: 2 # Decoder decoder: backbone: out_channels: [128, 256] # 2个尺度 neck: in_channels: [128, 256] # 输入2个尺度 out_channels: [256, 256] # 输出拼接→512 # 任务头 heads: object: in_channels: 512 # 单尺度输入 map: in_channels: 512 # 单尺度输入 grid_transform: output_scope: [[-50, 50, 0.167], [-50, 50, 0.167]] # 600×600 ``` ### **特征尺寸验证** ```python # 从训练日志验证 Epoch [1][10700/15448] ├─ memory: 18893 MB ├─ loss/map/...: 正常训练 ✅ └─ loss/object/...: 正常训练 ✅ # 说明: # 1. 两个任务头都正常工作 → 输入尺寸正确 # 2. 显存占用18.9GB → 符合单尺度BEV特征的预期 # 3. 360×360的BEV特征足够支持600×600的分割输出 ``` --- ## 📚 参考代码位置 | 组件 | 文件路径 | 关键代码行 | |------|----------|----------| | BEVFusion主流程 | `mmdet3d/models/fusion_models/bevfusion.py` | L332-340 (fusion+decoder) | | SECOND Backbone | `mmdet3d/models/backbones/second.py` | L84-97 (输出多尺度) | | SECONDFPN Neck | `mmdet3d/models/necks/second.py` | L83-99 (concat成单尺度) | | 检测头forward | `mmdet3d/models/fusion_models/bevfusion.py` | L346 | | 分割头forward | `mmdet3d/models/fusion_models/bevfusion.py` | L349 | | 分割头实现 | `mmdet3d/models/heads/segm/enhanced.py` | L192-246 | --- ## 🔬 实验建议 如果未来想要尝试多尺度BEV方案,可以考虑: 1. **方案A:多尺度BEV生成** - 在DepthLSSTransform阶段生成多个分辨率的BEV (如180×180, 360×360) - 但需要修改融合逻辑,增加显存和计算量 2. **方案B:保持当前单尺度设计** - 优点:架构简洁,特征共享好,显存友好 - 当前设计已经能支持600×600的高分辨率分割 - **推荐方案** ✅ --- **文档创建时间**: 2025-11-03 **当前训练阶段**: Phase 4A Stage 1 (FP32, Epoch 1, Iter 10700/15448) **BEV分辨率**: 360×360 @ 0.2m (Stage 1) **目标分割分辨率**: 600×600 @ 0.167m