DETR3d原理和源码解读


代码链接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_3d3d box的尺寸和位置等
gt_labels_3c3d 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)
  1. self_attn
    query[b,num_query,embed_dims]进行self_attention,位置编码为query_pos
    目标编码之间进行交互,据说可以移除冗余框;为了让模型训练的更快更稳定(后面需要测试以下这个self_attention的作用)

  2. 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最小的匹配结果

### DETR 源码解析及其 PyTorch 官方教程 #### 1. **DETR 的整体架构** DETR 是一种端到端的目标检测算法,其核心组件包括 Transformer 编码器解码器、位置编码以及多头注意力机制。它摒弃了传统的非极大值抑制 (NMS) 锚框设计,转而采用集合预测的方式完成目标检测任务。 - DETR 使用了一个简单的 CNN 主干网络提取特征图,并将其展平为一维序列输入给 Transformer。 - 通过引入可学习的位置嵌入向量来增强空间信息的学习能力[^1]。 #### 2. **主要模块详解** ##### (1)**项目配置与数据处理** `CocoDetection` 类用于加载 COCO 数据集并返回图像张量与其对应的标注信息。 `ConvertCocoPolysToMask` 则负责将 COCO 格式的多边形掩膜转换成二值掩膜矩阵形式以便后续计算损失函数时使用。 ```python from torchvision.datasets import CocoDetection import transforms as T class ConvertCocoPolysToMask(object): def __call__(self, image, target): w, h = image.size # 转换过程省略... return image, target ``` ##### (2)**Transformer 结构** Transformer 构成了 DETR 的核心部分,分为编码器解码器两大部分: - **编码器**: 接收来自 Backbone 提取的特征图作为输入,经过多次自注意操作后输出高阶语义表示; - **解码器**: 输入一组固定的查询向量(query vectors),这些向量会逐步更新并通过交叉注意机制获取全局上下文信息最终生成边界框坐标及类别概率分布[^5]。 具体实现上定义了 `TransformerEncoderLayer`, `TransformerDecoderLayer` 等子模块分别对应单层 Encoder 或 Decoder 的逻辑[^6]。 ##### (3)**位置编码** 为了帮助模型更好地捕捉像素间相对距离关系,在送入 Transformer 前需附加额外的空间先验知识即正弦型位置编码(Sine Positional Encoding)[^7]: ```python def sine_position_encoding(x_shape, dim=256): temperature = 10000. num_pos_feats = dim // 2 mask = torch.zeros((x_shape[-2], x_shape[-1]), dtype=torch.bool).to(device) not_mask = ~mask y_embed = not_mask.cumsum(0, dtype=torch.float32) x_embed = not_mask.cumsum(1, dtype=torch.float32) eps = 1e-6 y_embed = y_embed / (y_embed[:, -1:] + eps) x_embed = x_embed / (x_embed[-1:, :] + eps) dim_t = torch.arange(num_pos_feats, dtype=torch.float32, device=device) dim_t = temperature ** (2 * (dim_t // 2) / num_pos_feats) pos_x = x_embed[..., None] / dim_t pos_y = y_embed[..., None] / dim_t pos_x = torch.stack((pos_x[..., 0::2].sin(), pos_x[..., 1::2].cos()), dim=-1).flatten(-2) pos_y = torch.stack((pos_y[..., 0::2].sin(), pos_y[..., 1::2].cos()), dim=-1).flatten(-2) pos = torch.cat((pos_y, pos_x), dim=-1).permute(2, 0, 1).unsqueeze(0) return pos.repeat(x_shape[0], 1, 1, 1) ``` ##### (4)**Backbone 设计** 通常选用 ResNet 系列预训练好的卷积神经网络充当主干网路角色,提供高质量低分辨率特征映射供下游任务利用[^8]。 ##### (5)**Loss Function** 总损耗由三方面构成:分类误差、L1 回归偏差度量项还有 GIoU 度量标准共同决定优化方向[^9]。 --- #### 3. **如何按照官方教程运行 DETR?** 根据参考资料中的描述可以得知如下步骤指南: 1. 首先克隆官方仓库至本地环境; 2. 下载预训练权重文件放置指定路径下; 3. 修改配置参数适配个人需求场景比如调整 batch size 大小或者 epoch 数目等等; 4. 执行脚本启动训练流程观察日志变化趋势直至收敛为止[^3]. 对于 RT-DETR 这种改进版本而言,则提供了更大的自由度允许开发者自行调节某些超参从而满足特定应用场景下的性能指标要求而不必完全依赖于重头再来一遍完整的迭代周期[^4]. ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知其所以然也

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值