BEVFromer论文研读

news2024/12/22 19:11:55

1. 总体结构

image

上图为BEVFormer在t时刻的网络结构。图(a) 表示的是BEVFormer的encoder层。BEVFormer有6个encoder层,每一个encoder除了本文自定义的三个组件外都和传统的transformers结果一致。自定义的三个组件分别是网格状的BEV queries,TSA和SCA。其中BEV queries的参数是可学习的,它通过注意力机制查询多相机视角下的BEV空间特征;图(b)是SCA空间交叉注意力机制,每个BEV query只会提取图像感兴趣区域的特征;©是TSA时间自注意力机制,每个BEV query包括当前时刻的BEV queries和历史时刻的BEV 特征。

在推理时,在t时刻,首先喂入多相机视角图片进入backbone,获得多视角特征图,同时会保留t-1时刻的BEV 特征。在每一个encoder层,首先会使用BEV queries通过TSA查询t-1时刻的BEV 特征,然后BEV queries通过SCA查询多视角特征图的空间特征。在经过FFN(feed-forward network)后的输出作为下一层encoder的输入。就这样经过6个encoder层后,产生当前t时刻的BEV特征。将该特征作为输入,经过3D检测头和地图分割头输出最终预测的3D目标框和语义地图。

2. deformable attention

参考

Deformable DETR: DEFORMABLE TRANSFORMERSFOR END-TO-END OBJECT DETECTION

https://blog.csdn.net/weixin_40671425/article/details/121453942

之后有时间再细看。

3. BEV queries

预先定义一个形状为[H,W,C]的可学习的queries,代码中设置H=200,W=100,C=256。对于BEV平面上的每个网格大小都对应着真实世界的s米。BEV queries的中心对应当前自车位置。依据常见做法,在输入BEVFormer之前,BEV queries中添加可学习的位置编码。

# bevformer_head.py 151行 [20000,256]
bev_queries = self.bev_embedding.weight.to(dtype)  

在transformer.py第158-162行中,对queries做如下处理:

# add can bus signals
can_bus = bev_queries.new_tensor(
[each['can_bus'] for each in kwargs['img_metas']])  # [:, :]
can_bus = self.can_bus_mlp(can_bus)[None, :, :]
bev_queries = bev_queries + can_bus * self.use_can_bus

其中,can_bus为车辆自身在当前时刻的一些数据信息,包括线速度、角速度等信息。

4. temporal self-attention

为了更好的检测移动中物体的速度和解决严重遮挡的物体,bevformer作者提出temporal self-attention(TSA)用来将历史信息融合进当前特征中。

image

5. 历史BEV queries如何结合当前时刻的queries?

根据当前车辆位置信息,对前一时刻的prev_bev做微调,确保在同样的网格grid区域对应同样的真实世界的实际位置。

if prev_bev is not None:
	if prev_bev.shape[1] == bev_h * bev_w:
		prev_bev = prev_bev.permute(1, 0, 2)
		if self.rotate_prev_bev:
			for i in range(bs):
				# num_prev_bev = prev_bev.size(1)
				rotation_angle = kwargs['img_metas'][i]['can_bus'][-1]
				tmp_prev_bev = prev_bev[:, i].reshape(
				bev_h, bev_w, -1).permute(2, 0, 1)
				tmp_prev_bev = rotate(tmp_prev_bev, rotation_angle,
				center=self.rotate_center)
				tmp_prev_bev = tmp_prev_bev.permute(1, 2, 0).reshape(
				bev_h * bev_w, 1, -1)
				prev_bev[:, i] = tmp_prev_bev[:, 0]

在encoder.py BEVFormerEncoder类中,对prev_bev做如下处理:

当prev_bev存在时,将上面调整后的prev_bev和当前的bev_query合并。

if prev_bev is not None:
    prev_bev = prev_bev.permute(1, 0, 2)
    prev_bev = torch.stack(
        [prev_bev, bev_query], 1).reshape(bs*2, len_bev, -1)

在encoder.py BEVFormerLayer类中,在TSA的forward函数里,传入的value和key都是prev_bev,如果prev_bev为None时,用当前query代替:

if value is None:
    assert self.batch_first
    bs, len_bev, c = query.shape
    value = torch.stack([query, query], 1).reshape(bs*2, len_bev, c)

从t-1到t时刻,不同移动的目标在真实世界中有着不同的偏移,故在不同时刻对于相同的目标的BEV特征建立精确的关联性是非常有挑战的事情。本文作者通过TSA来建立这种关联性。具体公式:

image

对应代码(temporal_self_attention.py):

output = self.multi_scale_deformable_attn(
            value, spatial_shapes, reference_points, sampling_offsets, attention_weights
        ).flatten(2)
output = torch.mean(output,keepdim=True,dim=0)

6. Spatial Cross-Attention

由于在自动驾驶的3D感知任务中,输入是基于多视角图像的,其多头注意力计算消耗相当高。在bevformer中,作者基于2D的deformable attention方法,提出了Spatial Cross-Attention(SCA)。每一个BEV query都会根据六路相机视角提取感兴趣区域的空间特征。如下图所示:

image

上图为SCA示意图,中间区域的BEV query,周围为六路图像特征。从图中可以看到BEV query平面在z轴延伸四个点,用于采样图像中不同高度的空间特征。

首先,初始化采样点ref_3d,W为bev平面的宽,H为bev平面的高,Z为柱子的高,num_points_in_pillar表示每个柱子上采样的点的数目,在Z轴方向上也初始化了采样点,包含了路面上不同高度的物体。(代码在encoder.py的get_reference_points函数)

zs=torch.arange(0.5, Z-0.5+((Z-1)/num_points_in_pillar), (Z-1)/(num_points_in_pillar-1),dtype=dtype,
                                device=device).view(-1, 1, 1).expand(num_points_in_pillar, H, W) / Z
xs=torch.arange(0.5, W-0.5+((W-1)/W), (W-1)/(W-1),dtype=dtype,
                                device=device).view(1, 1, W).expand(num_points_in_pillar, H, W) / W
ys=torch.arange(0.5, H-0.5+((H-1)/H), (H-1)/(H-1),dtype=dtype,
                                device=device).view(1, H, 1).expand(num_points_in_pillar, H, W) / H
            
ref_3d = torch.stack((xs, ys, zs), -1).view(1,4,-1,3)

初始化后,将ref_3d点集范围缩放至pc_range指定的范围内,其中pc_range=[-30,-15,-2,30,15,2],表示以当前自车作为中心,取前后30米范围,左右15米范围,上下2米范围内的物体坐标。

# reference_points等于上面的ref_3d
reference_points = reference_points * torch.tensor(
            [
                pc_range[3] - pc_range[0],
                pc_range[4] - pc_range[1],
                pc_range[5] - pc_range[2],
            ],
            dtype=reference_points.dtype,
            device=reference_points.device,
        ).view(1, 1, 1, 3) + torch.tensor(
            pc_range[:3], dtype=reference_points.dtype, device=reference_points.device
        )

再利用传进来的lidar2img,将lidar坐标系下的采样点投至像素坐标系下。

reference_points_cam = torch.matmul(lidar2img.to(torch.float32),
                               reference_points.to(torch.float32)).squeeze(-1)

因为某个物体不一定在六路视角下同时都存在,所以这里对reference_points_cam做了条件判断,滤除在某些视角下不存在的坐标点,这样大大节约了计算资源。

上文获得的reference_points_cam即作为query的参考点,根据这些参考点采样对应视角下对应的特征。最后将采样的特征加权求和作为SCA的输出。具体公式如下:

image

对应代码(spatial_cross_attention.py):

queries = self.deformable_attention(query=queries_rebatch.view(bs*self.num_cams, max_len, self.embed_dims), key=key, value=value,
                                            reference_points=reference_points_rebatch.view(bs*self.num_cams, max_len, D, 2), spatial_shapes=spatial_shapes,
                                            level_start_index=level_start_index).view(bs, self.num_cams, max_len, self.embed_dims)
for j in range(bs):
    for i, index_query_per_img in enumerate(indexes):
        slots[j, index_query_per_img] += queries[j, i, :len(index_query_per_img)]

count = bev_mask.sum(-1) > 0
count = count.permute(1, 2, 0).sum(-1)
count = torch.clamp(count, min=1.0)
slots = slots / count[..., None]

7. 结果

image

具体结果可以查看原文。

特别说明:本系列文章仅供本文学习使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/687193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【智慧交通项目实战】 《 OCR车牌检测与识别》(三):基于改进CRNN的车牌识别

👨‍💻作者简介: CSDN、阿里云人工智能领域博客专家,新星计划计算机视觉导师,百度飞桨PPDE,专注大数据与AI知识分享。✨公众号:GoAI的学习小屋 ,免费分享书籍、简历、导图等&#xf…

接口测试实战篇,吐血整理汇总,接口测试你知多少?

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 接口测试&#xf…

网络安全应急响应最全教学从懵懂—入门—精通(2023年6月)

目录 0、写在前面1、概念及应急响应流程2、Windows排查2.1文件排查2.2、进程排查2.3、系统信息排查2.4、工具排查2.5、日志排查 3、Linux排查3.1、文件排查3.2、进程排查3.3、系统信息排查3.4、后门排查3.5、日志排查3.5.1、基于时间的日志管理3.5.2、系统日志管理3.5.3、中间件…

计算机毕业论文内容参考|基于网络的打印机数据传输系统的设计与实现

文章目录 导文前言绪论课题背景国内外现状与趋势课题内容相关技术与方法介绍系统分析系统设计系统实现系统测试总结与展望导文 计算机毕业论文内容参考|基于网络的打印机数据传输系统的设计与实现 前言 打印机是现代办公和生活中不可或缺的设备之一,随着信息化和网络化的发展…

常用激活函数及偏导

常用激活函数及偏导 derivative.py import numpy as np import matplotlib.pyplot as pltplt.subplots_adjust(hspace0.5 , wspace0.5) rows 3 cols 2def plot_style(ax):# 设置轴隐藏ax.spines[top].set_visible(False) ax.spines[right].set_visible(False)# 设置轴位置ax.…

python 创建二维列表【空列表或定长列表】

正确写法: 空列表设置了初始值的定长列表 ### 创建3行的二维空列表 ### a [[] for i in range(3)] print(a) # [[], [], []]### 每一行非空,并设定初始值及其长度 ### ### 创建3行,每一行列表初始化全0的列表,且长度为5 ### a…

Redis 实现库存扣减

在日常开发中有很多地方都有类似扣减库存的操作,比如电商系统中的商品库存,抽奖系统中的奖品库存等。这次分享的是库存的操作怎么防止商品被超卖。 解决方案 基于数据库单库存基于数据库多库存基于redis 解决思路 使用mysql数据库,使用一个…

[架构之路-216]- 架构 - 概念架构 - 模块(Module)、组件(Component)、包(Package)、对象、函数的区别

前言: 在软件架构中,一个重要的任务就是切分系统,而切分系统进程涉及到一个基本的概念,如模块(Module)、组件(Component)、包(Package)、对象,本…

亚马逊云科技以用户为中心,持续丰富安全服务和解决方案

AI加持安全,自动化运营成未来趋势 亚马逊云科技始终在云安全领域不断创新探索、深耕发力,随着全球技术的发展而持续迭代安全能力。 当下,以ChatGPT为代表的AIGC成为最出圈的热点,大量的科技巨头纷纷涌入AI赛道,投入了…

16. WebGPU 数据内存布局

在 WebGPU 中,提供给它的几乎所有数据都需要在内存中设定布局,以匹配在着色器中定义的内容。这与 JavaScript 和 TypeScript 形成鲜明对比,后者很少出现内存布局问题。 在 WGSL 中,当编写着色器时,通常定义 struct 。…

Redis集群详解

目录 一、前言二、Redis 集群方案应该怎么做?都有哪些方案?三、twemproxy四、分而治之-codis1、codis简介2、Codis 分片原理3、不同的 Codis 实例之间槽位关系如何同步?4、假如Redis扩容,如何调整槽位的?5、codis优缺点…

巧用 overflow-scroll 实现丝滑轮播图

前言: 近期我在项目中就接到了一个完成轮播图组件的需求。最开始我也像大家一样,直接选择使用了知名的开源项目 “Swiper”,但是后来发现它在移动端项目中某些测试环境下会白屏一段时间。无论如何调试都不能修复这个问题,于是就自己上手写了个…

Java智慧工厂UWB高精度人员定位管理系统源码

一、系统概述: 智慧工厂高精度定位管理系统源码,采用UWB定位技术,通过部署UWB定位设备实现人、车、物精确定位,打造可寻、可视、可防、可控的一体化管控平台。UWB定位系统具有容量大、稳定性强、精度高、安装便捷、易维护、操作简…

pebblely无需代码连接集简云数据表的方法

1 使用场景 当电商UI接到一个设计产品图的需求时,按照常规的工作安排,从对接需求到最后完成效果图最短时间都要在5天左右,如果遇到高要求的客户,后期还需要在电脑上进一步调整细节,一张成片起码要花上数小时时间去完成…

LabVIEW开发压电陶瓷特性测试系统

LabVIEW开发压电陶瓷特性测试系统 目前,随着科学技术的飞速发展,各个领域都需要纳米级的精密定位系统。而压电定位系统是迄今为止已经得到认可的微纳定位系统。该系统主要由压电驱动系统、位移测量传感器和控制系统组成。其中,整个压电驱动系…

oracle 使用sql语句实现交换一个表中两条记录的某个字段的内容

不要太忙了 好好珍惜眼下 的真爱 (马晓静sorry~) 表 test --------------- id | i_order --------------- 1 | 22 2 | 23 --------------- 转换后结果为: --------------- id | i_order --------------- 1 | 23 2 | …

【云原生丶Docker】Docker镜像常用命令大全

镜像是Docker中最为核心也是最具创造性的概念!在理解Docker的核心概念文章中,我们理解了镜像的含义,下面让我们一起操作一些镜像,包括拉取、推送镜像等操作。 1、镜像支持哪些命令 通过 docker image help 查看 Docker 支持的镜像…

解决nacos频繁输出get changegroupkeys日志

# 1、根据心跳日志,定位日志输出的包名 c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]# 2、在 IDEA 中搜索 ClientWorker 所在的包路径 package com.alibaba.nacos.client.config.impl;# 3、在任意格式的配置文件中将该包路径的日志设置为…

Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理

Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理 目录 Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理 一、简单介绍 二、实现原理 三、注意实现 四、简单实现步骤 五、关键代码 六、附加 创建新的 .NET Core ,获取 Azure.AI.OpenAI d…

公司个人年终工作总结【10篇】

公司个人年终工作总结1 20__年即将过去,在公司领导的悉心关怀下和同事们的帮助指导下,结合我自身的努力,在工作、学习等各方面都取得了长足的进步,尤其是在保险理赔专业知识和技能培养方面的成熟,使我成为一名合格的车…