实例分割新思路之 SOLO v1&v2 深度解析

date
May 17, 2022
Last edited time
Mar 27, 2023 08:52 AM
status
Published
slug
实例分割新思路之SOLOv1&v2深度解析
tags
DL
CV
summary
type
Post
Field
Plat
实例分割新思路之SOLO v1&v2深度解析
实例分割一般有两种做法,一种是top-down,既先检测 bbox,后在每个bbox中进行mask的分割,例如Mask R-CNN。第二种为bottom-up做法,先分割出每一个像素,再进行归类。本文介绍的两篇论文另辟蹊径, 直接分割实例 mask,属于box-free的做法。正如YOLO大神Joseph Redmon所说 "Boxes are stupid anyway though, I'm probably a true believer in masks except I can't get YOLO to learn them" 。本文就是摒弃了boxes进行实例分割,因此有必要对该论文进行深入分析。 参考的代码为在mmdetection的基础上实现的: 首先思考一个问题,能否像语义分割一样进行实例分割?实例分割和语义分割在算法处理上最大的不同就是,实例分割需要处理同类别的实例重叠或粘连的问题。那么如果将不同的实例分配到不同的输出channel上,不就可以解决这个问题了吗?本文作者正是这种思路,不过这样也面临两个问题: 一是通道分配顺序的问题,语义分割是根据类别进行通道分配的。而对于实例分割,相同类别的不同实例需要分配到不同通道上,需要解决按照什么样的规则分配。二是尺度问题,不同尺度的物体利用相同大小的输出来预测会导致正负样本不平衡,以及小目标分割边缘不够精细的问题。对于这两个问题,本文作者给出了解答。作者首先对MS COCO数据集进行统计,发现在验证集中,绝大多数(约98.9%)的实例要么中心位置不同,要么大小不同。因此可以通过中心位置和对象大小直接区分实例, 既location 和 sizes。所以作者利用位置来分配实例应该落入哪一个通道,利用FPN来解决尺度问题。 具体做法为: 类似YOLO中的做法,首先将图片等分为 个格子。网络输出为两个分支:分类分支和mask分支。分类分支的大小为 , 为类别数量。mask分支大小为 , 为预测的最大实例个数,按照从上到下从左到右的方式与原图位置对应起来。当目标物体中心落入哪一个格子,分类分支对应位置以及mask分支对应通道负责该物体的预测。例如实例分配到格子 , 则mask分支上通道 负责预测该目标的mask, 每个格子都只属于一个单独的实例。这就是论文对Locations的设计。 而对于Sizes,则采用通用做法:FPN。大的特征图负责预测小的目标,小的特征图负责预测大的目标。 FPN也可以一定程度上缓解目标重叠的问题,尺度不同的实例会被分配到不同FPN输出层中进行预测。 包括两个方面,一是FPN同一层正负样本分配的策略。二是FPN不同层正负样本分配的策略。 对于给定gt mask的质心 、宽度w和高度h,设置比例因子 ,这里 。当被缩小后的box落入原图上某几个格子,这些格子对应的分类分支位置以及mask分支channel为正样本,否则为负样本。每一个gt平均有3个正样本。代码如下: # 分类分支的正负样本分配,这里的top,down,left,right为gt box缩小sigma倍后的box上下左右值 cate_label[top:(down+1), left:(right+1)] = gt_label # 对于mask分支的正样本分配,在0.2倍的gt box内grid cell对应的通道均分配为mask正样本 seg_mask = mmcv.imrescale(seg_mask, scale=1.
实例分割新思路之SOLO v1&v2深度解析

前言

实例分割一般有两种做法,一种是 top-down,既先检测 bbox,后在每个 bbox 中进行 mask 的分割,例如 Mask R-CNN。第二种为 bottom-up 做法,先分割出每一个像素,再进行归类。
notion image
本文介绍的两篇论文另辟蹊径, 直接分割实例 mask,属于 box-free 的做法。本文就是摒弃了 boxes 进行实例分割,因此有必要对该论文进行深入分析。

SOLO v1

head 设计

首先思考一个问题,能否像语义分割一样进行实例分割?实例分割和语义分割在算法处理上最大的不同就是,实例分割需要处理同类别的实例重叠或粘连的问题。那么如果将不同的实例分配到不同的输出 channel 上,不就可以解决这个问题了吗?本文作者正是这种思路,不过这样也面临两个问题
  1. 一是通道分配顺序的问题,语义分割是根据类别进行通道分配的。而对于实例分割,相同类别的不同实例需要分配到不同通道上,需要解决按照什么样的规则分配。
  1. 二是尺度问题,不同尺度的物体利用相同大小的输出来预测会导致正负样本不平衡,以及小目标分割边缘不够精细的问题。
对于这两个问题,本文作者给出了解答。作者首先对 MS COCO 数据集进行统计,发现在验证集中,绝大多数(约 98.9%)的实例要么中心位置不同,要么大小不同。因此可以通过中心位置和对象大小直接区分实例, 既 location 和 sizes。所以作者利用位置来分配实例应该落入哪一个通道,利用 FPN 来解决尺度问题。
notion image
具体做法为:
类似 YOLO 中的做法,首先将图片等分为 个格子。网络输出为两个分支:分类分支和 mask 分支。分类分支的大小为 为类别数量。mask 分支大小为 为预测的最大实例个数,按照从上到下从左到右的方式与原图位置对应起来。当目标物体中心落入哪一个格子,分类分支对应位置以及 mask 分支对应通道负责该物体的预测。例如实例分配到格子 , 则 mask 分支上通道 负责预测该目标的 mask, 每个格子都只属于一个单独的实例。这就是论文对 Locations 的设计。
而对于 Sizes,则采用通用做法:FPN。大的特征图负责预测小的目标,小的特征图负责预测大的目标。 FPN 也可以一定程度上缓解目标重叠的问题,尺度不同的实例会被分配到不同 FPN 输出层中进行预测。

正负样本分配策略

包括两个方面,一是 FPN 同一层正负样本分配的策略。二是 FPN 不同层正负样本分配的策略。

FPN 同一层

对于给定 gt mask 的质心 、宽度 和高度 ,设置比例因子 ,这里 。当被缩小后的 box 落入原图上某几个格子,这些格子对应的分类分支位置以及 mask 分支 channel 为正样本,否则为负样本。每一个 gt 平均有 3 个正样本。代码如下:

FPN 不同层

论文设置 scale_ranges=((1, 96), (48, 192), (96, 384), (192, 768), (384, 2048)),分别对应不同 FPN 的输出层。当实例的尺度落入某一个区间,则该 FPN 分支负责该实例的预测。由于不同区间存在重叠的情况,因此会存在不同 FPN 层预测相同的目标,这样同样会增加正样本的数量。代码如下:

可视化分析

为了更清晰理解样本分配策略,这里进行了可视化。如图所示,在原图中,蓝色框表示图片等分的格子,这里设置分为 个格子。绿色框为目标物体的 gt box,黄色框表示缩小到 0.2 倍数的 box,红色框表示负责预测该实例的格子。下方黑白图为 mask 分支的 target 可视化,为了便于显示,这里对不同通道进行了拼接。 左边的第一幅图,图中有一个实例,其 gt box 缩小到 0.2 倍占据两个格子,因此这两个格子负责预测该实例。下方的 mask 分支,只有两个 FPN 的输出匹配到了该实例,因此在红色格子对应的 channel 负责预测该实例的 mask。第二幅图,图中分布大小不同的实例,可见在 FPN 输出的 mask 分支上,从小到大负责不同尺度的实例。这里值得注意的是,FPN 输出的 mask 分支,其尺度并不是统一的,而是从大到小的,这里为了便于显示才缩放到统一尺寸上。
notion image
notion image

CoordConv

本文利用了 CoordConv,目的是为了加强卷积神经网络对位置信息的处理。CoordConv 做法非常简单, 直接在原始 tensor 上利用 concatenate 的方式扩两个通道,分别存储 x 和 y 的坐标,并归一化到 之间。显式地把位置信息带入到下一个卷积操作里面。不过 CoordConv 也引起了一些争议,但该论文(SOLO)中使用还是起到了不错的效果,本文不去讨论。
这一点,原作在知乎也给出了自己的看法: 关于 CoordConv 和 Dice Loss:这些并不是比普通 Conv 和 BCE Loss 更高级的东西,只是在我们这种情况下更适用而已: CoordConv 用来提供全局位置信息,Dice Loss 来解决分割区域小的问题。而 Mask R-CNN 是没有这样的需求的。
具体做法如下,创建一个包含像素坐标 tensor(标准化至 ),和原始通道 concatenate,因此可以看到 Channel 数为(256+2),最后两个通道提供全图位置信息,再送入到后续的卷积运算中。代码如下:

Decoupled head

由于 mask 分支预测 个通道, 如果 grid cell 设置过多的话,该输出通道会过于庞大。因此论文提出 Decoupled head 的改进方式。具体见下图,将 mask 分支拆分为 方向和 方向两个分支,每一个分支的通道数为 。将两个分支按照 element-wise 的方式进行相乘获取 mask 输出,这样预测通道由原来的 变为了 个,实验发现精度并没有明显的损失。此时想要获取第 个格子预测的 mask,只需要将 分支的第 个通道和 分支的第 个通道取出来,进行 element-wise 乘即可,其中
notion image
代码如下:

loss

loss 包括两部分,分别是分类分支的 loss 和 mask 分支的 loss。分类 loss 直接使用 FocalLoss,注意这里输出采用的是 sigmoid 激活。总 loss 为:
mask 分支 loss 如下:
值得注意的是,mask 分支的 loss 仅仅在 ( 为 target 在位置 的分类标签)。可见在没有分配到的目标的输出层,是不计算 loss 的,既该层被当做忽略样本。
对于 作者尝试了 BCE、FocalLoss 以及 Dice loss(DL),发现 DL 优于 FL 和 BCE。 Dice loss 会侧向于对正样本的挖掘,之前的文章做过深入的分析。mask 的 loss 代码如下:

预测过程

因此整个预测的过程为:
  1. 提取所有分类分支的预测概率值,并利用阈值(例如 0.1)进行过滤;
  1. 获取过滤后剩下的分类位置对应的 索引;
  1. 分支 通道和 分支 通道利用 element-wise 相乘的方式获取该类别的 mask;
  1. 利用阈值(例如 0.5)对 mask 进行筛选;
  1. 对所有 mask 进行 nms;
  1. 将最终 mask 缩放到原图大小。

实验

notion image
notion image

solo v2

v2 在 v1 的基础上进行改进,其网格设计、正负样本分配策略、CoordConv、loss 等操作完全继承与 V1。主要区别有以下两点:
  1. 继续优化改进了 mask 输出的 head,利用动态的方式获取;
  1. 提出了 Matrix NMS,可以更快速的进行 mask 的 NMS;

动态 mask head

v1 采用的是 Decoupled head 的方式,分别预测 X 分支和 Y 分支,使用的时候再进行 element-wise 相乘。v2 继续进行了优化,提出了 dynamic head。如下图,mask 预测分为了 kernel 分支和 feature 分支。
notion image

feature 分支:

直接将 FPN 的输出进行融合为一个 tensor,融合的方式为卷积 + 上采样来保证所有层尺寸相同,最终为输入图片 1/4 大小。值得注意的是在 FPN 最小输出层的处理上,同样利用了 CoordConv 来保证位置编码被输入进行。融合方式如下:
notion image

kernel 分支:

kernel 分别直接来自 FPN 每个分支,和 FPN 的数目是对应上的。因此对于每一个 FPN 分支来说:
对于最终每一个 的 tensor,可以理解为有 个卷积核,分别提取对应位置的 mask。计算 loss 的时候,只需要根据 target 分配的位置,从 个卷积核中提取对应的 tensor 作为卷积核对 feature 进行 的卷积操作,该 卷积的输入通道为 ,输出 个通道的 mask。预测过程中,只需要将经过阈值过滤的类别得分对应的位置提取卷积核进行卷积提取 mask 操作既可,提高了运算的速度。
如果想要使用 卷积,那么就需要每个卷积核拥有 个参数。

Matrix NMS

文章提出了 Matrix NMS,可以理解为:Matrix NMS 结合 soft NMS 、 Fast NMS ,并实现对 mask 求 IOU。这里分别回顾一下这三种技术:
soft NMS:NMS 改进之一,为了防止 IOU 较大且非虚检的预测被删掉,来自论文《Improving Object Detection With One Line of Code》。传统的 NMS 将 IOU 大于阈值的检测框直接删掉,而 soft NMS 将 IOU 大于阈值框得分做了惩罚,惩罚分为线性惩罚和高斯惩罚两种。 当所有 box 经过惩罚修正后,再利用阈值对 box 进行过滤。代码解析如下:
Fast NMS: NMS 改进之一,目的是为了提速,来自论文 YOLACT。由于 IOU 计算具有对称性,即
因此该方法是利用 triu 函数对 IOU 矩阵进行上三角化,然后对 IOU Matrix 执行按列取最大值操作,再抑制 IOU 大于阈值的 box。代码如下:
mask 求 IOU:由于 box 求 IOU 比较简单,这里不再给出。而 mask 求 IOU,会比 box 复杂,也更耗时,这里给出直接求出 IOU matrix 的方式。
本文中提出了 Matrix NMS,使用并行的矩阵运算单次地实现 NMS,不需要多次迭代。Matrix NMS 可以做到在不到 1ms 的时间里处理 500 张 mask,并且比目前最快的 Faster NMS 要高 0.4% AP。论文给出的伪代码如下:
notion image

预测过程

预测过程和 v1 类似,主要区别是 v2 提取 mask 的利用分类分支对应的卷积核,对特征图进行卷积求 mask。另外,获取得到的所有 mask 进行 Matrix NMS 合并重复的 mask。

实验

notion image
 
notion image
 

© Lazurite 2021 - 2024