Faster RCNN 实现思路详解

懒得重新编辑公式了,可以移步知乎https://zhuanlan.zhihu.com/p/133467109

 

注:可以先看文末总结

 

1.Faster RCNN 整体思路概述

如图1.1所示,Faster RCNN 的整体框架按照功能区分,大致分为4个模块,分别是特征提取网络backbone模块、RPN模块、RoI and RoI pooling模块和RCNN模块。

Faster RCNN 实现思路详解_第1张图片

图 1.1 Faster RCNN 整体框架

  • Backbone模块:主要负责接收输入数据,并进行数据预处理和特征提取得到输入图像对应的feature maps,并传递给下一层。这部分论文中用的VGG16和ZF框架,后来又有人用Resnet。

  • RPN network模块:这一模块主要有两个功能,一方面要生成一组proposals(图像中可能是前景的区域坐标),并将其传递给RoI模块;另一方面要计算RPN网络的损失,用于更新网络的参数。

  • RoI模块:对proposals进行降采样,并按proposals的坐标提取出feature maps中的特征,并将其传入下一层。

  • RCNN network模块:这一模块主要有两个功能,一方面用多层全连接网络对RoI传入的特征进行分类和回归,以得到预测目标的位置和标签;另一方面计算RCNN的损失,用于更新网络的参数。

如图1.1所示绿色框中的部分仅在训练时存在,整个结构的核心部分主要集中在后面三个部分,下面将对其进行详细的梳理。

 

2.Backbone模块

这一模块主要是利用效果比较好的卷积网络结构进行特征提取,这里就不详细介绍了。以VGG16为例,如图2.1所示,选取VGG16的前五层,取第五层pooling之前的数据作为feature maps。这里假设输入数据预处理后的尺度是则feature maps的尺度是 [3\times600\times800] ,则feature maps的尺度是[512\times37\times50][512\times37\times50]​​​​​​​[512\times37\times50]。特征图中第二个和第三个维度中的每一个点都可以看成是原图中不同区域经过backbone层之后提取出的特征。

Faster RCNN 实现思路详解_第2张图片

图 2.1 Backbone 的结构图

 

3. RPN network模块

如图3.1所示为RPN network的总体框架。

Faster RCNN 实现思路详解_第3张图片

图 3.1 RPN network 整体框架及数据流关系(绿色部分表示仅在训练时存在)

 

3.1 RPN网络的输入输出和任务

  • 输入:feature maps

  • 输出:proposals(bounding box 的位置坐标)

  • 任务:训练RPN网络;根据feature maps计算proposals

这里思考几个问题,如果按照常规的有监督学习思路对RPN网络进行组织训练,即以ground true bounding box(ground true bbox)的坐标进行回归,以其类别标签进行分类。对于分类问题问题不大,但是因为ground true bbox 的标签在原图上的随机性比较大,数据分布比较广,很难找到合适的网络使回归损失收敛。

因此作者想到了另一个方法,不直接输出box的真值,而是通过一定的映射关系(后面会讲)输出固定基box坐标下的偏移值。这样训练起来网络要容易收敛许多。

上面说的基box就是下面要讲的anchor。

 

3.2 Anchor 与 anchor的生成

Anchor简单来说就是在原图上的一些矩型框,但是这一系列矩形框与feature maps相关联。如图3.2所示,对于feature maps上的某一个点都会生成一定数量的anchor,论文中采用三种尺寸(128, 256, 512),以及三种长宽比(1:1, 1:2 , 2:1),组合起来一共有九种情况,即特征图上的每个点都会生成九个anchor。在代码中用每个anchor的左上角和右下角坐标来表示其位置。以一个特征点的九个anchor为例,就是生成如下形式的box坐标矩阵,维度为[9, 4]。

​
[[ -84.  -40.   99.   55.]
 
[-176.  -88.  191.  103.]
 
[-360. -184.  375.  199.]
 
[ -56.  -56.   71.   71.]
 
[-120. -120.  135.  135.]
 
[-248. -248.  263.  263.]
 
[ -36.  -80.   51.   95.]
 
[ -80. -168.   95.  183.]
 
[-168. -344.  183.  359.]]
 

Faster RCNN 实现思路详解_第4张图片

图 3.2 feature maps中某一点的anchors

但是刚才得到的坐标点是以这九个anchor的几何中心作为坐标原点得到的box坐标,因此还需要求anchors在原图坐标系下的box坐标。

首先要将feature maps映射到原图上,因为在backbone网络中对原图进行降采样得到feature maps,采样步长 stride = 16,因此将feature maps的坐标点乘以16,便可以映射回原图尺度。然后分别以这[37, 50]个点为原点,生成所有的anchors坐标。Anchor generate模块便是完成这部分功能,如图3.3所示。

Faster RCNN 实现思路详解_第5张图片

图 3.3 Anchor generate 功能示意图

生成的总anchors数为​​​​​​​37\times50\times9=16650​​​​​​​37\times50\times9=16650 个。这有些类似于穷举的方法,16650个预选框,总能有一些框比较贴合实际物体所在区域。但问题是这些贴合实际的框应该与ground true bounding box有些差异,并不完全吻合。所以需要一定的修正,这就是接下来要说的问题。

 

3.3 RPN网络的预测值

这部分功能主要由图3. 1.a中的Head模块完成,这里需要注意的是RPN网络的预测值和输出不同。此模块共有两个输出结果:

  • Objectness:预测anchors是前景还是背景的可能性大小

  • Pre bbox delta:预测anchors与ground true bounding box 的偏移量。

Head模块接收feature maps ,首先利用 [3\times3] 的卷积进行更深层的特征提取,然后利用两个 [1\times1] 卷积分别实现分类网络和回归网络。

在物体检测中通常将有物体的位置称为前景,没有物体的位置称为背景。在RPN的分类网络中,只需要区分出前景背景信息即可,因此这是一个二分类问题,考虑到每个特征点有9个anchor,所以分类网络中的卷积网络有 [9\times2]=18 个通道。同理回归网络要输出对anchor的修正,所以卷积层对应有 [9\times4]=36 个通道。

Faster RCNN 实现思路详解_第6张图片

图 3.1.a Head 和Box decode模块

 

3.4 修正值与anchors关系

考虑某一特定的anchor,其中心点的坐标是 (x, y) ,宽是 w ,高是 h ,假设它对应的ground true bounding box坐标为 (x_0, y_0) ,宽是 w_0 ,高是 h_0 ,则对应的偏移值计算公式为:

\begin{align} t_x &= \frac{(x_0 - x)}{w}\\ t_y &= \frac{(y_0 - y)}{y}\\ t_w &= log\frac{w_0}{w}\\ t_w &= log\frac{h_0}{h} \end{align}\tag1

3.3中Head模块输出的便是所有anchors的偏差值,利用式(1),可以实现RPN网络的偏差值与原值的相互转换。

 

3.5 解码与编码

通过3.4和3.3知道head模块输出的并不是预测bounding box的位置坐标,要求位置坐标还需要利用anchors的坐标进行转换。这里约定两个过程:

  • 解码:已知偏差坐标(t_x, t_y, t_w, t_h)和基(在RPN中可以认为是anchor)坐标 (x_1, y_1, x_2, y_2) ,求预测bounding box坐标 (x_1^, ,y_1^,, x_2^, ,y_2^,) 的过程。

  • 编码:已知ground true bbox坐标 (x_1^, ,y_1^,, x_2^, ,y_2^,) 和基(在RPN中可以认为是anchor)坐标 (x_1, y_1, x_2, y_2) ,求偏差坐标 (t_x, t_y, t_w, t_h) 的过程。

图3.1.a中的Box decode 模块完成解码过程,对Head模块传来的的pre bbox delta解码之后生成在原图坐标系下的pre bounding box 的位置坐标。

图3.1.c中Box code 完成编码过程。

具体实现还要考虑到原始图像的大小,进而对解码结果进行修整。

 

3.6 NMS 与生成proposals

现在假设RPN模型已经训练成功,网络处于inference阶段,Head模块可以输出较理想的objectness 和 pre bbox delta 值。在经过box decode之后会输出所有anchors的objectness得分和pre bounding box坐标。最后利用filter proposals模块完成NMS和生成proposals的任务。如图3.1.b所示,具体描述如下:

  • 根据objectness的前景得分进行排序,按一定比例选出前12000个pre bbox 得到最初的建议区域。

  • 考虑到一个物体可能会有多个bounding box重叠对应,所以在应用非极大值抑制(NMS)将重叠框去掉。

  • 最后在剩余的bbox中,根据objectness前景得分随机抽取2000个box,作为最终的proposals。

Faster RCNN 实现思路详解_第7张图片

图3.1.b Filter proposalss模块

 

3.7 RPN network的训练

为了让RPN网络能够提出良好的proposals,需要对网络进行训练。就像传统的有监督网络一样,在训练前我们需要明确,模型的预测值、真值和损失函数这三个要素。预测值在3.3中已经介绍,这里介绍真值和损失函数。图3.1.c 为训练部分结构图。

Faster RCNN 实现思路详解_第8张图片

图 3.1.c RPN 训练部分结构图

3.7.1 RPN network的真值

RPN网络的预测值是对anchors的分类和回归修正,其真值也有两个——对应anchors的类别标签和真实偏差值。这一部分主要由Assign targets to anchors模块完成。

注意这两者的求取都是建立在anchors的基础之上。

为了便于理解,先介绍以下ground true的形式:

  • Ground true label:假设需要区分的类别有C种,则label的值属于整数[0, C],label的个数为输入图片中目标的个数。假如C=3, 有2个目标,则label = [1, 0]或[0, 2]……

  • Ground true bounding box:形式为box的左上角和右下角坐标如 (x_1, y_1, x_2, y_2) ,box个数为输入图片中目标的个数。假如C=3, 有2个目标,则box{[1, 2, 3, 4], [5, 6, 7, 8]}。

  • 注:与box中对应位置的label值即为该位置的目标类别。

(1)真值标签(target labels)的求取

在这一部分标签主要要区分出前景和背景,不需要具体的分类,因此标签值有两个:

  • 0:背景

  • 1:前景

前景背景的区分是通过计算ground true bounding box与anchors的IoU值来区分的,这里需要计算每个ground true bbox和anchors的IoU,也就是说会形成一个IoU矩阵。假设ground true bbox有N个,则IoU大小为[N, 166500]具体的判断标准如下:

  • 对于任何一个anchor与所有的gt box最大IoU小于阈值0.3(可以调整的参数),则视为负样本。

  • 对于任何一个gt box,与其有最大IoU的anchor视为正样本。

  • 对于任何一个anchor,与所有gt box的IoU大于阈值0.7(可以调整的参数),则视为正样本。

  • -1标签:在编程时,可以将IoU值在0.3-0.7之间的anchor标签置位-1,作为无效anchor的标记。这部分anchor不参与分类和回归损失的计算。

(2)真实坐标(target regression)的求取

这部分的主要思路是,利用IoU矩阵,对于某一anchor找到与其IoU值最大的gt box坐标,作为其真实坐标,依次找到所有的anchors真值。

注:

1)这里有一个问题:对某些不符合前景标准的anchor也进行了真值赋值,但是在后续计算中,会根据target label进行抽样,不符合前景背景标准的target regression不会被计算到。

2)这里求得的所有anchor的真值坐标是 (x_1, y_1, x_2, y_2) 形式的,还需要对其进行编码操作(box code)才能得到RPN网络的回归真值target regression。

3.7.2 RPN network损失函数的计算

经过3.7.1和3.2,RPN获得了网络的预测值和真值,现在可以计算损失函数了。

(1)抽取正负样本

由于网络预测的bounding box综数接近两万,并且大部分box标签都是背景,如果都计算损失的话则正负样本失去平衡,不利于网络收敛。因此,RPN默认选择256(可调整)个bounding box进行损失计算,其中最多不超过128(可调整)个正样本。如果超过则进行随机抽取。

(2)损失函数的计算

RPN损失函数主要有两部分组成,即分类损失和回归损失,如下所示:

L({p_i, t_i}) = \frac{1}{N_{cls}}\sum_iL_{cls}(p_i, p_i^*)+\lambda\frac{1}{N_{reg}}\sum_ip_i^*L_{reg}(t_i, t_i^*)\tag{2}

L_{cls}(p_i, p_i^*) 代表了晒算出来的256个box的分类损失,这里是一个二分类问题,使用的是交叉熵函数。其中 p_i 为真值, p_i^* 为预测值。

L_{reg}(t_i, t_i^*) 代表了回归损失,回归损失使用的是 smooth_{L1} 函数,如下所示。其中 t_i 为真值, t_i^* 为预测值。

L_{reg}(t_i, t_i^*) = \sum_{i\in{x, y, w, h}}smooth_{L1}(t_i, t_i^*)\\ smooth_{L1}(t_i, t_i^*) = \begin{cases} 0.5 \times x^2 &&if \,\,\,|x|<1\\ |x|-0.5&&otherwise \end{cases} \tag3

注:在训练阶段RPN的损失函数会传递到RCNN部分一起计算总的损失函数,进而进行反馈,改善网络效果。

至此RPN部分的所有内容梳理完毕。

 

4. RoI and RoI pooling模块

 

4.1 RoIs的获得

训练时由RPN网络传输过来的proposals的数量为2000个,其中仍然有很多背景框,真正的存在目标的前景占比很少。因此在进行特征提取之前要对proposals进行再次筛选。筛选的流程如图4.1所示。

  • 计算IoU矩阵和分配标签的过程和RPN网络中Assign targets to anchors模块一致,这里只是将anchors替换成了proposals。这里就不重复介绍了。

  • 在分配完标签之后,在所有正负样本中选出256(参数可调节)个样本,正样本数按照一定比例提取,同样比例可以调整。

最后选出的256个proposals即为RoIs。

Faster RCNN 实现思路详解_第9张图片

图 4.1 RoI 和 RoI pooling 结构图

 

4.2 RoI pooling

在4.1中得到的RoIs区域,实际是对应原图中可能是前景和背景的bbox坐标,我们需要将这个坐标映射到feature maps上,进而提取出RoI区域对应特征图。然后再传递给后面的全连接层进行分类和回归。

这里有一个问题是,特征最后要输入到全连接层进行计算,所以要求输入的特征图大小是一样的。而由于RoI 的bbox大小不同,其提取的特征大小也不同,因此特征传递给FC层之前需要进行一定的处理,这就是RoI pooling的主要作用。

论文中统一将特征图pooling到 [7\times7] 大小。

具体的方法这里就不详细介绍了。

注:由于RoI pooling在实现的时候会多次取整,导致精度不高。后来常用maskRCNN中的RoI Align代替。

 

5. RCNN network

 

5.1 RCNN的输入输出和任务

  • 输入:RoI and RoI pooling 网络传递过来的 固定维度的pooling maps特征图

  • 输出:目标类别和位置偏差的预测值,以及RCNN Loss。

  • 任务:训练RCNN网络;对pooling maps进行学习,利用三层全连接网络进行标签分类及位置回归。

 

5.2 全连接模块

这里用三层全连接层对特征进行处理,如图所示。前两层是VGG16中的第六第七层,最后一层是两个全连接层,分别对256个RoIs区域进行类别预测和位置预测。

Faster RCNN 实现思路详解_第10张图片

图 5.1 全连接网络结构图

图中C代表需要检测的类别,背景算作第0类,所以类别预测输出的维度是 [256\times(1+C)] 。位置预测需要对每一类都预测出位置所以输出维度是 [256\times(1+C)\times4] 。

 

5.3 RCNN网络的训练

在训练之前我们来梳理以下RCNN网络的预测值和真值。RCNN 的预测值在5.2中已经求出,就是RCNN网络的输出值。

(1)RCNN网络的真值

RCNN网络的真值是RoIs区域的类别标签和与对应的真实坐标的偏差。RoIs区域对应的真实坐标在RoI模块中的assign targets中实际已经得到,具体过程同3.7.1中RPN部分一致。

注:这里得到的RoIs target location 是编码前的表示,所以需要进行box code计算偏差,才是真正的RCNN网络的真值。

(2)损失函数

损失函数的计算和RPN部分相同,不在重复。

  • 需要注意的是这里的分类损失是C+1类,而不是二分类;

  • 回归损失只计算正样本部分对应类别的损失。

举例说明第二点。假设第3个区域为正样本且是第K类,则对应pre bbox delta中的[3,K, :]的delta值参与损失计算。

至此RCNN中关于训练和inference的思路全部梳理完毕。图5.2展示了RoI and RoI pooling和RCNN模块之间的关系和数据流。

Faster RCNN 实现思路详解_第11张图片

图5.2 RoI and RoI pooling及RCNN模块之间的关系和数据流(绿色部分表示仅在训练时存在)

 

6. 总结

本文主要从编程实现的角度梳理了Faster RCNN的流程,重点介绍了RPN部分的实现。RoI and RoI pooling和RCNN部分的结构和RPN网络实际上十分类似,很多的思路都是想通的,因此介绍的并不详细。

比如:RPN的预测值是对anchors进行修正,得到proposals;RCNN网络其实是对RoI进行修正得到最终的预测结果。其修正的目的都是为了使被修正的bbox经过修正后能够更接近ground true bbox。

关于RoI pooling和RoI Align:其二者的具体方法本文没有介绍,这部分的内容并不影响读者对整个网络的理解,如果想要了解,建议阅读原文、源码或其他博客。

关于参数上细节:整个框架中有许多可调节的超参数,如anchor的大小 和 长宽比、生成proposals时的下采样数等等。而且有些参数在训练和inference时并不相同。如果读者想要了解请参考源码。

关于参考代码:本文的主要参考代码是torchvision包中自带的fasterrcnn_resnet50_fpn()实现。

关于配图:图3.3中的部分图直接截取自

Object Detection and Classification using R-CNNs​www.telesens.co

你可能感兴趣的:(目标检测)