目录
代码链接https://github.com/WangYueFt/detr3d
原理简介:
不同于LSS、BEVDepth的bottom-up式,先进行深度估计,设计2D转3D的模块。DETR3D是一种3D转2D的top-down思路。先预设一系列预测框的查询向量object querys,利用它们生成3D reference point,将这些3D reference point 利用相机参数转换矩阵,投影回2D图像坐标,并根据他们在图像的位置去找到对应的图像特征,用图像特征和object querys做cross-attention,不断refine object querys。最后利用两个MLP分支分别输出分类预测结果与回归预测结果。正负样本则采用和DETR相同的二分图匹配,即根据最小cost在900个object querys中找到与GT数量最匹配的N个预测框。由于正负样本匹配以及object querys这种查询目标的方式与DETR类似,因此可以看成是DETR在3D的扩展。
数据准备:
把你的nuscenes数据集,软链接或者直接放到工程下的data文件夹内
预训练权重不想下载就修改detr3d_res101_gridmask.py
load_from=‘’
运行方法:
/home/xxx/anaconda3/envs/{YOUR_ENV}/lib/python3.8/site-packages/torch/distributed/launch.py --nproc_per_node=1
tools/train.py
projects/configs/detr3d/detr3d_res101_gridmask.py
nproc_per_node为GPU数量
源码阅读:
#数据输入:
data_batch的包含四个变量:
变量 | 作用 |
---|---|
img_meta | 图像尺寸,lidar2img外参等 |
gt_bboxes_3d | 3d box的尺寸和位置等 |
gt_labels_3c | 3d box的类别 |
img | 输入图像Tensor |
前向传播
GridMask数据增强
随机遮掩防止过拟合
backbone+neck
输入图像为
[b,n,c,w,h]
其中b为batch,n为摄像头数量
每张图像处理是一样的,所以b和n维度合并,输入到backbone的shape为
[bn,c,w,h]
backbone为resnet,经过backbone输出为
[[bn,64,w/4,h/4],[bn,128,w/8,h/8],[bn,256,w/16,h/16],[bn,512,w/32,h/32]]
neck为fpn,经过neck的输出为
[[bn,64,w/8,h/8],[bn,64,w/16,h/16],[bn,64,w/32,h/32],[bn,64,w/64,h/64]]
b和n维度解开:
[[b,n,64,w/8,h/8],[b,n,64,w/16,h/16],[b,n,64,w/32,h/32],[b,n,64,w/64,h/64]]
head
Detr3DTransformer
目标qurey:query_embeds,shape=[num_query,embed_dims * 2]
前一半作为position_embedding, 后一半作为content_embedding
query_pos, query = torch.split(query_embed, self.embed_dims , dim=1)
query_pos经过全连接生成reference_points(目标的参考3d位置,范围[0,1],以整个bev图为参考):[b,num_query,embed_dims]->[b,num_query,3]
DetrTransformerDecoderLayer(BaseTransformerLayer)
-
self_attn
query[b,num_query,embed_dims]进行self_attention,位置编码为query_pos
目标编码之间进行交互,据说可以移除冗余框;为了让模型训练的更快更稳定(后面需要测试以下这个self_attention的作用) -
cross_attn
query[b,num_query,embed_dims]线性映射为attention_weights [b,1,num_query,n,num_points,num_level]
其中num_points为采样点数量,num_level为特征层数量
feature_sampling
reference_points转换到lidar坐标系下,再根据lidar2img转到图像坐标系,再除以图像尺度归一化到[-1,1]之间
使用F.grid_sample在多尺度特征中进行特征采样
mask标记在图像范围外的reference_points
attention_weights*mask屏蔽无效query
将得到的output首先和attention_weigth相乘,然后连续三个sum(-1),将不同相机,不同尺度的feature直接相加,将这些特征都融合再一起,再通过一个out_proj的线性层,output就和之前shape一样了[b,num_query,embed_dims],方便下一次迭代.
注意: num_points实际上不论是几都等效于1,reference_points映射到图像只能是1对1,采样过程也是1对1.除非用deformable_detr.
Iterative Bounding Box Refinement(针对box的xyz位置信息)
初始一个reference_points,每次经过transfomer_layer的query再经过reg_branch层输出box的偏差,这个偏差和前一层的reference_points进行add操作,得到新得reference_points输入给下一级.
思考下:这个策略是不是和辅助损失相冲突?
loss
类别头只处理最后一层即可,reg头需要处理每一层用于Iterative Bounding Box Refinement
类别结果,来源于类别头
回归结果,来源于最后一个reg头和倒数第二层的reference_points
和DETR类似,在所有object queries预测出来的预测框和所有GT box之间利用匈牙利算法进行二分图匹配,找到使得cost最小的最优匹配。
①. 分别计算分类cost:focal loss, 回归cost:l1 loss, 两者的和作为cost代价矩阵
②. 利用二分图匹配获得使cost最小的匹配结果