1. lidar往camera投影导致的几何信息损失 (Geometric lossiness):
生成的深度图上,看起来相邻的两个像素点,其实在真实的三维空间中可能相距很远。
比如:
-
图像上两个物体边缘的像素挨在一起;
-
但它们的深度(z 值)差很多,一个在近处,一个在远处;
-
在3D空间中它们其实完全不相邻。
这说明 图像平面上的局部邻域不再代表真实3D空间的局部邻域,导致空间结构严重扭曲。
当你把 LiDAR 点云从 3D 空间投影到相机平面时,每个点的 (x,y,z)被映射成(u,v,d):
-
u,v是图像平面坐标;
-
d 是深度。
也就是说,从 3D → 2.5D:
-
每个像素只能保留一个深度;
-
不同物体如果在图像平面重叠(例如远处的树和近处的行人),投影后会"挤在一起";
-
图像的局部邻域(卷积核感受野)不再对应真实3D邻域。
这导致网络在图像平面上提取特征时,学不到正确的空间关系 。
这就是 "geometrically lossy" 的核心含义------不是数学误差,而是 结构丢失。
就是说两个lidar点可能投影到一个pixel上,这个pixel就会损失深度信息。
2.camera到BEV的高效转换:BEV pooling
每一帧camera相机点的数量比lidar点数量多了两个数量级,计算量巨大
2.1 先说在干什么:什么是 camera BEV pooling?
在 camera → BEV 的过程中,本质操作是:
把"相机特征点云(camera feature point cloud)"
按 BEV 网格分桶(binning)+ 聚合(pooling)
形式上等价于:
python
for each BEV grid cell:
collect all camera feature points that fall into this grid
aggregate their features (sum / mean / max)
这里的"camera feature point cloud"指的是:
-
图像特征 (H×W×C)
-
每个像素沿着多个 depth bin 被 back-project 成 3D 点
-
得到一个 规则但数量巨大的"伪点云"
2.2 Precomputation:为什么 camera 点云可以预计算?
原文关键句
Different from LiDAR point clouds, the coordinates of the camera feature point cloud are fixed
含义拆解
1️⃣ LiDAR vs Camera 的本质差别
| 传感器 | 点的位置 |
|---|---|
| LiDAR | 每一帧都不同(随场景变化) |
| Camera | 只由相机参数决定(像素 + depth bin) |
对于 camera:
-
像素坐标
(u, v)是固定的 -
depth bins 是固定采样的
-
相机内外参是固定的(标定后)
👉 所以 每个 camera feature point 的 3D 坐标是固定的
👉 它落在哪个 BEV grid cell 也是固定的
2️⃣ 他们预计算了什么?
离线 / 初始化时:
对每一个 camera feature point:
计算其 3D 坐标
计算其 BEV grid index
按 grid index 对所有点排序
记录每个点在排序后的位置(rank)
point_id → bev_grid_id → sorted_rank
3️⃣ 推理时发生了什么?
During inference, we only need to reorder all feature points
不再计算投影
不再算 grid index
只做一次 feature tensor 的重排(gather)
之前慢的方法是这样把2D backbone之后的每个点归到BEV空间对应grid中的:
python
for each frame:
for each pixel (u,v):
for each depth bin d:
X = backproject(u,v,d, K, T) # 几何计算 ❌
grid_id = bev_index(X) # floor / clamp ❌
append feature to grid
现在只需要这样:
你从 backbone / view transformer 得到的是:
features: [N, C]其中:
N = H × W × D第 i 行是 point_id = i 的 feature
gather"做的事情:
reordered_features = features[rank]
也就是:
把 feature tensor 的行顺序,
按"预先算好的 rank"重新排一遍
📉 代价变化:
-
原本:17ms(动态 grid 关联)
-
优化后:4ms(纯 reorder)
👉 这是第一个大加速点
2.3 Interval Reduction:真正的 500ms 杀手在哪里?
问题本质
完成 grid association 后:
属于同一个 BEV grid 的点
在 tensor 中是 连续的一段区间(interval)
现在要做:
对每个 grid 的 interval 做 sum / mean
❌ 传统实现(prefix sum / scan)
existing implementation first computes the prefix sum over all points
BEV pooling的传统实现(本质是每个grid中所sum pooling):
对所有点做 全局 prefix sum
在 grid 边界处相减,得到每个 grid 的 sum
为什么慢?
1️⃣ prefix sum 在 GPU 上很贵
-
需要 tree reduction
-
多级同步
-
难以 scale
2️⃣ 大量无用计算
-
prefix sum 计算了:
- 所有中间位置的 partial sum
-
但 真正需要的只有 interval 边界
3️⃣ DRAM 访问爆炸
-
写入大量中间结果
-
memory-bound
📉 结果:
feature aggregation 500ms
✅ 他们的优化:grid-parallel kernel
核心思想(非常重要)
不要再"按点并行",而是"按 BEV grid 并行"
新 kernel 怎么做?
we assign a GPU thread to each grid
也就是:
python
for each BEV grid (parallel):
start = interval_start[grid]
end = interval_end[grid]
sum features from start to end write result
为什么快?
| 旧方案 | 新方案 |
|---|---|
| 点级并行 | grid 级并行 |
| prefix sum | 直接 interval reduce |
| 有数据依赖 | 无依赖 |
| 写大量中间结果 | 只写最终结果 |
性能变化(非常夸张)
-
500ms → 2ms
-
完全消除 tree reduction
-
几乎不访问 DRAM 中间状态
2.4 最终 Takeaways:为什么这一步是 BEVFusion 的"关键使能器"
性能总结
camera-to-BEV transformation is 40× faster
| 阶段 | 延迟 |
|---|---|
| 原始实现 | >500ms |
| 优化后 | 12ms |
| 占整网比例 | ~10% |
👉 如果没有这个优化,camera BEV 是根本跑不动的
对比其他工作的做法
| 方法 | 思路 | 是否精确 |
|---|---|---|
| [63] | 假设 depth 均匀 | ❌ 近似 |
| [20] | 截断 grid 内点数 | ❌ 近似 |
| BEVFusion | 纯工程优化 | ✅ 精确 |
👉 BEVFusion 的优势是:
数学上等价
工程上极快
不牺牲精度
2.5用一句话总结
camera→BEV 的瓶颈不是模型,而是 "大规模点 → BEV grid 的聚合实现方式" ;
通过 预计算投影 + grid 级并行的 GPU kernel ,
他们把一个原本 500ms 的操作,精确无近似地压到了 12ms,
从而使 camera--LiDAR BEV 融合在工程上成为可能。
3.高度信息
在 BEV 中,高度信息并不完全丢失 ,但通常是以 压缩 或 简化 的方式处理:
🔹 1. LiDAR 到 BEV 转换中的高度处理
LiDAR 提供的 原始点云数据 是 三维 的,包括 xxx、yyy、和 zzz 坐标,其中 zzz 就是高度信息。在 BEV 空间中,通常会采用以下两种方式来处理高度信息:
-
投影到 2D 平面 :LiDAR 的点云数据被投影到 BEV 视图时,高度(z)维度通常会被压缩 ,意味着高度信息被 映射 到二维平面。大多数情况下,这种转换只保留了 水平坐标(x, y) ,并将 z 值(高度)忽略掉,或映射到其他形式的信息上(比如使用深度图、体素表示等)。
-
高度信息的保留 :某些高级方法可能会将 高度信息 以 额外的特征 保留下来,例如:
-
使用 体素(Voxel)表示,在每个体素内保持 z 值的统计特性(如最大值、平均值等);
-
将高度信息以不同的 通道 (channels)或 附加层(additional layers)的形式保存在 BEV 特征图中。
-
这些做法允许网络在 BEV 中有某种形式的"高度感知",但是它不像原始 LiDAR 点云那样直接体现出 精确的三维结构。
🔹 2. 相机到 BEV 转换中的高度处理
对于相机数据,相机本身并没有提供显式的高度信息(只提供图像上的 2D 像素),所以:
-
深度信息 (z)是通过相机投影和深度图获得的,通常每个像素的 深度值 是对场景中各点的 垂直距离的估计。
-
在 BEV 中,深度信息通过 光线投射 被转换回 3D 空间,形成密集的 BEV 特征图。虽然相机本身没有直接的高度信息,但通过这种光线投射,深度信息也在 BEV 中 以某种方式保留下来 ,比如每个射线对应的 深度值 作为特征的一部分。
🔹 3. 总结:高度信息的保留
-
LiDAR到BEV :高度信息通常 会被简化或丢弃,但有时会通过体素、层次化特征或额外的通道方式部分保留。
-
相机到BEV :由于相机没有直接的高度信息,BEV 中的高度信息是通过 深度估计 来推测和恢复的,依赖于光线投射来保留场景的空间感知。
尽管高度信息在 BEV 中不如 LiDAR 点云中那样直接和完整,但 通过巧妙的特征融合与投影技术 ,大多数情况下仍能保留 足够的空间信息 以完成感知任务,特别是在 3D 物体检测、路径规划等任务中。
camera中正前方一个物体的平面有相同的深度信息和宽度信息,同时也有高度信息,投影后高度信息会完全压缩,从一个2D平面变成BEV中的一条线。