RCNN很好地解决了目标检测分类和定位的问题。但是缺点是速度太慢。
原因1:2k个候选区域都要经过变形成统一的正方形才能依次输入CNN进行特征提取。候选区域可能是互相包含的,这就导致原图同一个区域特征的重复提取。
原因2:RCNN的分类和回归是分开的,耗费时间和空间。每个候选区域都要经过相同的CNN和分类+回归,复杂度与候选区域数量成正比。
如下图所示,R-CNN先得到约2000个候选区域,对每个候选区域进行warp,特征提取,SVM分类与Bbox的位置回归。
Ross Girshick在15年推出Fast RCNN。同样使用最大规模的网络,FastRCNN和RCNN相比,训练时间从84小时减少为9.5小时,测试时间从47秒减少为0.32秒。我们看看Fast RCNN是如何解决最开始提到的两个问题的。
针对问题1
原始做法是先得到原始图像的ROI,再分别送CNN,改进思路是直接将原图送入CNN得到feature map,然后再加入候选框的信息,在feature map上得到候选区域映射的patch。这样就只对图像进行了一次卷积特征的计算,比RCNN提速100倍。
这样做又会引入两个新问题,原始先得到ROI可以通过warp归一化尺寸控制到全连接时的大小,那现在在特征图上怎么进行尺寸的归一化,总不能继续warp吧?还有,既然是在特征图上找ROI,那候选区域与特征图的对应关系如何确定呢?
关于第一点尺寸归一化的问题,何恺明研究员在2014的论文中将空间金字塔池化Spatial Pyramid Pooling(SPP)结构引入了CNN,使CNN可以处理任意size和scale的图像。
如上图所示,在卷积层和全连接层之间加入了SPP layer。此时网络的输入可以是任意尺度的,在SPP layer中每一个pooling的filter会根据输入调整bin大小,从右到左三级bin的个数分别是1,4,16,这样SPP的输出尺度始终是固定的,是1+4+16维。提取候选区特征和构建金字塔的过程都在ROI Pooling中完成。
为什么bin的个数之和就是输出的维度呢?因为这一层使用最大池化(max pooling)来将RoI区域转化成固定大小为HW的特征图。如下图,我们可以设定每个候选区域的分块数,但依然不能保证每一个bin内的大小是一样的,最大池化就可以简单理解成求块内最大值的过程,这样不管每一个bin是多大,最后都只输出1个值:最大值。
Fast-RCNN就使用了SPPlayer的变种——RoI pooling层。SPP是金字塔结构,每层的最大池化结果拼接做输出,但其实金字塔的每层都可以起到归一化尺寸的目的。RoI pooling层就只使用了金字塔的一层,因为实验表明多尺度学习只增加了一点点mAP,但是计算量成倍增加。
关于第二点特征图位置与候选框位置对应关系的问题。这里要引入感受野Receptive Field的概念,表示特征图中每个像素点源自哪部分原始像素点的加权和。由特征图是可以倒推出特征图中每个像素点的感受野的,计算过程受到卷积核填充因子和步长的影响,为了方便计算,设定卷积核尺寸为F时填充大小为F/2,那么映射关系就只与步长S有关:特征图(0,0)位置对应的感受野中心坐标是(0,0);特征图(x,y)位置对应的感受野中心坐标是(Sx,Sy)。但现在我们已知的是空域的候选框位置,怎么得到该候选框在特征图中的位置呢,其实和感受野的颜色关系是差不多的,都是S倍的关系,只不过要根据取整的关系进行正负1的调整:
Given a window in the image domain, we project the left (top) boundary by: x 0 = bx/Sc + 1 and the right (bottom) boundary x 0 = dx/Se − 1.
针对问题2
另外,之前RCNN的处理流程是先提proposal,然后CNN提取特征,之后用SVM分类器,最后再做bbox regression,而在Fast-RCNN中,作者巧妙的把bbox regression放进了神经网络内部,与region分类和并成为了一个multi-task模型,损失函数使用了多任务损失函数(multi-task loss),将边框回归直接加入到CNN网络中训练。实际实验也证明,这两个任务能够共享卷积特征,并相互促进。
既然是多任务,那么损失函数就由两项构成:一个是分类损失,一个是回归损失。因为是多分类,理所当然地使用softmax得到该RoI属于各个标签的概率,。但是这里没有使用交叉熵,对于真实标签,
对于使用回归来修正Bbox的定位,我们首先要以四元组的形式来表示方框的位置和大小:,回归损失就是四个维度的损失和:
其中smooth函数:
函数曲线如下:
最终的损失函数:
其中用于平滑分类与回归的权重,在实验中取1。[]是艾弗森括号,满足括号内内容时取1,否则取0(此时RoI类别是背景,没有定位框,忽略回归任务)。
Reference:
1.http://shartoo.github.io/RCNN-series/
2.https://blog.csdn.net/shenxiaolu1984/article/details/51036677
3.https://www.cnblogs.com/skyfsm/p/6806246.html