Object Detection(四)Mask R-CNN

之前介绍了 R-CNN Fast R-CNN Faster R-CNN,这是本系列的第四篇Mask R-CNN

Mask R-CNN是何凯明在Faster R-CNN基础上加入一个新分支,集Object Detection 和 Instance Segmentation于一体的新网络。该网络在进行目标检测的同时完成了高质量的实例分割。

首先我们先来看看实例分割(Instance segmentation)和语义分割(Semantic segmentation)的区别


Object Detection(四)Mask R-CNN_第1张图片

图中的c和d图,c图是对a图进行语义分割的结果,d图是对a图进行实例分割的结果。两者最大的区别就是图中的"cube对象",在语义分割中给了它们相同的颜色,而在实例分割中却给了不同的颜色。即实例分割需要在语义分割的基础上对同类物体进行更精细的分割。
下面我们就开始介绍Mask R-CNN,首先是Mask R-CNN整体的结构


Object Detection(四)Mask R-CNN_第2张图片

这张图可能不是很具体,那再看看下面这张图。


Object Detection(四)Mask R-CNN_第3张图片

和Faster R-CNN整体相似,只是将Faster R-CNN中的RoI Pooling 替换成了RoI Align 并加了一个mask branch。

Mask R-CNN有以下几个贡献:

  • 替换卷积backbone
  • 引入RoI Align 替换RoI Pooling
  • Loss Function

贡献

Resnet + FPN

在Faster R-CNN中提取特征的卷积神经网络使用的是VGG,在Mask R-CNN中为了获得更强的特征表达能力,作者使用了Resnet,为了获取多尺度信息还引入了FPN网络。

RoI Align

RoI Align是Mask R-CNN中特别重要的一环,说到RoI Aligh我们先来看看Faster R-CNN中的RoI Pooling。通过这样图可以很好的理解RoI Pooling的工作原理


Object Detection(四)Mask R-CNN_第4张图片

那RoI Pooling有什么问题呢?

ROI Pooling 的作用是根据预选框的位置坐标在特征图中将相应区域池化为固定尺寸的特征图,以便进行后续的分类和包围框回归操作。由于预选框的位置通常是由模型回归得到的,一般来讲是浮点数,而池化后的特征图要求尺寸固定。故ROI Pooling这一操作存在两次量化的过程。

  • 将候选框边界量化为整数点坐标值。
  • 将量化后的边界区域平均分割成 k x k 个单元(bin),对每一个单元的边界进行量化。
Object Detection(四)Mask R-CNN_第5张图片

经过上述两次量化,此时的候选框已经和最开始回归出来的位置有一定的偏差,这个偏差会影响检测或者分割的准确度。在论文里,作者把它总结为“不匹配问题(misalignment)。
我们再通过何凯明slide中的例子来理解一下。如下图


Object Detection(四)Mask R-CNN_第6张图片

如图我们输入的是一张800x800的图像,在图像中有两个目标(猫和狗),狗的bbox大小为665x665,经过VGG16网络后,我们可以获得对应的feature map,如果我们对卷积层进行Padding操作,我们的图片经过卷积层后保持原来的大小,但是由于池化层的存在,我们最终获得feature map 会比原图缩小一定的比例,这和Pooling层的个数和大小有关。在该VGG16中,我们使用了5个池化操作,每个池化操作都是2Pooling,因此我们最终获得feature map的大小为800/32 x 800/32 = 25x25(是整数),但是将狗的bbox对应到feature map上面,我们得到的结果是665/32 x 665/32 = 20.78 x 20.78,结果是浮点数,含有小数,但是我们的像素值可没有小数,那么作者就对其进行了量化操作(即取整操作),即其结果变为20 x 20,在这里引入了第一次的量化误差;然而我们的feature map中有不同大小的ROI,但是我们后面的网络却要求我们有固定的输入,因此,我们需要将不同大小的ROI转化为固定的ROI feature,在这里使用的是7x7的ROI feature,那么我们需要将20 x 20的ROI映射成7 x 7的ROI feature,其结果是 20 /7 x 20/7 = 2.86 x 2.86,同样是浮点数,含有小数点,我们采取同样的操作对其进行取整吧,在这里引入了第二次量化误差。其实,这里引入的误差会导致图像中的像素和特征中的像素的偏差,即将feature空间的ROI对应到原图上面会出现很大的偏差。原因如下:比如用我们第二次引入的误差来分析,本来是2,86,我们将其量化为2,这期间引入了0.86的误差,看起来是一个很小的误差呀,但是你要记得这是在feature空间,我们的feature空间和图像空间是有比例关系的,在这里是1:32,那么对应到原图上面的差距就是0.86 x 32 = 27.52。这个差距不小吧,这还是仅仅考虑了第二次的量化误差。这会大大影响整个检测算法的性能,因此是一个严重的问题。


RoI Align layer

为了解决ROI Pooling的上述缺点,作者提出了ROI Align这一改进的方法。

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

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

为了得到为了得到固定大小(7X7)的feature map,ROIAlign技术并没有使用量化操作,即我们不想引入量化误差,比如665 / 32 = 20.78,我们就用20.78,不用什么20来替代它,比如20.78 / 7 = 2.97,我们就用2.97,而不用2来代替它。
那么如何处理这些浮点数呢,使用“双线性插值”算法。


Object Detection(四)Mask R-CNN_第8张图片

双线性插值是一种比较好的图像缩放算法,它充分的利用了原图中虚拟点(比如20.56这个浮点数,像素位置都是整数值,没有浮点值)四周的四个真实存在的像素值来共同决定目标图中的一个像素值,即可以将20.56这个虚拟的位置点对应的像素值估计出来。厉害哈。如上图所示,蓝色的虚线框表示卷积后获得的feature map,黑色实线框表示ROI feature,最后需要输出的大小是2x2,那么我们就利用双线性插值来估计这些蓝点(虚拟坐标点,又称双线性插值的网格点)处所对应的像素值,最后得到相应的输出。这些蓝点是2x2Cell中的随机采样的普通点,作者指出,这些采样点的个数和位置不会对性能产生很大的影响,你也可以用其它的方法获得。然后在每一个橘红色的区域里面进行max pooling或者average pooling操作,获得最终2x2的输出结果。我们的整个过程中没有用到量化操作,没有引入误差,即原图中的像素和feature map中的像素是完全对齐的,没有偏差,这不仅会提高检测的精度,同时也会有利于实例分割。

下面是何凯明ppt中的一个插图,比较好的说明了RoI Align的工作原理。


Object Detection(四)Mask R-CNN_第9张图片
Object Detection(四)Mask R-CNN_第10张图片
Object Detection(四)Mask R-CNN_第11张图片
Object Detection(四)Mask R-CNN_第12张图片
Object Detection(四)Mask R-CNN_第13张图片

Loss Function

在Faster R-CNN的基础上加了一个分支,于是Loss就变成了


前两个都是定义在Faster R-CNN中的。
mask branch 会对每个RoI的输出纬度为Kmm,即对K个类分别输出了一个m*m的mask。
因为mask输出时使用了 a per-pixel sigmoid,所以Lmask的定义为the average binary cross-entropy loss(二值的sigmoid交叉熵损失)


结果

Object Detection(四)Mask R-CNN_第14张图片
Object Detection(四)Mask R-CNN_第15张图片

更多细节请参考论文地址
bolg参考12


小结

至此,R-CNN系列的文章就讲完了,其实这几篇文章看了还是有一段时间了,之前感觉了解得还是比较清楚了,但是最近写这几篇blog的时候发现之前了解的还是不够清楚,甚至很多细节地方还是错的。

你可能感兴趣的:(Object Detection(四)Mask R-CNN)