MaskRCNN

实例分割的第一个模型,创造性地结合Faster RCNN和FCN,分别完成实例的定位、分类及Mask生成,同时为了解决ROI Pooling的量化误差问题,提出ROI Align替换

什么是 Mask RCNN?

  • 在 FasterRCNN]的基础上新增 FCN分割模块,黑色部分为原来的 Faster-RCNN,红色部分为在 Faster 网络上的修改。
  • 另一个改进是通过 ROIAlign替换 Faster RCNN 的感兴趣区域池化(RoIPooling),解决图像和网络输出的对齐问题,极大提升语义分割的效果
  • 可以认为是目标检测 +语义分割的结合,更具体一点就:RPN+ROIAlign+Fast RCNN+ FCN

Mask RCNN的网络结构?

  • 骨干网络: 使用 ResNet +特征金字塔网络 (FeaturePyramidNetwork, FPN)提取多尺度的特征

  • 感兴趣区域的池化: 采用 ROIAlign而不是 Faster RCNN 的感兴趣区域池化(RoIPooling)

  • box分类与回归: FasterRCNN一致

  • object mask: 使用 FCN

    Mask RCNN使用FPN生成多尺度的特征图,ROIAlign使用哪个尺度的特征图? ^83n58t

    • 假设 FPN 产生了特征金字[P2, P3, P4, P5, P6],通过下列公式决定宽 w 和高 h 的 ROI 到底要从哪个 Pk 来切

      k=k0+log2(wh/224)k=\left\lfloor k_{0}+\log _{2}(\sqrt{w h} / 224)\right\rfloor

    • 其中 224 表示预训练 ImageNet 图片大小,k0 表示面积为 wxh=224x224 的 ROI 所在层级,论文将 k0 设置为 p4,如果 ROI 小于 224,比如说 122x122,则使用 k0-1=4-1=3 层特征池化
    • 这种做法很合理,大尺度的ROI要从低分辨率的feature map上切,有利于检测大目标,小尺度的ROI要从高分辨率的feature map上切,有利于检测小目标

    Mask RCNN的损失函数?

    • 总的损失函数L=Lcls+Lbox+LmaskL = L_{cls} + L_{box} + L_{mask}
    • LclsL_{cls}表示bounding box的分类损失值:使交叉熵损失(CrossEntropyLoss)
    • LboxL_{box}表示bounding box的回归损失值:使平滑绝对值损失(Smooth L1 Loss)
    • LmaskL_{mask}表示mask部分的损失值:使二值交叉熵损失BCELoss ,该损失一般配合sigmoid函数使用

    Mask RCNN的训练过程?

    • 主干网络部分:将图片送入到 CNN 特征提取网络得到特征图
    • RPN 部分:对特征图的每一个像素位置设定固定个数的 ROI(Anchor),然后将 ROI 区域送入 RPN 网络进行二分类 (前景和背景) 以及坐标回归,以获得精炼后的 ROI 区域
    • ROIAlign 部分:对获得的 ROI 区域执 ROIAlign 操作,即先将原图和 feature map 的 pixel 对应起来,然后将不同目标的 feature map 转为相同大小的 featrue
    • 目标检测部分:对这些 ROI 区域进行多类别分类,得到预测的目标位置及类别
    • 分割部分:最后目标检测得到的所有目标输入 FCN,得到每个目标的掩码预测结果

    Mask RCNN 如何对目标进行分割预测?

    • 经过 ROIAlign获得 ROI 区域特征后,对每个像素进行分类,实现分割

    Mask RCNN如何进行关键点检测任务?

    • 让Mask RCNN预测k个mask,每个mask对应一个关键点类型,比如左肩、右肘,使用cross entropy loss,鼓励网络只检测一个关键点

    什么是ROIAlign?

    • MaskRCNN-20230408143911
    • ROIPooling 和 RoIAlign 的目的都是为了获取目标定长的特征,都是经历:原图目标->特征图区域->池化特征 2 次映射过程
    • ROIPooling:映射时经历两次取整,一次是目标->特征图,一次是特征图->池化,这样的操作对语义分割这种位置敏感的模型影响较大
    • RoIAlign:映射时并没有取整的过程,可以全程使用浮点数操作,最后通[[语义分割基础知识#^2ec19a|双线性插值(BilinearInterpolation)]] 计算浮点数位置的像素值 (特征值)

    ROIAlign如何计算池化结果?

    • 假设模型输入是:3x512x512,经过特征提取得到512x16x16的特征,即数据下采样512/16=32倍,现有目标位置(192,296),大小145x200
    • ROI 映射: 计算得到该目标在特征图上位置为:(296/32=9.25, 192/32=6),大小为 (200/32=6.25, 145/32=4.53),ROIAlign 保留小数
    • 将ROI区域划分为大小相等的9个框,每个框的宽高为(6.25,4.53)/3=(2.08,1.51)
    • 在每个框内取 4 个采样点,取样方法为将框横纵方向进行 3 等分,取框内的划分点作为采样点,如第一个点坐标 (X_box+(box_width/3) x1, Y_box+(box_height/3) x1)=(9.94, 6.50) 、第二个点坐标 (X_box+(box_width/3) x1, Y_box+(box_height/3) x2) =(9.94, 7.01)…
    • 计算采样点的数值:按双线性插值 的原理,按照采样点与单元中心的距离计算采样点数值,依次计算采样点值
    • ROI区域池化:根据一个bin内的4个采样点,使用最大池化获得该区域的池化特征,依次使用上述方法计算,可以得到所有bin的池化结果

    为什么在语义分割中使用ROIAlign,而不使用ROIPool? ^the4hh

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

    Mask RCNN目标分类为什么不使用类别竞争机制(softmax)?

    • MaskRCNN-20230408143914-1
    • 使用sigmoid(二分类)和使用softmax(多类别分类)的AP相差很大,证明了分离类别和mask的预测是很有必要的