1、前言

在BEV空间下进行视觉任务逐渐成为自动驾驶中的技术主流,为了搞懂如何在BEV下进行视觉任务,打算利用BEVFormer这个项目来理解其步骤,本文为BEVFormer的运行以及整体框架的梳理(源码看的有点乱了),后续如果源码看的比较熟练了,再准备出一个比较详细的注释。
BEVFormer源码:https://github.com/fundamentalvision/BEVFormer
BEVFormer学习文章:https://zhuanlan.zhihu.com/p/543335939

BEVFormer学习视频:https://www.bilibili.com/video/BV1rK411o7PS/?spm_id_from=333.788&vd_source=2055b62125c0277a0d6878f41c89fec2
欢迎正在学习或者想学习BEV模型的朋友加入交流群一起讨论、学习论文或者代码实现中的问题 ,可以加 v群:Rex1586662742,q群:468713665

2、运行

学习一个项目的必经之路首先是要将这个项目运行起来,建议完全按照官方的安装环境的方式,避免发生问题,装完环境后,按照官方的命令运行即可。那么如何进行debug来逐行进行查看呢?我使用的是pycharm进行debug,可以分为如下两个步骤

  • 链接launch.py
    首先找到当前conda环境(bev)下的的 launch.py文件链接到本项目
sudo ln -s /home/***/miniconda3/envs/bev/lib/python3.8/site-packages/torch/distributed/launch.py ./
  • 编辑配置
    点击运行,选择配置文件,脚本路径填入launch.py的绝对路径,形参中填入以下参数,需要修改为本机路径,一般来说就可以进行debug了,如果报错说找不到数据集里面的图片,那么就参考下文的第三条。
--nproc_per_node=1
--master_port=29503
/data/rex/BEV/BEVFormer-master/tools/test.py
/data/rex/BEV/BEVFormer-master/projects/configs/bevformer/bevformer_tiny.py
/data/rex/BEV/bevformer_tiny_epoch_24.pth
--launcher
pytorch
--eval
bbox
  • 链接数据集
    运行时,有可能报错说找不到data数据集,可以在tools/test.py 里面加上
print(os.getcwd())
sys.path.append(os.getcwd())

然后将项目里面的data数据集路径链接到os.getcwd()路径下面下面,运行时就不会报错了。

3、网络结构

按照惯例,首先还是要放一张论文中的示意图来进行说明,下图中,主要分为三个 部分,最左边的backbone,中间×6 的encoder,中间上面的Det/Seg Heads。

第一部分就是ResNet + FPN,BEVFormer主要的主要实在第二部分encoder进行了创新,即Temporal Self-Attention,Spatial Cross-Attention。

4、模型配置文件

本文采用的是tiny模型进行测试,几个模型之间的不同点主要在于bev_query的大小以及FPN的多尺度特征个数配置文件为projects/configs/bevformer/bevformer_tiny.py,模型的网络结构在此进行定义,运行时,首先会对下面的模块进行注册,从上到下基本上就是forward的步骤了。

model = dick(type='BEVFormer',...,# 主干网络img_backbone = dict(type='ResNet',...)# 提取不同尺度的特征img_neck=dict(type='FPN',...)# 编解码pts_bbox_head = dict(type='BEVFormerHead',...transformer=dict(type='PerceptionTransformer',...# 编码网络encoder=dict(type='BEVFormerEncoder',...# 单个block 推理时将会重复6次transformerlayers=dict(type='BEVFormerLayer',attn_cfgs=[dict(type='TemporalSelfAttention'...),dict(type='SpatialCrossAttention',deformable_attention=dict(type='MSDeformableAttention3D'...))]))# 解码网络decoder=dict(type='DetectionTransformerDecoder',...# decode blocktransformerlayers=dict(type='DetrTransformerDecoderLayer',attn_cfgs=[dict(type='MultiheadAttention',),dict(type='CustomMSDeformableAttention',...)])))bbox_coder = dict(type='NMSFreeCoder'...)# 可学习的位置编码positional_encoding = dict(type='LearnedPositionalEncoding',...)
)

5、forward 流程

能够进行debug后,就可以逐行代码进行查看变量的shape了,由于该项目涉及了很多模块,而且是用openmmlab实现的,刚接触时会有点绕,于是通过多次调试,我记录了推理的大致流程,基本上可以按下面的数字依次进行。

1、tools/test.py

outputs = custom_multi_gpu_test(model, data_loader, args.tmpdir,args.gpu_collect)
# 进入到projects/mmdet3d_plugin/bevformer/apis/test.py

2、projects/mmdet3d_plugin/bevformer/apis/test.py

def custom_multi_gpu_test(...):...for i, data in enumerate(data_loader):with torch.no_grad():result = model(return_loss=False, rescale=True, **data)# 进入到 projects/mmdet3d_plugin/bevformer/detectors/bevformer.py...

3、projects/mmdet3d_plugin/bevformer/detectors/bevformer.py

class BEVFormer(...):def forward(...):if return_loss:return self.forward_train(**kwargs)else:return self.forward_test(**kwargs)# 进入到下面 self.forward_testdef forward_test(...):...# forwardnew_prev_bev, bbox_results = self.simple_test(...)# 进入到下面 self.simple_test...def simple_test(...):# self.extract_feat 主要包括两个步骤 img_backbone、img_neck,通过卷积提取特征# 网络为resnet + FPN# 如果是base模型,img_feats 为四个不同尺度的特征层# 如果是small、tiny,img_feats 为一个尺度的特征层img_feats = self.extract_feat(img=img, img_metas=img_metas)# Temproral Self-Attention + Spatial Cross-Attentionnew_prev_bev, bbox_pts = self.simple_test_pts(img_feats, img_metas, prev_bev, rescale=rescale)# 进入到下面 self.simple_test_ptsdef simple_test_pts(...):# 对特征层进行编解码outs = self.pts_bbox_head(x, img_metas, prev_bev=prev_bev)# 进入到 projects/mmdet3d_plugin/bevformer/dense_heads/bevformer_head.py

4、projects/mmdet3d_plugin/bevformer/dense_heads/bevformer_head.py

class BEVFormerHead(DETRHead):def forward(...):...if only_bev:...else:outputs = self.transformer(...)# 进入到 projects/mmdet3d_plugin/bevformer/modules/transformer.pyfor lvl in range(hs.shape[0]):# 类别outputs_class = self.cls_branches[lvl](hs[lvl])# 回归框信息tmp = self.reg_branches[lvl](hs[lvl])outs = ...return out# 返回到 projects/mmdet3d_plugin/bevformer/detectors/bevformer.py  simple_test_pts函数中

5、projects/mmdet3d_plugin/bevformer/modules/transformer.py

class PerceptionTransformer(...):def forward(...):# 获得bev特征bev_embed = self.get_bev_features(...)def get_bev_features(...):# 获得bev特征 block * 6bev_embed = self.encoder(...)# 进入到projects/mmdet3d_plugin/bevformer/modules/encoder.py...# decoderinter_states, inter_references = self.decoder(...)# 进入到 projects/mmdet3d_plugin/bevformer/modules/decoder.py 中return bev_embed, inter_states, init_reference_out, inter_references_out# 返回到projects/mmdet3d_plugin/bevformer/dense_heads/bevformer_head.py

6、projects/mmdet3d_plugin/bevformer/modules/encoder.py

class BEVFormerEncoder(...):def forward(...):...for lid, layer in enumerate(self.layers):out = ...# 进入到下面的 class BEVFormerLayerclass BEVFormerLayer(...):def forward(...):# 通过layer进入到不同的模块中for layer in self.operation_order:# tmporal_self_attentionif layer == 'self_attn':# self.attentions 为 temporal_self_attention模块query = self.attentions[attn_index]# 进入到projects/mmdet3d_plugin/bevformer/modules/temporal_self_attention.py#  Spatial Cross-Attentionelif layer == 'cross_attn':query = self.attentions[attn_index]# 进入到 projects/mmdet3d_plugin/bevformer/modules/spatial_cross_attention.py

7、projects/mmdet3d_plugin/bevformer/modules/temporal_self_attention.py

class TemporalSelfAttention(...):def forward(...):output = ...# 残差链接   返回的结果为 Spatial Cross-Attention 模块的输入return self.dropout(output) + identity# 返回到projects/mmdet3d_plugin/bevformer/modules/encoder.py

8、projects/mmdet3d_plugin/bevformer/modules/spatial_cross_attention.py

class SpatialCrossAttention(...):
def forward(...):queries = self.deformable_attention(...)# 进入到下面的MSDeformableAttention3Dreturn self.dropout(slots) + inp_residual# 返回到返回到projects/mmdet3d_plugin/bevformer/modules/encoder.py# self.deformable_attentionclass MSDeformableAttention3D(BaseModule):def forward(...):eightsoutput = ...return output# 返回到上面 SpatialCrossAttention

9、projects/mmdet3d_plugin/bevformer/modules/decoder.py

class DetectionTransformerDecoder(...):def forward(...):for lid, layer in enumerate(self.layers):output = layer(...)# 进入到下面CustomMSDeformableAttention...if self.return_intermediate:intermediate.append(output)intermediate_reference_points.append(reference_points)return output, reference_points# 返回到 projects/mmdet3d_plugin/bevformer/modules/transformer.pyclass CustomMSDeformableAttention(...):def forward(...):'''query: [900, 1, 256] query_pos:[900, 1, 256] 可学习的位置编码'''output = multi_scale_deformable_attn_pytorch(...)output = self.output_proj(output)return self.dropout(output) + identity# 返回到上面的DetectionTransformerDecoder

6、总结

经过上面的步骤,基本疏通了BEVFormer的推理步骤,但是里面存在许多细节,由于还在看源码,以及有一些问题还没解决,后续的详解版本会对代码里面的变量进行详细注解(已经在写了,如果没啥问题的话),维度以及作用,一方面是加深对BEVFormer的理解,另一方面提高自己对BEV模型的认知。

[BEV] 学习笔记之BEVFormer(一)相关推荐

  1. [BEV]学习笔记之BEVDepth(原理+代码)

    文章目录 1.前言 2.模型简介 3.代码解析 4.总结 1.前言 继lift-splat-shoot之后,纯视觉BEV感知又有了新的进展,如旷视科技.华中理工和西安交大提出来的BEVDepth.本文 ...

  2. [BEV] 学习笔记之Lift, Splat, Shoot

    在开源的BEV模型中,可以追溯到2020年nvidia开源的 Lift-Splat- Shoot这篇论文中,论文的核心是显示的估计图像的深度特征,并转化为BEV特征,作为BEV视角下的开山鼻祖,自然是 ...

  3. [BEV] 学习笔记之BEVDet(原理+代码解析)

    前言 基于LSS的成功,鉴智机器人提出了BEVDet,目前来到了2.0版本,在nuscences排行榜中以mAP=0.586暂列第一名.本文将对BEVDet的原理进行简要说明,然后结合代码对BEVDe ...

  4. 3D目标检测学习笔记

    博主初学3D目标检测,此前没有相关学习背景,小白一枚-现阶段的学习重点是点云相关的3D检测. 本文是阅读文章:3D Object Detection for Autonomous Driving: A ...

  5. MIPS体系结构学习笔记

    MIPS体系结构学习笔记 第一章 概述 第二章 MIPS的体系结构 相关寄存器的时序 32个通用寄存器 通用寄存器的命名 32个浮点寄存器 基本地址空间 第三章 协处理器0(cp0):MIPS处理器控 ...

  6. 【MOT】多目标追踪学习笔记之MOTR

    1.前言 由于transformer的成功,现已经在多目标跟踪领域(MOTR)广泛应用,例如TransTrack和TrackFormer,但这两个工作严格来说不能算作端到端的模型,而MOTR的出现弥补 ...

  7. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  8. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  9. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

最新文章

  1. 使用 雨林木风 Ghost XP SP3 装机版 YN9.9 安装 Win7 (SP1)
  2. 你究竟了解多少HTML代码
  3. c++socket模型之我见
  4. python 高并发 select socket_python – 使用select处理多个请求
  5. (精简)Spring框架的IoC(替代工厂类实现方法)和AOP(定义规则,约定大于配置)
  6. linux安装多版本php_linux如何安装多个php版本
  7. 软件开发公司能开发哪些类型的app软件
  8. 华为云学习笔记(二)
  9. win10打开红警卡死的解决方法--win10专业版
  10. 新鲜出炉2010笑话集锦,我竟然一个都没听过
  11. 复旦大学高等代数学习指导书(白皮书)的评价
  12. win怎么在计算机里按日期搜索文件,Windows下怎么按时间查找文件
  13. 从一个例子开始体验轻量级类隔离容器 SOFAArk | SOFAChannel#11 直播整理
  14. 下拉菜单html菜鸟教程,Bootstrap 下拉菜单
  15. 怎样缩短c语言的占内存大小,关于优化:减少C语言中的内存使用的最佳实践是什么?...
  16. Java唐诗学习系统
  17. 3D模型欣赏:清纯美丽小姐姐
  18. STM32中的看门狗
  19. 超市通:修改价格牌、标签格式
  20. 深入谈谈String.intern()在JVM的实现

热门文章

  1. c语言自定义函数格式化,自定义函数的形式
  2. linux 基础 --04-07
  3. 2014假期学习安排和感触
  4. 剑走偏锋:基于静态检测的IE漏洞检测工具IEFuzz
  5. php 查看数组的指针,php数组指针
  6. STM32定时器中断配置
  7. 如何在Docker中安装MySQL数据库
  8. 岁月总有不动声色的力量
  9. MySQL学习之基础语法详解
  10. PHP扩展代码结构详解