一文读懂Faster RCNN

来源:信息网络工程研究中心 本文约7500字,建议阅读10+分钟 本文从四个切入点为你介绍Faster R-CNN网络。
经过R-CNN和Fast RCNN的积淀,Ross B. Girshick在2016年提出了新的Faster RCNN,在结构上,Faster RCNN已经将特征抽取(feature extraction),proposal提取,bounding box regression(rect refine),classification都整合在了一个网络中,使得综合性能有较大提高,在检测速度方面尤为明显。
1 Conv layers
2 Region Proposal Networks(RPN)
- 2.1 多通道图像卷积基础知识介绍
- 2.2 anchors
- 2.3 softmax判定positive与negative
- 2.4 bounding box regression原理
- 2.5 对proposals进行bounding box regression
- 2.6 Proposal Layer
3 RoI pooling
- 3.1 为何需要RoI Pooling
- 3.2 RoI Pooling原理
4 Classification
5 Faster RCNN训练
- 5.1 训练RPN网络
- 5.2 通过训练好的RPN网络收集proposals
- 5.3 训练Faster RCNN网络
Questions and Answer

Conv layers。作为一种CNN网络目标检测方法,Faster RCNN首先使用一组基础的conv+relu+pooling层提取image的feature maps。该feature maps被共享用于后续RPN层和全连接层。 Region Proposal Networks。RPN网络用于生成region proposals。该层通过softmax判断anchors属于positive或者negative,再利用bounding box regression修正anchors获得精确的proposals。 Roi Pooling。该层收集输入的feature maps和proposals,综合这些信息后提取proposal feature maps,送入后续全连接层判定目标类别。 Classification。利用proposal feature maps计算proposal的类别,同时再次bounding box regression获得检测框最终的精确位置。
首先缩放至固定大小MxN,然后将MxN图像送入网络; 而Conv layers中包含了13个conv层+13个relu层+4个pooling层; RPN网络首先经过3x3卷积,再分别生成positive anchors和对应bounding box regression偏移量,然后计算出proposals; 而Roi Pooling层则利用proposals从feature maps中提取proposal feature送入后续全连接和softmax网络作classification(即分类proposal到底是什么object)。

新出炉的pytorch官方Faster RCNN代码导读:
捋一捋pytorch官方FasterRCNN代码
https://zhuanlan.zhihu.com/p/31426458

1 Conv layers
所有的conv层都是:kernel_size=3,pad=1,stride=1 所有的pooling层都是:kernel_size=2,pad=0,stride=2

2 Region Proposal Networks(RPN)

2.1 多通道图像卷积基础知识介绍
对于单通道图像+单卷积核做卷积,第一章中的图3已经展示了; 对于多通道图像+多卷积核做卷积,计算方式如下:

2.2 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.]]
表矩形左上和右下角点坐标。9个矩形共有3种形状,长宽比为大约为
三种,如图6。实际上通过anchors就引入了检测中常用到的多尺度方法。

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


2.3 softmax判定positive与negative

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}}
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 N*H*W, ""with integer values in {0, 1, ..., C-1}.";
2.4 bounding box regression原理

表示,分别表示窗口的中心点坐标和宽高。对于图 11,红色的框A代表原始的positive Anchors,绿色的框G代表目标的GT,我们的目标是寻找一种关系,使得输入原始的anchor A经过映射得到一个跟真实窗口G更接近的回归窗口G',即:给定anchor
;寻找一种变换F,使得:
,其中
。

先做平移:

再做缩放:

这四个变换。当输入的anchor A与GT相差较小时,可以认为这种变换是一种线性变换, 那么就可以用线性回归来建模对窗口进行微调(注意,只有当anchors A和GT比较接近时,才能使用线性回归模型,否则就是复杂的非线性问题了)。
了。线性回归就是给定输入的特征向量X, 学习一组参数W, 使得经过线性回归后的值跟真实值Y非常接近,即Y=WX。对于该问题,输入X是cnn feature map,定义为Φ;同时还有训练传入A与GT之间的变换量,即
。输出是
四个变换。那么目标函数可以表示为:
是对应anchor的feature map组成的特征向量,
是需要学习的参数,
是得到的预测值(*表示 x,y,w,h,也就是每一个变换对应一个上述目标函数)。为了让预测值
与真实值
差距最小,设计L1损失函数:

说完原理,对应于Faster RCNN原文,positive anchor与ground truth之间的平移量
与尺度因子
如下:
,即训练目标是:输入 Φ的情况下使网络输出与监督信号尽可能接近。那么当bouding box regression工作时,再输入Φ时,回归网络分支的输出就是每个Anchor的平移量和变换尺度
,显然即可用来修正Anchor位置了。2.5 对proposals进行bounding box regression

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}}
变换量。大小为50*38*2k 的positive/negative softmax分类特征矩阵; 大小为 50*38*4k 的regression坐标回归特征矩阵。
2.6 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"}}
变换量rpn_bbox_pred,以及im_info;另外还有参数feat_stride=16,这和图4是对应的。
生成anchors,利用对所有的anchors做bbox regression回归(这里的anchors生成和训练时完全一致)
;按照输入的positive softmax scores由大到小排序anchors,提取前pre_nms_topN(e.g. 6000)个anchors,即提取修正位置后的positive anchors; 限定超出图像边界的positive anchors为图像边界,防止后续roi pooling时proposal超出图像边界(见文章底部QA部分图21); 剔除尺寸非常小的positive anchors; 对剩余的positive anchors进行NMS(nonmaximum suppression) Proposal Layer有3个输入:positive和negative anchors分类器结果rpn_cls_prob_reshape,对应的bbox reg的(e.g. 300)结果作为proposal输出。
生成anchors -> softmax分类器提取positvie anchors -> bbox reg回归positive anchors -> Proposal Layer生成proposals
3 RoI pooling
原始的feature maps RPN输出的proposal boxes(大小各不相同)
3.1 为何需要RoI Pooling
从图像中crop一部分传入网络; 将图像warp成需要的大小后传入网络。

3.2 RoI Pooling原理
layer {name: "roi_pool5"type: "ROIPooling"bottom: "conv5_3"bottom: "rois"top: "pool5"roi_pooling_param {pooled_w: 7pooled_h: 7spatial_scale: 0.0625 # 1/16}}
由于proposal是对应MxN尺度的,所以首先使用spatial_scale参数将其映射回(M/16)x(N/16)大小的feature map尺度; 再将每个proposal对应的feature map区域水平分为pooled_w x pooled_h 的网格; 对网格的每一份都进行max pooling处理。

4 Classification

通过全连接和softmax对proposals进行分类,这实际上已经是识别的范畴了; 再次对proposals进行bounding box regression,获取更高精度的rect box。


5 Faster RCNN训练
在已经训练好的model上,训练RPN网络,对应stage1_rpn_train.pt 利用步骤1中训练好的RPN网络,收集proposals,对应rpn_test.pt 第一次训练Fast RCNN网络,对应stage1_fast_rcnn_train.pt 第二训练RPN网络,对应stage2_rpn_train.pt 再次利用步骤4中训练好的RPN网络,收集proposals,对应rpn_test.pt 第二次训练Fast RCNN网络,对应stage2_fast_rcnn_train.pt

5.1 训练RPN网络


表示positive softmax probability,
;反之IoU<0.3时,认为是该anchor是negative,
;至于那些0.3<IoU<0.7的anchor则不参与训练);t代表predict bounding box,t* 代表对应positive anchor对应的GT box。可以看到,整个Loss分为2部分:cls loss,即rpn_cls_loss层计算的softmax loss,用于分类anchors为positive与negative的网络训练; reg loss,即rpn_loss_bbox层计算的soomth L1 loss,用于bounding box regression网络训练。注意在该loss中乘了
,相当于只关心positive anchors的回归(其实在回归中也完全没必要去关心negative)。
和
差距过大,用参数λ平衡二者(如
,
时设置
),使总的网络Loss计算过程中能够均匀考虑2种Loss。这里比较重要是
使用的soomth L1 loss,计算公式如下:
在RPN训练阶段,rpn-data(python AnchorTargetLayer)层会按照和test阶段Proposal层完全一样的方式生成Anchors用于训练; 对于rpn_loss_cls,输入的rpn_cls_scors_reshape和rpn_labels分别对应
与
,参数隐含在
与
的caffe blob的大小中;对于rpn_loss_bbox,输入的rpn_bbox_pred和rpn_bbox_targets分别对应 t 与 t* ,rpn_bbox_inside_weigths对应
,rpn_bbox_outside_weigths未用到(从smooth_L1_Loss layer代码中可以看到),而
同样隐含在caffe blob大小中。
5.2 通过训练好的RPN网络收集proposals

5.3 训练Faster RCNN网络
将提取的proposals作为rois传入网络,如图21蓝框; 计算bbox_inside_weights+bbox_outside_weights,作用与RPN一样,传入soomth_L1_loss layer,如图21绿框。

Q&A
为什么Anchor坐标中有负数?

Anchor到底与网络输出如何对应?

为何有ROI Pooling还要把输入图片resize到固定大小的MxN?
拓展
编辑:黄继彦
评论
