【论文】Shaoqing Ren, Kaiming He, Ross Girshick, Jian Sun. Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks.(pdf)
整体框架
Faster RCNN 可以分为 4 个大模块;
-
Conv Layers
用于图片的特征提取,经过一系列的 conv + relu + pooling 的特征映射
-
Region Proposal Networks
用于推荐候选区域,替代之前在 RCNN 或 Fast RCNN 中的 search selective,通过 softmax 判断 anchor 属于正样本还是负样本,然后利用 bbox regression 修正 anchor 获得精确的 proposal
-
RoI Pooling
和 Fast RCNN 一样,将不同大小形状的 proposal 转换为固定大小的输出 proposal feature
-
Classification
利用 proposal feature 计算 proposal 的类别,同时再次使用 bbox regression 获得加测框的最终精确位置
下面展示了 Faster RCNN 的细节处理,假设输入一张任意大小的图片 P×QP\times QP×Q
- 首先,缩放至固定大小 M×NM\times NM×N,然后再将图片送入网络
- Conv Layers 包含了 13 个卷积层(kernel_size = 3, padding = 1, stride = 1) + 13 个 ReLU + 4 个 池化层(kernel_size = 2, padding = 0, stride = 2)
- RPN 首先经过 3×33\times33×3 的卷积,分别生成 positive anchor 和对应的 bbox regression,然后计算出需要的 proposal
- RoI Pooling 则利用 proposal 对应 feature map 得到 proposal feature。后续送入全连接网络通过 softmax 做分类
Conv Layers
Faster RCNN 中对所有卷积都进行了 padding 处理(padding = 1),于是经过 3×33\times33×3 的卷积后输出图的大小并不发生改变(经过卷积后 (M?3+2×1)/1+1=M(M-3+2\times1)/1+1=M(M?3+2×1)/1+1=M)
这样的好处是,每次经过池化层图片大小缩小为原来的一半,即 M2×N2\frac{M}{2}\times\frac{N}{2}2M?×2N?,而卷积和 relu 不改变图片大小,于是在经过 Conv Layers 后,图片变为 M16×N16\frac{M}{16}\times\frac{N}{16}16M?×16N?,这样在 RoI Pooling 时将非常容易对齐
Anchor Generation Layer
Fast RCNN 中会反复提到一个概念——anchor,所谓 anchor 其实就是一组矩形框,9 个矩形有 3 种形状,长宽比大约为 1:11:11:1、、、1:21:21:2 和 2:12:12:1,实际上通过关 anchor 就引入了检测中常用的多尺度方法
在 Conv Layers 输出的 feature map 的每个点都配备这 9 个 anchor 作为初始的检测框,这样获得的检测框存在不准确的问题也不用太担心,后面会有两次机会通过回归修正检测框的位置
我们对论文图片做如下两点解释:
-
首先,Conv Layers 中的 conv5 的输出维度为 256,也就是有 256 张特征图,选用这一层的特征做 RPN 的输入,那么在每个点上维度都是 256
-
假设每个点有 kkk 个 anchor,每个 anchor 分为 positive 和 negative,那么分类得分就是 2k2k2k;同时,每个 anchor 都有 (x,y,w,h)(x, y, w, h)(x,y,w,h) 4 个偏移量,所以会有 4k4k4k coordinates
于是,接下来 anchor generation layer 的操作就是在原图尺度上生成密密麻麻的候选 anchor,论文中原图的大小为 800×600800\times600800×600,在通过 Conv Layer 后,feature map 的大小就是 50×3850\times3850×38(向上取整),那么就会生成 50×38×9=1710050\times38\times9=1710050×38×9=17100 个 anchor
Bounding Box Regression
如下图所示,红色的框为提取的 positive anchor box,绿色的框为 ground truth box,即便红色的框可以识别出飞机,但是由于定位不准确,我们需要 bbox regression 对红色的框进行微调,使得其更加接近于 ground truth
对于一个 box 使用 (x,y,w,h)(x,y,w,h)(x,y,w,h) 表示,分别表示中心点的位置和宽高。下图中还是用红色的框表示 positive anchor box A=(Ax,Ay,AwAh)A=(A_x,A_y,A_wA_h)A=(Ax?,Ay?,Aw?Ah?),绿色的框表示 ground truth box G=(Gx,Gy,Gw,Gh)G=(G_x,G_y,G_w,G_h)G=(Gx?,Gy?,Gw?,Gh?),我们希望寻得一种关系可以使 AAA 经过映射得到一个跟 ground truth box 更接近的 regression box G′=(Gx′,Gy′,Gw′,Gh′)G'=(G'_x,G'_y,G'_w,G'_h)G′=(Gx′?,Gy′?,Gw′?,Gh′?)
我们先做平移操作
Gx′=Aw?dx(A)+AxGy′=Ah?dy(A)+AyG'_x=A_w\cdot d_x(A)+A_x\\ G'_y=A_h\cdot d_y(A)+A_y Gx′?=Aw??dx?(A)+Ax?Gy′?=Ah??dy?(A)+Ay?
再做缩放
Gw′=Aw?exp(dw(A))Gh′=Ah?exp(dh(A))G'_w=A_w\cdot exp(d_w(A))\\ G'_h=A_h\cdot exp(d_h(A)) Gw′?=Aw??exp(dw?(A))Gh′?=Ah??exp(dh?(A))
其实,我们需要学习的参数只有 4 个 dx(A),dy(A),dw(A),dh(A)d_x(A),d_y(A),d_w(A),d_h(A)dx?(A),dy?(A),dw?(A),dh?(A),在 anchor box 与 ground truth box 之间的差异不太大时,我们可以将其看作是一种线性变换,那么就可以使用线性回归来微调(差异过大时,这时将是一个非线性的问题)
线性变换可以表示为 Y=WXY=WXY=WX,输入是 anchor 对应的 feature map 组成的特征向量 ?(A)\phi(A)?(A),训练同时传入 AAA 与 GGG 之间的差异 (tx,ty,tw,th)(t_x,t_y,t_w,t_h)(tx?,ty?,tw?,th?),那么变换的目标函数就可以表示为
d?(A)=W?T??(A)d_*(A)=W_*^T\cdot\phi(A) d??(A)=W?T???(A)
为了让预测值 d?(A)d_*(A)d??(A) 与真实值 t?t_*t?? 的差距最小,设计 L1 损失函数
Loss=∑iN∣t?i?W?T??(Ai)∣Loss=\sum_i^N|t_*^i-W_*^T\cdot\phi(A^i)| Loss=i∑N?∣t?i??W?T???(Ai)∣
函数优化目标为
W^?=argminW?∑iN∣t?i?W?T??(Ai)∣+λ∣∣W?∣∣\hat W_*=\underset{W_*}{argmin}\ \sum_i^N|t_*^i-W_*^T\cdot\phi(A^i)|+\lambda||W_*|| W^??=W??argmin? i∑N?∣t?i??W?T???(Ai)∣+λ∣∣W??∣∣
实际中使用 smooth-L1 损失
smoothL1(x)={σ2x22∣∣x∣<1σ2∣x∣∣?0.5σ2otherwisesmooth_{L1}(x)=\left\{\begin{matrix} \frac{\sigma^2x^2}{2} & ||x|<\frac{1}{\sigma^2}\\ |x||-\frac{0.5}{\sigma^2} & otherwise \end{matrix}\right. smoothL1?(x)={
2σ2x2?∣x∣∣?σ20.5??∣∣x∣<σ21?otherwise?
清楚了 bbox regression 下面我们要做的就是在 RPN 的第二条路径对 proposal 进行 bbox regression,论文中通过 1×11\times11×1 的卷积实现,卷积的输出为 36,刚好对应一个点 9 个 anchor,每个 anchor 有 4 个回归偏量
Region Proposal Network
Faster RCNN 抛弃传统的滑动窗口和 ss(Selective Search)方法生成检测框,直接采用 RPN 生成检测框。RPN 网络分为两条线,一条通过 softmax 分类判断 anchor 是正样本分类还是负样本分类,一条计算 anchor 的 bbox regression 偏移量。后面的 proposal 层负责综合 positive anchor 和回归的偏移量获得 proposal,同时提出太小或超出边界的检测框
RPN 训练的整个损失函数可以表示为
L({pi},{ti})=1Ncls∑iLcls(pi,pi?)+λ1Nreg∑ipi?Lreg(ti,ti?)L(\left\{p_i\right\},\left\{t_i\right\})=\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^*) L({
pi?},{
ti?})=Ncls?1?i∑?Lcls?(pi?,pi??)+λNreg?1?i∑?pi??Lreg?(ti?,ti??)
pip_ipi? 表示 positive softmax probability;如果第 iii 个 anchor box 与 ground truth box 的 IoU > 0.7 则 pi?=1p_i^*=1pi??=1 ,如果 IoU < 0.3,pi?=0p_i^*=0pi??=0,至于,IoU 落在 0.3 到 0.7 之间的 anchor 则不参与训练;ttt 表示 predicted bounding box,t?t^*t? 代表 positive anchor 对应的 ground truth box
回归损失乘以了一个系数 pi?p_i^*pi?? 表示我们只关心 positive anchor 的损失。由于实际计算中,NclsN_{cls}Ncls? 和 NregN_{reg}Nreg? 的数量级相差较大,所以引入了平衡因子 λ\lambdaλ
如前面所述,LregL_{reg}Lreg? 使用 smooth-L1 损失
Lreg(ti,ti?)=∑i∈{x,y,w,h}smoothL1(ti?ti?)ProposallayerL_{reg}(t_i,t_i^*)=\sum_{i\in\left\{x,y,w,h\right\}}smooth_{L_1}(t_i-t_i^*)Proposal layer Lreg?(ti?,ti??)=i∈{
x,y,w,h}∑?smoothL1??(ti??ti??)Proposallayer
tx=(x?xa)/wa,ty=(y?ya)/hatw=log(w/wa),th=log(h/ha)tx?=(x??xa)/wa,ty?=(y??y)/hatw?=log(w?/wa),th?=log(h?/ha)t_x=(x-x_a)/w_a,\ t_y=(y-y_a)/h_a\\ t_w=log(w/w_a),\ t_h=log(h/h_a)\\ t_x^*=(x^*-x_a)/w_a,\ t_y^*=(y^*-y)/h_a\\ t_w^*=log(w^*/w_a),\ t_h^*=log(h^*/h_a) tx?=(x?xa?)/wa?, ty?=(y?ya?)/ha?tw?=log(w/wa?), th?=log(h/ha?)tx??=(x??xa?)/wa?, ty??=(y??y)/ha?tw??=log(w?/wa?), th??=log(h?/ha?)
其中,x,xa,x?x,x_a,x^*x,xa?,x? 分别对应 predicted box,anchor box 和 ground truth box
proposal layer
proposal layer 负责综合回归偏量和 positive anchor,计算出精确的 proposal。除了回归偏量和 positive anchor 外,proposal layer 还有一个输入 im_info,以及一个参数 feature_stride = 16
- feature_stride 记录了 Conv Layers 的缩放程度,即经过 4 次池化,每次缩小为原来的一半,最终的 feature map 为 M16×N16\frac{M}{16}\times\frac{N}{16}16M?×16N?
- 对于一张任意大小 P×QP\times QP×Q 的图像都会缩放到固定大小 M×NM\times NM×N,im_fo 记录的则是这一步的缩放信息,即 im_fo=[M,N,scale_factor]im\_fo = [M, N, scale\_factor]im_fo=[M,N,scale_factor]
proposal layer 具体的工作流程如下:
- 利用回归偏量对所有的 anchor 做位置修正生成 anchor
- 按照输入的 positive softmax socre 对 anchor 进行排序,然后提取前 12k 个(测试时 6k)修正位置后的 positive anchor
- 限定超出图像边界的 positive anchor 为图像边界,防止后续 RoI Pooling 时 proposal 超出图像边界
- 剔除尺寸非常小的 positive anchor
- 对剩余的 positive anchor 进行非最大抑制,然后取前 2k 个(测试时300 个) positive anchor
- 最后取挑出 128 个正样本和 128 个负样本用于训练
值得一提的是这里 proposal layer 的输出是对应 M×NM\times NM×N 输入尺度的,而不是 feature map 上的尺度
RoI Pooling
为什么需要 RoI Pooling 呢?
在历史上,网络训练好后输入图像的尺寸也就固定了,对于输入大小不同的图像有两种解决方法:(1)从图像中截取出固定大小的区域;(2)将图像 warp 成固定大小。但是这两种方式都存在一定的问题,第一种破坏了图像的完整结构,第二种破坏了图像的原始形状信息
而 RoI Pooling 的提出正是为了解决这些问题,对大小形状不同的 proposal 进行一个统一化的处理。RoI Pooling 在 Fast RCNN 中就已经提出,大致流程也是相同的:
- 由于前面传入的 proposal 尺寸对应 M×NM\times NM×N,所以先将其映射回 M16×N16\frac{M}{16}\times\frac{N}{16}16M?×16N? 的 feature map 大小进行讨论
- 将每个 proposal 对应的区域分为 pooled_w×pooled_hpooled\_w\times pooled\_hpooled_w×pooled_h(e.g. 7×77\times77×7)大小的网格
- 最后进行 max pooling 操作
Classification
Classification 通过前面的 proposal feature map 经过全连接层和 softmax 计算每个 proposal 对应每个类别的得分。同时,在 Classification 中会再次利用 bbox regression 对每个 proposal 的位置进行精修
Faster RCNN 训练
RPN 和 Fast RCNN 都会要求利用 CNN 网络提取图像特征,所以论文的做法是使 RPN 和 Fast RCNN 共享同一个卷积网络。于是,Fast RCNN 的训练类似于一种弄迭代的过程:
- 先训练 RPN,然后使用得到的候选区域训练 Fast RCNN
- 接着使用 Fast RCNN 中关于卷积网络的部分去初始化 RPN,然后再次训练 RPN,这里不跟新关于卷积网络的内容,仅更新 RPN 特有的部分
- 最后再次训练 Fast RCNN,这里也是不更新关于卷积网络的部分,仅更新 Fast RCNN 特有的层
(现在,在 github 上开源的实现大多采用近似联合训练 approximate joint training,采用端到端的一步训练)
下面两幅图展示了 Fast RCNN 的完整流程