初步了解
Occupancy算法和BEV算法整体框架很接近,主要是呈现形式的区别。
BEV算法
BEV算法是一种将来自不同传感器(如摄像头、激光雷达、毫米波雷达等)的数据转换为车辆正上方俯瞰视角的统一表示的方法,使得车辆有一个直观且多视角空间一致的环境感知,可以较好解决2D图像的遮挡问题,一般还会融入时序信息,便于追踪、建图、路径规划等任务是一个。一般有BEV camera,BEV LiDAR和BEV fusion方案。图片来自https://www.bilibili.com/read/cv33348453/
BEV模型的一般步骤:
- 特征提取模块:使用2D/3D Backbone对多视角图像/点云特征提取
- 视角转换模块:2D转3D再转BEV(如LSS)、Voxel拍平等
- BEV特征编码:在BEV空间中对特征进行进一步编码(多模态融合、时序融合等),以获得更丰富的3D特征表示
- 检测或其他下游任务:将编码后的BEV特征送入特定的检测头或其他任务头进行目标检测或其他感知任务
上述图片来自https://news.eeworld.com.cn/qcdz/ic662864.html
BEV表示方法的局限性:
- 2D特征表示,缺少高度信息(如悬空物体)
- 存在未知物体无法识别(未在数据集中出现过)
Occupancy算法
Occupancy是一种三维表示,它将环境或者一个连续的物体划分为一系列的立方体(或称为体素,voxels),并为每个体素分配一个值表示该体素是否被物体占据(该部分是属于物体点或者非物体点),可以是0/1二元表示,也可以是[0, 1]之间的一个概率值,对应下图左边部分;同时每个占用的体素还能带有语义信息,即对应的类别预测,对应下图右边部分。
Occupancy模型一般步骤:
- 特征提取:使用不同的网络结构从图像或其他传感器数据中提取特征
- 体素化表示:使用attention、反卷积等生成3D体素网格(或类似NeRF的3D重建技术)
- 占用预测:基于提取的特征,预测每个体素是否被占用
- 后处理:对网格进行简化、细化、平滑或其他处理,以优化占用预测结果
优点:
- 更丰富的几何信息:3d的表示,更精确描述物体位置和形状(如悬空物体)、能处理未知类别物体(占用栅格则存在物体)
- 易用于各种下游任务:可以用于3D检测和分割,或者灵活地转为BoundingBox、Freespace可行驶区域等形式
缺点:
- 计算复杂度:三维表示计算密集度更高,占用网格的存储和处理需要更多的计算资源
- GT难制作:训练需要大量的三维标注数据(空间、时序),数据的获取和标注非常耗时且昂贵
一些Occupancy算法
主要参考A Survey on Occupancy Perception for Autonomous Driving: The Information Fusion Perspective这篇综述,简单介绍一些occ算法
LiDAR-Centric
激光雷达为中心的占用感知又有2D、3D、融合几种,一般都先对点云进行特征提取和体素化,然后转换到对应特征空间,如2D的BEV、TPV(BEV基础上增加2个视角,三视图表征3d空间)或者3D的体素特征,然后经过类似transformer的编码器-解码器模块进行表示增强,如果是融合路线则会将2D和3D结果合在一起取做占用预测,否则单独接个占用头去预测网格占用。
一些前沿方法
Year | Venue | Paper Title | Link |
---|---|---|---|
2024 | CVPR | PaSCo: Urban 3D Panoptic Scene Completion with Uncertainty Awareness (Best paper award candidate) | Project Page |
2023 | T-IV | Occupancy-MAE: Self-supervised Pre-training Large-scale LiDAR Point Clouds with Masked Occupancy Autoencoders | Code |
2023 | arXiv | PointOcc: Cylindrical Tri-Perspective View for Point-based 3D Semantic Occupancy Prediction | Code |
Vision-Centric
视觉为中心的占用是主流,有单目和环视两种。一般是从多摄像头图像中提取前视图特征图,然后从2D特征变3D特征,同时会加上空间信息融合和时序融合(可选),最后接上占用头预测占用情况,有以下几个关键的部分
2D到3D变换
有三类方法:
- 一种是借助相机内外参从3D投影到2D匹配后采样的projection方法;
- Back projection是2D到3D,一般会用对2D做深度估计(如LSS)然后投影到3D空;
- 最后是基于CrossAttention的方法硬做,让网络自己学,3D空间的特征作为Query,2D特征图作为Key,Value,然后做CrossAttention计算(一般是DeformableAttention减少计算量)让网络自己找到和它相关的特征;
空间信息融合
这步是为了将多个视角下的2D特征叠在一起构建3D特征(有重叠区域),有average(每个视角一样重要,求平均)和Cross Attention(网络学习后自动分配重要性)两种方法
时序融合
时序融合可以显著提高感知性能,包含时空对齐和特征融合两步:
- 时空对齐是利用自车的位姿信息,用对应的TF变换,将t-k时刻的特征变换到当前t时刻,然后采样一个时间窗口的变换特征和当前时刻特征融合在一起
- 不同的算法在融合方式上有区别,有三种类型:
- PanoOcc直接concate在一起,然后用3D卷积融合一下
- Voxformer为代表的用Cross Attention(类似空间融合)方式,当前帧特征作为query,历史特征为Key,Value,让网络自己学习哪些特征更重要
- FullySparse是从历史特征中采样部分融合先从Channel维度再从特征点维度mixing在一起然后展平,mixing的方式就是矩阵乘法,对应矩阵会根据当前帧特征更新(类似Attention经全连接层变换得到)
一些前沿方法
其中SparseOcc、FlashOcc帧率会比较高点,可能更接近实际使用落地
Multi-Modal Occupancy
多模态的Occ算法一般有两个分支,图像分支和之前的类似,从2D变换到3D的特征后与提取到的3D点云特征融合,融合方式也分直接concate、按权重叠加、CrossAttention方式自动学习,针对图像和点云融合后的特征也可以再用SelfAttention/CrossAttention等方式调整一下再丢给占用预测头
一些前沿方法
3D Occupancy数据集
Occupancy难点
来自Occupancy任务是难在数据还是算法上?总结的难点
gt难做:真值稠密化(不能太稀疏)、动静态目标不能有拖影、地面干净无误检、区分遮挡和非遮挡元素、类别划分正确、细粒度足够等等;这就涉及到前景稠密化、背景稠密化、多帧如何有效拼接?如何分割地面?如何清理地面等多个方面,实施起来难度较大,需要很多trick,很多同学训出来的模型往往误检测一大堆…
模型优化:如何将2D特征有效投影到3D空间,如何把计算量较大的模型轻量化部署等,都是行业比较关注的难题
模型监督模式:模型的监督部分关注监督模式,是直接用Occ真值监督还是通过点云监督,或是自监督?如果没有3D真值怎么办?能否借助NeRF完成2D层面上的监督,直接绕开3D真值?这些都是学术界和工业界比较关注的部分。
Occ3D-nuScenes数据集
基本信息
比较主流的数据集,用于CVPR 2023自动驾驶挑战赛,基于nuScenes数据集制作得到。一共有18个类别,0-16类别同nuScenes-lidarseg,17类“free”代表没有被占据的栅格体素。每个体素分辨率是0.4m × 0.4m × 0.4m,覆盖范围是x,y方向[-40m, 40m],z方向[-1m ,5.4m],基础信息如下:
Type | Info |
---|---|
mini | 404 |
train | 28,130 |
val | 6,019 |
test | 6,008 |
cameras | 6 |
voxel size | 0.4m |
range | [-40m, -40m, -1m, 40m, 40m, 5.4m] |
volume size | [200, 200, 16] |
#classes | 0 - 17 |
标注方式
下方图片一般的Occupancy标注制作流程,来自Occ3d这篇论文。简单来讲就是第一步先聚合多帧点云中已标注的静态、动态物体,并进行网格重建修补孔洞,这样对聚合后的点云做体素化就能得到比较稠密的标注数据,;然后使用光线投射(Ray Casting)对漏标的体素进行更完善标注,即遮挡推理(Occlusion Reasoning);再基于图像上的分割标注对误标的体素调整,即基于图像监督的体素精调(Image-guided Voxel Refinement)。
体素稠密化(Voxel Densification)
单帧点云是非常稀疏的,用来做体素占用gt效果不好,要实现稠密化,有以下几个步骤:
- 取多帧点云数据,将其中的静态物体(建筑等)、动态物体(人、车等)区分并标注
- 静态物体直接叠加多帧点云构成当前帧,可以再基于定位信息运动补偿来对齐多帧点云;针对动态物体,先扣取出来对应物体的点云,将点从激光坐标系转换到BBOX坐标系后进行多帧聚合(这块论文没有明确讲解,官方代码不完整,也没看到这部分的;个人理解是为多帧中同一物体构建同一个坐标系,方便直接叠加在一起)。然后将聚合后的动态物体放回到当前帧中,这样物体都更密集了
- 一般数据中标注的都是关键帧,因此还会用KNN将关键帧附近的未标注的几帧点云进行自动标注,有点类似做个tracking
- 聚合后的多帧点云难免会有些缝隙孔洞,论文中使用VDBFusion算法对点云进行Mesh reconstruction
- 最终对聚合后的点云进行体素化,因为点云已经有语义信息(类别标注),所以每个体素可以根据包含的点云确定体素的语义(包含多种可能要靠投票机制来确定体素的语义),这样就得到一个相对密集的体素标注
Occlusion Reasoning for Visibility Mask
这一步会对体素标注进一步处理,并考虑不同视角下(激光视角、相机视角)的可见性,原理见下图的左边部分3a。
激光视角下,如果激光射线打到的对应体素标记为占用(体素内也会有点云数据),对应红色网格;而在此之前穿过的体素则是空气,没有物体因此标记为“free”,对应白色网格,最终得到的就是[mask_lidar]标签。由于传感器安装位置区别,会有一些体素在点云中有而图像中看不到(视角受限,如青蓝色、米黄色格子),同样根据光线投影可以得到在相机视角下的体素占用情况,即[mask_camera]标签。由于大多数模型都是基于图像进行占用预测,所以常用[mask_camera]来做evaluation,那些在激光中有而图像上没有的体素一般会被忽略,这也为mIoU计算漏洞埋下伏笔,下面的评价指标有讲。
Image-guided Voxel Refinement
这步是用图像上的mask信息对一些误标、多标的体素修正,原理见上图3b部分。还是基于光线投影法,将体素和相机中心连线得到射线,该射线也会穿过图像即每个射线将体素和像素能连接起来(怎么做到的论文没有啊…),如果体素类别和像素类别一致则为同一个物体,匹配成功,即体素标签正确,否则就是误标。如上图粉红色类别A所在的射线,像素上是物体A起始的位置(再右边一个像素就是物体B了),所以射线连接的体素应该也是物体在体素中的起始位置,而右边那个绿色的体素就是误标的,应该标记为"free";同样对紫色射线一样,只有像素标签和体素标签一致才匹配成功,否则就算有体素占用但类别不一致也算误标(对应另外那个绿格)。
最终标注效果
评价指标
C是类别数,$ 𝑇𝑃_𝑐 , 𝐹𝑃_𝑐 , 𝐹𝑁_𝑐$ 分别是对某个类别
c
i
c_{i}
ci的 true positive, false positive, and false negative 预测个数,最终mIoU是个类别IoU的均值,公式如下
m
I
o
U
=
1
C
∑
c
=
1
C
T
P
c
T
P
c
+
F
P
c
+
F
N
c
,
mIoU=\frac{1}{C}\sum\limits_{c=1}^{C}\frac{TP_{c}}{TP_{c}+FP_{c}+FN_{c}},
mIoU=C1c=1∑CTPc+FPc+FNcTPc,
另外mIoU指标有个漏洞,SparseOcc 纯稀疏3D占用网络和 RayIoU 评估指标这篇讲的很清楚,下图也是其论文中的。简单来说就是Occ3D-nuScenes计算mIoU时有个visible mask参数,如果为True会只会将相机可见区域的体素纳入计算,而对Ignored类的物体不算loss,如下图的墙体为GT,后面墙体部分为不可见区域。第一种情况,gt完全没预测TP=0,所以IoU=0;第二种情况,预测和gt贴合,TP部分完全一直,但是因为墙体后面多预测的部分不纳入计算,不会被当成FP,所以FP、FN都是0,最终IoU为1;同理第三种情况,FP和TP大小一样,但墙体后面多预测部分还是不算做FP,最终IoU为0.5。这意味着鼓励模型预测一个厚表面,越厚能和gt重合概率越大,而且多预测还没惩罚。这个漏洞能让BEVFormer用上visible mask之后,mIoU从24涨到了39,足足15个点。
其他数据
来自 HuaiyuanXu/3D-Occupancy-Perception 的整理
Dataset | Year | Venue | Modality | # of Classes | Flow | Link |
---|---|---|---|---|---|---|
OpenScene | 2024 | CVPR 2024 Challenge | Camera | - | ✔️ | Intro. |
Cam4DOcc | 2024 | CVPR | Camera+LiDAR | 2 | ✔️ | Intro. |
Occ3D | 2024 | NeurIPS | Camera | 14 (Occ3D-Waymo), 16 (Occ3D-nuScenes) | ❌ | Intro. |
OpenOcc | 2023 | ICCV | Camera | 16 | ❌ | Intro. |
OpenOccupancy | 2023 | ICCV | Camera+LiDAR | 16 | ❌ | Intro. |
SurroundOcc | 2023 | ICCV | Camera | 16 | ❌ | Intro. |
OCFBench | 2023 | arXiv | LiDAR | -(OCFBench-Lyft), 17(OCFBench-Argoverse), 25(OCFBench-ApolloScape), 16(OCFBench-nuScenes) | ❌ | Intro. |
SSCBench | 2023 | arXiv | Camera | 19(SSCBench-KITTI-360), 16(SSCBench-nuScenes), 14(SSCBench-Waymo) | ❌ | Intro. |
SemanticKITT | 2019 | ICCV | Camera+LiDAR | 19(Semantic Scene Completion task) | ❌ | Intro. |