YOLACT : Real-time Instance Segmentation论文解读

好久没写论文解读了。整个6月到7月中旬都在琢磨tensorflow C++的API和生成dll。今天为大家带来一篇实时性的实例分割论文,入选ICCV2019,我认为是一篇相当有水平的工作。在能保证实时性的情况下,某些指标和针对某一种情况,效果居然比二阶段的分割方法还要好,速度是二阶段网络的几十倍吧。如果采用模型剪枝和量化,说不定工业上就能运行实例分割了。


updated on 2019.12.26

yolact已经出了yolact++
项目地址和yolact一致。同一作者。


idea

作者巧妙的将实例分割分为两个子任务:

  • 为每一个anchor生成一系列的蓝本mask(prototype mask)
  • 为每一个anchor预测一系列的mask系数(coefficients),这些系数的长度和上一步一系列蓝本mask的长度一致。就是说,每一个mask对应了一个值(coefficient)。

然后把系数和mask线性组合。就是一个mask和对应的系数相乘,然后所有的mask和系数的乘积求和。形式可以用下面的公式描述。
f i n a l m a s k = ∑ i n m a s k i × c o e f f i c i e n t i final mask = \sum_i^n mask_i \times coefficient_i finalmask=inmaski×coefficienti

和一般做实例分割的方法不一样吗,二阶段的实例分割一般遵循,先找到框,再分割的思路。作者提出的方法,两个子任务是并行的。子任务之间没有联系,并行处理。整个网络是单阶段的。棒!

Method

作者认为,mask具有空间连续性,即相邻的像素很可能被认为是一个类的。单阶段的目标检测算法都是依赖全连接层,(作者估计把1x1的卷积也当做全连接层了)那么就会出现一个问题,FC层的输出是没有空间的连续性的。MaskRcnn等一干算法,通过RePooling(Align,pooling)操作来重新获得空间连续性。但是这样就注定没法得到实时的效果了。作者将实例分割分解为两个子任务,全部都是基于卷积网络,自然不会遇到空间不连续的问题。

在这里插入图片描述
既然有两个子任务,并且前面提到了,两个子任务是并行的,所以整个网络就会有两个大的分支。

  • 其中一个分支,沿着FPN的P3输出到ProtoNet,预测蓝本mask
  • 另一个分支,将FPN的修正,即C5经过两个3x3的stride为2的卷积,作为P7和P6,C5和P5联系。从P7,P6,P5,P4,P3都去预测bbox和score。经过PredictionHead,和NMS输出。

protoNet

这个子网络,预测k个mask,过程就和语义分割完全一致。
在这里插入图片描述
就是一个上采样的过程。卷积层全是3x3的,上采样的过程是先Upsample,然后接conv层。和语义分割不同的是,这个网络不直接参与计算损失函数

mask 的 系数(coefficients)

ProtoNet预测了K个mask,每一个maks都对应一个系数,就是在prediction head分支预测出来。
需要注意的是,这个分支同样需要计算坐标值的回归值(4个),类别概率(c个),mask的系数(k个)。就是说,一个anchor对应4+c+个输出。k个系数要接tanh激活函数

两个分支的聚合(assembly)

predictionHead分支的过程:

  • 每一个anchor对应c+k+4和值,按照score过滤一个anchor,接着NMS继续过滤一些anchor,这些活下来的anchor(论文用surviving)作为系数分支最终的输出。

两个分支的聚合就是简单地线性组合。这一点就是在idea那里提到了,mask*系数 再求和。然后再用sigmoid把值映射到0-1.
在这里插入图片描述
在这里插入图片描述
P是 h × w × k h\times w\times k h×w×k,C是 n × k n\times k n×k,那么M就是 h × w × n h \times w \times n h×w×n,n是预测目标个数,就是活下来的anchor数目。k是mask的数目。我们可以发现,即便是不同的目标(n的index不用),他们使用的mask是一样的。导致分割结果的不同,是因为不同的anchor的k个系数不一样,而通过用系数的线性组合,居然可以得到不同实例的分割图。赞!
作者也说了,本来也有更加复杂的融合方法,但他们就简单地使用了线性组合。

损失函数

bboxes分支和
score分支就用ssd提出的办法,mask分支就用BCE。

cropping mask

由于实例分割的特殊性,一张图有很多目标,如果把这些目标都在原图的大小计算损失函数,大的目标损失函数值之和较大,而小的目标损失函数值之和,因为像素数量不一样嘛,所以再求平均之后(除以像素总数),小目标的梯度相对于大目标就很小了,导致网络可能不重视小目标的分割。为了避免这个问题,作者的办法是:

  • 在训练的时候,得到原图大小的mask,按照ground truth,把各个目标mask都crop出来,计算损失函数,再除以各自crop出来的区域像素总数。
  • 在预测的时候,根据bboxes分支的目标预测框,把mask crop出来,再去和系数做线性组合,然后经过sigmiod和阈值分割。然和按照位置把得到的mask还原回原图位置上。

Mask分支预测的Prototype 起到了什么作用

在这里插入图片描述
作者展示了6个Prototype mask,(k=6),作者发现,每一个mask都有目标的某一部分(partition)很敏感。比如第4个mask,对左下角的目标很敏感;第3个mask对目标的边沿很敏感。通过线性组合,恰好组合形成实例目标的分割结果。

更多的details

不介绍了。不能像以前看论文那么细了,导师催得紧。目前注重方法。不过源码还是要看的。
这部分本该涉及:

  • backbone 经过修改的ResNet101 + FPN结构,anchor也有修改
  • Fast NMS
  • 加入语义分割loss辅助监督
  • 一些缺点,比如mask的泄露(mask不在目标身上),

实验效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里推荐一篇博客写的不错。比我详细

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值