计算机系统应用教程网站

网站首页 > 技术文章 正文

使用mmdetection2.0实现SOLOV2-全新的实例分割框架

btikc 2024-08-30 13:18:47 技术文章 14 ℃ 0 评论

本文介绍 使用mmdetection2.0实现SOLOV2-全新的实例分割框架

笔者近日在做一些实例分割到tensorrt的操作,发现,对于许多二阶段的实例分割算法,转换到另一个推理平台很麻烦,主要是这里面存在RPN的一些操作,即便是类似于CenterMask这样的模型,也需要先获取box,然后经过ROIAlign和ROIPool来得到需要的mask,这个过程不仅计算繁琐,而且很难导出到我们想要的模型格式,比如ONNX就不支持这里面的很多op。当我看到这张图的时候,我发现,SOLOV2的性能似乎比maskrcnn差不多,推理速度只要一半,并且速度和精确度都超过了BlendMask。今天我们就用mmdetection 2.0的版本来实现一个SOLOV2.

就目前来讲,很多实例分割算法存在的问题弊端主要是:

  • 速度太慢了,比如Maskrcnn,虽然声名远扬,但是要把它部署到realtime,还是很困难的;
  • 精度不够,比如Yolact,即便是Yolact++,其精度其实也只能说差强人意,连MaskRCNN都比不上的实力分割,速度再快,也会限制它的使用场景;
  • BlendMask,CenterMask这类的算法,都差不多,基于FCOS构建,本质上没啥区别,还是和MaskRCNN整体流程差不多,只不过检测器变了而已,对于部署来说依旧很麻烦。

当然本文要解决的问题并不是部署问题,而是告诉大家,我们有一个速度更快,精度更好的模型,而且部署相对来说可能更好一点。那么第一步是不是得用python实现一波呢?

SOLOV2

对于SOLO系列算法,具体的来龙去脉就不赘述了。先放一个指标对比:



对于V2来讲,变化最大的可能就是这个动态的mask head:

image-20200611173529266

class SOLOV2Head:
    ....
    def forward(self, feats, eval=False):
            new_feats = self.split_feats(feats)
            featmap_sizes = [featmap.size()[-2:] for featmap in new_feats]
            upsampled_size = (feats[0].shape[-2], feats[0].shape[-3])
            kernel_pred, cate_pred = multi_apply(self.forward_single, new_feats,
                                              list(range(len(self.seg_num_grids))),
                                              eval=eval)
            # add coord for p5
            x_range = torch.linspace(-1, 1, feats[-2].shape[-1], device=feats[-2].device)
            y_range = torch.linspace(-1, 1, feats[-2].shape[-2], device=feats[-2].device)
            y, x = torch.meshgrid(y_range, x_range)
            y = y.expand([feats[-2].shape[0], 1, -1, -1])
            x = x.expand([feats[-2].shape[0], 1, -1, -1])
            coord_feat = torch.cat([x, y], 1)
            feature_add_all_level = self.feature_convs[0](feats[0]) 
            for i in range(1,3):
                feature_add_all_level = feature_add_all_level + self.feature_convs[i](feats[i])
            feature_add_all_level = feature_add_all_level + self.feature_convs[3](torch.cat([feats[3],coord_feat],1))

            feature_pred = self.solo_mask(feature_add_all_level)   
            N, c, h, w = feature_pred.shape
            feature_pred = feature_pred.view(-1, h, w).unsqueeze(0)
            ins_pred = []

            for i in range(5):
                kernel = kernel_pred[i].permute(0,2,3,1).contiguous().view(-1,c).unsqueeze(-1).unsqueeze(-1)
                ins_i = F.conv2d(feature_pred, kernel, groups=N).view(N,self.seg_num_grids[i]**2, h,w)
                if not eval:
                    ins_i = F.interpolate(ins_i, size=(featmap_sizes[i][0]*2,featmap_sizes[i][1]*2), mode='bilinear')
                if eval:
                    ins_i=ins_i.sigmoid()
                ins_pred.append(ins_i)
            return ins_pred, cate_pred

对于mask的head大概可以通过这个实现,(code credit @Epiphqny).

论文中solov2最高可以达到42.6的 AP,我们实际训练下来可以达到接近40 AP的水平,这个水平大大的超越同样backbone的其他实例分割方法。

Results

我们在一些开源的SOLO上,将代码迁移到了mmdetection最新的2.0版本下。最新的测试结果如下:






这个效果总的来说还是非常不错的。我们已经将代码部署到了神力平台,如果你对实例分割感兴趣可以下载我们的code跑一跑

http://t.manaai.cn

http://manaai.cn/aicodes_detail3.html?id=61

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表