实例分割主要有两大类别,而这两大类方法都不够直接。
- 自上而下即detect-then-segment:太依赖于目标检测的准确率
- 自下而上:为每个像素学习一个嵌入向量(有点像Cornernet),该方法依赖于每个像素的嵌入学习和分组后处理。
出发点:一张图片中的实例基本的不同是什么?要么具有不同的中心点,要么具有不同的大小。所以是否可以直接利用这两个信息去区分实例?
实现:引入”实例类别“,也就是量化的中心点位置和物体大小,根据实例的位置和大小为实例中的每个像素分配类别。
- 中心点位置
一张图片可以被分为 个网格,所以定义 个中心点位置类别。将这些类别加在通道上,对应的通道负责对应网格的实例掩码。 - 大小
利用FPN来预测多种尺度大小的实例。
相关工作
Top-down
基于检测的方法
- FCIS:将RPN生成的ROIs和位置敏感分数图结合在一起
- Mask R-CNN:给Faster R-CNN添加了分支
- PANet:在Mask R-CNN的基础上增强了特征表示来提高精度
- Mask Scoring R-CNN:添加了mask-IoU分支去估计mask的质量并且打分去提高精度
- TensorMask:在给定的滑动窗口里分割。
缺点:太依赖于anchor
Bottom-up
基于语义分割的方法
- SGN将实例分割问题分解为一系列子分组问题。
- SSAP学习像素对的亲和力金字塔,即两个像素属于同一实例的概率,并通过级联图分区顺序生成实例。
缺点:精度不高,需要分组后处理
Direct
没有直接利用mask annotations进行训练,也没有直接预测实例mask和类别。
- AdaptIS
- PolarMask
模型结构
上图所示是简单的一个框架,并没有FPN。SOLO将实例分割分为两个子任务,类别预测和实例掩码生成,将一张图片划分为
个网格,如果一个物体的质心落在某个网格(若有多个物体落在该网格?该思路的前提是每个网格必须属于一个实例,因此只有一个类别),那么这个网格有两个任务:
- 预测该物体的类别
- 生成该物体的实例掩码
branch
如下图所示便是两个分支,分别对应上述的两个任务。除了输出卷积,其他卷积都是
,分类分支的Align代表的是自适应性池化、插值或者region-grid插值,这三种的效果都差不多。
对于每一个FPN,后面都会接一个上述的分支结构(SOLO head),从而实现多尺度预测。
加入了FPN后提高了大约8个点,可见作用很大。
对于类别预测分支,当网格 和center region有大于阈值的重叠的则认为是正例。center region定义为 的区域,这里的中心点并不是bbox的中心,而是质心,其中 。这来源于center sampling,在Foveabox和FCOS中都有所体现。对于每个正例都有一个二值的mask,也就是在上分支中标记出正例所在的grid后,找到其所对应下分支 的通道中的一个通道进行标注。
对于Mask分支,之所以有
的通道,就是作者所说的中心点位置类别,第
个网格的instance mask对应第
个通道(
)。
生成mask的分支类似于语义分割,是FCN(全卷积神经网络),具有平移不变性,然而本方法的mask不是直接生成,而是基于网格的位置(
个通道),所以需要平移可变性。
如何解决卷积带来的平移不变性?
借鉴于CoordConv,创建一个与输入相同的空间大小的张量,其中包含像素坐标,这些坐标被标准化至[-1,1],并和原始的输入进行通道上的concat。若原始输入大小为
,则新输入张量的大小为
,其中最后两个通道为
像素坐标,从而提供全局位置信息。
消融实验中,一个的CoordConv能提高3.6的精度,再加反而没必要,可见该操作确实提供了一些位置信息。
损失函数
定义损失函数如下式:
是分类分支的损失函数,用的是Focal Loss。
是mask生成的损失函数,如下式所示:
表示的是正样本的个数(??),
是分类和mask的target,
当
大于0时为1。对于
表示Dice Loss(因为这个损失相比于BCE、focal loss效果更好)。
Inference
前向传播得到类别分数
和相应的mask
,其中
。
首先用置信度阈值0.1过滤掉分数比较低的预测,然后选取前500个排好序的mask进行NMS操作,然后用0.5的阈值进行mask二值化,保留前100个instance mask进行评估。
实验
Decoupled SOLO head
原来的head有
个通道,这计算量还是很大的,并且有实例的网格远远小于没有实例的网格,有些通道没有必要,所以作者提出了Decoupled SOLO head,将通道变为
,减少显存的同时精度也没有降低。