MaskRCNN网络结构
MaskRCNN作为FasterRCNN的扩展,产生RoI的RPN网络和FasterRCNN网络。
结构:ResNet101+FPN
代码:TensorFlow+ Keras(Python)
代码中将Resnet101网络,分成5个stage,记为[C1,C2,C3,C4,C5];这里的5个阶段分别对应着5中不同尺度的feature map输出,用来建立FPN网络的特征金字塔(feature pyramid).
先通过两张MaskRCNN整体网络结构图,再附带一张绘制了stage1和stage2的层次结构图(stage3到stage5的结构层次比较多,未绘制),整体了解下MaskRCNN网络。
MaskRCNN网络结构泛化图:
MaskRCNN网络结构细化图:
stage1和stage2层次结构图:
Mask-RCNN 技术要点
● 技术要点1 - 强化的基础网络
通过 ResNeXt-101+FPN 用作特征提取网络,达到 state-of-the-art 的效果。
● 技术要点2 - ROIAlign
采用 ROIAlign 替代 RoiPooling(改进池化操作)。引入了一个插值过程,先通过双线性插值到14*14,再 pooling到7*7,很大程度上解决了仅通过 Pooling 直接采样带来的 Misalignment 对齐问题。
PS: 虽然 Misalignment 在分类问题上影响并不大,但在 Pixel 级别的 Mask 上会存在较大误差。
后面我们把结果对比贴出来(Table2 c & d),能够看到 ROIAlign 带来较大的改进,可以看到,Stride 越大改进越明显。
● 技术要点3 - Loss Function
每个 ROIAlign 对应 K * m^2 维度的输出。K 对应类别个数,即输出 K 个mask,m对应池化分辨率(7*7)。Loss函数定义:
Lmask(Cls_k) = Sigmoid (Cls_k),平均二值交叉熵 (average binary cross-entropy)Loss,通过逐像素的 Sigmoid 计算得到。
Why K个mask?通过对每个 Class 对应一个 Mask 可以有效避免类间竞争(其它Class 不贡献 Loss )。
ROIpooling
ROI pooling就不多解释了,直接通过一个例子来形象理解。假设有一个8x8大小的feature map,要在这个feature map上得到ROI,并且进行ROI pooling到2x2大小的输出。
假设ROI的bounding box为
如图:
划分为2x2的网格,因为ROI的长宽除以2是不能整除的,所以会出现每个格子大小不一样的情况。
进行max pooling的最终2x2的输出为:
ROI Align
在Faster RCNN中,有两次整数化的过程:
- region proposal的xywh通常是小数,为了方便操作会把它整数化。
- 将整数化后的边界区域平均分割成 k x k 个单元,对每一个单元的边界进行整数化。
两次整数化的过程如下图所示:
事实上,经过上述两次整数化,此时的候选框已经和最开始回归出来的位置有一定的偏差,这个偏差会影响检测或者分割的准确度。在论文里,总结为“不匹配问题”(misalignment)。
为了解决这个问题,ROI Align方法取消整数化操作,保留了小数,使用以上介绍的双线性插值的方法获得坐标为浮点数的像素点上的图像数值。但在实际操作中,ROI Align并不是简单地补充出候选区域边界上的坐标点,然后进行池化,而是重新进行设计。
下面通过一个例子来讲解ROI Align操作。如下图所示,虚线部分表示feature map,实线表示ROI,这里将ROI切分成2x2的单元格。如果采样点数是4,首先将每个单元格子均分成四个小方格(如红色线所示),每个小方格中心就是采样点。这些采样点的坐标通常是浮点数,所以需要对采样点像素进行双线性插值(如四个箭头所示),就可以得到该像素点的值了。对每个单元格内的四个采样点进行maxpooling,就可以得到最终的ROIAlign的结果。
参考源码:https://github.com/matterport/Mask_RCNN
参考文献:
https://zhuanlan.zhihu.com/p/37998710
https://www.cnblogs.com/wangyong/p/9305347.html