💛前情提要💛
本文是传知代码平台
中的相关前沿知识与技术的分享~
接下来我们即将进入一个全新的空间,对技术有一个全新的视角~
本文所涉及所有资源均在传知代码平台可获取
以下的内容一定会让你对AI 赋能时代
有一个颠覆性的认识哦!!!
以下内容干货满满,跟上步伐吧~
📌导航小助手📌
- 💡本章重点
- 🍞一. 概述
- 🍞二. 方法
- 🍞三.演示效果
- 🍞四.核心逻辑
- 🫓总结
💡本章重点
- 使用稀疏查询进行3D目标检测
🍞一. 概述
SparseBEV是一个基于查询的单阶段检测器,具有L个解码器层。SparseBEV首先使用图像主干和FPN结构逐帧处理输入的多摄像机视频。之后,在BEV空间中初始化一组稀疏支柱查询,并通过自适应自注意力进行聚合。这些查询通过自适应时空采样和自适应混合与图像特征交互,以进行3D目标检测。
🍞二. 方法
尺度自适应自我注意力机制
基于密集BEV的方法通常使用BEV编码器来对多尺度BEV特征进行编码,然而,由于SparseBEV没有明确的构建BEV特征,如何在BEV空间中聚合多尺度特征仍然是一个挑战。
在这项工作中,SparseBEV认为自注意可以发挥BEV编码器的作用,因为查询是在BEV空间中定义的。因此,SparseBEV提出了尺度自适应自注意(SASA),它在查询的指导下学习适当的感受域。
注意力机制不仅考虑查询特征之间的相似性,还考虑它们之间的距离,公式如下:
自适应时空采样
对于每一帧,SparseBEV使用线性层从查询特征自适应地生成一组采样偏移量,这些偏移被转换为基于查询支柱的3D采样点。
与BEVFormer的可变形注意力相比,SparseBEV的采样点对查询柱和查询特征都具有自适应性,从而更好地覆盖不同大小的对象。此外,这些点不限于查询,因为SparseBEV不限制采样偏移的范围。
接下来,SparseBEV根据运动扭曲采样点来执行时间对齐。在自动驾驶中,有两种运动,一种是自我运动,一种是对象运动。自车运动描述汽车在环境中行驶时从自身角度的运动,而对象运动是指环境中其他物体在自动驾驶汽车周围移动时的运动。
处理对象运动
在自动驾驶中,瞬时速度可以等于短时间窗口内的平均速度,因此,SparseBEV使用查询中的速度矢量,自适应地将采样点扭曲到以前的时间戳。
处理自车运动
接下来,我们SparseBEV数据集提供的自我姿态对采样点进行扭曲。首先将点变换到全局坐标系,然后变换到帧t的局部坐标系。
🍞三.演示效果
🍞四.核心逻辑
前向过程
def forward(self, mlvl_feats,img_metas):
# 类似于DAB-DETR,其中查询被显式表示为最终的结果,所以可以直接进行细化处理,采用同样的操作,所以属于静态
query_bbox = self.init_query_bbox.weight.clone() # [Q, 10]
#query_bbox[..., :3] = query_bbox[..., :3].sigmoid()
# query denoising
B = mlvl_feats[0].shape[0]
# BEV中都是在头部就使用了prepare_dn的形式,头部就完成了所有的事情,包括预测的结果,query其中是包含噪声的情况
query_bbox, query_feat, attn_mask, mask_dict = self.prepare_for_dn_input(B, query_bbox, self.label_enc, img_metas)
cls_scores, bbox_preds = self.transformer(
query_bbox,
query_feat,
mlvl_feats,
attn_mask=attn_mask,
img_metas=img_metas,
)
# 将边界框重新转换为现实坐标中
bbox_preds[..., 0] = bbox_preds[..., 0] * (self.pc_range[3] - self.pc_range[0]) + self.pc_range[0]
bbox_preds[..., 1] = bbox_preds[..., 1] * (self.pc_range[4] - self.pc_range[1]) + self.pc_range[1]
bbox_preds[..., 2] = bbox_preds[..., 2] * (self.pc_range[5] - self.pc_range[2]) + self.pc_range[2]
bbox_preds = torch.cat([
bbox_preds[..., 0:2],
bbox_preds[..., 3:5],
bbox_preds[..., 2:3],
bbox_preds[..., 5:10],
], dim=-1) # [cx, cy, w, l, cz, h, sin, cos, vx, vy]
# 如果采用了denoise的形式,这是一步重构策略比较重要,
if mask_dict is not None and mask_dict['pad_size'] > 0: # if using query denoising
# 此时获得的是denoise后的结果
output_known_cls_scores = cls_scores[:, :, :mask_dict['pad_size'], :]
output_known_bbox_preds = bbox_preds[:, :, :mask_dict['pad_size'], :]
# 此时是需要进行match的情况
output_cls_scores = cls_scores[:, :, mask_dict['pad_size']:, :]
output_bbox_preds = bbox_preds[:, :, mask_dict['pad_size']:, :]
# 此时是输出的结果,但输出的结果不一定需要完全正确,真值是没有output的形式
mask_dict['output_known_lbs_bboxes'] = (output_known_cls_scores, output_known_bbox_preds)
# 将其进行修改,其中all_cls_scores只保存match的query的形式
outs = {
'all_cls_scores': output_cls_scores,
'all_bbox_preds': output_bbox_preds,
'enc_cls_scores': None,
'enc_bbox_preds': None,
'dn_mask_dict': mask_dict,
}
else:
outs = {
'all_cls_scores': cls_scores,
'all_bbox_preds': bbox_preds,
'enc_cls_scores': None,
'enc_bbox_preds': None,
}
return outs
部署方式
# Install PyTorch 2.0 + CUDA 11.8
conda create -n sparsebev python=3.8
conda activate sparsebev
conda install pytorch==2.0.0 torchvision==0.15.0 pytorch-cuda=11.8 -c pytorch -c nvidia
# PyTorch 1.10.2 + CUDA 10.2 for older GPUs
conda create -n sparsebev python=3.8
conda activate sparsebev
conda install pytorch==1.10.2 torchvision==0.11.3 cudatoolkit=10.2 -c pytorch
# Install other dependencies:
pip install openmim
mim install mmcv-full==1.6.0
mim install mmdet==2.28.2
mim install mmsegmentation==0.30.0
mim install mmdet3d==1.0.0rc6
pip install setuptools==59.5.0
pip install numpy==1.23.5
# Install turbojpeg and pillow-simd to speed up data loading (optional but important):
sudo apt-get update
sudo apt-get install -y libturbojpeg
pip install pyturbojpeg
pip uninstall pillow
pip install pillow-simd==9.0.0.post1
pip install numpy==1.23.5
pip install fvcore
pip install einops
# Compile CUDA extensions:
cd models/csrc
python setup.py build_ext --inplace
🫓总结
综上,我们基本了解了“一项全新的技术啦” 🍭 ~~
恭喜你的内功又双叒叕得到了提高!!!
感谢你们的阅读😆
后续还会继续更新💓,欢迎持续关注📌哟~
💫如果有错误❌,欢迎指正呀💫
✨如果觉得收获满满,可以点点赞👍支持一下哟~✨
【传知科技 – 了解更多新知识】