使用稀疏查询进行3D目标检测

285 阅读8分钟

本文所涉及所有资源均在传知代码平台可获取。

概述

方法

SparseBEV是一个基于查询的单阶段检测器,具有L个解码器层。SparseBEV首先使用图像主干和FPN结构逐帧处理输入的多摄像机视频。之后,在BEV空间中初始化一组稀疏支柱查询,并通过自适应自注意力进行聚合。这些查询通过自适应时空采样和自适应混合与图像特征交互,以进行3D目标检测。

查询范式

SparseBEV首先定义了一组可学习查询,其中每个查询都由其平移[x,y,z][x,y,z],维度[w,l,h][w,l,h],旋转θθ和速度[vx,vy][v x,v y]表示。查询被初始化为BEV空间中的支柱,其中z被设置为0,h被设置为~4m。初始速度[vx,vy]=0[v x,v y]=0,其他参数(x,y,w,l,θ)(x,y,w,l,θ)来自于随机高斯分布。遵循Sparse R-CNN,SparseBEV将D维查询特征附加到每个查询框,以对丰富的实例特征进行编码。

尺度自适应自我注意力机制

基于密集BEV的方法通常使用BEV编码器来对多尺度BEV特征进行编码,然而,由于SparseBEV没有明确的构建BEV特征,如何在BEV空间中聚合多尺度特征仍然是一个挑战。

在这项工作中,SparseBEV认为自注意可以发挥BEV编码器的作用,因为查询是在BEV空间中定义的。因此,SparseBEV提出了尺度自适应自注意(SASA),它在查询的指导下学习适当的感受域。

首先,SparseBEV计算了BEV空间中查询中心之间的所有对距离D∈RN×NDR N×N(N是查询的数量)

注意力机制不仅考虑查询特征之间的相似性,还考虑它们之间的距离,公式如下

其中Q,K,V∈RN×dQ,K,VR N×d是查询本身,d是通道维数,ττ是控制每个查询的感受野的标量。当τ=0τ=0的时候,它退化维具有全局感受野的原始自注意力机制,随着ττ的增长,远程查询的注意力权重变小,接受域变窄。

在实践中,感受野控制器ττ对每个查询都是自适应的,并且对每个头部都是特定的。假设由H个头,SparseBEV使用线性变换从给定的查询q∈RdqR d生成头部特定τ1,τ2,...,τHτ1,τ2,...,τ H.

自适应时空采样

对于每一帧,SparseBEV使用线性层从查询特征自适应地生成一组采样偏移量{(Δxi,Δyi,Δzi)}{(Δx iy iz i)},这些偏移被转换为基于查询支柱的3D采样点。

与BEVFormer的可变形注意力相比,SparseBEV的采样点对查询柱和查询特征都具有自适应性,从而更好地覆盖不同大小的对象。此外,这些点不限于查询,因为SparseBEV不限制采样偏移的范围。

接下来,SparseBEV根据运动扭曲采样点来执行时间对齐。在自动驾驶中,有两种运动,一种是自我运动,一种是对象运动。自车运动描述汽车在环境中行驶时从自身角度的运动,而对象运动是指环境中其他物体在自动驾驶汽车周围移动时的运动。处理对象运动

在自动驾驶中,瞬时速度可以等于短时间窗口内的平均速度,因此,SparseBEV使用查询中的速度矢量,自适应地将采样点扭曲到以前的时间戳。

其中TtT t表示先前t时刻的帧(T0T0表示当前时刻的帧)

处理自车运动

接下来,我们SparseBEV数据集提供的自我姿态对采样点进行扭曲。首先将点变换到全局坐标系,然后变换到帧t的局部坐标系。

其中Et=[R∣t]E t=[Rt]是帧t时候的自车位置

采样

对于每个时间戳,SparseBEV使用相机内参和外参将扭曲的采样点{(xt,i′,yt,i′,zt,i′)}{(x t,i′,y t,i′,z t,i′)}投影到每个视图上。由于相邻视图之间纯在重叠,投影点可能会碰到一个或多个视图,这些视图被称为v。对于每个命中视图K,SparseBEV有来自图像主干的多尺度特征图Fk,j∣j∈{1,2,...,Nfeat}F k,jj∈{1,2,...,N f e a t}。特征首先在图像平面中通过双线性插值B进行采样,然后在比例轴上加权。

其中NfeatN f e a t是多尺度特征图的数量。PkP k是视图k的投影函数,wijw i j是第j个特征图上的第i个点的权重,并且通过线性变换从查询特征中生成。

自适应混合

给定不同时间戳和位置的采样特征,关键是如何在查询的指导下对齐进行自适应解码。受AdaMixer的启发,SparseBEV通过动态卷积和MLP混合器来解码和聚合时空特征。假设总共有T个帧,每个帧有5个采样点,SparseBEV首先将它们进行堆叠生成P=T×SP=T×S个点,因此,采样特征被组织维f∈RP×CfR P×C

通道混合

SparseBEV首先在f上执行通道混合,以增强目标的语义信息,根据特征查询q生成动态权重。

其中WcW c是动态权重,并且在不同的帧和不同采样点之间共享。

点混合

接下来,SparseBEV将特征进行转置,并且将动态权重应用于它的点维:

其中WpW p是动态权重,并且在不同的通道上进行共享。

在通道混合和点混合后,时空特征被线性层展平和聚合,最终的回归和分类预测分别由两个MLPs计算。

演示效果

bbox可视化

采样点可视化

核心逻辑

前向过程

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

准备数据集

1.从如下网站nuScenes数据集下载数据集,并且把放入 data/nuscenes文件夹下

  1. 从如下网址下载pkl文件Google Drive并且解压缩它们.

  2. 形成的文件夹如下图所示

data/nuscenes
├── maps
├── nuscenes_infos_test_sweep.pkl
├── nuscenes_infos_train_sweep.pkl
├── nuscenes_infos_train_mini_sweep.pkl
├── nuscenes_infos_val_sweep.pkl
├── nuscenes_infos_val_mini_sweep.pkl
├── samples
├── sweeps
├── v1.0-test
└── v1.0-trainval

参考文献

github地址

论文地址

感觉不错,点击我,立即使用