【实例分割系列:一】Mask RCNN 论文笔记解析

2017 CVPR
Mask R-CNN
Mask RCNN, PyTorch

Instance Segmentation

Introduction

Mask RCNN = Faster RCNN + ResNet-FPN + Mask

在这里插入图片描述

Motivation

  • 强化的基础网络
    通过 ResNeXt-101+FPN 用作特征提取网络,达到 state-of-the-art 的效果。

  • ROI Pooling → ROI Align
    解决特征图与原始图像上的RoI不对准问题

    • ROI Pooling 是一种针对每一个RoI的提取一个小尺度特征图(e.g. 7x7)的标准操作
    • ROI Align 使用双线性插值(bilinear interpolation)在每个RoI块中4个采样位置上计算输入特征的精确值,并将结果聚合(使用max或者average)。
  • 分割、分类、定位同时进行
    检测和分割是并行出结果的,而不像以前是分割完了之后再做分类

    • FCNs是对每个像素进行多类别分类,它同时进行分类和分割
    • Mask RCNN 对每个类别独立地预测一个二值掩模,没有引入类间竞争,每个二值掩模的类别依靠网络RoI分类分支给出的分类预测结果
  • Loss Function

    • mask loss
      由原来的 FCIS 的 基于单像素softmax的多项式交叉熵变为了基于单像素sigmod二值交叉熵。
      softmax会产生 FCIS 的 ROI inside map 与 ROI outside map的竞争。但文章作者确实写到了类间的竞争, 二值交叉熵会使得每一类的 mask 不相互竞争,而不是和其他类别的 mask 比较 。

Network

faster rcnn

Mask rcnn

“head” 作用是将RoI Align的输出维度扩大,这样在预测Mask时会更加精确。
在Mask Branch的训练环节,作者没有采用FCN式的SoftmaxLoss,反而是输出了K个Mask预测图(为每一个类都输出一张),并采用average binary cross-entropy loss训练,

  • two-state
    extract feature 、RPN
    对RPN找到的每个RoI进行 分类、定位、找到binary mask(对于 Faster RCNN 的每个 Proposal Box 使用 FCN 进行语义分割)
    注意:这里和其他分割网络(先 mask 然后分类 )是不同的

  • Loss
    L = L c l s + L b o x + L m a s k L=Lcls+Lbox+Lmask L=Lcls+Lbox+Lmask

  • Mask Representation
    没有采用全连接层并且使用了RoIAlign,可以实现输出与输入的像素一一对应

backbone

resnet-50,resnet-101,resnext-50,resnext-101;FPN

Mask

Faster RCNN使用resnet50时,从CONV4导出特征供RPN使用,这种叫做ResNet-50-C4

对于新增加的mask支路,其对于每个ROI的输出维度是 K ∗ m ∗ m K*m*m Kmm,其中 m ∗ m m*m mm表示mask的大小,K表示K个类别,因此这里每一个ROI一共生成 K K K个binary mask,这就是文章中提到的class-specific mask概念。

在得到预测mask后,对mask的每个像素点值求sigmoid函数值(即所谓的per-pixel sigmoid),得到的结果作为Lmask(交叉熵损失函数)的输入之一。

  • sigmoid:A logistic function or logistic curve is a common “S” shape (sigmoid curve).
    二分类损失
  • softmax:softmax is a generalization of logistic function that “squashes”(maps) a K-dimensional vector z of arbitrary real values to a K-dimensional vector σ(z) of real values in the range (0, 1) that add up to 1.
    多分类损失

送进mask分支的ROI其实是只有正样本的ROI才被送进去。只有正样本ROI才会用于计算Lmask,正样本的定义和目标检测一样,都是IOU大于0.5定义为正样本。

问题

怎么做到区别 实例而不是类别??

对于每一个ROI,如果检测得到ROI属于哪一个分类,就只使用哪一个分支的相对熵误差作为误差值进行计算。

举例说明:分类有3类(猫,狗,人),检测得到当前ROI属于“人”这一类,那么所使用的Lmask为“人”这一分支的mask。
这样的定义使得我们的网络不需要去区分每一个像素属于哪一类,只需要去区别在这个类当中的不同小类。

我们定义的Lmask允许网络为每一类生成一个mask,而不用和其它类进行竞争;我们依赖于分类分支所预测的类别标签来选择输出的mask。

  • FCN
  • Mask-RCNN

    Mask-RCNN不是一次性对所有的通道channel上的像素求多分类损失,而是只在每一个ROI所对应的类别上对每一个像素求一个sigmoid二分类

第一个ROI我们只在对应的K=3的类别中,即在channel为3的通道上的那个mask上面对每一个像素求二分类
第二个ROI我们只在对应的K=8的类别中,即在channel为8的通道上的那个mask上面对每一个像素求二分类

  • 关键问题:怎么知道每一个ROI到底是那个类别呢?
    • 借助分类网络
      分类网络告诉分割网络这个对应的 ROI 是属于哪一个类别 K 。
    • 好处:
      定义的 Lmask 允许网络为每一类生成一个mask,只用在自己的类别(即channel)上计算损失,而不用和其它类进行竞争。
      对每个固定的类别的那张特征图的每一个像素计算损失之后,然后再求所有像素的平均,这也是文章中将Lmask称为average binary cross-entropy loss的原因。

ROI Align 原理?

  • 为了得到为了得到固定大小(7X7)的feature map,ROIAlign技术并没有使用量化操作,即我们不想引入量化误差,比如665 / 32 = 20.78,我们就用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 中的像素是完全对齐的,没有偏差,这不仅会提高检测的精度,同时也会有利于实例分割。

Pytorch

Mask RCNN, PyTorch

改进

基于 Mask RCNN 的改进:

Reference

https://blog.csdn.net/jiongnima/article/details/79094159
https://zhuanlan.zhihu.com/p/37998710
https://blog.csdn.net/linolzhang/article/details/71774168
https://blog.csdn.net/u014380165/article/details/81878644
https://blog.csdn.net/xiamentingtao/article/details/78598511
https://blog.csdn.net/wangdongwei0/article/details/83110305
https://blog.csdn.net/qq_27825451/article/details/89677068

猜你喜欢

转载自blog.csdn.net/qq_31622015/article/details/101118867