ECCV2022 :BEVFormer 基于时空 Transformer 学习 BEV 表征

论文标题:BEVFormer: Learning Bird’s-Eye-View Representation from Multi-Camera Images via Spatiotemporal Transformers

论文链接:https://arxiv.org/abs/2203.17270

代码链接:https://github.com/fundamentalvision/BEVFormer

前言

目前存在的问题:1)流行的框架是基于深度信息的(LSS)生成 BEV 特征的,这种范式对深度值或深度分布的准确性很敏感。因检测性能会受到符合误差的影响,BEV 特征不准确会严重影响最终的性能。2)现有的多相机目标检测方法很少利用时间信息,简单堆叠不同时刻的 BEV 特征会带来额外的计算代价和推理信息,效果并不理想。

基于以上两点,本文作者选用了 Transfomer 动态聚合有价值的特征,利用 BEV 特征循环传递过去到现在的时间信息。

网络架构

在这里插入图片描述

核心流程:

  • 输入 4 个样本,包括 1 个当前样本、3 个历史样本,经过 backboneFPN 生成多尺度特征 F t − 3 F_{t-3} Ft3 F t − 2 F_{t-2} Ft2 F t − 1 F_{t-1} Ft1 F t F_{t} Ft
  • F t − 3 F_{t-3} Ft3 F t − 2 F_{t-2} Ft2 F t − 1 F_{t-1} Ft1 依次输入 encoder 生成 BEV 特征 B t − 3 B_{t-3} Bt3 B t − 2 B_{t-2} Bt2 B t − 1 B_{t-1} Bt1
  • B t − 1 B_{t-1} Bt1BEV Queries 输入 Temporal Self-Attention 查询并融合时间信息
  • F t F_t Ft 与融合时间信息后的 BEV Queries 输入 Spatial Cross-Attention 查询并融合空间信息
  • 循环 6 次最终输出当前 BEV 特征 B t B_t Bt

多尺度特征

BEVFormer 使用 resnet101 返回 stage1 , stage2 , stage3 阶段的特征,然后传入到 FPN 生成 4 种多尺度特征。

bevformer.py#extract_img_feat()

img = img.reshape(B * N, C, H, W) # torch.Size([6, 3, 928, 1600])
# resnet101返回stage1, stage2, stage3的feature maps
# 特征维度分别为512, 1024, 2048
# torch.Size([6, 512, 116, 200]), torch.Size([6, 1024, 58, 100])
# torch.Size([6, 2048, 29, 50])
img_feats = self.img_backbone(img)
# FPN返回4个feature maps,特征维度256
# torch.Size([6, 256, 116, 200]), torch.Size([6, 256, 58, 100])
# torch.Size([6, 256, 29, 50]), torch.Size([6, 256, 15, 25])
img_feats = self.img_neck(img_feats)

历史 BEV 特征

随机获取前 2 秒内的 3 个样本,经过 backboneFPN 获取多尺度特征 F t − 3 F_{t-3} Ft3 F t − 2 F_{t-2} Ft2 F t − 1 F_{t-1} Ft1,然后,迭代生成历史 BEV 特征 B t − 3 B_{t-3} Bt3 B t − 2 B_{t-2} Bt2 B t − 1 B_{t-1} Bt1

生成历史 BEV 特征的逻辑与生成当前 BEV 特征的逻辑一致,区别在于不需要进行反向传播。

transformer.py#obtain_history_bev()

# torch.Size([1, 3, 6, 3, 928, 1600])
bs, len_queue, num_cams, C, H, W = imgs_queue.shape
imgs_queue = imgs_queue.reshape(bs*len_queue, num_cams, C, H, W) 
# 获取多尺度特征(4个尺度,长宽分别为(116, 200)、(58, 100)、(29, 50)、(15, 25))
img_feats_list = self.extract_feat(img=imgs_queue, len_queue=len_queue)
# 迭代生成t-3,t-2,t-1时刻BEV特征
prev_bev = None
for i in range(len_queue):
    img_metas = [each[i] for each in img_metas_list]
    # 根据第二个维度len_queue拆分img_feats_list torch.Size([1, 6, 256, 116, 200])
    img_feats = [each_scale[:, i] for each_scale in img_feats_list]
    # pts_bbox_head 方法就是根据历史BEV和当前图片生成当前BEV
    # 此处循环迭代,以此生成t-3,t-2,t-1时刻BEV特征
    prev_bev = self.pts_bbox_head(img_feats, img_metas, prev_bev, only_bev=True)

BEV Queries

以车为中心,将 BEV 平面分成 (H , W ) 个网格,每个网格对应真实世界中的某块区域。

bevformer_base.py

# 点云范围,102.4, 102.4, 8
point_cloud_range = [-51.2, -51.2, -5.0, 51.2, 51.2, 3.0]
bev_h_ = 200 # BEV平面高
bev_w_ = 200 # BEV平面宽

真实世界的 HW 都是102.4, BEV 平面 HW 都是200,则每个网格代表的真实世界的大小就是相应位置 0.512mx0.512m 的区域。

Q ∈ R H × W × C Q\in\mathbb{R}^{H\times W\times C} QRH×W×C 是网格状的可学习参数,每个 q u e r y ∈ R 1 × C query\in\mathbb{R}^{1\times C} queryR1×C 负责 BEV 平面中相应的网格单元。

bevformer_head.py

# 表示Q结构时,将H,W拉平处理 torch.Size([(40000, 256)])
bev_queries = nn.Parameter(bev_h * bev_w, embed_dims)

时间自注意力

时间自注意力和空间交叉注意力最终的实现都是基于 deformable attention 。时间自注意力以 B t − 1 B_{t-1} Bt1BEV Quereis 作为入参,查询并融合时间信息。若 B t − 1 B_{t-1} Bt1 不存在则退化为自注意力。

BEV 平面网格的中心点作为时间自注意力中所需要的 reference points

encoder.py#get_reference_points()

ref_y, ref_x = torch.meshgrid(
                torch.linspace(0.5, H - 0.5, H, dtype=dtype, device=device),
                torch.linspace(0.5, W - 0.5, W, dtype=dtype, device=device)
            ) # torch.Size([200, 200])
ref_y = ref_y.reshape(-1)[None] / H # torch.Size([1, 40000])
ref_x = ref_x.reshape(-1)[None] / W # torch.Size([1, 40000])
ref_2d = torch.stack((ref_x, ref_y), -1) # torch.Size([1, 40000, 2])

根据 can_bus 里面的信息可以求出车的旋转角度和平移距离,移动 B t − 1 B_{t-1} Bt1 Q Q Q 对齐,记对齐后的历史 BEV 特征为 B t − 1 ′ B_{t-1}^{'} Bt1 。与 deformable attention 不同,时间自注意力中的每个 query 会与 t 时刻的 BEV queries B t − 1 B_{t-1} Bt1 交互,交互的结果求均值得到时间信息,再将时间信息融合到 BEV Queries 中。若 B t − 1 B_{t-1} Bt1 不存在,时间自注意力退化成自注意力。

value = torch.stack([query, query], 1) # 前一时刻BEV特征不存在,退化成自注意力
# value = torch.stack([prev_bev, query], 1) # 前一时刻BEV特征存在,时间自注意力

# 根据query获取 offsets 和 attention weights
query = torch.cat([value[:bs], query], -1) # torch.Size([1, 40000, 512])
sampling_offsets = self.sampling_offsets(query) # torch.Size([1, 40000, 8, 2, 1, 4, 2])
attention_weights = self.attention_weights(query).view(bs, num_query,
           	self.num_heads, self.num_bev_queue, self.num_levels * self.num_points)
sampling_locations = reference_points + sampling_offsets

output = MultiScaleDeformableAttnFunction.apply( # torch.Size([2, 40000, 256])
                value, spatial_shapes, level_start_index, sampling_locations,
                attention_weights, self.im2col_step)
# 与prev_bev和与query交互的结果求均值
output = output.mean(-1) # torch.Size([40000, 256, 1])
self.dropout(output) + identity

T S A ( Q p , { Q , B t − 1 ′ } ) = ∑ V ∈ { Q , B t − 1 ′ } D e f o r m A t t n ( Q p , p , V ) TSA(Q_p, \{Q, B_{t-1}^{'}\}) = \sum_{V\in\{Q, B_{t-1}^{'}\}}DeformAttn(Q_p, p, V) TSA(Qp,{Q,Bt1})=V{Q,Bt1}DeformAttn(Qp,p,V)

Q p Q_p Qp :BEV平面位置 p = ( x , y ) p = (x, y) p=(x,y) 对应的 query

Q Q Q : BEV Queries

B t − 1 ′ B_{t-1}^{'} Bt1 : 与 BEV Queries 对齐后的前一刻 BEV 特征

空间交叉注意力

空间交叉注意力以融合时间信息的 BEV Queries F t F_t Ft 作为入参,查询并融合空间信息。与时间自注意力从 2D 平面选取 reference points 不同,空间交叉注意力需要从 3D 空间中选取 reference points

BEV 平面上的每个网格沿着 z 轴往上延伸,然后,在柱状体内采样获取 reference points 。实质上就是在以车为中心的 3D 空间分成一个个小立方体,取立方体的中心作为 reference points

encoder.py#get_reference_points()

# 以bevformer_base.py配置为例,H, W, Z 分别 102.4m, 102.4m, 8m
# 归一化处理,用于后续等比例放大
zs = torch.linspace(0.5, Z - 0.5, num_points_in_pillar, dtype=dtype,
                    device=device).view(-1, 1, 1).expand(num_points_in_pillar, H, W) / Z 
xs = torch.linspace(0.5, W - 0.5, W, dtype=dtype,
                    device=device).view(1, 1, W).expand(num_points_in_pillar, H, W) / W
ys = torch.linspace(0.5, H - 0.5, H, dtype=dtype,
                    device=device).view(1, H, 1).expand(num_points_in_pillar, H, W) / H
# torch.Size([4, 200, 200, 3]) 4x200x200个立方体,每个立方体用(x,y,z)坐标表示
ref_3d = torch.stack((xs, ys, zs), -1) 

reference points 是归一化后的逻辑位置,用它计算出真实世界中的位置,然后通过相机的 projection matrix 将真实世界中的位置点投影到相机图片上,最后计算出归一化的图片坐标。为了减少计算量,使用掩码将投射不到的图片区域掩码。

encoder.py#point_sampling()

# 从img_meta取出每张图片的lidar2img矩阵,即投影矩阵projection matrix
lidar2img = img_meta['lidar2img']

# 参考点中的是逻辑位置,以0.5开始,需要转换成真实世界中的位置, x,y,z 都需要,此处只列举了 x
reference_points[..., 0:1] = reference_points[..., 0:1] * 
									(pc_range[3] - pc_range[0]) + pc_range[0]

# 计算出图片坐标
reference_points_cam = torch.matmul(lidar2img, reference_points)

eps = 1e-5
bev_mask = (reference_points_cam[..., 2:3] > eps) # torch.Size([4, 1, 6, 40000, 1])
# 投影时得到的3*1维,此时最后一位不一定是1,一定要经过归一化,即除以z后(x, y)才能作为图像上的点
# torch.Size([4, 1, 6, 40000, 2])
reference_points_cam = reference_points_cam[..., 0:2] / torch.maximum(
    reference_points_cam[..., 2:3], torch.ones_like(reference_points_cam[..., 2:3]) * eps)
reference_points_cam[..., 0] /= img_metas[0]['img_shape'][0][1] # 归一化,除以W
reference_points_cam[..., 1] /= img_metas[0]['img_shape'][0][0] # 归一化,除以H
# <=0 || >= 1 超出范围,加掩码 torch.Size([4, 1, 6, 40000, 1])
bev_mask = (bev_mask 
            & (reference_points_cam[..., 1:2] > 0.0) & (reference_points_cam[..., 1:2] < 1.0)
            & (reference_points_cam[..., 0:1] < 1.0) & (reference_points_cam[..., 0:1] > 0.0))

根据归一化的图片坐标,可以确定每个 reference points 对应的 F t F_t Ft 中的位置(与相应的 H, W 相乘)。后续与 Deformable Attenton 类似,在 F t F_t Ft 的相应位置附近采样,输出采样点的加权和(空间信息),在与 BEV Queries 融合。

S C A ( Q p , F t ) = 1 ∣ V h i t ∣ ∑ i ∈ V h i t ∑ j = 1 N r e f D e f o r m A t t n ( Q p , P ( p , i , j ) , F t i ) SCA(Q_p, F_t) = \frac{1}{|\mathcal{V_{hit}}|}\sum_{i\in \mathcal{V_{hit}}}\sum_{j=1}^{N_{ref}}DeformAttn(Q_p, \mathcal{P(p, i, j)}, F_t^i) SCA(Qp,Ft)=Vhit1iVhitj=1NrefDeformAttn(Qp,P(p,i,j),Fti)
Q p Q_p QpBEV 平面位置 p = ( x , y ) p = (x, y) p=(x,y) 对应的 query

F t F_t Ft : 时刻 t 的图片特征

V h i t \mathcal{V_hit} Vhit : p = ( x , y ) p = (x, y) p=(x,y) 沿着 z 轴采样的点投影到的相机图片

N r e f N_{ref} Nref : 每个 queryreference points 数量

P ( p , i , j ) \mathcal{P(p, i, j)} P(p,i,j) : 3D 点投影到 2D 点的投影函数

结论

BEVFormer 可以有效的聚合时空信息,生成强大的BEV特征,同时支持 3D 检测和地图语义分割任务。

缺陷:基于相机的方法与基于激光雷达的方法在效果和效率上仍存在很大的差距。从 2D 信息准确推断 3D 位置仍然是基于相机的方法面临的一个长期挑战。

影响:聚合时空信息可以显著提高视觉感知模型的性能。

参考资料

https://arxiv.org/abs/2203.17270

https://github.com/fundamentalvision/BEVFormer

https://zhuanlan.zhihu.com/p/543335939

https://www.bilibili.com/video/BV1PF411c78z

https://www.bilibili.com/video/BV1rK411o7PS

小龟慢跑

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值