Faster R-CNN

Faster R-CNN 的思想

Faster R-CNN可以简单的看做“区域生成网络RPNs + Fast R-CNN”的系统,用区域生成网络代替Fastr-CNN中的Selective Search方法。Faster R-CNN着重解决这个系统中的三个问题:
1.如何设计区域生成网络;
2.如何训练区域生成网络;
3.如何让区域生成网络和Fast RCNN 网络共享特征提取网络。
在整个Faster R-CNN 算法中,有三种尺度:
1.原图尺度:原始输入的大小,不受任何限制,不影响性能。
2.归一化尺度:输入特征提取网络的大小
3.网络输入尺度:输入特征检测网络的大小,在训练时设置,源码为224x224

Faster R-CNN框架介绍

Faster R-CNN模型

Faster R-CNN 算法由两大模块/4个主要内容组成:

1.RPN候选框提取模块;
2.Fast R-CNN检测模块
其中,RPN是全卷积神经网络,用于提取候选框;Fast R-CNN基于RPN提取得proposal检测并识别proposal中的目标。

1.Conv layers。作为一种CNN网络目标检测方法,Faster RCNN首先使用一组基础的conv+relu+pooling层提取image的feature maps。该feature maps被共享用于后续RPN层和全连接层。
2.Region Proposal Networks。RPN网络用于生成region proposals。该层通过softmax判断anchors属于positive或者negative,再利用bounding box regression修正anchors获得精确的proposals。
3.Roi Pooling。该层收集输入的feature maps和proposals,综合这些信息后提取proposal feature maps,送入后续全连接层判定目标类别。
4.Classification。利用proposal feature maps计算proposal的类别,同时再次bounding box regression获得检测框最终的精确位置。

下图展示了基于VGG16的Faster R-CNN 网络结构,可以清晰的看到该网络对于一副任意大小PxQ的图像:

1.首先缩放至固定大小MxN,然后将MxN图像送入网络;
2.而Conv layers中包含了13个conv层+13个relu层+4个pooling层;
3.RPN网络首先经过3x3卷积,再分别生成positive anchors和对应bounding box regression偏移量,然后计算出proposals;
4.而Roi Pooling层则利用proposals从feature maps中提取proposal feature送入后续全连接和softmax网络作classification(即分类proposal到底是什么object)。

Conv layers

Conv layers 包含了conv,pooling,relu三种层。这里有个重要的信息,在Conv layers 中:
1.所有的conv层都是:kernel_size=3, pad=1, stride=1
2.所有的pooling层都是:kernel_size=2, pad=0, stride=2
为何重要?在Faster RCNN Conv layers中对所有的卷积都做了扩边处理( pad=1,即填充一圈0),导致原图变为 (M+2)x(N+2)大小,再做3x3卷积后输出MxN 。正是这种设置,导致Conv layers中的conv层不改变输入和输出矩阵大小。如图:


卷积示意图

类似的是,Conv layers中的pooling层kernel_size=2,stride=2。这样每个经过pooling层的MxN矩阵,都会变为(M/2)x(N/2)大小。综上所述,在整个Conv layers中,conv和relu层不改变输入输出大小,只有pooling层使输出长宽都变为输入的1/2。

那么,一个MxN大小的矩阵经过Conv layers固定变为(M/16)x(N/16)!这样Conv layers生成的feature map中都可以和原图对应起来。

RPN 介绍

RCNN解决的是,“为什么不用CNN做classification呢?”

Fast R-CNN解决的是,“为什么不一起输出bounding box和label呢?”

Faster R-CNN解决的是,“为什么还要用selective search呢?”

Faster R-CNN抛弃了传统的滑动窗口和Selective Search 方法,直接使用RPN生成检测框。

RPN网络结构

RPN 网络实际分为2条线,上面一条通过softmax分类anchors获得positive和negative分类,下面一条用于计算对于anchors的bounding box regression偏移量,以获得精确的proposal。而最后的Proposal层则负责综合positive anchors 和对应bounding box regression偏移量获取proposals,同时剔除太小和超出边间的proposals。

anchors

所谓anchors,实际上就是一组矩阵

[[ -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.]]

其中每行的4个值(x1,y1,x2,y2)表矩阵左上和右下角点的坐标,9个矩阵共有3种形状,长宽比为大约为 width:height∈{1:1,1:2,2:1},如下图,实际上通过anchors就引用了检测中常用到的多尺度方法。

anchors示意图

那么这9个anchors是做什么的呢?借用Faster RCNN论文中的原图,如图,遍历Conv layers计算获得的feature maps,为每一个点都配备这9种anchors作为初始的检测框。这样做获得检测框很不准确,不用担心,后面还有2次bounding box regression可以修正检测框位置。


解释一下上面这张图的数字。

1.在原文中使用的是ZF model中,其Conv Layers中最后的conv5层num_output=256,对应生成256张特征图,所以相当于feature map每个点都是256-dimensions
2.在conv5之后,做了rpn_conv/3x3卷积且num_output=256,相当于每个点又融合了周围3x3的空间信息,同时256-d不变。
3.假设在conv5 feature map中每个点上有k个anchor(默认k=9),而每个anhcor要分positive和negative,所以每个点由256d feature转化为cls=2k scores;而每个anchor都有(x, y, w, h)对应4个偏移量,所以reg=4k coordinates。
4.补充一点,全部anchors拿去训练太多了,训练程序会在合适的anchors中随机选取128个postive anchors+128个negative anchors进行训练

其实RPN最终就是在原图尺度上,设置了密密麻麻的候选Anchor。然后用cnn去判断哪些Anchor是里面有目标的positive anchor,哪些是没目标的negative anchor。所以,仅仅是个二分类而已

那么Anchor一共有多少个?原图800x600,VGG下采样16倍,feature map每个点设置9个Anchor,所以:ceil(800/16)xceil(600/16) x9=17100
其中ceil()表示向上取整,是因为VGG输出的feature map size= 50*38。

Gernerate Anchors

softmax判定positive与negative

一副MxN大小的矩阵送入Faster RCNN网络后,到RPN网络变为(M/16)x(N/16),不妨设 W=M/16,H=N/16。在进入reshape与softmax之前,先做了1x1卷积,如图

RPN中判定positive和negative网络结构

该1x1卷积定义如下:

layer {
name: "rpn_cls_score"
type: "Convolution"
bottom: "rpn/output"
top: "rpn_cls_score"
convolution_param {
num_output: 18 # 2(positive/negative) * 9(anchors)
kernel_size: 1 pad: 0 stride: 1
}
}

可以看到其num_output=18,也就是经过该卷积的输出图像为WxHx18大小,这也就刚好对应了feature maps每一个点都有9个anchors,同时每个anchors又有可能是positive和negative,所有这些信息都保存WxHx(9*2)大小的矩阵。为何这样做?后面接softmax分类获得positive anchors,也就相当于初步提取了检测目标候选区域box(一般认为目标在positive anchors中)。

那么为何要在softmax前后都接一个reshape layer?其实只是为了便于softmax分类,至于具体原因这就要从caffe的实现形式说起了。在caffe基本数据结构blob中以如下形式保存数据:

blob=[batch_size, channel,height,width]

对应至上面的保存positive/negative anchors的矩阵,其在caffe blob中的存储形式为[1, 2x9, H, W]。而在softmax分类时需要进行positive/negative二分类,所以reshape layer会将其变为[1, 2, 9xH, W]大小,即单独“腾空”出来一个维度以便softmax分类,之后再reshape回复原状。贴一段caffe softmax_loss_layer.cpp的reshape函数的解释,非常精辟:

"Number of labels must match number of predictions; "
"e.g., if softmax axis == 1 and prediction shape is (N, C, H, W), "
"label count (number of labels) must be NHW, "
"with integer values in {0, 1, ..., C-1}.";

综上所述,RPN网络中利用anchors和softmax初步提取出positive anchors作为候选区域

bounding box regression 原理

如图所示绿色框为飞机的Ground Truth(GT),红色为提取的positive anchors,即便红色的框被分类器识别为飞机,但是由于红色的框定位不准,这张图相当于没有正确的检测出飞机。所以我们希望采用一种方法对红色的框进行微调,使得positive anchors和GT更加接近。


对于窗口一般使用四维向量(x, y, w, h)表示,分别表示窗口的中心点坐标和宽高,如下图,红色的框A代表原始的positive Anchors,绿色的框G代表目标的GT,我们的目标是寻找一种关系,使得输入原始的anchor A经过映射得到一个跟真实窗口G更接近的回归窗口G',即:

给定anchor

寻找一种变换F,使得:


其中
image.png

那么经过何种变换F才能从A变为G`呢?简单思路就是:

1.先做平移



2.在做缩放


观察上面4个公式发现,需要学习的是

这四个变换。当输入的anchor A与GT相差较小时,可以认为这种变换是一种线性变换, 那么就可以用线性回归来建模对窗口进行微调(注意,只有当anchors A和GT比较接近时,才能使用线性回归模型,否则就是复杂的非线性问题了)。

接下来的问题就是如何通过线性回归获得

了。线性回归就是给定输入的特征向量X, 学习一组参数W, 使得经过线性回归后的值跟真实值Y非常接近,即
对于该问题,输入X是cnn feature map,定义为Φ;同时还有训练传入A与GT之间的变换量,即(tx,ty,tw,th)。输出是
四个变换。那么目标函数可以表示为:

其中
是对应anchor的feature map组成的特征向量,
是需要学习的参数,
是得到的预测值(*表示 x,y,w,h,也就是每一个变换对应一个上述目标函数)。为了让预测值
与真实值
差距最小,设计L1损失函数:

函数优化目标为:


为了方便描述,这里以L1损失为例介绍,而真实情况中一般使用soomth-L1损失。

需要说明,只有在GT与需要回归框位置比较接近时,才可近似认为上述线性变换成立。
说完原理,对应于Faster RCNN原文,positive anchor与ground truth之间的平移量 (tx,ty)与尺度因子(tw,th)如下:



对于训练bouding box regression网络回归分支,输入是cnn feature Φ,监督信号是Anchor与GT的差距(tx,ty,tw,th),即训练目标是:输入 Φ的情况下使网络输出与监督信号尽可能接近。那么当bouding box regression工作时,再输入Φ时,回归网络分支的输出就是每个Anchor的平移量和变换尺度 (tx,ty,tw,th),显然即可用来修正Anchor位置了。

对proposals 进行bounding box regression

在了解bounding box regression后,再回头来看RPN网络第二条线路,如图:


RPN中的bbox reg

上图中1x1卷积的caffe prototxt定义:

layer {
name: "rpn_bbox_pred"
type: "Convolution"
bottom: "rpn/output"
top: "rpn_bbox_pred"
convolution_param {
num_output: 36 # 4 * 9(anchors)
kernel_size: 1 pad: 0 stride: 1
}
}

可以看到其 num_output=36,即经过该卷积输出图像为WxHx36,在caffe blob存储为[1, 4x9, H, W],这里相当于feature maps每个点都有9个anchors,每个anchors又都有4个用于回归的

变换量。

VGG输出50x38x512的特征,对应设置50x38xk个anchors,而RPN输出:

1.大小为50x38x2k的positive/negative softmax分类特征矩阵。
2.大小为50x38x4k 的regression坐标回归特征矩阵。

恰好满足RPN完成positive/negative分类+bounding box regression坐标回归.

Proposal Layer

Proposal Layer负责综合所有

变换量和positive anchors,计算出进准的proposal,送入后续RoI Pooling Layer。还是先来看看Proposal Layer的caffe prototxt定义:

layer {
name: 'proposal'
type: 'Python'
bottom: 'rpn_cls_prob_reshape'
bottom: 'rpn_bbox_pred'
bottom: 'im_info'
top: 'rois'
python_param {
module: 'rpn.proposal_layer'
layer: 'ProposalLayer'
param_str: "'feat_stride': 16"
}
}

Proposal Layer有3个输入:positive vs negative anchors分类器结果rpn_cls_prob_reshape,
对应的bbox reg的


变换量rpn_bbox_pred,以及im_info;另外还有参数feat_stride=16。

首先解释im_info。对于一副任意大小PxQ图像,传入Faster RCNN前首先reshape到固定MxN,im_info=[M, N, scale_factor]则保存了此次缩放的所有信息。然后经过Conv Layers,经过4次pooling变为WxH=(M/16)x(N/16)大小,其中feature_stride=16则保存了该信息,用于计算anchor偏移量。

Proposal Layer forward(caffe layer的前传函数)按照以下顺序依次处理:

1.生成anchors,利用

对所有的anchors做bbox regression 回归
2.按照输入的positive softmax scores由大到小排序anchors,提取前pre_nms_topN(e.g. 6000)个anchors,即提取修正位置后的positive anchors。
3.限定超出图像边界的positive anchors为图像边界,防止后续roi pooling时proposal超出图像边界
4.剔除尺寸非常小的positive anchors
5.对剩余的positive anchors进行NMS(nonmaximum suppression)
6.Proposal Layer有3个输入:positive和negative anchors分类器结果rpn_cls_prob_reshape,对应的bbox reg的(e.g. 300)结果作为proposal输出
之后输出proposal=[x1, y1, x2, y2],注意,由于在第三步中将anchors映射回原图判断是否超出边界,所以这里输出的proposal是对应MxN输入图像尺度的,

RoI Pooling 原理

layer {
name: "roi_pool5"
type: "ROIPooling"
bottom: "conv5_3"
bottom: "rois"
top: "pool5"
roi_pooling_param {
pooled_w: 7
pooled_h: 7
spatial_scale: 0.0625 # 1/16
}
}

其中有新参数pooled_w和pooled_h

1.由于proposal是对应MxN尺度的,所以首先使用spatial_scale参数将其映射回(M/16)x(N/16)大小的feature map尺度;
2.再将每个proposal对应的feature map区域水平分为pooled_w*pooled_h 的网格
3.对网格的每一份都进行max pooling处理。

这样处理后,即使大小不同的proposal输出结果都是 pooled_w*pooled_h 固定大小,实现了固定长度输出。


proposal示意图

Classification

Classification部分利用已经获得的proposal feature maps,通过full connect层与softmax计算每个proposal具体属于那个类别(如人,车,电视等),输出cls_prob概率向量;同时再次利用bounding box regression获得每个proposal的位置偏移量bbox_pred,用于回归更加精确的目标检测框。Classification部分网络结构如图:

Classification部分网络结构图

从RoI Pooling获取到7x7=49大小的proposal feature maps后,送入后续网络,可以看到做了如下2件事:

1.通过全连接和softmax对proposals进行分类,
2.再次对proposals进行bounding box regression,获取更高精度的rect box

损失函数

最小化目标函数,FasterR-CNN中对一个图像的函数定义为:

其中:


RPN与Fast R-CNN特征共享

RPN和Fast R-CNN都是独立训练的,要用不同方式修改它们的卷积层。因此需要开发一种允许两个网络间共享卷积层的技术,而不是分别学习两个网络。注意到这不是仅仅定义一个包含了RPN和Fast R-CNN的单独网络,然后用反向传播联合优化它那么简单。原因是Fast R-CNN训练依赖于固定的目标建议框,而且并不清楚当同时改变建议机制时,学习Fast R-CNN会不会收敛。
RPN在提取得到proposals后,作者选择使用Fast-R-CNN实现最终目标的检测和识别。RPN和Fast-R-CNN共用了13个VGG的卷积层,显然将这两个网络完全孤立训练不是明智的选择,作者采用交替训练(Alternating training)阶段卷积层特征共享:

第一步,我们依上述训练RPN,该网络用ImageNet预训练的模型初始化,并端到端微调用于区域建议任务;

第二步,我们利用第一步的RPN生成的建议框,由Fast R-CNN训练一个单独的检测网络,这个检测网络同样是由ImageNet预训练的模型初始化的,这时候两个网络还没有共享卷积层;

第三步,我们用检测网络初始化RPN训练,但我们固定共享的卷积层,并且只微调RPN独有的层,现在两个网络共享卷积层了;

第四步,保持共享的卷积层固定,微调Fast R-CNN的fc层。这样,两个网络共享相同的卷积层,构成一个统一的网络。

注意:第一次迭代时,用ImageNet得到的模型初始化RPN和Fast-R-CNN中卷积层的参数;从第二次迭代开始,训练RPN时,用Fast-R-CNN的共享卷积层参数初始化RPN中的共享卷积层参数,然后只Fine-tune不共享的卷积层和其他层的相应参数。训练Fast-RCNN时,保持其与RPN共享的卷积层参数不变,只Fine-tune不共享的层对应的参数。这样就可以实现两个网络卷积层特征共享训练。

你可能感兴趣的:(Faster R-CNN)