1 Faster RCNN操作流程
- 1. 卷积层(conv layer):【输入为整张图片,输出为提取的feature map】用于提取图片的特征,比如VGG16。
- 2. RPN模块(Region Proposal Network):【输入为feature map,输出为候选区域】。这里替代之前的search selective。
- 首先生成很多Anchor box,对其进行裁剪过滤后通过softmax判断anchor属于前景(foreground)或者后景(background),属于二分类;
- 另一分支bbox regression来修正anchor box,形成较精确的proposal。
- 3. RoI pooling(与Fast RCNN中相同):【输入为feature map】用于将不同大小的输入转换为固定长度的输出。
- 4. Classify + Bbox Regression:【输出候选区域所属的类,和其在图像中的精确位置】
1.1 基准网络(base block)
Faster RCNN的特征提取模块使用的是VGG16(去掉了pool5及fc层):
- 13个conv层【kernel_size=3,padding=1】:卷积层不会改变feature map的大小
- 13个relu层。
- 4个pooling层【kernel_size=2,padding=2】。pooling层改变feature map的大小,为原来的1/2。总共4层pooling,所以图片下采样率
Faster RCNN支持任意尺寸的输入,上图中input size=(P,Q)。
首先进行规范化尺寸,在检测时会将最小边缩放到600,最大边不超过1000。假定M*N=1000*600,经过基准网络VGG16的卷积模块,feature map的size为 60*40(1000/16~60, 600/16~40)。则feature map的维度为60*40*512(512为channel)。
1.2 RPN block
经典的检测方法生成候选框都很耗时:OpenCV asaboost使用的滑动窗口+图像金字塔生成检测框、RCNN中使用Selective Search生成检测框。
Faster RCNN直接使用RPN(CNN)生成检测框,极大提升了检测框的生成速度。
接下来是网络这样设计的详细介绍
1.2.1 Anchor boxes的生成规则
对于图像里目标检测边界框
【方法1】训练一个回归任务,输出4个值代表边界框的(xmin, ymin, xmax, ymax)。 这种方法存在问题:(1) 图像中的目标尺寸存在多尺度。常见的均方差作为loss难以训练。(2)实际预测时,无法保证xmin<xmax。【方法2】预先设定好候选框,然后学习真实的bbox与候选框的偏移量。例:获取box:xcenter、ycenter、width、height,网络标签为Δxcenter、Δycenter、Δwidth、Δheight。偏移量一般数值较小且处于同一量级,网络可以很好的学习
!!!所以就要进行候选框的预设定的操作,也就是下面的anchor boxes的生成。
经过基准网络后,得到feature map的大小为 w*h,作为RPN的输入。
【anchor】feature map上的任意一个元素。用滑动窗口(conv)扫过feature map,滑动窗口的中心就是anchor,此中心会遍历feature map的每一个元素,所以anchor是遍历feature map上的每个元素。由于特征图和原始图像之间存在比例关系,在特征图上面密集的点对应到原始图像上面是有16个像素的间隔,如下图所示:
【anchor boxes】以base_anchor在input map上的映射点为中心构建的框
需要注意的是,anchor是基于feature map定义的,但anchor boxes是相对于原始图片的。
【RPN制作标签流程如下】:
- 1. RPN的输入feature map ,选定某一个元素为anchor。
- 2. 找到base_anchor在input map上的映射点(对应感受野的中心):input_size=(W,H),output_size=(w, h)。经过基准网络的下采样率S(所有pooling层的步长累乘)。则有W=S*w,H=S*h。假设anchor的为(x,y),对应的anchor boxes的中心为(S*x, S*y)。
- 3. 以映射点为中心,使用3个尺度(面积)和3个长宽比,生成 k=9个anchor boxes。anchor boxes的尺寸是根据输入图像尺寸定义的
- 在代码实现中,def generate_anchors(base_size=16, ratios=[0.5, 1, 2], scales=2**np.arange(3, 6))
- 明确的得知,在feature map中的基础大小为16,多宽高比例为[0.5, 1, 2],多尺度为[16*8=128, 16*16=256, 16*32=512],也就是feature map中16*16大小的anchor box,通过宽高比变换和多尺度变换,对应于原图中的region proposal。
此时由三种面积(128*128,256*256,512*512)和三种长宽比(1:1, 1:2, 2:1)
- 4. 边界框对应的两种标签:分类+回归
- cls中对应的有2k个输出,代表k个边界框内是否为物体。这里不关心object的类别,只关心是object还是background
- reg中对应的有4k个输出,代表k个边界框的坐标和真实检测框的坐标的偏移量。
以上的流程,是对于某一个anchor的操作。
1.2.2 Anchor的特性
【anchor boxes的数量】对于RPN输入feature map的大小为 w*h,对应的有w*h 个anchor、w*h*k个anchor boxes。
【平移不变性】当输入图片中的目标发生平移,但不会影响锚点和提议框的生成。作为比较,MultiBox方法[27]使用的k-means生成800个锚点,如果目标平移,MultiBox生成的提议框可能也会改变。
平移不变性也减小的模型的大小。该层的参数比MultiBox少了两个量级,期望可以在PASCAL VOC上有更小的过拟合
- MultiBox有(4+1)*800维的全连接输出层,MultiBox中的GoogleNet为1534*(4+1)*800 = 6.1*10^6 个参数
- Faster RCNN中当k=9时有(4+2)*9维的卷积输出层。对于VGG16,具有512*(4+2)*9 = 2.8*10^4 个参数
【多尺度锚点作为回归的参考】多尺度预测的方法
- 1.基于图像/特征金字塔:例如DPM[8]和基于CNN的方法。图像在多个尺度上进行缩放,针对每个尺度计算特征映射(HOG[8]或者深卷积特征,这种方法有效,但也耗时)。其中HOG并未深入了解
- 2.特征映射上使用多尺度(或不同长宽比) 的滑动窗口:相当于一个“滤波器金字塔”。这种方法通常和第一种联合使用
- 3.多尺度锚点的方法(锚点金字塔):这样可以只依赖单一尺度的图像和特征映射,并使用单一的尺寸和滤波器(特征映射上的滑动窗口)。多尺度锚点设计是共享特征的关键组件,不需要额外的成本来处理尺度,这样更具有成本效益。
Faster RCNN使用了多尺度的锚点、单尺度的卷积层。下面会通过实验对比锚点的多尺度的效果。
1.2.3 RPN的loss function
对feature map上的每个像素分别生成9个anchor boxes,对这些anchor boxes进行过滤和标记。
二分类的label:
- 1. 去掉超过W*H 即原图边界的anchor boxes
- 2. 如果anchor boxes 与 ground-truth box 的IoU值最大,标记为正样本,label=1
- 3. 如果anchor boxes 与 groud-truth boxes 的IoU>0.7,标记为正样本,label=1(当极少情况,这个条件找不到正样本,还是要依赖IoU最大找出正样本)
- 4. 如果anchor boxes 与 groud-true boxes的IoU<0.3,标记为负样本,label=0
- 剩余的anchor boxes被舍弃,不用于最终训练,label=-1
检测框偏移量的label:
- ground-truth boxes:真实框的中心点的位置(
) 和宽高 (
)
- anchor boxes:候选框中心点的位置 (
) 和宽高 (
)
- predict boxes:RPN预测的检测框的中心位置 (
) 和宽高 (
)
上图中的黑框是anchor box,红框是predict box。实际的框计算示意图同理
所以RPN的loss function如下图
:使用的是交叉熵。
为标签,
为预测。
是训练时的batchsize=256
:
,使用的是smoothL1(在fast rcnn总结里面的损失函数处有介绍),
为标签,
为预测。
是训练时的batchsize=256,
表示回归算是仅对正锚点激活,否则被禁用。
:平衡参数。设置为10,使cls和reg项的权重大致相等。
方程中的两项,通过各自的batchsize进行了归一化。我们通过实验发现:(1) 结果对宽范围的值不敏感[Table9];(2) 归一化不是必须的,可以简化。
1.2.4 RPN的结构图
概述一下RPN的计算流程:
经过基准网络VGG16后,feature map的大小为原图的1/16【feature map(60*40)的 1*1,对应原图(1000*600)的16*16】(默认k=9)
- feature map A,size=(1, 60, 40, 512)
- A 经过conv(3*3*512)*512,输出B的 output_size= (1, 60, 40, 512)
- 分类:B 经过conv(1*1*512)*18,output_size=(1, 60, 40, 18);在经过reshape,得到Ycls。
- 回归:B 经过conv(1*1*512)*36,output_size=(1, 60, 40, 36),得到Yreg。
- 训练时,也是在这里设置标签,进行RPN的训练
- 利用Ycls和Yreg,得到很多候选框。经过Proposal层,结合使用NMS筛选出约300个候选框,输入到下一层。
训练时的RPN结构图
红框:不关心基准网络的结构,所以将基准网络用ConvLayers代替,用红框圈出,后续图都如此
紫框:网络结构中部分,其余部分是label训练处理的流程。
rpn-data:(python AnchorTargetLayer)层会按照和test阶段Proposal层完全相同的方法用于训练
rpn_loss_cls:rpn_cls_score_reshape --->> p,rpn_labels -->>p*,Ncls参数被隐含了
rpn_loss_bbox:rpn_bbox_pred -->> t,rpn_bbox_targets -->> t*,rpn_bbox_inside_weight对应为p*。
1.2.4 Proposal layer
综合anchor box、相应的得分、偏移量的信息,使用非极大值抑制 (NMS),筛选出较为精准的Proposal boxes(对应M*N维度),送入到RoI pooling。
caffe源码中的处理方式:
- 1. 生成 w*h*9 个anchor box,然后加上RPN的输出Δx、Δy、Δw、Δh,得到了较为更准确的边界框。
- 2. 根据RPN的输出Ycls (boxes的得分)排序,提取前N(eg. 6000)个修正后的anchors box
- 3. 候选框超出图像时,限定为图像边界
- 4. 去除非常小的候选框(w<threshold 或 h<threshold)
- 5. 使用NMS(对于NMS的介绍,在RCNN中有介绍到)
- 6. 将剩余的anchor 按照各自的得分排序,选出前W (eg.300) 为Proposal的输出。
- 7. 将Proposal的输出scores、rois保存在python pickle文件中
RPN的网络结构整体的流程就是
【生成设定的候选框anchor boxes】 --->> 【候选框内的数据的分类+偏移量回归】 --->> 【使用NMS筛选出指定数量的候选框】
1.3.任务模块(task block)
基准模型提取的feature map、RPN提取的Proposal,输入到任务模块中。
为了接受不同尺度的数据,所以需要RoI pooling层,将不同维度的feature map转化成相同维度。所以RoI pooling相当于任务模块的接口。
1.3.1 RoI pooling
在自己总结的Fast R-CNN中,有介绍RoI pooling的相关内容
这里RoI pooling的输入:【原始的feature maps】+【RPN输出的proposal boxes (尺寸不固定)】
这里RoI pooling的输出:固定维度的特征。
在代码实现中,
RoI pooling 的输入为:VGG16最后一层输出的feature map大小 (60,40,512)、RPN层产生的300个proposal boxes。
- 遍历每个proposal boxes将其坐标值缩小16倍,也就是获取了proposal boxes在特征图上的尺度。
- 对每个boxes内的特征图,划分成7*7个小区域,每个区域内使用maxpooling
RoI pooling的输出为:300*(7*7*512) 维度的特征(batchsize=300)
看到这里有疑问:(1) 如果boxes中的feature map的尺寸小于7应该怎样处理?(2) 并且输入图中的boxes对应到特征图上的boxes,不是整除的关系;使用7*7得到小区域,也不是一定是整除的关系。两次的向下取整的操作,造成了一定的精度损失,这又该怎样解决呢?
答:(1) 代码中应有处理方式,后续补充。(2) Faster RCNN并未解决该问题,而是在后续的Mask RCNN中得到了优化。
1.3.2 全连接层
RoI pooling层的输出大小为 (300, 7,7,512),输入到全连接层。分为两个任务
- 分类:对proposal boxes进行分类,计算具体属于哪一类(人、桌子等)
- 回归:再次对proposal boxes进行偏移量回归。得到最终的boxes。
训练时的结构图:
蓝框:从前面保存的pickle文件中读取出scores和rois,rois传入网络
绿框:计算bbox_inside_weights+bbox_outside_weights传入soomth_L1_loss(??????)
2 Faster RCNN的训练
基准网络选择VGG,使用预训练好的参数。实际训练过程的步骤:
- (1) 用预训练好的VGG初始化网络,单独训练RPN(训练好后,获取proposal boxes并保存)
- (2) 用预训练好的VGG初始化网络,使用上一步的proposal boxes作为输入,训练FasterRCNN。(此时两个网络参数不共享)
- (3) 使用(2)中的Faster RCNN网络参数初始化RPN网络。但基准网络VGG权重固定不训练,值更新RPN模块。(此时两个网络共享了共有的卷积层)
- (4) 联合训练:固定基准网络VGG权重不训练,RPN block 和 task block同时训练。
这里只是用了类似的2次循环训练。作者表述,循环更多次后效果并没有提升。
2.1 训练RPN网络
基准网络:预训练好的VGG
优化器:SGD
batch:每一个mini-batch包含从一张图片中随机提取的256个anchor(注意不是所有的anchor都用于训练),正样本和负样本比例为1:1。如果图个图片中正样本数小于128,则多用一些负样本以满足256个Proposal训练。
初始化:新增的2层参数用均值为0,标准差为0.01的高斯分布来进行初始化,其余层(都是共享的卷积层,与VGG共有的层)参数用ImageNet分类预训练模型来初始化
参数化设置:个
在PASCAL数据集上:
前60k个mini-batch进行迭代,学习率设置为0.001;
后20k个mini-batch进行迭代,学习率设置为0.0001;
设置动量momentum=0.9,权重衰减为0.0005
画图工具:http://ethereon.github.io/netscope/#/editor
https://blog.csdn.net/w113691/article/details/78644982