BEV相关论文与博客

任务描述

BEV感知,就是根据车辆上不同方位的各种传感器的数据,获得一个鸟瞰视图(或特征图),用于地图分割、3D目标检测等下游任务。相比于根据2D图像建立完全3D场景的任务相比,BEV类似于2.5D的场景建模。

关于视图变换

Projection, 2D->3D->2D

理想情况下的BEV是什么?举例子说明:倒车入库,在不停地观察左右后视镜时,结合我们的“驾驶经验”,我们慢慢在脑海中建立了当前车位的鸟瞰图场景。把左右后视镜换成相机,怎么建立这种俯视图呢?

直接的想法是: 1. 图像逆变换; 2. 目标(分割图/bbox)逆变换;

先忽略有关“驾驶经验”的部分,先来回顾一下相机是怎么把3D世界投影到图像上的。先使用齐次坐标系,行内横写列向量。

设世界坐标系下有一点 \(\vec p = (x, y, z, 1)\),考虑到车辆自身在道路上的平移/旋转,该点在车辆坐标系下的坐标为 \(\vec p_{V} = T_V\vec p\),其中 \(T_V\) 是平移旋转变换矩阵。各个位置的摄像机相对于车辆又有不同的平移旋转变换 \(T_{C_i}\),在第 \(i\) 个相机坐标系下, \(\vec p_{C_i} = T_{C_i}\vec p_V\),( \(T_{C_i}T_V\) 即相机外参)。

接下来是从相机坐标系到像素坐标系的投影,由于没有正交于像素平面方向平移,我们使用 \(\vec p_{C_i}\) 的非齐次坐标 \(\mathbf p_{C_i} = (x', y', z')\)。根据针孔相机模型,可以得到:

\[ z'\vec p_{uv} = K\mathbf p_{C_i} \]

其中 \(K\) 是相机内参,由厂家或标定得到。\(\vec p_{uv} = (u, v, 1)\)。标量 \(z'\) 即在相机坐标系下该点到相机平面的距离。在最终的图像上,只由 \((u,v)\) 位置的 RGB信息,而深度信息被丢失了。这使得从像素 \((u,v)\) 回到原世界坐标是不可解的。

只从几何关系考虑,图像上每个像素与相机视锥中物体表面的点是一一对应的。然而考虑透射、反射、散射等光学现象,一个像素的RGB值并非原原本本对应物体表面的颜色。假设我们知道准确的深度信息,我们可以还原一个3D空间的“曲面”,但因为上述原因的存在,纹理信息不能复原。当然,如果我们输入的是像素分割图,经过逆变化至少能得到一个近处密集、远处稀疏的分割点云(曲面状)。

从3D到鸟瞰试图的投影,只要在世界坐标系的高度轴方向上规约即可。可以使用最大规约获得在几何上正确的鸟瞰图。但是对于像素纹理不一定正确。

源于遮挡关系,只能还原“曲面”的性质也将使得BEV试图中的物体往往残缺不全/形状怪异。这将造成巨大的语义损失,不利于分割和检测。 回到最开始的假设,行驶过程中车辆和相机的姿态变化会改变相机外参,这样让变换后的结果随时间“抖动”明显,也不利于分割和检测。

就像人只看到车头能想象出车辆全身形状一样,这就需要“驾驶经验”(模型先验)来补全。对于模型而言,就是构建一个BEV视图的特征空间,尽可能地将多个相机透视视图、多个雷达以及激光雷达的数据对齐融合到该BEV特征图上。

这篇博客主要记录BEV特征图的构建方法,略过3D目标检测、地图分割等各种头的设计和实现。

Homography, 2D->2D

在已知两个相机内外参、以及地平面信息(地面法向量)时,求出两个相机视图的单应性矩阵的方法可参考知乎 - 从单应矩阵推导到自动驾驶环视投影应用

关于Occupancy Grid Map

Occupancy Grid Map 是机器人常用的一种地图表示方式,机器人顶部的激光雷达(LIDAR)以一定频率发出激光(laser),根据激光往返时间算出车身到障碍物在某一时刻的距离。将车所在的地平面栅格化表示,根据激光信息估计每个栅格 \(x_i\) 的状态 \(m_i\)\(m_i=1\) 表示occupied,\(m_i = 0\) 表示 free。考虑到每一次激光雷达都有测量误差,设前 \(t\) 时刻的测量值为 \(z_{1:t}\),事实上需要把 \(m_i\) 视为随机变量,并估计后验概率 \(p(m_i | z_{1:t})\)

使用 log-odds \(\log\frac{p(m_i=1)}{p(m_i=0)}\) 表示状态,可以用贝叶斯公式建模,最终得到类似于“后验=先验+似然”的简单形式(知乎 - 占据栅格地图),“似然”是一个常数参数。

其他预备知识

论文阅读

Camera

BEV-IPM

本文以单张front-view的相机照片为输入,在通过“惯性测量”尽可能消除相机的pitch进而roll旋转后,通过将front-view变换成bev-view的确定的单应性矩阵,实现2D平面到2D平面的直接变换。最后在失真比较严重的BEV图像上直接训练2D旋转目标检测模型,检测车辆的地面位置,从而实现距离估计。

除了失真的影响,还需要满足所有车辆与地面平行且处于地面(保证单应性矩阵有效)、相机相对于车辆绝对固定(相机外参不变)的假设。

Learning to Look around Objects for Top-View Representations of Outdoor Scenes

LearnLookAround训练流程

这篇文章在没有BEV地图分割标注的情况下,输入单张图片和分割模型预测的mask,使用CNN预测背景的seg和depth(包含对原来前景区域下seg和depth的inpainting);之后再用这个seg和depth以及相机内参得到相机坐标系下的分割点云并拍平(z)、离散化(x,y)到BEV平面。从论文的实例中可以看到这样初始化的BEV分割非常不好。最后做一个BEV seg的refinement。

方法忽略了路上的任何前景物体,包括汽车行人等,应用性不高。

VPN

VPN框架图

在这篇文章中将BEV称为cross-view。

本文使用N个视角(至多6个),M个模态(至多3个,RGB, Depth, Seg),在第一个训练阶段,使用合成数据,转化为对齐的BEV特征并解码为seg训练。在第二个训练阶段(域自适应),设计了simGAN的策略让对真实图片的BEV分割结果与合成BEV分割gt相似。

视图转换、融合的建模:

  1. 将任何一种模态的输入均展平后通过全连接网络学习视图变换关系;
  2. 特征融合模块应该采用的是某种加权和的方式,保证输出特征与输入视图变换模块之前大小一致;

问题:

完全抛弃了各种几何约束,这使得当更换相机或者相机位置等改变时,即使在相同场景下也需要重新训练。

OFT

正交特征变换(OFT)

该方法先输入单张相机的透视视图,在经过前端特征提取器后得到透视特征 \(\mathbf f\);为了获得一个BEV“特征体” \(\mathbf g\),通过相机内参,将组成特征体的边长为 \(r\) 的voxel特征表示为对应的所有透视pixel特征的和;最后将 \(\mathbf g\) 在高度方向上使用可学习权重加权得到 BEV特征 \(\mathbf h\),在经过topdown网络之后连接检测头。

在上述变换的过程中,事实上构建了 2D点 到 3D点 的一对多的关系:\(\mathbf f(u,v)\) 与在所有可能的深度上映射到的3D点都有连接,期望在后续的学习中能够学到哪种映射关系是正确的。在高度方向的聚合是为了减少计算成本/显存占用,如果在有可用的深度信息下,能否用来优化这种一对多映射关系(尽可能靠近一对一),加快模型收敛?

考虑到一个voxel特征是其中所有3d点特征的均值,因此 pixel 到 voxel 满足多对多的映射关系。

还有一个映射密度的问题可能存在影响特征图质量,在距离相机更近(指顶角越大)的地方的一个voxel,其映射到的pixel数量更多。

LSS

从像素特征lift到点云特征

本文从任意数量的相机透视视角建立BEV特征,最后进行地图分割。

在将2D视图lift到3D视锥(frustum)中时,本文每个pixel的深度并不是确定的(正如笔者在OFT中说的一对多关系)。因此,对于每个pixel特征 \(\mathbf c\),与深度向量 \(\alpha\) 的外积得到在该pixel到相机孔射线上,一系列3D点的向量,最终构成了点云特征。 接着在点云空间中划分垂直地面的柱体(pillar),并使用sum pooling的方式将各个主体内的点云特征splat到BEV视角。

OFT是先建立voxel,之后对voxel中对应的不同2D点的(插值?)特征进行(无权重的)平均,最后加权求和一个柱体中的voxel;LSS则是从pixel出发,建立点云特征,保持同一条射线上的点云线性相关,最后在直接求和一个主体中的voxel。从直觉上,LSS的加权时机更合理。

PON

PON整体架构

本文继承了Occupancy Grid Maps的基本思想,希望使用多帧的相机视图来估计占据概率。

\[ p(m_i|z_t) = f_\theta(z_t, M_t^{-1}x_i) \]

其中,x_i 表示相机坐标系下某点坐标,\(M_t\) 表示相机外参,\(z_t\) 观测到该点占据状态,\(m_i\) 表示该点在BEV坐标系下是否被占据的状态;

理论上,正确的变换顺序是,先左乘内参矩阵的逆,再左乘外参矩阵的逆;这里直接左乘外参矩阵的逆,只有在相机的旋转/平移与投影方向正交时,才能保证两个变换可以交换。根据该点,此方法需要相机平面始终垂直于BEV平面?

在不同帧的状态迁移上,仍然使用贝叶斯方式;

在坐标变换上,这篇文章不是用投影关系2D->3D->2D,而是类似估计单应性矩阵的方式 2D->2D;在像素的H维度collapse,再往BEV的Z维度expand (均使用全连接层);

本文还有一个独特的假设是,高分辨率的特征图映射到更远的BEV区域;(某种程度上也平衡了远处和近处的稀疏关系)

M2BEV

本文使用多个相机视角,并训练多任务模型。

M2BEV在进行特征视角变换时,使用与LSS类似的策略,但是区别在于M2BEV对于每个pixel使用uniform的深度分布,即取消了可学习的深度向量 \(\alpha\)

为什么这样就比LSS减少了3倍显存占用?需要看代码

在构建好4D的voxel特征之后(具体怎么从点云特征构建该voxel特征没说,是同一个voxel内点云特征求均值吗?),使用所谓的S2C操作,其实就是将voxel特征沿着高度方向拼接起来,之后连接2D卷积减少拼接维度。

如果连接的2D卷积是单层1x1卷积的话,本质上与OFT中学习权重加权求和是一样的。

本文考虑了远处的voxel包含的pixel特征更稀疏的问题,为远处的样本点的分割损失应用更大的权重。

受到FreeAnchor的启发,设计了3D版本的learning to match的anchor到gt的匹配方式 (待看)。

使用了在nuScenes上的2D detector pretraining,用于初始化2D encoder,在训练过程中为不同尺度的特征使用了2D 检测头,计算aux loss。

Understanding Bird's-Eye View Semantic HD-maps Using an Onboard Monocular Camera

BEV HD-Maps的训练流程

本文是最早使用单目相机的多帧输入预测BEV地图分割的工作。

在处理透视图像特征时,将动态的前景目标和静态的区域分开解码,因为静态区域编码可能是重叠的(一个像素有多个静态标签),且前景目标只在关键帧有标注。

在已知相机内外参、地面坐标时,可以求得FV到BEV的单应性矩阵,how?

且在已知每一帧ego2global的变换时,可以将关键帧前后共 \(N\) 个frame的特征、静态区域heatmap均对齐到关键帧

不同帧的融合、特征与不同heatmap的融合如下图所示:

BEV HD-Map的时序特征融合策略

PYVA

CVP模块:与VPN类似,PYVA在将FV的feature变换到BEV的feature时,使用的是MLP:\(X' = \mathcal{F}_\text{MLP}(X)\) ;但是在此基础之上,再建立一组MLP将BEV feature变换回 FV feature:\(X'' = \mathcal{F}'_\text{MLP}(X')\);最小化 \(X''\)\(X\)\(\mathcal{L}_1\) 距离。

PYVA的CVT模块

CVT模块:之后,用 \(X'\) 作为query,\(X\)\(X''\) 分别作为key和value。计算 query \(X'\) 和 key \(X\) 的余弦相似度矩阵 \(R\),之后选出\(R\) 每一行的最大值 \(W\) 以及对应的索引 \(H\);使用该索引选择 value \(X''\) 对应的向量 \(T\)

上述操作与一个标准cross attn十分类似,以BEV特征为Q,以FV特征为K,V,Q、K、V使用不同的MLP获得更加丰富的表达。之后相当于将attention中的温度设为0(退化为argmax)得到了 \(T\)

之后是一些不太一样的shortcut

\[ X_{out} = X' + \mathcal{F}_{conv}(\operatorname{Concat}(X', T))\odot W \]

NEAT

NEAT模型结构

NEAT使用多视角单帧图像,以及目的坐标作为输入,预测未来 \(Z\) 个时刻的航路点(waypoint)和当前以及未来 \(Z\) 个时刻的BEV分割。

将多个视图图像分别过ResNet,得到的 \(S\times T\) 张特征图(视图数 \(S=3\),输入帧数 \(T=1\))均划分成 \(P\)\(C\) 通道的patch,并加上速度编码以及位置编码,送入一个Transformer进行自注意力,得到 \(\mathbf{c}\in \mathbb{R}^{STP\times C}\)

之后使用输出坐标系t时刻的位置坐标、时刻以及目的坐标组成的 \(\mathbf{p} = (x,y,t,x',y')\) 作为Q,希望能与 \(\mathbf{c}\) 的信息进行交换,进而最后能够用于解码 \((x,y)\) 位置距离waypoint的偏移,以及该位置的label。

Q是坐标,K,V是特征,这样也能attention? 一般的,笔者会想到把Q搞成带有位置编码的可学习的embedding,在本文里,直接搞了一个MLP \(a_\phi: \mathbb{R}^5\times\mathbb{R}^C\rightarrow \mathbb{R}^{STP}\),用这个函数来计算相似度。笔者还不太理解这个MLP是具体怎么设计的?

为什么要迭代?attention map不是一次计算好的,以解决显存占用?第 \(i\) 次迭代计算 \(\mathbf{p}\)\(c_{i-1}\) 的相似度 \(a_{i}\),归一化后再对 \(\mathbf{c}\) 加权得到 \(c_i\)。(其中 \(\mathbf c_0\)\(\mathbf c\)\(STP\) 个向量的均值)

非最后一次迭代的输出也可以在解码后受到监督作为aux loss。

解码器还是那个神奇的 MLP 结构 \(d_{\psi}: \mathbb{R}^5\times \mathbb{R}^{C} \rightarrow \mathbb{R}^K\times \mathbb{R}^2\)

BEVFormer

LiDAR

VoxelNet

这篇论文完全没有用到BEV视角。只要知道VoxelNet将3D点云划分为若干voxel,接着对非空voxel,用其中点云特征聚合得到4D voxel特征,并建立了voxel特征到3D点云坐标的哈希表。后面的特征计算用了非常费时的3D卷积。

知乎 - VoxelNet: 基于点云的三维空间信息逐层次学习网络

SECOND

SECOND基于VoxelNet改进。用稀疏3D卷积代替VoxelNet中的3D卷积。

知乎 - SECOND算法解析

PointPillars

PointPillars使用LiDAR数据做3D目标检测,并且不想用任何3D卷积。

知乎 - PointPillars: Fast Encoders for Object Detection from Point Clouds解读

CenterPoint

Camera+LiDAR

MV3D

MV3D网络结构

MV3D先将3D点云分别投影到front view和bird eye's view作为LiDAR输入,以获得更紧密的表示;对于鸟瞰网格视图,将点云信息为编码为M张高度图,1张密度图,1张强度图;对于前视网格视图,将点云信息投影到圆柱面而非平面以获得更加密集的表示,并使用高度、距离和强度3通道表示。一般的特征提取网络提取图像特征。

接下来,使用BEV下的LiDAR图预测3D proposals,再将其投影到前视视角和鸟瞰视角作为各自的2D候选区并各自进行ROI pooling。最后再进行deep fusion融合特征。

笔者觉得,按照文中3D点云到front view下所谓“圆柱面”的投影公式(定义源于Vehicle Detection from 3D Lidar Using Fully Convolutional Network),应该是个球面啊;

这里对点云特征的编码可以说是非常具有早期的hand-coded feature的感觉了。

AVOD

大致思路与MV3D一样,就是在BEV中提3D proposal再投影。

AVOD相比于MV3D的改进