mmdetection RPNHead--_init_layers()
RPNHead类包含的函数:
(1)_init_():初始化函数
(2)_init_layers():设置Head中的卷积层
(3)forward_single():单尺度特征图的前向传播
(4)loss:Head损失函数计算
(5)_get_bboxes_single():将单个图像的输出转换为bbox预测
(6)_bbox_post-processing_method:bbox后续处理方法
这里介绍的是_init_layers_()函数:
1 def _init_layers(self): 2 """Initialize layers of the head.""" 3 if self.num_convs > 1: 4 rpn_convs = [] 5 for i in range(self.num_convs): 6 if i == 0: 7 in_channels = self.in_channels 8 else: 9 in_channels = self.feat_channels 10 # use ``inplace=False`` to avoid error: one of the variables 11 # needed for gradient computation has been modified by an 12 # inplace operation. 13 rpn_convs.append( 14 ConvModule( 15 in_channels, 16 self.feat_channels, 17 3, 18 padding=1, 19 inplace=False)) 20 self.rpn_conv = nn.Sequential(*rpn_convs) 21 else: 22 self.rpn_conv = nn.Conv2d(self.in_channels, self.feat_channels, 3, padding=1) 24 self.rpn_cls = nn.Conv2d(self.feat_channels, self.num_base_priors * self.cls_out_channels, 1) 27 self.rpn_reg = nn.Conv2d(self.feat_channels, self.num_base_priors * 4, 1)
in_channels(int):输入特征映射中的通道数。
feat_channels(int):隐藏通道的数量。
函数说明:
这个函数是完成Head中卷积层的设置。代码14行可以看到,这里使用的是MMCV中的ConVModule类来构建卷积层,使用他的方便之处在于,它会在卷积层后自动加上归一化层和激活函数。
RPNHead的卷积层主要由三个部分组成,rpn_conv, rpn_cls, rpn_reg。num_cls的值影响rpn_conv的层数。
num_cls的值可在配置文件中rpn_head的字典里设置,默认是1。
self.num_convs=1,RPNHead的结构是:
如果self.num_convs>1,RPNHead的结构如下:
可以看到,通过3×3的卷积层之后,会再经过分类分支和回归分支,用于完成目标的分类和定位。rpn_cls和rpn_reg都是1×1的卷积层。输入通道是feat_channels,输出通道分别是cls_out_channels*num_base_priors和num_base_priors*4。
cls_out_channels,num_base_priors都是RPNHead继承自父类的参数。
关于cls_out_channels属性值的代码如下:
1 if self.use_sigmoid_cls: 2 self.cls_out_channels = num_classes 3 else: 4 self.cls_out_channels = num_classes + 1
如果use_sigmoid_cls为真,cls_out_channels就是类别数,否则是类别数加一。
use_sigmoid的变量值是从loss_cls的配置字典的获取的。默认为False,可以在配置文件中查看是否设置了真值。
1 self.use_sigmoid_cls = loss_cls.get('use_sigmoid', False)
关于num_base_priors属性值的代码如下
1 self.prior_generator = build_prior_generator(anchor_generator) 2 # Usually the numbers of anchors for each level are the same 3 # except SSD detectors. So it is an int in the most dense 4 # heads but a list of int in SSDHead 5 self.num_base_priors = self.prior_generator.num_base_priors[0]
这里看不出来,这个值具体是啥,我上网查了一番后得到,num_base_priors = num(anchor_scales)*num(anchor_ratios)。
num_base_priors是每个特征点产生的锚框的数量。
由此可以知道,分类和回归的输出通道的含义是
cls_out_channels*num_base_priors,所有锚框对应的类别分类(这里的类别指的是,是否是目标,不是具体的目标类别)
num_base_priors*4,所有的锚框对应的回归值的输出。(对应的是中心点的偏移量和宽高的缩放量)