Detect-and-Track论文:3D Mask R-CNN Caffe2源代码解析——3.RPN&FPN构建

2023-05-16

在第二部分,我们对ResNet18的结构进行了分析。当图像经过ResNet18后,会产生Feature Map(特征图)。这些特征图将会被送到RPN(Region Proposal Network-候选区域生成网络)中来产生RoI。在此文章采用的RPN中,使用了FPN结构。

参考内容链接如下:

Detect-and-Track源代码:【网页链接】

Generic Object Detection综述文章:【网页链接】

FPN论文:【网页链接】


目录

一、RPN简单回顾

二、FPN简单回顾

三、RPN&FPN构建过程

1. model_builder.py

2. FPN3D.py

四、一些疑问


一、RPN简单回顾

首先看一下RPN是怎么来的,在综述文献中我们看到R-CNN家族进化史中的这个部分:

尽管Fast R-CNN在R-CNN的基础上提升了速度,但是候选区域的计算(Selective Search)成为了Fast R-CNN的瓶颈。Faster R-CNN用CNN网络来代替Selective Search生成候选区域,速度得到了数量级级别的提升。RPN的主要步骤如下:

卷积:首先对Backbone卷积得到的特征图再进行一次卷积,目的有两个:再次提取特征、重新设置一下张量的维度。

红色框部分“For Each Spatial Location”:此处以特征图上每个像素为中心,生成一系列Anchors(锚框),每个锚框有3个尺度,3个纵横比(一般来说是这样的设定)。最后会像下图这个样子。

sibling FC layers之后这些锚框进入两个“sibling FC layers”(姐妹全连接网络)Cls和Reg:分类和回归。分类是要进行前景/背景分类,本质是一个二分类,确定这个锚框是否是背景。对于前景的锚框,网络会基于Ground Truth(人标记的框),对锚框进行修正,修正结果如下:

 


二、FPN简单回顾

FPN被提出的初衷就是提高网络对物体尺度的敏感性。R-CNN家族前期的网络都是在单个尺度上的Feature Map上进行分析,这导致了小物体在卷积之后变得更小,增大了识别难度。而FPN采用了金字塔结构,使得网络可以在不同的特征图层上对物体进行识别,提高了小物体识别准确率。其原理可以用此结构图来阐明:

左侧是我们用Backbone对图像进行卷积的过程,随着卷积的进行,特征图越来越厚,分辨率越来越小。之前我们是采用某一个层上的特征图用于识别,现在进行扩展:

Backbone:一般采用ResNet,左侧每层自底向上依次命名为:C1、C2、C3、C4。其中C1分辨率最大,C4分辨率最小。每层之间长宽差2倍,面积差4倍。

右侧上采样:在右侧,最小的图像C4直接传递过来变为P4。P4进行上采样后,尺度与C3保持一致。经过“lateral conn /侧连接”后,与C3相加得到P3。以此类推得到P2。

lateral conn:侧连接,P层的得出,既需要上级P层的上采样,还需要C级的求和。

注意:左侧结构中,随着C层级别的升高,蓝色框逐渐变厚。蓝框代表“语义强度”,即抽象的程度。可以发现,随着卷积的进行:分辨率越低,语义强度越强;分辨率月高,语义强度曰弱。而通过这种侧连接的方式,右侧P层中,每层都由两部分构成:一个是强语义支流上采样得来,一个是高分辨率支流得来。所以P层中每层都包含丰富的语义含义。这也是FPN的精妙之处。


三、RPN&FPN构建过程

1. model_builder.py

此文件中的build_generic_fast_rcnn_model()函数构建了整个网络,其中包含RPN&FPN构建的下列代码,代码主要包含三部分:

★首先选择FPN库,使用3D版本。

[Key]之后构建RPN网络,调用add_fpn_rpn_outputs()函数,构建含有FPN的RPN网络。

★最后将FPN中各层信息取出。

# Select the FPN lib, based on whether the head is 3D or 2D,3D
		# 先选择FPN库,3D还是2D
		if cfg.MODEL.VIDEO_ON and cfg.VIDEO.BODY_HEAD_LINK == '':
			FPN_lib = FPN3D
			head_3d = True
			out_time_dim = cfg.VIDEO.NUM_FRAMES_MID		# 3
		else:
			FPN_lib = FPN
			head_3d = False
			out_time_dim = 1

		# ★  Add the RPN branch(区域候选网络)
		if cfg.MODEL.FASTER_RCNN:	# True  使用Faster-RCNN
			if cfg.FPN.FPN_ON:		# FPN特征金字塔
				FPN_lib.add_fpn_rpn_outputs(	# 创建带FPN的RPN
					model, blob_conv, dim_conv, spatial_scale_conv,
					time_dim=out_time_dim)
				model.CollectAndDistributeFpnRpnProposals()
			else:
				# 创建一个单独的RPN
				add_rpn_outputs(model, blob_conv, dim_conv, spatial_scale_conv,
								nd=head_3d, time_dim=out_time_dim)

		if cfg.FPN.FPN_ON:
			# Code only supports case when RPN and ROI min levels are the same
			assert cfg.FPN.RPN_MIN_LEVEL == cfg.FPN.ROI_MIN_LEVEL	# 都是2
			# FPN RPN max level might be > FPN ROI max level in which case we
			# need to discard some leading conv blobs (blobs are ordered from
			# max level to min level)
			num_roi_levels = cfg.FPN.ROI_MAX_LEVEL - cfg.FPN.ROI_MIN_LEVEL + 1	# 5-2+1 = 4
			blob_conv = blob_conv[-num_roi_levels:]	# 把最后四个取出来:2、3、4、5层
			spatial_scale_conv = spatial_scale_conv[-num_roi_levels:]

2. FPN3D.py

add_fpn_rpn_outputs()就是RPN的构建过程。首先一个for循环对每层进行处理,内部if筛选出feat第2层单独进行处理,else处理第3、4、5、6层。

def add_fpn_rpn_outputs(model, blobs_in, dim_in, spatial_scales, time_dim):
	# blobs_in是什么?怎么还分层了?ResNet的时候就取出了每层的feat?
	
	num_anchors = len(cfg.FPN.RPN_ASPECT_RATIOS)	# 长度为3   (0.5, 1, 2)
	dim_out = dim_in
	raise NotImplementedError('Redo bbox_targets like in model_builder.py')
	if cfg.VIDEO.DEBUG_USE_RPN_GT:
		raise NotImplementedError('Need to implement this similar to non-FPN')

	k_max = cfg.FPN.RPN_MAX_LEVEL  # coarsest level of pyramid	6层 最粗糙
	k_min = cfg.FPN.RPN_MIN_LEVEL  # finest level of pyramid	2层 最清晰
	
	assert len(blobs_in) == k_max - k_min + 1		# 共有5层
	
	for lvl in range(k_min, k_max + 1):	# 遍历2到6层
		bl_in = blobs_in[k_max - lvl]  # blobs_in is in reversed order
		sc = spatial_scales[k_max - lvl]  # in reversed order
		slvl = str(lvl)

		# 对金字塔第2层创建RPN
		if lvl == k_min:
		
			# ★Create conv ops with randomly initialized weights and
			# zeroed biases for the first FPN level; these will be shared by
			# all other FPN levels
			# RPN hidden representation
			conv_rpn_fpn = model.ConvNd(
				bl_in, 'conv_rpn_fpn' + slvl,	# conv_rpn_fpn2
				dim_in, dim_out, [cfg.VIDEO.TIME_KERNEL_DIM.HEAD_RPN, 3, 3],
				pads=2 * [cfg.VIDEO.TIME_KERNEL_DIM.HEAD_RPN // 2, 1, 1],
				strides=[1, 1, 1],
				weight_init=('GaussianFill', {'std': 0.01}),		# randomly initialized weights
				bias_init=('ConstantFill', {'value': 0.}))		# zeroed biases
			model.Relu(conv_rpn_fpn, conv_rpn_fpn)
			
			# ★Convert to 2D. Earlier was averaging in time, now moving to channel
			conv_rpn_fpn_timepool = model.MoveTimeToChannelDim(	# 以前有时间维度,现在整合成为2D
				conv_rpn_fpn, 'conv_rpn_timepooled_fpn' + slvl)	# conv_rpn_timepooled_fpn2
			
			# ★Proposal classification scores 分类得分
			rpn_cls_logits_fpn = model.Conv(		# 经过整合的feat在这里转化为logits(概率前体)
				conv_rpn_fpn_timepool, 'rpn_cls_logits_fpn' + slvl,	# rpn_cls_logits_fpn2
				dim_out * time_dim, num_anchors, 1, pads=0, stride=1,	# 每个锚框有一个分数
				weight_init=('GaussianFill', {'std': 0.01}),
				bias_init=('ConstantFill', {'value': 0.}))
				
			# ★Proposal bbox regression deltas 约束框回归
			rpn_bbox_pred_fpn = model.Conv(
				conv_rpn_fpn_timepool, 'rpn_bbox_pred_fpn' + slvl,	# rpn_bbox_pred_fpn2
				dim_out * time_dim, 4 * time_dim * num_anchors, 1, pad=0, stride=1,	# 每个锚框有4个点,共有3张图像
				weight_init=('GaussianFill', {'std': 0.01}),
				bias_init=('ConstantFill', {'value': 0.}))
			
			# 实例框可视化分类得分(这个没有用上)			
			# Proposal visibility classification scores
			# TODO(rgirdhar): Need to use this in future
			# rpn_vis_cls_logits_fpn =
			model.Conv(
				conv_rpn_fpn_timepool, 'rpn_vis_cls_logits_fpn' + slvl,
				dim_out * time_dim, num_anchors * time_dim, 1, pads=0, stride=1,		# 3张图像总共的锚框数
				weight_init=('GaussianFill', {'std': 0.01}),
				bias_init=('ConstantFill', {'value': 0.}))
				
		# 3、4、5、6层都在这里
		else:
			# Share weights and biases
			sk_min = str(k_min)		# 这个就是2
			
			# ★RPN hidden representation(就是feat再过一次卷积)
			conv_rpn_fpn = model.ConvShared(		#  添加conv op,与其它conv op共享weights和biases.
				bl_in, 'conv_rpn_fpn' + slvl,
				dim_in, dim_out, [3, 3, 3],
				pads=2 * [1, 1, 1], strides=[1, 1, 1],
				nd=True,
				weight='conv_rpn_fpn' + sk_min + '_w',
				bias='conv_rpn_fpn' + sk_min + '_b')
			model.Relu(conv_rpn_fpn, conv_rpn_fpn)
			
			# ★Convert to 2D. Earlier was averaging in time, now moving to channel
			conv_rpn_fpn_timepool = model.MoveTimeToChannelDim(		# 这个操作把时间维度去掉了
				conv_rpn_fpn, 'conv_rpn_timepooled_fpn' + slvl)
				
			# ★Proposal classification scores
			rpn_cls_logits_fpn = model.ConvShared(
				conv_rpn_fpn_timepool, 'rpn_cls_logits_fpn' + slvl,
				dim_out * time_dim, num_anchors, 1, pad=0, stride=1,	# 出来的通道数是num_anchors,3张图像中锚框分类概率
				weight='rpn_cls_logits_fpn' + sk_min + '_w',
				bias='rpn_cls_logits_fpn' + sk_min + '_b')
				
			# ★Proposal bbox regression deltas
			rpn_bbox_pred_fpn = model.ConvShared(
				conv_rpn_fpn_timepool, 'rpn_bbox_pred_fpn' + slvl,
				dim_out * time_dim, 4 * time_dim * num_anchors	# 3张图像每一个锚框都有4个坐标
				, 1, pad=0, stride=1,	 weight='rpn_bbox_pred_fpn' + sk_min + '_w',
				bias='rpn_bbox_pred_fpn' + sk_min + '_b')
				
			# Proposal visibility classification scores
			# TODO(rgirdhar): Need to use this in future
			# rpn_vis_cls_logits_fpn =
			model.ConvShared(
				conv_rpn_fpn_timepool, 'rpn_vis_cls_logits_fpn' + slvl,
				dim_out * time_dim, num_anchors * time_dim, 1, pad=0, stride=1,
				weight='rpn_vis_cls_logits_fpn' + sk_min + '_w',
				bias='rpn_vis_cls_logits_fpn' + sk_min + '_b')

		# 预测模式的时候才会使用,用来生成Proposals
		if not model.train or cfg.MODEL.FASTER_RCNN:
			# Add op that generates RPN proposals
			# The proposals are needed when generating proposals from an
			# RPN-only model at inference time, but *not* when training it
			lvl_anchors = generate_anchors(
				stride=2. ** lvl,
				sizes=(cfg.FPN.RPN_ANCHOR_START_SIZE * 2. ** (lvl - k_min), ),
				aspect_ratios=cfg.FPN.RPN_ASPECT_RATIOS,
				time_dim=time_dim)
			rpn_cls_probs_fpn = model.net.Sigmoid(
				rpn_cls_logits_fpn, 'rpn_cls_probs_fpn' + slvl)
			# Need to use this in future
			# rpn_vis_cls_probs_fpn = model.net.Sigmoid(
			#     rpn_cls_logits_fpn, 'rpn_vis_cls_probs_fpn' + slvl)
			model.GenerateProposals(
				[rpn_cls_probs_fpn, rpn_bbox_pred_fpn, 'im_info'],
				['rpn_rois_fpn' + slvl, 'rpn_roi_probs_fpn' + slvl],
				anchors=lvl_anchors,
				spatial_scale=sc)

四、一些疑问

1.并没有看到侧连接的步骤,而是在卷积后直接进行Cls和Reg。难道不采用这种结构?

2.在看ResNet结构时,并没有看到存储各个C层特征图。但是在RPN构建函数中,直接将blobs_in做为输入。是什么时候存储的C层?

3. model.ConvShared函数中的Shared是什么意思?哪里的参数共享?

 

欢迎交流!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Detect-and-Track论文:3D Mask R-CNN Caffe2源代码解析——3.RPN&FPN构建 的相关文章

  • TensorFlow-Slim API 官方教程

    https blog csdn net u014061630 article details 80632736 TF Slim 模块是 TensorFlow 中最好用的 API 之一 尤其是里面引入的 arg scope model var

随机推荐

  • Tensorflow笔记4:Saver

    Saver类位于tf train中 xff0c 属于训练过程中要用到的方法 xff0c 主要作用就是保存和加载save amp restore ckpt 最简单的保存应用举例 xff1a saver span class token pun
  • Tensorflow笔记4:学习率衰减策略tf.train.cosine_decay_restarts

    TF在learning rate decay py中提供了几种非常骚气的学习率下降方法 xff0c 今天就来玩一玩 只需要简单的参数设定 xff0c 就能够产生神奇的lr衰减效果 首先简介lr的一般使用方法 xff1a lr span cl
  • ffmpeg使用笔记

    视频压缩 ffmpeg i lt input gt vcodec libx264 crf 25 lt output gt 分辨率调整 ffmpeg i 123 mp4 s 960x540 1 mp4 视频截取 截取 xff08 t1 43
  • Pytorch 入门

    1 加载模型 seg model 61 torchvision models detection maskrcnn resnet50 fpn pretrained 61 True seg model 61 seg model cuda 1
  • 小白之通俗易懂的贝叶斯定理

    原文链接 xff1a https zhuanlan zhihu com p 37768413 概率论与数理统计 xff0c 在生活中实在是太有用了 xff0c 但由于大学课堂理解不够深入 xff0c 不能很好地将这些理论具象化并应用到实际生
  • tf.variable_scope中的reuse

    一 两种scope xff1a variable与name tf variable scope 是对变量进行命名管理 xff0c 而tf name scope 是对算子 op 进行命名管理 xff0c 二者相互不影响 见下例 xff1a i
  • HTML+CSS 简易搜索框

    搜索框是页面中很常见的一种 xff0c 下面分享一段简单搜索框案例 xff0c 直接上代码 HTML部分 lt DOCTYPE html gt lt html gt lt head gt lt meta charset 61 34 UTF
  • frp内网穿刺/反向代理教程

    文章目录 前言一 明确基本概念二 frp下载与使用1 云服务器做为Server端2 GPU服务器做为Client端3 远程访问 三 云服务器防火墙端口开启 前言 frp 是一个高性能的反向代理应用 xff0c 可以帮助开发者轻松地进行内网穿
  • Keras模型基本流程

    文章目录 前言一 Keras流程二 Keras中的模型定义1 基于Sequential 类2 基于函数式API 前言 目前打算看tensorflow probability模块 xff0c 但是发现整个都是适配Keras的 xff0c 很多
  • pytorch自动混合精度训练

    from torch cuda amp import autocast GradScaler Init Step 1 Create Model model device start epoch 61 create model opt if
  • Linux系统查看CPU个数&超线程&线程数

    小命令 xff1a Linux查看CPU详细信息 简书 jianshu com Intel CPU产品规范 xff1a 英特尔 产品 xff1a 处理器 xff0c 英特尔 NUC 迷你电脑 xff0c 内存和存储 xff0c 芯片组 in
  • Tensorflow学习笔记(1)——Tensorflow-CPU版安装躺坑实录

    从今天开始就要出品自己的Tensorflow系列啦 xff01 由于是第一篇关于Python的博文 xff0c 所以先把接触Python以来的感想和心得都放了进来 xff0c 想看Tensorflow的博友请直接跳到标题三 一 Python
  • Tensorflow学习笔记(3)——图、会话基本语法

    前言 xff1a Tensorflow xff0c 与我们之前熟悉的C C 43 43 Python的确不太一样 xff0c 建议初学者当作一门新的语言来学 如果看的过程中忽然有一种 的确不太一样 的感觉 xff0c 并且明白了哪里不一样
  • Tensorflow学习笔记(2)——Tensorflow-GPU版安装总结

    经历了N多次的失败 xff0c TF GPU的环境终于搭建好了 xff0c 全程连着弄了三天 现在把安装中的注意事项总结一下 xff0c 希望大家少走弯路 xff01 先把自己的配置列表说一下 xff1a Windows7 x64 VS20
  • 深度学习基础——彻底掌握卷积层的计算

    机器学习也是刚刚入门 xff0c 虽然对卷积 池化等过程很熟悉 xff0c 但是一直不太清楚具体的计算 xff0c 幸好在博文上看到了讲解过程 xff0c 看完以后受益匪浅 xff0c 然后自己又重新写了一遍 有这个表格 xff0c 再也不
  • Mask R-CNN 简介与论文笔记

    本篇文章是面向Mask R CNN的初学者 xff0c 旨在梳理大体思路 xff0c 认识框架基础概念 由于自己现在大四 xff0c 也是刚刚入足深度学习领域 xff0c 所以文章中免不了有错误之处 xff0c 欢迎各位博友批评指正 本博文
  • Detect-and-Track论文:3D Mask R-CNN Caffe2源代码解析——1.模型构建梳理

    这篇博文的内容是对Detect and Track的源代码进行解析 xff0c 由于是第一篇 xff0c 所以展示的是代码的脉络 xff0c 以及如何寻找到3D Mask R CNN的构建过程 博文的目录是按照文件来的 xff1a 参考内容
  • INRIA数据集

    INRIA数据集 HOG 43 SVM是经典的行人检测方法 xff0c 论文作者同时搞了一个INRIA数据集 INRIA数据集官方页面 xff1a http pascal inrialpes fr data human xff0c 不过说真
  • Detect-and-Track论文:3D Mask R-CNN Caffe2源代码解析——2.ResNet18_3D解析

    在上一篇博文中 xff0c 我们对Detect and Track论文源码中模型构建部分进行了代码梳理 xff0c 此篇博文我们对其采用的主干网络ResNet18进行详细分析 参考内容链接如下 xff1a Detect and Track论
  • Detect-and-Track论文:3D Mask R-CNN Caffe2源代码解析——3.RPN&FPN构建

    在第二部分 xff0c 我们对ResNet18的结构进行了分析 当图像经过ResNet18后 xff0c 会产生Feature Map xff08 特征图 xff09 这些特征图将会被送到RPN xff08 Region Proposal