Introduction
Instance Segmentation(实例分割)不仅要正确的找到图像中的objects,还要对其精确的分割。所以Instance Segmentation可以看做object dection和semantic segmentation的结合。
Mask RCNN是Faster RCNN的扩展,对于Faster RCNN的每个Proposal Box都要使用FCN进行语义分割。
引入了RoI Align代替Faster RCNN中的RoI Pooling。因为RoI Pooling并不是按照像素一一对齐的(pixel-to-pixel alignment),也许这对bbox的影响不是很大,但对于mask的精度却有很大影响。
引入语义分割分支,实现了mask和class预测的关系的解耦,mask分支只做语义分割,类型预测和bbox回归任务交给另一个分支。这与原本的FCN网络是不同的,原始的FCN在预测mask时还用同时预测mask所属的种类。
1 Backbone: ResNet-FPN进行特征提取
主要解决的问题是目标检测在处理多尺度变化问题是的不足,现在的很多网络都使用了利用单个高层特征(比如说Faster R-CNN利用下采样四倍的卷积层——Conv4,进行后续的物体的分类和bounding box的回归),但是这样做有一个明显的缺陷,即小物体本身具有的像素信息较少,在下采样的过程中极易被丢失,为了处理这种物体大小差异十分明显的检测问题,经典的方法是利用图像金字塔的方式进行多尺度变化增强,但这样会带来极大的计算量。所以这篇论文提出了特征金字塔的网络结构,能在增加极小的计算量的情况下,处理好物体检测中的多尺度变化问题。
多尺度检测在目标检测中变得越来越重要,对小目标的检测尤其如此。现在主流的目标检测方法很多都用到了多尺度的方法。Feature Pyramid Network (FPN)则是一种精心设计的多尺度检测方法。
FPN结构中包括自下而上,自上而下和横向连接三个部分,如下图所示。这种结构可以将各个层级的特征进行融合,使其同时具有强语义信息和强空间信息。
Bottom-up pathway
从下到上路径。可以明显看出,其实就是简单的特征提取过程,和传统的没有区别。具体就是将ResNet作为骨架网络,根据feature map的大小分为5个stage。stage2,stage3,stage4和stage5各自最后一层输出conv2,conv3,conv4和conv5分别定义为 [公式] ,他们相对于原始图片的stride是{4,8,16,32}。需要注意的是,考虑到内存原因,stage1的conv1并没有使用。
Top-down pathway
自上而下是从最高层开始进行上采样,这里的上采样直接使用的是最近邻上采样,而不是使用反卷积操作,一方面简单,另外一方面可以减少训练参数。横向连接则是将上采样的结果和自底向上生成的相同大小的feature map进行融合。具体就是对 [公式] 中的每一层经过一个conv 1x1操作(1x1卷积用于降低通道数),无激活函数操作,输出通道全部设置为相同的256通道,然后和上采样的feature map进行加和操作。
自顶向下的过程通过上采样(up-sampling)的方式将顶层的小特征图。放大到上一个stage的特征图一样的大小。
上采样的方法是最近邻插值法:
Lateral connections
在融合之后还会再采用3*3的卷积核对已经融合的特征进行处理,目的是消除上采样的混叠效应(aliasing effect)。
将ResNet-FPN和Fast RCNN进行结合,实际上就是Mask RCNN的了,但与最初的Faster RCNN不同的是,FPN产生了特征金字塔
[
P
2
,
P
3
,
P
4
,
P
5
]
[P2,P3,P4,P5]
[P2,P3,P4,P5] ,而并非只是一个feature map。金字塔经过RPN之后会产生很多region proposal。 ,也就是说要在
[
P
2
,
P
3
,
P
4
,
P
5
]
[P2,P3,P4,P5]
[P2,P3,P4,P5]中根据region proposal切出ROI进行后续的分类和回归预测。问题来了,我们要选择哪个feature map来切出这些ROI区域呢?实际上,我们会选择最合适的尺度的feature map来切ROI。具体来说,我们通过一个公式来决定宽w和高h的ROI到底要从哪个
[
P
2
,
P
3
,
P
4
,
P
5
]
[P2,P3,P4,P5]
[P2,P3,P4,P5]来切:
这里224表示用于预训练的ImageNet图片的大小。 K O K^O KO 表示面积为 W ∗ H = 224 ∗ 224 W*H = 224*224 W∗H=224∗224的ROI所应该在的层级。作者将 K O K^O KO 设置为4,也就是说K的ROI应该从 P 4 P4 P4 中切出来。假设ROI的scale小于224(比如说是112 * 112), K = K 0 − 1 = 3 K = K^0 - 1=3 K=K0−1=3 ,就意味着要从更高分辨率的 P 3 P3 P3 中产生。另外, K K K值会做取整处理,防止结果不是整数。
这种做法很合理,大尺度的ROI要从低分辨率的feature map上切,有利于检测大目标,小尺度的ROI要从高分辨率的feature map上切,有利于检测小目标。
2 ROI Pooling——ROI Align
在Faster RCNN中,有两次整数化的过程:
1 region proposal的xywh通常是小数,但是为了方便操作会把它整数化。
2 将整数化后的边界区域平均分割成 k x k 个单元,对每一个单元的边界进行整数化。
事实上,经过上述两次整数化,此时的候选框已经和最开始回归出来的位置有一定的偏差,这个偏差会影响检测或者分割的准确度。在论文里,作者把它总结为“不匹配问题”(misalignment)。
为了解决这个问题,ROI Align方法取消整数化操作,保留了小数,使用双线性插值的方法获得坐标为浮点数的像素点上的图像数值。但在实际操作中,ROI Align并不是简单地补充出候选区域边界上的坐标点,然后进行池化,而是重新进行设计。
下面通过一个例子来讲解ROI Align操作。如下图所示,虚线部分表示feature map,实线表示ROI,这里将ROI切分成2x2的单元格。如果采样点数是4,那我们首先将每个单元格子均分成四个小方格(如红色线所示),每个小方格中心就是采样点。这些采样点的坐标通常是浮点数,所以需要对采样点像素进行双线性插值(如四个箭头所示),就可以得到该像素点的值了。然后对每个单元格内的四个采样点进行maxpooling,就可以得到最终的ROIAlign的结果。
在相关实验中,作者发现将采样点设为4会获得最佳性能,甚至直接设为1在性能上也相差无几。事实上,ROI Align 在遍历取样点的数量上没有ROIPooling那么多,但却可以获得更好的性能,这主要归功于解决了misalignment的问题。
ROI Pool和ROIAlign性能比较
由前面的分析,我们就可以定性的得到一个结论,ROIAlign会使得目标检测的效果有很大的性能提升。根据上表,我们进行定量的分析,结果表明,ROIAlign使得mask的AP值提升了10.5个百分点,使得box的AP值提升了9.5个百分点。
3 Head: 添加了并列的FCN层(mask层)
添加并列的 FCN 层(mask 层),这个目的很明显是为了给框里的目标进行分割,那么它具体是怎么进行分割的呢?比如下面这张图:
这个人我框到了以后,我是怎么把这个人给分割出来的呢,也就是我框的这个框中,我怎么只给这个人上了色,假如这个框中还有其它的我需要识别的目标,我并没有给其他的目标上色,也就是它是怎么做到,我框的是那个类别,那么上色的就是那个类别呢?下面来看下:
深度学习之图像分割网络FCN、MaskRCNN总结_第7张图片
mask网络分支采用FCN对每个ROI的分割输出维数为Km^2,即K个类别的mm的二值mask,采用像素级sigmod,对每个类别的mm进行sigmod
经过rpn网络生成的预测框经过ROI Align后,再经过FCN网络输出K * mm的feature map,K表示一共要检测的目标的类别总数,它是怎么做的呢?
有K个mm的面,每个mm的面就代表一个类别的预测,比如总共有人,狗,猫三个类别,那么K=3,其中一个mm面预测狗这个类别,想下一个面只预测一个类别,那么我只需要用sigmod就可以了,注意,这里的一个面预测一个类别指的是对这个面上的每个像素点进行类别预测,因为是分割,所以我只需要对每个像素点进行sigmod,假如对狗这个面的每个像素进行sigmod的话,设置阀值为0.5,大于0.5为狗,小于0.5就不是狗,,所以对所有像素进行sigmod后,就能把是狗的像素和不是狗的像素进行分开了,然后把是狗的像素给打上颜色,狗就画出来了,同样,其它的面也是这样,,那么我具体选择那个面进行画呢,这就看这个框的分类任务,如果对这个框的分类是狗的话,那么我只会拿狗的面进行画或者上色,计算损失,我只会拿狗的面计算损失,预测我也是拿狗的面进行预测然后resize到原图
Loss cls和 Loss box 与faster rcnn的定义没有区别。需要具体说明的是 Loss mask ,假设一共有K个类别,则mask分割分支的输出维度是
K
∗
m
∗
m
K * m * m
K∗m∗m , 对于
m
∗
m
m * m
m∗m 中的每个点,都会输出K个二值Mask(每个类别使用sigmoid输出)。需要注意的是,计算loss的时候,并不是每个类别的sigmoid输出都计算二值交叉熵损失,而是该像素属于哪个类,哪个类的sigmoid输出才要计算损失(如图红色方形所示)。并且在测试的时候,我们是通过分类分支预测的类别来选择相应的mask预测。这样,mask预测和分类预测就彻底解耦了。
根据上表的分析,我们知道Mask R-CNN利用两个分支将分类和mask生成解耦出来,然后利用Binary Loss代替Multinomial Loss,使得不同类别的mask之间消除了竞争。依赖于分类分支所预测的类别标签来选择输出对应的mask。使得mask分支不需要进行重新的分类工作,使得性能得到了提升
FCN是对每个像素进行多类别softmax分类,然后计算交叉熵损失,这种做法是会造成类间竞争的,而每个类别使用sigmoid输出并计算二值损失,可以避免类间竞争。实验表明通过这种方法,可以较好地提升性能。
4 Result
Updated baseline:使用不同的超参数,延长迭代次数至180k次,初始学习率不变,在120k和160k时减小10倍,NMS的阈值从默认的0.3改为0.5。
End-to-end training:之前的学习都是先训练RPN,然后训练Mask RCNN。
ImageNet-5k pre-training: 数据量比coco增加了5倍,预训练更有效
Train-time augmentation:训练数据增强
Model architecture:使用152-layer的ResNeXt
Non-local:
Test-time augmentation:
分析了ROI Pool的不足,提升了ROIAlign,提升了检测和实例分割的效果;
将实例分割分解为分类和mask生成两个分支,依赖于分类分支所预测的类别标签来选择输出对应的mask。同时利用Binary Loss代替Multinomial Loss,消除了不同类别的mask之间的竞争,生成了准确的二值mask;
并行进行分类和mask生成任务,对模型进行了加速。