Mask R-CNN论文笔记

Mask R-CNN

Mask R-CNN是在Faster R-CNN上结合了FPN和RoI Align的新模型,其中增加预测每个RoI mask的通路,从而同时实现了分类,回归,分割三个问题,模型能够应用到Instance Segmentation,Detection等各式各样的问题上,表现都非常优秀。

Mask R-CNN的相关论文解读也是非常多,但是要了解其精髓,主要还是要弄清楚两个核心问题。第一,是如何将RoI Pooling替换为RoI Align;第二,是如何在原始的Faster R-CNN上增加了对于mask的分类。

RoI Align

要明白RoI Align的原理首先要理解RoI Pooling有什么问题。简单来说就是RoI Pooling使用的是一种最邻近插值方法,也就是每次在RPN回归出的Proposal位置映射到后面的feature map上不能整除的时候就进行四舍五入的方法找到临近的整点代替,这样的做法会使得最终的RoI位置和原始的Proposal位置有translation,这种偏移对于小物体的识别影响更为严重。

由于预选框的位置通常是由模型回归得到的,一般来讲是浮点数,而池化后的特征图要求尺寸固定。Roi Pooling中带来了这种量化误差的地方有两处:

  • 将候选框边界量化为整数点坐标值。
  • 将量化后的边界区域平均分割成 k x k 个单元(bin),对每一个单元的边界进行量化。

事实上,经过上述两次量化,此时的候选框已经和最开始回归出来的位置有一定的偏差,这个偏差会影响检测或者分割的准确度。在论文里,作者把它总结为“不匹配问题(misalignment)。

我们以一个例子来说明这个问题,如下图所示,这是一个Faster-RCNN检测框架。输入一张800*800的图片,图片上有一个665*665的包围框(框着一只狗)。图片经过主干网络提取特征后,特征图缩放步长(stride)为32。因此,图像和包围框的边长都是输入时的1/32。800正好可以被32整除变为25。但665除以32以后得到20.78,带有小数,于是ROI Pooling 直接将它量化成20。接下来需要把框内的特征池化7*7的大小,因此将上述包围框平均分割成7*7个矩形区域。显然,每个矩形区域的边长为2.86,又含有小数。于是ROI Pooling 再次把它量化到2。经过这两次量化,候选区域已经出现了较明显的偏差(如图中绿色部分所示)。更重要的是,该层特征图上0.1个像素的偏差,缩放到原图就是3.2个像素。那么0.8的偏差,在原图上就是接近30个像素点的差别,这一差别不容小觑。(reference:详解 ROI Align 的基本原理和实现细节)

为了解决ROI Pooling的上述缺点,作者提出了ROI Align这一改进的方法(如下图)。ROI Align的思路很简单:取消量化操作,使用双线性内插的方法获得坐标为浮点数的像素点上的图像数值,从而将整个特征聚集过程转化为一个连续的操作,。值得注意的是,在具体的算法操作上,ROI Align并不是简单地补充出候选区域边界上的坐标点,然后将这些坐标点进行池化,而是重新设计了一套比较优雅的流程:

  • 遍历每一个候选区域,保持浮点数边界不做量化。
  • 将候选区域分割成k x k个单元,每个单元的边界也不做量化。
  • 在每个单元中计算固定四个坐标位置,用双线性内插的方法计算出这四个位置的值,然后进行最大池化操作。

关于双线性插值的具体只是,可以参考这里:图像处理: 五种插值法

Mask Prediction

对于做实例分割,作者将segmentation问题和classification问题分开来训练,单独加了一条通路(FCN)在RoI Align层之后,单独学习每个RoI的二值 mask map。

首先对图片做检测,找出图像中的ROI,对每一个ROI使用ROIAlign进行像素校正,然后对每一个ROI使用设计的FCN框架进行预测不同的实例所属分类,最终得到图像实例分割结果。 介绍一下网络使用的损失函数为分类误差+检测误差+分割误差。

分类误差和检测误差在farster R-CNN当中已经介绍过了,可以去文献当中查找。分割误差为新的东西,对于每一个ROI,mask分支定义一个K*m^2维的矩阵表示K个不同的分类对于每一个m*m的区域,对于每一个类都有一个。对于每一个像素,都是用sigmod函数进行求相对熵,得到平均相对熵误差Lmask。对于每一个ROI,如果检测得到ROI属于哪一个分类,就只使用哪一个分支的相对熵误差作为误差值进行计算。(举例说明:分类有3类(猫,狗,人),检测得到当前ROI属于“人”这一类,那么所使用的Lmask为“人”这一分支的mask。)这样的定义使得我们的网络不需要去区分每一个像素属于哪一类,只需要去区别在这个类当中的不同分别小类。

整体的网络结构还是和之前的非常相似,这里作者尝试了如上的两种结构,一种是Faster R-CNN的构造,一种是FPN的构造。

具体的这部分的构造和实验结果都可以在原文中查看,这里就不赘述了。

最后这里引用一下知乎上一个回答

”””

主要改进点在:

  1. 基础网络的增强,ResNeXt-101+FPN的组合可以说是现在特征学习的王牌了
  2. 分割 loss 的改进,由原来的 FCIS 的 基于单像素softmax的多项式交叉熵变为了基于单像素sigmod二值交叉熵,经 @Oh233同学指正 ,softmax会产生FCIS的 ROI inside map与ROI outside map的竞争。但文章作者确实写到了类间的竞争, 二值交叉熵会使得每一类的 mask 不相互竞争,而不是和其他类别的 mask 比较 。
  3. RoIAlign 层的加入,说白了就是对 feature map 的插值,直接的ROIPooling的那种量化操作会使得得到的mask与实际物体位置有一个微小偏移,个人感觉这个没什么 insight,就是工程上更好的实现方式

文章还指出在物体检测中,Mask-RCNN 比一般的 state-of-the-art 方法(用Fatser-RCNN+ResNet-101+FPN实现)在 bounding-box 的 AP 上高3.6个点,1.1来自ROIAlign,0.9来自多任务训练,1.6来自更好的基础网络(ResNeXt-101)

说一点个人愚见,这么好的效果是由多个阶段的优化实现的,大头的提升还是由数据和基础网络的提升:多任务训练带来的好处其实可以看作是更多的数据带来的好处;FPN 的特征金字塔,ResNeXt更强大的特征表达能力都是基础网络

”””