图像是规则的二维网格,像素密集、连续,卷积网络天然适配。
点云是什么、为什么难、主流路线怎么选、模块怎么串、工程和量化哪里最容易翻车。
1. 点云是什么?先把“数据本身”讲清楚
1.1 点云的本质:三维世界的离散采样
点云(Point Cloud)可以看成:
一组在 3D 空间中的离散点,用来刻画真实世界的几何结构。
- x, y, z:三维坐标(在某个坐标系下)
常见还会带: - intensity(反射强度)
- timestamp(时间戳/相位)
- ring(激光线号)
工程里最常见的张量形状是:
1.2 点云 vs 图像:不是“稀疏图像”,而是另一种数据范式
这是理解点云算法的第一道坎。
维度 | 图像 | 点云 |
|---|---|---|
数据结构 | 规则网格 (H×W×C) | 无序点集 (N×C) |
密度 | 高且均匀 | 稀疏且不均 |
连续性 | 强 | 弱 |
空白区域 | 背景也有意义 | 大量“什么都没有” |
关键难点 | 表达纹理/语义 | 表达几何/结构 |
一句话总结:
图像是规则空间上的信号,点云是不规则空间中的几何采样。
因此 CNN 不能直接“吃”原始点云。
1.3 点云在自动驾驶里为什么重要?
它天然提供:
- 真实深度(不是估计出来的)
- 高精度几何结构(距离、尺寸、形状)
对光照不敏感
很多系统的分工逐渐变成:
图像:语义/纹理/类别
点云:几何/距离/空间结构
BEV:统一的空间中间表示(融合/检测都方便)
2. 点云算法到底在做什么?——核心矛盾与第一步“结构化”
点云算法的根本矛盾只有一个:
不规则、稀疏、动态点数的点集,如何变成规则、可计算、可部署的结构?
所以点云网络最关键的不是“backbone 多深”,而是最开始那几步:
点怎么分桶(voxel/pillar)
同一个桶里点怎么聚合
聚合后的特征怎么回到 BEV 网格
你可以把点云 pipeline 粗暴理解成:
3. 三条主流路线:Point / Voxel / Pillar(先建立全景图)
3.1 Point-based:直接处理点(PointNet 系)
优点:概念直观,保留几何细节
缺点:点数大时很吃算力,工程落地难
在自动驾驶主流 3D 检测里用得不算多(更多出现在局部模块或研究里)。
3.2 Voxel-based:体素化(VoxelNet / SparseConv)
典型信息流:
代价:3D / 稀疏算子复杂,动态稀疏结构对部署要求高
3.3 Pillar-based:PointPillars(工程常用)
典型信息流:
代价:高度结构没有显式网格,只能靠“隐式编码进通道”
4. 认知分水岭:scatter → BEV vs collapse → BEV(必须讲透)
4.1 scatter → BEV(PointPillars)
不建立 Z 维网格
- 同一 XY 位置的所有高度信息,最终被压进一个 pillar embedding
- 高度关系是 隐式的(点的 z/统计量进入通道)
4.2 collapse → BEV(VoxelNet / SparseConv)
- Z 维被切成层(体素高度层)
先在 3D 空间里学习“上下(高度)结构”
再沿 Z 折叠成 BEV(sum/max/learned collapse)
4.3 一句话总结(建议你在文中加粗)
scatter 是“先放弃高度,再用网络弥补”;
collapse 是“先理解高度,再做信息压缩”。
因为复杂场景里同一 XY 位置可能出现多层结构(桥下/车顶/地面等)。
“高度结构”建模得越早、越显式,模型越容易学对。
5. CenterPoint 到底是什么?它在体系里扮演什么角色?
很多人把 CenterPoint 当作“点云网络”,其实更准确地说:
CenterPoint 是 BEV 上的检测范式(head 思想),不是点云编码方式。
它做的事是:
- 在 BEV 上预测中心点 heatmap
回归尺寸、方向、速度等属性
- PointPillars 输出的 BEV
- VoxelNet/SparseConv collapse 后的 BEV
所以应该这样理解组织关系:
6. 常用计算模块地图:从点到 BEV 的关键桥梁
下面这几类模块,你在阅读任何点云工程代码时都会反复遇到。
6.1 Voxelization / Pillarization(分桶)
关键超参:
点云范围(x_min..x_max 等)
- voxel/pillar size(网格分辨率)
每格最大点数(max_points_per_voxel)
最大 voxel 数(max_voxels)
它们直接决定:精度、速度、内存三者取舍。
6.2 Pillar/Voxel Feature Encoder(桶内聚合)
常见做法:
- 对点做相对坐标(相对 pillar 中心/均值)
拼接强度、距离等
MLP + max/mean 聚合
很多实现的本质就是:一个轻量版 PointNet。
6.3 Scatter / BEV Pooling(稀疏 → 稠密)
这一步决定你能不能“像 2D 一样做检测”。
- 输入:[M, C] 的稀疏桶特征 + 坐标
- 输出:[B, C, H, W] 的 BEV 伪图像
7. 重头戏:PointPillarsScatter 两种写法(原始实现 vs 优化实现)
算法上它只做一件事:把稀疏 pillar 特征铺回规则 BEV 画布。
7.1 输入输出先讲明白
- voxel_features: [M, C](全 batch 的 pillar 拼接)
- coors: [M, 4],常见 [batch_id, z, y, x]
- 输出:canvas: [B, C, H, W]
7.2 原始直观实现:手写 scatter(容易理解,但工程不友好)
7.3 为什么原始实现工程代价很高?
- B*H*W*C 巨大,但绝大多数格子是空的(全 0)
- canvas[indices] = ... 是典型不规则写入(高级索引/scatter),对很多平台不友好
会引入大中间张量、动态图不稳定
量化时 observer 统计容易被稀疏零分布拖偏
原始写法适合帮助理解,最终落地通常要“算子化”。
7.4 工程优化实现:算子化 point_pillars_scatter(推荐)
项目推荐使用地平线内部实现(加速了)作为“工程最佳实践”, 使用示例如下:
优势不是“代码更短”,而是:
避免 Python 层不规则 scatter
形状更稳定、更利于图编译
更适配芯片与量化策略(算子边界清晰)
8. 芯片落地:点云模型真正难在哪?
从工程落地角度,难点通常不在卷积,而在:
- 索引密集:scatter / gather / pooling
- 动态稀疏结构:每帧点数、桶数变化
- 大空间画布:H×W 很大但有效点很少
- 稀疏算子支持:SparseConv 往往受限于平台能力
这也是为什么很多边缘平台更偏好:
- PointPillars + 2D backbone + CenterPoint head
而不是全套 SparseConv。
9. 量化:点云模型为什么更容易“炸”?
点云模型量化的难点通常来自:
9.1 分布极端
- 空桶很多(大量 0)
少数桶点数很高
少数位置特征幅值很大
这会导致 scale 被极端值拉爆,有效精度下降。
9.2 索引 + 数值混合
Scatter/Pooling 里常见“索引控制数据流”,量化边界放错容易出怪问题。
9.3 信息被压得太早
如果高度信息过早被压缩(或被量化误差污染),后续 backbone 再强也补不回来。
工程建议(可写成 checklist):
先验证浮点中间量分布:pillar数、稀疏率、Z 分布
再决定哪些模块保持高精度 / 哪些模块量化
对 scatter/pooling 这类模块谨慎设置量化边界
尽量使用平台已优化算子替代手写索引逻辑
10. 结语:点云算法不是“更复杂的 CNN”
理解 scatter vs collapse,理解桥梁模块(voxel/pillar/scatter/pooling)在何处丢信息、何处放大误差,你就真正开始“看懂点云”。
这是我在“人在途中”的阶段性整理,希望能成为大家提供学习参考。
