Faster-RCNN算法详解
Faster-CNN结构图(以下是Faster-RCNN的结构图)
上图中的目标检测包含了包括region proposal(生成ROI)、feature extraction(特征提取网络)、classification(ROI分类)、regression(ROI回归)。而faster-rcnn利用一个神经网络将这4个模块结合起来,训练了一个端到端的网络。
输入:
将P*Q的图形reshape成M*N大小的图形,文中reshape成800x600
特征提取网络:
通常由conv+pooling+relu组成,常用训练好的网络(VGG,Inception, Resnet),得到的图形叫做特征提取图。原文中共有13个conv,13个relu, 4个poling
- 所有conv层中,kernel_size = 3, pad=1; 填充之后图像大小为(m+2)*(n+2),使用3X3卷积核做运算之后,输出的图像大小为mxn,不改变图像的大小。
- 所有pooling层,kernel_size = 2, stride=2; 使图像缩小一半。
RPN网络(生成ROI):这是Faster-CNN的巨大优势
1.Anchors(feature map后做3x3 padding=1的卷积之后开始添加anchor,共有9个)
- 文中每个点有9个矩阵,长宽比width:height=[1:1, 1:2,2:1]三种形状(所以有9种矩阵)
关于anchor size:根据检测图像人为设置的,能够基本覆盖整个图形大小
遍历feature map的每一个点,为每一个点准备9种anchor作为初始的检测框
解释上图:
- 原文中使用的是ZF model, 最后的conv5层num_output=256,对应生成256张特征图,所以相当于feature map每个点都是256-d
- 在conv5之后做3x3卷积,输出还是256-d
- Feature map中每个点都有9个anchor,每个anchor又分为foreground和background,所以每个点有 2k(k为anchors数)个scores值, 每个anchor有4个坐标偏移量 regression=4k(k为anchors数)
- 训练全部anchors太庞大,会选取256个anchors进行训练
如何选取这256个anchors?
即计算这些foreground ROI与真实目标之间的bounding box的偏差值,包括Δx、Δy、Δw、Δh, 然后做NMS(非极大值抑制,即根据分类的得分对这些ROI进行排序,然后选择其中的前256个ROI);
2.使用softmax判定foreground和background
对于M*N大小的图片,到达RPN模块后变成了(m/16)*(n/16)大小
- 输入是每一点的9个anchor框
- 先做1*1卷积,,输出大小为W*H*9*2 也就是输出18张图形,W,H分别是anchor的长和宽,9是有9个anchor,2是代表foreground和background
- 两个reshape是为了便于softmax分类。运算数据类型[batch_size,channel,height,width],将[1,2*9,H,W]变为[1,2,H*9,W]的形式,便于softmax分类
3.对proposals进行bounding box regression
3.1Bounding box regression详解:
上图中绿色框为ground truth,红色框为提取的foreground anchor,但是红色的框定位不正确,相当于没有正确的识别飞机。我们是否可以采取一些微调措施,使得foreground anchor与ground truth接近。
对于窗口一般使用四维向量(x, y, w, h)表示,分别表示窗口的中心点坐标和宽高
假设A的数据值为A=(Ax, Ay, Aw, Ah),寻找一种映射f,使得f(Ax, Ay, Aw, Ah)=(G'x, G'y, G'w, G'h),其中(G'x, G'y, G'w, G'h)≈(Gx, Gy, Gw, Gh)
先平移再缩放
接下来就是如何dx(A),dy(A),dw(A),dh(A),对于已知输入和输出我们可以使用线性回归(只能求解对于A各G非常接近的情况)
输入X是一张经过num_output=1的1x1卷积获得的feature map,定义为Φ;同时还有训练传入的GT,即(tx, ty, tw, th)。输出是dx(A),dy(A),dw(A),dh(A)四个变换。那么目标函数可以表示为:
*代表x,y,w,h四个参数,其中Φ(A)是对应anchor的feature map组成的特征向量,w是需要学习的参数,d(A)是得到的预测值,为了让预测值和真实值最小,定义损失函数:
所以我们的优化目标为:
3.2做1*1卷积,输出为W*H*9*4维数据,W、H分别是anchor的大小,9是有9个anchor,4是4个用于回归的[dx(A),dy(A),dw(A),dh(A)]变换量
4.Proposal layer: 负责综合[dx(A),dy(A),dw(A),dh(A)]和foreground,送入后续的POI polling
共有三个输入:classification layer, regression layer和im_info,
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则保存了该信息。所有这些数值都是为了将proposal映射回原图而设置的
proposal按照以下顺序处理:
- 再次生成anchors(因为对anchors做了调整之后),对所有的anchors做bounding box regression位置回归(这里的anchors生成顺序和之前的一样)
- 按照softmax 产生的 foreground scores从大到小排序,选取前N个(文中=?)anchors,即提取修正后的N个foreground anchors
- 利用feat_stride和im_info将anchors映射回原图,判断foreground anchors是够大范围超出边界,提出严重超出边界的foreground anchors
- 进行非极大值抑制nms (nonmaximun suppression)
- 再次按照nms后的foreground scores由大到小排序,提取前M个foreground anchors
- 输出proposal=[x1, y1, x2, y2],注意,由于在第三步中将anchors映射回原图判断是否超出边界,所以这里输出的proposal是对应MxN输入图像尺度
ROI Pooling: 解决proposal大小不一致的问题,将proposal都固定成一样大小的图形
- 输入包括:最开始的feature map 和 proposal中输出的proposal box
-
为什么需要ROI pooling:将不同大小的proposal reshape成7*7大小的数据块
对于传统的CNN来说(AlexNet, VGG, ResNet)训练好模型之后,输入输出的图像尺寸的固定大小的,对于图像不固定有两种解决办法
①wrap操作,就是缩放图像成想要的大小
②crop操作,就是将图像截取成想要的大小
- 对foreground做anchors box regression中做了线性回归,这样获得的proposal也是大小不固定的。因此引入了POI Pooling
ROI Pooling 详解:
①该层中有pooled_w=pooled_h=7,spatial_scale=1/16三个参数
②使用spatial_scale参数将proposals映射到feature map中
(注意:之前使用feature_stride=16也映射过一次,但是映射到M*N大小的原图形位置,而这个映射是映射到feature map, feature map的大小是(M/16)*(N/16))
③将proposal切割成7*7大小的数据块,每一份都做max pooling 这样就将不同的proposalsz统一成7*7大小的proposal
Classification and regression
- 输入: ROI Pooling操作获得的proposal feature map
- 做fully connection(全连接)和relu(整流线性单元) 分支为两部分
①上一部分做bounding box regression,获得位置偏移参数,提高怒表检测框的精度
②下一部分加入softmax层计算每个proposal属于哪一个类别,输出classification概率
③注意,这里的全连接层其中的参数W,B都是提前训练好的
Faster-CNN训练过程
- Faster-CNN是在训练好的模型上进一步训练的(VGG,ZF)
- 在a的基础上训练RPN网络,对应stage1_rpn_train.pt
- 收集b中的proposals,对应rpn_test.pt
- 第一次训练Fast RCNN网络,对应stage1_fast_rcnn_train.pt
- 第二训练RPN网络,对应stage2_rpn_train.pt
- 再次利用步骤e中训练好的RPN网络,收集proposals,对应rpn_test.pt
- 第二次训练Fast RCNN网络,对应stage2_fast_rcnn_train.pt
1.训练RPN网络
RPN的损失函数是:
上述公式中,i表示anchors index,pi表示foreground softmax predict概率,pi*代表对应的GT predict概率(即当第i个anchor与GT间IoU>0.7,认为是该anchor是foreground,pi*=1;反之IoU<0.3时,认为是该anchor是background,pi*=0;至于那些0.3<IoU<0.7的anchor则不参与训练);t代表predict bounding box,t*代表对应foreground anchor对应的GT box
从上图和上述公式中可以看到RPN由两部分损失组成:
- 分类损失,图中的rpn_cls_loss,用于将anchors分类为foreground和background
- 回归损失,即rpn_loss_bbox层计算的soomth L1 loss,用于bounding box regression网络训练。在该loss中乘了pi*,相当于只关心foreground anchors的回归
- 由于在实际过程中,Ncls和Nreg差距过大,用参数λ平衡二者(如Ncls=256,Nreg=2400时设置λ=10),使总的网络Loss计算过程中能够均匀考虑2种Loss。这里比较重要是Lreg使用的soomth L1 loss,计算公式如下:
2.收集RPN训练好的proposals
利用之前的RPN网络,获取proposal rois,同时获取foreground softmax probability,如图,然后将获取的信息保存在python pickle文件中。该网络本质上和检测中的RPN网络一样,没有什么区别。
3.训练Fast-RCNN网络
- 读取之前保存好的python pickle文件
- 将ROIS传入网络,篮框所示
- 将foreground possibility作为bbox_inside_weights输入网络
- 计算出bbox_outside_weights(即RPN损失函数中的λ)输入网络