3. LSS核心思想
LSS(Lift, Splat, Shoot)是BEV感知中极具代表性的范式,它把“从多相机图像直接生成BEV特征”拆解为三个语义清晰的阶段:Lift把2D图像特征抬升为3D视锥点云,Splat把视锥点云按空间位置泼洒到BEV网格,Shoot在BEV特征上执行下游任务(如分割、检测、规划)。理解这三阶段,是掌握多视图BEV工程的关键。
一、核心原理:从2D到3D再到BEV的两次坐标变换
LSS的核心不是“端到端黑盒”,而是显式地构造了一个可微的几何映射。设第 i 个相机的图像特征为 F_i ∈ R^{H×W×C},其外参为 T_i,内参为 K_i。Lift阶段为每个像素预测一组离散深度分布 α_i(u,v,d),并沿相机射线生成 D 个视锥点:
# 视锥点生成(伪代码)
for u, v in image_grid:
for d in depth_bins:
p_cam = d * K_inv @ [u, v, 1]^T # 相机坐标系
p_ego = T_cam_to_ego @ p_cam # 自车坐标系
feature = F_i[u, v] * α_i(u, v, d) # 深度加权特征
frustum_points.append((p_ego, feature))
这样,每个相机都产生一个“视锥点云”,每个点携带位置和特征。Splat阶段则把这些点按 (x, y) 投影到BEV平面,使用体素池化(voxel pooling)把落入同一BEV网格的特征累加或求均值,得到统一的BEV特征图 B ∈ R^{X×Y×C}。Shoot阶段在 B 上接任务头,完成BEV分割、目标检测或运动规划。
一句话总结:Lift解决“2D特征如何获得3D位置”,Splat解决“多相机特征如何对齐到同一BEV网格”,Shoot解决“BEV特征如何服务下游任务”。
二、方法流程:三阶段的数据流与关键操作
下面用一张信号链/数据流图展示LSS的完整流程。图中从多相机图像出发,经过Lift生成视锥点云,再经Splat聚合为BEV特征,最后Shoot输出任务结果。
三、案例/场景:视锥点云生成与BEV特征聚合的工程细节
以6路环视相机、输入分辨率 900×1600、深度bin数 D=41、BEV网格 200×200、特征维度 C=64 为例。Lift阶段每个相机产生 900×1600×41 ≈ 5.9×10^7 个视锥点,6路合计约 3.5×10^8 个点。若直接存储,显存会瞬间爆炸。因此工程上必须做稀疏化:只保留深度分布中概率大于阈值的点,或使用体素池化在GPU上以原子操作累加。
Splat阶段的核心是“按位置归约”。每个视锥点根据其自车坐标 (x,y) 找到对应BEV网格索引,把特征累加到该网格。由于多个点可能落入同一网格,需要处理多相机重叠区域的重复累加问题。常见做法是:先对每个相机单独池化,再对多相机结果求均值或最大值;或者使用可见性掩码过滤被遮挡的点。
工程提示:体素池化通常用 scatter_add 实现,但要注意数值稳定性。若同一网格累加点数差异过大,建议先做log或sqrt缩放,再归一化。
四、误区/复盘:LSS不是“万能BEV”,这些坑要避开
- 误区一:深度分布越密越好。深度bin从41增加到80,精度可能提升,但显存和计算量近似线性增长。实际工程中需在
D=41~64之间权衡。 - 误区二:忽略相机外参标定误差。Lift依赖精确的
T_cam_to_ego,外参偏差1°就可能导致BEV特征错位数米。标定质量直接决定BEV质量。 - 误区三:Splat后不做归一化。不同BEV网格累加的点数不同,直接送入Shoot会导致特征尺度不一致。建议使用
count归一化或LayerNorm。 - 误区四:把LSS当成纯2D检测的替代。LSS的优势在于统一BEV空间,但小目标、远距离目标仍受深度估计精度限制,需结合时序融合或多帧累积。
| 阶段 | 输入 | 核心操作 | 输出 | 常见问题 |
|---|---|---|---|---|
| Lift | 2D特征 + 深度分布 | 沿射线生成视锥点,深度加权 | 视锥点云 (x,y,z,feat) | 深度估计不准、点云过密 |
| Splat | 视锥点云 + 外参 | 体素池化、多相机聚合 | BEV特征图 X×Y×C | 网格错位、重复累加 |
| Shoot | BEV特征图 | 任务头推理 | 分割/检测/规划结果 | 尺度不一致、任务冲突 |
复盘建议:调试LSS时,先可视化视锥点云在BEV平面的投影密度,确认多相机覆盖是否均匀;再检查体素池化后的BEV特征是否出现“空洞”或“过曝”。这两个现象通常指向外参标定或深度分布训练问题。