实例分割--CondInst论文分享

举报
yd_270793839 发表于 2023/04/13 10:00:43 2023/04/13
【摘要】 论文Conditional Convolutions for Instance Segmentation代码aim-uofa/AdelaiDet 写在前面论文出自沈春华团队,精品文章值得推荐。目前现有的实例分割方法主要有两类,一类是以Mask RCNN为代表的使用检测器+roi+mask head的方法,通过先检测,提取roi特征再前背景分割的方式获得实例级的分割结果, 这类方法需要分别对每...

论文Conditional Convolutions for Instance Segmentation
代码aim-uofa/AdelaiDet

写在前面

论文出自沈春华团队,精品文章值得推荐。目前现有的实例分割方法主要有两类,一类是以Mask RCNN为代表的使用检测器+roi+mask head的方法,通过先检测,提取roi特征再前背景分割的方式获得实例级的分割结果, 这类方法需要分别对每个物体提取特征,然后逐个通过mask head进行前背景分割,速度比较慢。 另一类是先采用语义分割获得每类的mask, 然后在在分割的mask上采用类似聚类的后处理方式获得每类的不同实例,后处理非常复杂、速度慢,针对遮挡、重叠等问题存在天然缺陷。 实例分割相比于检测的难点在于每个实例的大小不同, 而不能向检测那样直接回归一个固定长度的向量来确定目标。实例分割相比于语义分割的难点在于每个图片实例的个数不确定, 因此不能采用固定通道的mask在原图上直接分割出不同实例。CondInst针对这些困难,从一个新的角度解决实例分割问题, 其核心思想在于以实例为条件,动态的为每个实例生成一个mask head,然后使用生成的mask head在feature map上获得不同实例的分割结果。CondInst具有两个优点:1)通过全卷积网络解决了实例分割,无需进行ROI裁剪和特征对齐。2)由于动态生成的条件卷积的容量大大提高,因此mask head可以非常紧凑(例如3个卷积层,每个仅具有8个通道),从而可以显着加快推理速度。 在COCO数据集上, 性能优于Mask R-CNN。

##亮点
1、CondInst是完全由卷积组成的,并且不依赖于ROI操作。无需调整特征图的大小即可获得具有更高精确度的高分辨率实例mask。

2、与以前的方法不同,CondInst的mask head中的卷积会动态生成并以实例为条件。由于仅要求卷积预测一个实例的掩码,因此极大地减轻了学习要求,从而减轻了卷积的负载。与边界框检测器FCOS相比,CondInst仅需要多花费约10%的计算时间,甚至可以处理每个图像的最大实例数(即100个实例)

方法流程

CondInst建立在FCOS之上,相比于FCOS有两点差异1).增加了一个Fmask分支,Fmask的特征来自于P3层,拼接了每个位置的相对坐标,作为mask head的输入来生成最终的实例mask。2).在FCOS的检测头上增加了controller head,controller head的输出用作mask head的权重。对于每一个实例, controller head的输出肯定不同, 相当于为每个实例定制了一个mask head,这也是为什么叫做动态mask head的原因,当mask head用于全局的Fmask feature上时,就可以区分这个instance和北京,获得实例级分割结果。这种动态生成卷积核的思想来自于CondConv,将一个网络的输出直接作为卷积核的权重。

##动态mask head
controller是一个普通的卷积网络,它在每个位置预测一个m+k维的向量,m为mask head中权重的数量,k为mask head中bias的数量, 则将controller的输出可以分解为几组权重和bias,代码如下:

    assert params.dim() == 2
    assert len(weight_nums) == len(bias_nums)
    assert params.size(1) == sum(weight_nums) + sum(bias_nums)

    num_insts = params.size(0)
    num_layers = len(weight_nums)

    params_splits = list(torch.split_with_sizes(
        params, weight_nums + bias_nums, dim=1
    ))

    weight_splits = params_splits[:num_layers]
    bias_splits = params_splits[num_layers:]

    for l in range(num_layers):
        if l < num_layers - 1:
            # out_channels x in_channels x 1 x 1
            weight_splits[l] = weight_splits[l].reshape(num_insts * channels, -1, 1, 1)
            bias_splits[l] = bias_splits[l].reshape(num_insts * channels)
        else:
            # out_channels x in_channels x 1 x 1
            weight_splits[l] = weight_splits[l].reshape(num_insts * 1, -1, 1, 1)
            bias_splits[l] = bias_splits[l].reshape(num_insts)

    return weight_splits, bias_splits

获得权重之后,将其组成mask head,用于Fmask特征上获得每个实例的分割结果,代码如下:

    def mask_heads_forward(self, features, weights, biases, num_insts):
        '''
        :param features
        :param weights: [w0, w1, ...]
        :param bias: [b0, b1, ...]
        :return:
        '''
        assert features.dim() == 4
        n_layers = len(weights)
        x = features
        for i, (w, b) in enumerate(zip(weights, biases)):
            x = F.conv2d(
                x, w, bias=b,
                stride=1, padding=0,
                groups=num_insts
            )
            if i < n_layers - 1:
                x = F.relu(x)
        return x

注意一下,作者子啊代码中选取了置信度比较高的前100 mask head。

Inference

CondInst的inference比较直接,首先是检测部分得到检测的结果,然后采用box-based NMS来去除重复框,最后选出top 100的检测框,只有这部分instances会进行instance mask的预测。由于产生的mask head非常小,所以100个instance的mask预测时间只需要4.5ms,那么CondInst的预测时间仅比原始的FCOS增加了约10%。这里额外要说的一点是CondInst的box预测主要用于NMS,但不会参与instance mask的预测中,而Mask R-CNN是需要box来进行ROI croping。

实验结果

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。