实例分割主要有两大类别,而这两大类方法都不够直接。
出发点:一张图片中的实例基本的不同是什么?要么具有不同的中心点,要么具有不同的大小。所以是否可以直接利用这两个信息去区分实例?
实现:引入”实例类别“,也就是量化的中心点位置和物体大小,根据实例的位置和大小为实例中的每个像素分配类别。
Top-down
基于检测的方法
缺点:太依赖于anchor
Bottom-up
基于语义分割的方法
缺点:精度不高,需要分组后处理
Direct
没有直接利用mask annotations进行训练,也没有直接预测实例mask和类别。
上图所示是简单的一个框架,并没有FPN。SOLO将实例分割分为两个子任务,类别预测和实例掩码生成,将一张图片划分为 S × S S\times S S×S个网格,如果一个物体的质心落在某个网格(若有多个物体落在该网格?该思路的前提是每个网格必须属于一个实例,因此只有一个类别),那么这个网格有两个任务:
如下图所示便是两个分支,分别对应上述的两个任务。除了输出卷积,其他卷积都是 3 × 3 3\times 3 3×3,分类分支的Align代表的是自适应性池化、插值或者region-grid插值,这三种的效果都差不多。
对于每一个FPN,后面都会接一个上述的分支结构(SOLO head),从而实现多尺度预测。
加入了FPN后提高了大约8个点,可见作用很大。
对于类别预测分支,当网格 ( i , j ) (i,j) (i,j)和center region有大于阈值的重叠的则认为是正例。center region定义为 ( c x , c y , ϵ w , ϵ h ) (c_x,c_y,\epsilon w,\epsilon h) (cx,cy,ϵw,ϵh)的区域,这里的中心点并不是bbox的中心,而是质心,其中 ϵ = 0.2 \epsilon=0.2 ϵ=0.2。这来源于center sampling,在Foveabox和FCOS中都有所体现。对于每个正例都有一个二值的mask,也就是在上分支中标记出正例所在的grid后,找到其所对应下分支 S 2 S^2 S2的通道中的一个通道进行标注。
对于Mask分支,之所以有 S 2 S^2 S2的通道,就是作者所说的中心点位置类别,第 ( i , j ) (i,j) (i,j)个网格的instance mask对应第 k k k个通道( k = i × S + j k=i\times S+j k=i×S+j )。
生成mask的分支类似于语义分割,是FCN(全卷积神经网络),具有平移不变性,然而本方法的mask不是直接生成,而是基于网格的位置( S 2 S^2 S2个通道),所以需要平移可变性。
如何解决卷积带来的平移不变性?
借鉴于CoordConv,创建一个与输入相同的空间大小的张量,其中包含像素坐标,这些坐标被标准化至[-1,1],并和原始的输入进行通道上的concat。若原始输入大小为 H × W × D H\times W\times D H×W×D,则新输入张量的大小为 H × W × ( D + 2 ) H\times W\times (D+2) H×W×(D+2),其中最后两个通道为 x y xy xy像素坐标,从而提供全局位置信息。
消融实验中,一个的CoordConv能提高3.6的精度,再加反而没必要,可见该操作确实提供了一些位置信息。
定义损失函数如下式:
L = L c a t e + λ L m a s k L = L_{cate}+\lambda L_{mask} L=Lcate+λLmask
L c a t e L_{cate} Lcate是分类分支的损失函数,用的是Focal Loss。
L m a s k L_{mask} Lmask是mask生成的损失函数,如下式所示:
N p o s N_{pos} Npos表示的是正样本的个数(??), p ∗ 和 m ∗ p*和m* p∗和m∗是分类和mask的target, I I II II当 p i , j ∗ p_{i,j}^* pi,j∗大于0时为1。对于 d m a s k d_{mask} dmask表示Dice Loss(因为这个损失相比于BCE、focal loss效果更好)。
L D i c e = 1 − D ( p , q ) L_{Dice}=1-D(p,q) LDice=1−D(p,q)
前向传播得到类别分数 p i , j p_{i,j} pi,j和相应的mask m k m_k mk,其中 k = i ∗ S + j k=i*S+j k=i∗S+j。
首先用置信度阈值0.1过滤掉分数比较低的预测,然后选取前500个排好序的mask进行NMS操作,然后用0.5的阈值进行mask二值化,保留前100个instance mask进行评估。
原来的head有 S 2 S^2 S2个通道,这计算量还是很大的,并且有实例的网格远远小于没有实例的网格,有些通道没有必要,所以作者提出了Decoupled SOLO head,将通道变为 S + S S+S S+S,减少显存的同时精度也没有降低。