什么是目标检测(object detection):
目标检测(object detection),就是在给定的一张图片中精确找到物体所在的位置,并标注出物体的类别。所以,目标检测要解决的问题就是物体在哪里以及是什么的整个流程问题。
但是,在实际照片中,物体的尺寸变化范围很大,摆放物体的角度、姿态、在图片中的位置都不一样,物体之间可能还有重叠现象,这使得目标检测的难度变得很大。
目标检测算法:
传统的目标检测算法:
Cascade + HOG/DPM + Haar/SVM以及上述方法的诸多改进、优化。
候选区域/框(Region Proposal) + 深度学习分类的算法:
通过提取候选区域,并对相应区域进行以深度学习方法为主的分类的方案,比如R-CNN(Selective Search + CNN + SVM)、SPP-net(ROI Pooling)、Fast R-CNN(Selective Search + CNN + ROI)、Faster R-CNN(RPN + CNN + ROI)、Mask R-CNN(Mask Prediction Branch+RPN + CNN + ROI)等。
基于深度学习的回归算法:
YOLO、SSD、YOLOv2、YOLOv3等算法。
目标检测算法的演进(two-stage检测算法):
RCNN->SPP-net->Fast-RCNN->Faster-RCNN->Mask R-CNN:
目标检测任务:
如下图所示,目标检测其实包含两个子任务:图像的识别和定位。
图像识别(classification):
输入:图片;输出:物体的类别;评估方法:准确率。
定位(localization):
输入:图片;输出:方框在图片中的位置(x,y,w,h);评估方法:检测评价函数 intersection-over-union ( IOU ) 。
CNN网络已经可以完成图像识别分类的任务,我们只要解决定位的问题即可。
解决定位问题的思路一:
图片的标签中增加(x,y,w,h)标签,然后模型也预测一个(x,y,w,h)标签,将其看成回归问题来优化。这里有两个loss函数,一个是classification的loss函数,一般使用交叉熵函数;另一个是regression的loss函数,这里使用欧几里得距离(即两点之间的直线距离)作为loss函数。
我们对CNN神经网络做一点改动,在最后一个卷积层加了两个头:“分类头”和“回归头”。
Regression的部分其实有两种处理方法:
加在最后一个卷积层后面(如VGG);
加在最后一个全连接层后面(如R-CNN)。
regression的训练参数收敛的时间要长得多,我们还是应想办法转换为classification问题。
解决定位问题的思路二:
我们取不同大小的框,让框出现在不同的位置,得出这个框的判定得分(这个得分可以认为是这个框是框住这个物体的真实标签中的框的概率),取得分最高的那个框认为是最有可能框住这个目标物体的框。
如:
怎么确定这些框的大小和数量?
对一张图片,用各种大小的框(遍历整张图片)依次从图片左上角扫到右下角,这种方法叫做滑窗法(Sliding Window) 。这样我们每次都会截取一个和框一样大部分的图片,然后将图片输入到CNN,CNN会输出这个框的得分(classification)以及这个框图片对应的(x,y,w,h)标签(regression),然后classification和regression分别计算loss函数。
滑窗法(Sliding Window) :
首先对输入图像进行不同窗口大小的滑窗进行从左往右、从上到下的滑动。每次滑动时候对当前窗口截取的这部分的图片输入CNN网络进行分类(这个CNN网络是事先训练好的)。如果当前窗口得到较高的分类概率,则认为检测到了物体。
对每个不同窗口大小的滑窗都进行检测后,会得到不同窗口检测到的物体标记,这些窗口大小会存在重复较高的部分,最后采用非极大值抑制(Non-Maximum Suppression, NMS)的方法进行筛选。最终,经过NMS筛选后获得检测到的物体。
IOU(Intersection over Union,交集并集比):
IOU是一种测量在特定数据集中检测相应物体准确度的一个标准。通常我们在 HOG + Linear SVM object detectors 和 Convolutional Neural Network detectors (R-CNN, Faster R-CNN, YOLO等)中使用该方法检测其性能。
IOU的公式如下:
IoU相当于两个区域重叠的部分除以两个区域的集合部分得出的结果。
一般来说,score > 0.5或0.6 就可以认为重合度比较高了。
非极大值抑制(Non-Maximum Suppression):
非极大值抑制(Non-Maximum Suppression,NMS),顾名思义就是抑制不是极大值的元素,可以理解为局部最大搜索。
通用的NMS算法可以看这篇论文:Efficient Non-Maximum Suppression,这篇论文主要讲对1维和2维数据的NMS实现。
NMS算法在目标检测中的用法:
将所有框的得分排序,选中最高分及其对应的框;
遍历其余的框,如果和当前最高分框的重叠面积(IOU)大于一定阈值,则将这个框删除;
从未处理的框中继续选一个得分最高的,重复上述过程。
举例:
假设对于某个物体检测到 4 个框(Boxes)A、B、C、D,每个框属于这个物体的概率从小到大分别为S1、S2、S3、S4。
首先选择概率最大的框D,分别计算B1, B2, B3 与 B4 的重叠程度 IOU,判断其IOU是否大于预设定的阈值(比如将阈值设为0.5),假设B3的IOU超过阈值,则舍弃B3,标记B4为要保留的框;
然后从剩余的框B1, B2中选取概率最大的框B2,计算B1 与 B2 的重叠程度 IoU,假设B1的IOU也超过阈值,则舍弃B1,标记B2为要保留的框;
检查,发现已经没有既没有舍弃,也没有保留的框了,遍历结束;
滑窗法方法非常耗时,我们可以优化一下:
把思路一中的神经网络最后的全连接层也变成卷积层,如:
变为:
上面针对的都是单个物体的图片,如果图片中有多个物体该怎么办呢?
如果还是用上面的思路,我们需要的框的大小和数量会增加很多,这样非常耗时。
改进方法:
找出可能含有物体的框(也就是候选框,比如选1000个候选框),这些框之间是可以互相重叠互相包含的,而不是在图片上用各种大小的框(遍历整张图片)依次从图片左上角扫到右下角(暴力枚举)。
找出候选框(Region Proposal)的改进方法:
常用的有EdgeBoxes和Selective Search。
Selective Search算法:
这个算法其实是借鉴了层次聚类的思想,将层次聚类的思想应用到区域的合并上面。
算法论文:Selective Search for Object Recognition[J]. International Journal of Computer Vision, 2013
层次聚类思想:
最开始的时候将所有的每个数据点本身作为一个簇,然后找出距离最近的两个簇将它们合为一个,不断重复以上步骤直到簇的数量达到预设的簇的个数。
Selective Search算法的主要思想:
图像中物体可能存在的区域应该是有某些相似性或者连续性区域的。因此,选择搜索基于上面这一想法采用子区域合并的方法进行提取候选边界框。首先,对输入图像进行分割算法产生许多小的子区域。其次,根据这些子区域之间相似性(相似性标准主要有颜色、纹理、大小等等)进行区域合并,不断的进行区域迭代合并。每次迭代过程中对这些合并的子区域做外切矩形(bounding boxes),这些子区域外切矩形就是通常所说的候选框。
Selective Search算法的过程:
1、首先通过图像分割的方法(如大名鼎鼎的felzenszwalb算法)获得很多小的区域,假设现在图像上有n个预分割的区域(Efficient Graph-Based Image Segmentation),表示为R={R1, R2, ..., Rn};
2、计算区域集R里每个相邻区域的相似度S={s1,s2,…} ;
3、找出相似度最高的两个区域,将其合并为新集(即两个子区域合并为一个外切矩形(bounding boxes)的新区域),将这个新区域添加进R;
4、从S中移除所有与第3步中有关的子集(也就是被合并的区域所计算的相似度数值) ;
5、计算新集与所有子集的相似度 ;
6、跳至第3步,重复之后的过程,直到S为空。
为什么要介绍Selective Search算法呢,因为R-CNN和Fast R-CNN算法都是用它产生候选框(region proposal)!下面我们来看看R-CNN算法。
R-CNN(Regions with CNN features):
RCNN的论文:Rich feature hierarchies for accurate object detection and semantic segmentation
RCNN网络结构:
RCNN计算过程:
训练一个AlexNet分类模型;
将该模型输出层分类数从1000改为21(21是测试集中20个物体类别 + 1个背景),并去掉最后一个全连接层;
然后对上面的模型进行fine tuning,即用训练好的参数(可以从已训练好的模型中获得)初始化微调后的网络,然后用自己的数据接着训练;
利用Selective Search算法对一张图像生成1000-2000个候选框;
对每个候选框缩放成224*224的大小,然后输入CNN网络,保存第五个pool层的输出(即一个4096元素的一维向量,就是对候选框提取到的特征) ;
训练一个SVM分类器(二分类),然后将每个候选框提取到的特征输入到SVM进行分类,每个类别对应一个SVM,判断是不是属于这个类别,是就是positive,反之nagative;
对于SVM分好类的候选框做边框坐标的regression,用Bounding box回归值校正原来的建议窗口。对于每一个类,分别训练一个regression模型。
举例:
对狗分类的SVM:
候选框的regression:
RCNN网络也有一些缺点:
训练过程是多级流水线。R-CNN首先使用目标候选框对卷积神经网络使用log损失进行微调。然后,它将卷积神经网络得到的特征送入SVM。 这些SVM作为目标检测器,替代通过微调学习的softmax分类器。 在第三个训练阶段,学习检测框回归。
训练在时间和空间上的开销很大。对于SVM和检测框回归训练,从每个图像中的每个目标候选框提取特征,并写入磁盘。对于非常深的网络,如VGG16,这个过程在单个GPU上需要2.5天(VOC07 trainval上的5k个图像)。这些特征需要数百GB的存储空间。
目标检测速度很慢。在测试时,对每个测试图像中的1000-2000个目标候选框各自提取特征。用VGG16网络检测目标每个图像需要47秒(在GPU上)。
怎么解决这个问题呢?
这2000个候选框都是图像的一部分,那么我们可以先对整个图像提取卷积层的特征,然后将每个候选框在整个图像上的位置映射到卷积层的特征图上,这样对于一张图像我们只需要提一次卷积层特征,然后将每个候选框的卷积层特征输入到全连接层做后续操作。
但有一个问题还没有解决,就是每个候选框的大小不一样,而全连接的输入数据长度必须固定,SPP Net就可以解决这个问题。
SPP-Net(Spatial Pyramid Pooling Network,空间金字塔池化网络):
SPP Net论文:Spatial Pyramid Pooling in Deep ConvolutionalNetworks for Visual Recognition,2015
论文地址:https://arxiv.org/pdf/1406.4729.pdf
我们知道,CNN网络的卷积层输入不需要固定尺寸的图像,而全连接层需要固定大小的输入。在R-CNN中,我们是将每个候选框缩放(warp)或者截取(crop)成统一的224x224的大小,但这种缩放可能导致物体被拉伸变形或物体不全,这限制了识别精确度。
SPP Net的改进就是在最后一个卷积层和全连接层之间加入了一个SPP层(金字塔池化层)。此时网络的输入可以是任意尺度的,在SPP层中每一个pooling的filter会根据输入调整大小,保证传到下一层全连接层的输入固定。
SPP Net网络结构:
ROI Pooling层:
ROI是Region of Interest的简写,指的是在“特征图上的框”。
在SPP Net和Fast RCNN中, ROIS是指Selective Search完成后得到的所有“候选框”在特征图上的映射;
在Faster RCNN中,候选框是经过RPN算法产生的,然后再把各个“候选框”映射到特征图上,得到ROIS。
ROI pooling层计算过程:
根据输入的原始图像和Selective Search算法提供的1000-2000个候选框位置,产生整个原始图像得到的feature map上对应的框,也就是我们说的ROI(Region of Interest,即“特征图上的框”);
将映射后的区域划分为相同大小的块,块的数量是我们指定的;
对每个块进行max pooling操作。
这样我们就可以从不同大小的方框得到固定大小的相应的feature maps。输出的pooling结果的大小只和我们划分成多少块有关,而不取决于ROI和卷积feature maps的大小。
举例:
输入为一个8*8大小的feature map:
候选框位置坐标:(左上角,右下角坐标):(0,3),(7,8)。
先得到ROI,即feature map上与这个候选款位置对应的“特征图上的框”:
我们想让这个ROI Pooling层的输出为4个特征值,那么就要把候选框划分成4块(2*2):
对每个块做max pooling操作,得到结果:
SPP Net计算过程:
SPP层的具体结构:
SPP层的具体结构如上图,我们使用三层ROI Pooling层组成的SPP层,分别设置将图片切分成(1,4,16)块。这里是采用了论文Spatial Pyramid Pooling in Deep ConvolutionalNetworks for Visual Recognition中的设置参数(1,4,16);
我们将Selective Search算法提供的1000-2000个候选框的位置记录下来,然后通过比例映射到整张图像的feature map上,每个候选框得到一个自己的候选区域的特征图B,然后将B同时送入上面的SPP层的3个ROI Pooling层;
SPP层第一层将整个特征图B进行池化,第二层将特征图B切分成4个小的特征图再池化,第三层将特征图B切分成16个小的特征图再池化。分别得到1、4、16个特征值;
这样我们就得到了21个特征值。这21个特征值经过softmax函数后就可以分类了。
SPP Net网络也有显著的缺点:
像RCNN一样,训练过程是一个多级流水线,涉及提取特征,使用log损失对网络进行微调,训练SVM分类器,最后拟合检测框回归。但是有一点要注意,就是SPP Net的优化算法无法更新SPP层之前的卷积层(这些卷积层用来提取整张图像的特征)。这种限制(固定的卷积层)影响了深层网络的精度。
Fast R-CNN:
Fast R-CNN论文:Fast R-CNN
Fast R-CNN论文地址:https://arxiv.org/pdf/1504.08083.pdf
Fast-R-CNN项目地址:https://github.com/rbgirshick/fast-rcnn
Fast R-CNN就是在RCNN的基础上采纳了SPP Net方法,对RCNN作了改进,使得网络性能进一步提高。
同RCNN相比,Fast RCNN作了以下改进:
规避R-CNN中冗余的特征提取操作,Fast RCNN只对整张图像全区域进行一次特征提取;
用ROI pooling层取代最后一层max pooling层,直接在整张图像的feature map上找到Selective Search算法提供的1000-2000个候选框的位置对应的特征;
Fast RCNN网络末尾采用并行的不同的全连接层,可同时输出分类结果和窗口回归结果,实现了end-to-end的多任务训练(建议框提取除外),也不需要额外的特征存储空间(RCNN中这部分特征是供SVM和Bounding-box regression进行训练的);
采用SVD对Fast R-CNN网络末尾并行的全连接层进行分解,减少计算复杂度,加快检测速度。
Fast RCNN网络的结构:
其中在roi_pool5之前的网络结构均为可选的,参考的网络结构,作者论文中用到的有VGG和Alexnet。
Fast RCNN网络的计算过程:
使用Selective Search算法从图像红获得1000-2000个候选框。基本思路:使用分割方法将图像分成小区域。在此之后,观察现有的区域。之后以最高概率合并这两个区域。重复此步骤,直到所有图像合并为一个区域位置。合并规则与RCNN是相同的,优先合并以下四种区域: 颜色(颜色直方图)相近的; 纹理(梯度直方图)相近的; 合并后总面积小的。最后,所有已经存在的区域都被输出,并生成候选区域。
使用CNN网络提取原始图像的特征图,然后通过比例映射将所有的候选框映射到整张图像的feature map上,每个候选框得到一个自己的候选区域的特征图;
使用一个单层的ROI Pooling层对每一个候选框的特征图做max pooling,得到固定大小的输出维度向量;
使用SoftmaxLoss代替了SVM进行分类,使用SmoothL1Loss取代Bouding box回归。
Fast R-CNN损失函数分成两部分:
loss_cls损失函数:
该层根据之前输出的4096维特征,用softmax函数生成多个类别概率,根据生成的结果和标签计算loss,评估分类代价:
loss_bbox损失函数,评估回归损失代价,比较真实分类u对应的预测平移缩放参数和真实平移缩放参数v=
的差距:
结合分类损失和回归损失,Fast R-CNN总的loss函数为:
约定u=0为背景分类,那么[u≥1] 函数表示背景候选区域即负样本不参与回归损失,不需要对候选区域进行回归操作;
λ控制分类损失和回归损失的平衡,论文中所有实验λ=1。
Fast RCNN的缺点:
Fast RCNN仍然使用selective search算法生成候选框,这个过程很耗费时间,其进行候选区域提取所花费的时间约为2~3秒,而提取特征分类仅需要0.32秒,这就造成该模型无法满足实时的应用需求,而且因为使用selective search来预先提取候选区域,Fast RCNN并没有实现真正意义上的端到端训练模式。
Faster R-CNN:
Faster R-CNN论文:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
Faster R-CNN论文地址:https://arxiv.org/pdf/1506.01497.pdf
Faster R-CNN是Fast R-CNN网络的改进,Faster R-CNN使用RPN(Region Proposal Network)算法代替原来的Selective Search方法产生候选框(RPN层放在最后一个卷积层的后面),且产生候选框的CNN网络和目标检测的CNN网络是同一个CNN网络。这使得候选框的数目从原有的约2000个减少为300个,且建议框的质量也有本质的提高。Faster R-CNN生成候选框仅需约10ms,足以满足端到端的实时的应用需求。
Faster R-CNN网络结构:
注意:前面的CNN网络不一定要是VGG。比如我们可以用5层CNN网络的ZF模型。
Faster R-CNN的结构主要分为三大部分:
第一部分是共享的卷积层-backbone,第二部分是候选区域生成网络-RPN,第三部分是对候选区域进行分类的网络-classifier。
RPN与classifier部分均对目标框有修正。classifier部分就是Fast R-CNN结构。
RPN层(Region Proposal Network,区域生成网络 ):
RPN层的结构:
Anchor:
Anchor实际上指的是预先设置好长宽比与面积的候选框。但是这种候选框产生的机制与Selective Search算法不一样。
在论文中,作者为每一个位置生成9种anchor,包含三种面积(128×128,256×256,512×512),每种面积又包含三种长宽比(1:1,1:2,2:1)。
RPN层的计算过程:
原始图像先进入CNN网络后在最后一个卷积层(RPN层的前一个卷积层)输出了256个通道的feature map。假设每个通道的feature map的尺寸WXH;
对于一个大小为H*W的feature map,它上面每一个像素点对应9个anchor,这里有一个重要的参数feat_stride = 16, 它表示特征层上移动一个点,对应原图移动16个像素点(这个16实际上是因为前4个卷积层中一共经过了4次max pooling,每次pooling后feature map的长宽都减半,所以最后一个卷积层(是第五个卷积层,且第五个卷积层输出前没有max pooling)的输出feature map的长和宽都只有原始图像的16分之一,我们就认为我们是在原始图像上每隔16个像素点取一个位置,然后得到这个位置的9个anchor);
把WXH大小的feature map上的每一个点映射回原图,得到这些点的坐标,然后得到这些点的Anchors,每一个点都有9个Anchors(论文中设定为9个)。如果feature map有256个通道,每个通道的大小为W×H,则一共有W×H×9个anchors;
下图是9种anchor:
最后一个卷积层输出的256个通道的feature map再进入RPN层进行卷积(卷积核3*3),卷积出来的feature map仍然是256个通道,feature map的尺寸WXH不变;
RPN层输出的256通道feature map要分别进入两个全连接层:reg层和cls层
reg层:预测proposal的anchor对应的proposal的(x,y,w,h);
cls层:判断该proposal是前景(object)还是背景(non-object)。
针对上一层的WXH大小的feature_map的每一个像素点,在第一个卷积层卷积取出其256维的特征(一共256个通道),得到一个H*W个2*K的向量,每个2*K维的向量代表的就是针对每一个anchor,该像素点代表的原图中以这个像素点为中心的相应区域是它的前景还是背景的概率;
WXH大小的feature_map还要输入第二个卷积层,这个卷积层得到W*H*个4*K维的向量,即对WXH大小的feature_map的每一个像素点得到一个4*K维的特征向量,该特征向量中每四个值对应一个anchor的四个顶点的位置(对于窗口一般使用四维向量(x, y, w, h)表示,分别表示窗口的中心点坐标和宽高);
然后将H*W个2*K的向量输入softmax进行分类,注意这里softmax分类的含义是一个像素点中的9个anchor中哪一个anchor里是一个object的概率,也就是判断每一个anchor是对象还是背景;
Proposal的生成:
由上面anchors坐标和bbox回归参数计算得到预测框proposal的坐标;
处理proposal坐标超出图像边界的情况(使得坐标最小值为0,最大值为宽或高) ;
滤除掉尺寸(宽高)小于给定阈值的proposal;
对剩下的proposal按照目标得分(fg score)从大到小排序,提取约前2000个proposal(数量约等于WXH);
对提取的proposal进行非极大值抑制,筛选前300个proposal作为最后的输出。
如何训练这个RPN网络?
在计算Loss值之前,作者设置了anchors的标定方法。
正样本标定规则:
如果Anchor对应的reference box与ground truth的IoU值最大(可能Iou不到0.7),标记为正样本;
如果Anchor对应的reference box与ground truth的IoU>0.7,标记为正样本;
负样本标定规则:
如果Anchor对应的reference box与ground truth的IoU<0.3,标记为负样本。
剩下的既不是正样本也不是负样本,不用于最终训练。跨越了图像边界的样本也不用于最终训练。
这个网络的loss function就是一个用于分类的softmax loss和一个用于回归(即预测物体的候选框坐标)的smooth L1 loss,即有两种损失:
区域生成网络的前后景分类损失(Object or not object);
区域生成网络的区域位置损失(Bounding box proposal);
LOSS函数为:
为样本分类的概率值(表示anchor里是一个object的概率),
为样本的标定值(label),anchor为正样本时
为1,为负样本时
为0。
即是FAST RCNN中smooth函数的定义。
是一个平衡因子,具体设置可以参考论文,它与Ncls和Nreg有关。
这一项表示只有目标anchor的
(anchor是正样本)才有回归损失,其他anchor不参与计算。
两项损失函数分别由和
以及一个平衡权重λ归一化。分类损失的归一化值为minibatch的大小,即
;回归损失的归一化值为anchor位置的数量,即
;λ一般取值为10,这样分类损失和回归损失差不多是等权重的。
RPN网络的训练:
首先过滤掉超出图像边界的anchors ;
在训练RPN时,一个Mini-batch是由一幅图像中任意选取的256个proposal组成的,其中正负样本的比例为1:1;
如果正样本不足128,则多用一些负样本以满足有256个Proposal可以用于训练,反之亦然;
训练RPN时,与VGG共有的层参数可以直接拷贝经ImageNet训练得到的模型中的参数,剩下没有的层参数用标准差=0.01的高斯分布初始化。
RPN也有缺点,最大的问题就是对小物体检测效果很差,假设输入为512*512,经过网络后得到的feature map是32*32,那么feature map上的一个点就要负责周围至少是16*16的一个区域的特征表达,那对于在原图上很小的物体它的特征就难以得到充分的表示,因此检测效果比较差。
Faster R-CNN计算过程:
接上面RPN的结构,RPN得到的每一个proposal都输入一个单层的ROI Pooling层对做max pooling,得到固定大小的输出维度向量;
利用Softmax Loss(这里分类的是每个proposal属于哪一种物体) 和Smooth L1 Loss(探测边框回归)对分类概率和边框回归(Bounding box regression)联合训练,如果类别数为N+1(包括背景),分类层的向量维数为N+1,回归层的向量维数则为4(N+1)。这里的联合Loss和Fast R-CNN网络一样。
由下面的训练方法,我们可以发现不同训练阶段用的loss函数不一样,训练RPN时用的是RPN的损失函数;训练Fast R-CNN网络时用的还是原来Fast R-CNN网络的损失函数。
注意:
RPN网络和Fast R-CNN网络共用了前五层CNN网络!实际上,Faster R-CNN网络就是RPN网络+Fast R-CNN网络。
Faster R-CNN网络的训练:
第一步是训练RPN网络,用ImageNet模型M0初始化,训练得到模型M1;
第二步是利用第一步训练的RPN网络模型M1,生成Proposal P1。再使用Proposal P1,训练Fast R-CNN网络,同样用ImageNet模型初始化,训练得到模型M2。这两个阶段两个网络每一层的参数完全不共享;
第三步是使用第二步的Fast-RCNN网络参数初始化一个新的RPN网络,但是把RPN、Fast-RCNN共享的那些卷积层的learning rate设置为0,也就是不更新,仅仅更新RPN特有的那些网络层,重新训练,得到模型M3。此时,两个网络已经共享了所有公共的卷积层;
第四步是利用上一步训练的RPN网络模型M3,生成Proposal P2。仍然固定共享的那些网络层,把Fast R-CNN特有的网络层也加入进来,再使用Proposal P2训练Fast R-CNN网络,用RPN网络模型M3初始化,且卷积层参数和RPN参数不变,只微调Fast R-CNN独有的网络层,得到最终模型M4。
此时,该网络已经实现我们设想的目标,即网络内部预测proposal并实现检测的功能。
论文作者按上面步骤进行交替训练,只迭代2次的原因是作者发现多次的迭代并没有显著的改善性能。
ROI Pooling中存在的问题:
由于预选ROI的位置通常是有模型回归得到的,一般来说是个浮点数,而pooling后的特征图要求尺度固定,因此ROI Pooling这个操作存在两次数据量化的过程。首先将候选框边界量化为整数点坐标值,然后将量化后的边界区域平均分割成KxK个单元,对每个单元的边界进行量化。经过上面的两次量化操作,此时的ROI已经和最开始的ROI之间存在一定的偏差,这个偏差会影响检测的精确度。
如下图:
输入一张800x800的图片,图片中有一个665x665的候选框恰好框中一只狗。图片经过特征提取网络之后,整个图片的特征图变为800/32 * 800/32,即25x25,但是665/32=20.87,带有小数,ROI Pooling时会直接将它量化为20。这里引入了第一次量化偏差。由于最终的特征映射的大小为7x7,即需要将20x20的区域映射成7x7,矩形区域的边长为2.86,又一次将其量化为2。这里引入了第二次量化偏差。经过这两次量化,候选ROI已经出现了严重的偏差(如图中浅蓝色部分所示)。更重要的是,在特征图上差0.1个像素,对应到原图上就是3.2个像素。
当我们的候选框本身比较小时,这个偏差会显得非常大,严重影响结果。
Mask R-CNN:
论文:Mask R-CNN
论文地址:https://arxiv.org/pdf/1703.06870.pdf
Mask R-CNN是一个实例分割(Instance segmentation)算法,可以用来完成多种任务,包括目标分类、目标检测、语义分割、实例分割、人体姿态识别等,这个算法具有很好的扩展性和易用性。除此之外,我们可以更换不同的backbone architecture和Head Architecture来获得不同性能的结果。
整个Mask R-CNN算法的思路很简单,就是在原始Faster-rcnn算法的基础上面增加了FCN来产生对应的MASK分支。对于RPN前面的CNN网络,由VGG换成了ResNeXt-101(深度残差网络)。同时,对于ROI Pooling中存在的像素偏差问题,提出了ROIAlign策略来解决。即Faster-rcnn + FCN,或者说是RPN + ROIAlign + Fast-rcnn + FCN。
图像分类(Image classification)、目标检测(Object detection)、语义分割(Semantic segmentation)、实例分割(Instance segmentation)之间的区别:
语义分割和实例分割都是目标分割中的两个小的领域,都是用来对输入的图片做分割处理。 通常意义上的目标分割指的是语义分割,语义分割已经有很长的发展历史,已经取得了很好地进展,目前有很多的学者在做这方面的研究。而实例分割是一个从目标分割领域独立出来的一个小领域,是最近几年才发展起来的,与前者相比,后者更加复杂,当前研究的学者也比较少,是一个有研究空间的热门领域。
如下图,左下角图是语义分割的结果,右下角图是实例分割的结果。两者最大的区别就是图中的"cube对象",在语义分割中给了它们相同的颜色,而在实例分割中却给了不同的颜色。即实例分割需要在语义分割的基础上对同类物体进行更精细的分割。
Mask R-CNN网络结构:
Mask R-CNN网络可以分解成3个部分:Faster R-CNN、ROIAlign和FCN。
Faster R-CNN:
Faster R-CNN上面已经介绍过,可以往回翻看一下。
ROIAlign:
在介绍Faster R-CNN网络时,我们已经介绍了ROI Pooling中存在的问题,即ROI Pooling操作中的两次数据量化的过程中可能会引入偏差。
ROIAlign在这一点上进行了改进。ROI Pooling和ROIAlign最大的区别是:前者使用了两次量化操作,而后者并没有采用量化操作。
ROIAlign层中,ROI映射到feature map后,不再进行四舍五入。然后将候选区域分割成K x K个单元, 在每个单元中计算固定四个坐标位置,用双线性内插的方法计算出这四个位置的值,然后进行最大池化操作。
如:
举例:
假如还是上面ROI Pooling中存在的问题中的例子,现在我们用ROIAlign来处理它。
输入图片为800x800像素,图片中有一个665x665的候选框恰好框中一只狗。图片经过特征提取网络之后,整个图片的特征图变为800/32 * 800/32,即25x25,但是665/32=20.87,我们就用20.78,不用20替代它,20.78 / 7 = 2.97,我们就用2.97,也不用2来代替它。现在怎么用这些浮点值来计算呢?
我们的解决思路是使用“双线性插值”算法。双线性插值是一种比较好的图像缩放算法,它充分利用了原图中虚拟点(比如20.56这个浮点数,像素位置都是整数值,没有浮点值)四周的四个真实存在的像素值来共同决定目标图中的一个像素值,就可以将20.56这个虚拟的位置点对应的像素值估计出来。
比如下图中
蓝色的虚线框表示卷积后获得的feature map,黑色实线框表示ROI feature,最后需要输出的大小是2x2,那么我们就利用双线性插值来估计这些蓝点(虚拟坐标点,又称双线性插值的网格点)处所对应的像素值,最后得到相应的输出。这些蓝点是2x2Cell中的随机采样的普通点,作者指出,这些采样点的个数和位置不会对性能产生很大的影响,你也可以用其它的方法获得。然后在每一个橘红色的区域里面进行max pooling或者average pooling操作,获得最终2x2的输出结果。我们的整个过程中没有用到量化操作,没有引入误差,即原图中的像素和feature map中的像素是完全对齐的,没有偏差,这不仅会提高检测的精度,同时也会有利于实例分割。
FCN:
FCN算法是一个经典的语义分割算法,可以对图片中的目标进行准确的分割。其总体架构如上图所示,它是一个端到端的网络,主要的模快包括卷积和去卷积,即先对图像进行卷积和池化,使其feature map的大小不断减小;然后进行反卷积操作,即进行插值操作,不断的增大其feature map,最后对每一个像素值进行分类。从而实现对输入图像的准确分割。
关于FCN算法可以看这篇论文:https://arxiv.org/pdf/1411.4038.pdf
在论文:Mask R-CNN(https://arxiv.org/pdf/1703.06870.pdf)中,作者实际上提出了两种不同产生mask的网络结构:
左边的Faster R-CNN/ResNet:
对于左边的架构,我们的backbone使用的是预训练好的ResNet,使用了ResNet倒数第4层的网络。输入的ROI首先获得7x7x1024的ROI feature,然后将其升维到2048个通道(这里修改了原始的ResNet网络架构),然后有两个分支,上面的分支负责分类和回归,下面的分支负责生成对应的mask。由于前面进行了多次卷积和池化,减小了对应的分辨率,mask分支开始利用反卷积进行分辨率的提升,同时减少通道的个数,变为14x14x256,最后输出了14x14x80的mask模板。
右边的Faster R-CNN/FPN:
右边使用到的backbone是FPN网络,这是一个新的网络,通过输入单一尺度的图片,最后可以得到对应的Feature Pyramid(特征金字塔)。该网络可以在一定程度上面提高检测的精度,当前很多的方法都用到了它。由于FPN网络已经包含了res5,可以更加高效的使用特征,因此这里使用了较少的filters。该架构也分为两个分支,作用与前者相同,但是分类分支和mask分支和前者相比有很大的区别。可能是因为FPN网络可以在不同尺度的特征上面获得许多有用信息,因此分类时使用了更少的滤波器。而mask分支中进行了多次卷积操作,首先将ROI变化为14x14x256的feature,然后进行了5次相同的操作(不清楚这里的原理,期待着你的解释),然后进行反卷积操作,最后输出28x28x80的mask。即输出了更大的mask,与前者相比可以获得更细致的mask,因此可以更好的检测更加小的目标。
FPN网络(Feature Pyramid Networks,特征金字塔网络):
论文:Feature Pyramid Networks for Object Detection
论文地址:https://arxiv.org/pdf/1612.03144v2.pdf
在faster rcnn进行目标检测时,无论是rpn还是fast rcnn,roi 都作用在最后一层,这在大目标的检测上没有问题,但是对于小目标检测时,由于小目标占据的像素区域本来就小,当进行卷积池化到最后一层,特征图上对应的像素点就很少或者就没有了。所以,为了解决多尺度检测的问题,引入了FPN网络。
上面是4种特征金字塔网络。
图(a)是相当常见的一种多尺度方法,称为featurized image pyramid,这种方法在较早的人工设计特征(DPM)时被广泛使用,在CNN中也有人使用过。就是对input iamge进行multi scale,通过设置不同的缩放比例实现。这种可以解决多尺度,但是相当于训练了多个模型(假设要求输入大小固定),即便允许输入大小不固定,但是也增加了存储不同scale图像的内存空间。
图(b)就是CNN网络,cnn相比人工设计特征,能够自己学习到更高级的语义特征,同时CNN对尺度变化鲁棒,因此如图,从单个尺度的输入计算的特征也能用来识别,但是遇到明显的多尺度目标检测时,还是需要金字塔结构来进一步提升准确率。
从现在在imageNet和COCO数据集上领先的的一些方法来看,在测试的时候都用到了featurized image pyramid方法,即结合(a),(b)。 说明了特征化图像金字塔的每一级的好处在于,产生了多尺度的特征表示,每一级的特征都有很强的语义(因为都用cnn生成的特征),包括高分辨率的一级(最大尺度的输入图像)。 但是这种模式有明显的弊端,相比于原来方法,时间增长了4倍,很难在实时应用中使用,同样,也增大了存储代价。
图(c)是SSD方法中使用的CNN金字塔形的层级特征。SSD方法中的特征金字塔重利用了前向过程计算出的来自多层的多尺度特征图(这是CNN网络计算时本来就会生成的),因此这种重利用是不消耗额外的资源。但是SSD为了避免使用low-level的特征,放弃了浅层的feature map,而是从conv4_3开始建立金字塔,而且加入了一些新的层。也就是说,SSD放弃了重利用更高分辨率的feature map(最开始的两三层卷积出的feature map),但是这些feature map对检测小目标非常重要。这就是SSD与FPN的区别。
图(4)是FPN的结构,FPN是为了自然地利用CNN层级特征的金字塔形式,同时生成在所有尺度上都具有强语义信息的特征金字塔。FPN的结构设计了自下而上的路径和横向连接,以此融合具有高分辨率的浅层layer和具有丰富语义信息的深层layer。这样就实现了从单尺度的单张输入图像,快速构建在所有尺度上都具有强语义信息的特征金字塔,同时不产生明显的代价。
自上而下的路径和横向连接:
CNN的前馈计算就是自下而上的路径,特征图经过卷积核计算,通常是越变越小的,当然也有一些特征层的输出和原来大小一样,称为“相同网络阶段”(same network stage ),这与我们设计的CNN网络结构有关。对于我们的FPN网络,作者把网络的每个阶段定义一个金字塔级别, 然后选择每个阶段的最后一层的输出作为特征图的参考集。 这种选择是很自然的,因为每个阶段的最深层应该具有最强的特征。
比如说,对于ResNets,作者使用了每个阶段的最后一个残差结构的特征激活输出。将这些残差模块输出表示为{C2, C3, C4, C5},对应于conv2,conv3,conv4和conv5的输出,并且注意它们相对于输入图像具有{4, 8, 16, 32}像素的步长。考虑到内存占用,没有将conv1包含在金字塔中。
横向连接就是把更抽象,语义更强的高层特征图进行上取样,然后把该特征横向连接(lateral connections )至前一层特征,因此高层特征得到加强。要注意的是,横向连接的两层特征在空间尺寸上要相同。
如,把高层特征做2倍上采样(最邻近上采样法,可以参考反卷积),然后将其和对应的前一层特征结合(前一层要经过1 * 1的卷积核才能用,目的是改变channels,应该是要和后一层的channels相同),结合方式就是做像素间的加法。重复迭代该过程,直至生成最精细的特征图。迭代开始阶段,作者在C5层后面加了一个1 * 1的卷积核来产生最粗略的特征图,最后,作者用3 * 3的卷积核去处理已经融合的特征图(为了消除上采样的混叠效应),以生成最后需要的特征图。为了后面的应用能够在所有层级共享分类层,这里坐着固定了3*3卷积后的输出通道为d,这里设为256,因此所有额外的卷积层(比如P2)具有256通道输出。这些额外层没有用非线性。{C2, C3, C4, C5}层对应的融合特征层为{P2, P3, P4, P5},对应的层空间尺寸是相通的。
Mask R-CNN算法过程:
首先,输入一幅你想处理的图片,然后进行对应的预处理操作,或者预处理后的图片;
然后,将其输入到一个预训练好的神经网络中(ResNet等)获得对应的feature map;
接着,对这个feature map中的每一点设定预定个的ROI,从而获得多个候选ROI;
接着,将这些候选的ROI送入RPN网络进行二值分类(前景或背景)和BB回归,过滤掉一部分候选的ROI;
接着,对这些剩下的ROI进行ROIAlign操作(即先将原图和feature map的pixel对应起来,然后将feature map和固定的feature对应起来);
最后,对这些ROI进行分类(N类别分类)、BB回归和MASK生成(在每一个ROI里面进行FCN操作)。
Mask R-CNN的loss函数:
每个ROI的loss函数就是分类,回归加mask预测的损失之和。
其中Lcls和Lbox和Faster r-cnn中定义的相同。对于每一个ROI,mask分支有Km*m维度的输出,其对K个大小为m*m的mask进行编码,每一个mask有K个类别。注意这里mask的输出使用了sigmoid函数。最后可以通过与阈值0.5作比较输出二值mask。这样避免了类间的竞争,将分类的任务交给专业的classification分支。Lmask对于每一个像素使用二值的sigmoid交叉熵损失。