【实例分割】论文详解YOLACT:Real-time Instance Segmentation

news2024/11/16 13:42:48

🏆论文下载:paper

🏆代码下载:code


目录

🏆论文下载:paper

🏆代码下载:code

1.🌷🌷创新点

2.🌷🌷网络结构

2.1🍀🍀Backbone

2.2🍀🍀Protonet

2.3🍀🍀Prediction Head

2.4🍀🍀Masks Assembly

3.🌷🌷结果

3.1🍀🍀prototypes表现

3.2🍀🍀coco结果

4.🌷🌷代码

整理不易,欢迎一键三连!!!

送你们一条美丽的--分割线--


YOLACT是比较经典的one-stage实例分割方法,属于anchor-base流派,即需要anchor计算。

YOLACT:You Only Look ACoefficienTs(系数复数)

摘要:我们提出了一个简单的用于实时实例分割的全卷积模型,在 MS COCO上实现了 29.8 mAP,在单个 Titan Xp 上达到 33.5 fps ,比以前任何竞争方法都要快得多。
此外,我们仅在一个训练后就得到了这个结果图形处理器。 我们通过将实例分割分成两个并行子任务来实现这一点:(1)生成一组原型掩码和(2)预测每个实例掩码系数。 然后,我们通过将原型与掩码系数线性组合来生成实例掩码。 我们发现因为这个过程不依赖于重新池化,所以这种方法可以产生非常高质量的掩模,并且免费表现出时间稳定性。 此外,我们分析了模型的出色表现,虽然是全卷积的,但是它们学会以翻译变体方式自行本地化实例。 最后,我们还提出了快速 NMS,它是标准 NMS 的快 12 毫秒的替代品,但仅有边际性能损失。

1.🌷🌷创新点

  • 针对实例分割任务提出了一种简单的全卷积模型;

  • 这个模型在COCO数据集用一块Titan Xp完成了29.8mAP和33.5fps的实时分割效果;

  • 将任务分为两个平行的子任务。产生prototype masks和预测mask coefficients;

    • prototype masks
      卷积层:在提取空间相关信息上效果显著。

    • mask coefficients
      全连接层:在获取语义向量上效果显著。

  • 利用矩阵计算对NMS进行加速

2.🌷🌷网络结构

左侧(prototypes):蓝(低值)黄(高值)

中间(NMS/CROP/THRESHOLD):灰(没有训练的函数)

网络结构:RetinaNet ResNet-101+FPN

2.1🍀🍀Backbone

        采用卷积神经网络(例如ResNet101)做特征提取,然后将提取到的特征输入到特征金字塔网络中进行不同层级特征提取。ResNet的网络结构如图所示。从图中可以看出,ResNet的卷积模块一共有5个从conv1,conv2_x到conv5_x,分别对应图1 YOLACT模型中的C1-C5,然后将提取到的特征输入到特征金字塔网络中。YOLACT采用了多尺度的特征图, 从而可以检测到不同尺寸的物体,也就是在大的特征图上检测小的物体,在小的特征图上检测大的物体。

* 特征金字塔模块的主要作用是获取深度更深的特征图,且含有多个不同尺度的特征图。

2.2🍀🍀Protonet

        Protonet模块通过卷积和上采样获得Prototypes,Prototypes是多张mask的,mask中的亮(值大)的区域就是目标区域。最终通过线性组合生成的mask来获取每个实例的mask。

2.3🍀🍀Prediction Head

        预测头在RetinaNet的基础上多回归了一个mask系数,输出预测框Bbox,类别信息conf以及掩码系数。利用此系数与Protonet中的mask线性组合。YOLACT利用特征金字塔中的特征图(5个尺度)每个特征图的每个点都生成3个目标框,为了避免太多冗余目标框,使用NMS非极大值抑制来进行目标框筛选。

2.4🍀🍀Masks Assembly

        利用Prediction Head模块的mask系数与Protonet中的多张mask进行线性组合,每个目标得到一张mask。

损失函数:Lmask = BCE(M, Mgt)

3.🌷🌷结果

3.1🍀🍀prototypes表现

3.2🍀🍀coco结果

4.🌷🌷代码

        YOLACT类的定义:

class Yolact(nn.Module):
    """
    You can set the arguments by changing them in the backbone config object in config.py.

    Parameters (in cfg.backbone):
        - selected_layers: The indices of the conv layers to use for prediction.
        - pred_scales:     A list with len(selected_layers) containing tuples of scales (see PredictionModule)
        - pred_aspect_ratios: A list of lists of aspect ratios with len(selected_layers) (see PredictionModule)
    """

    def __init__(self):
        super().__init__()

        self.backbone = construct_backbone(cfg.backbone)

        if cfg.freeze_bn:
            self.freeze_bn()

        # Compute mask_dim here and add it back to the config. Make sure Yolact's constructor is called early!
        if cfg.mask_type == mask_type.direct:
            cfg.mask_dim = cfg.mask_size**2
        elif cfg.mask_type == mask_type.lincomb:
            if cfg.mask_proto_use_grid:
                self.grid = torch.Tensor(np.load(cfg.mask_proto_grid_file))
                self.num_grids = self.grid.size(0)
            else:
                self.num_grids = 0

            self.proto_src = cfg.mask_proto_src
            
            if self.proto_src is None: in_channels = 3
            elif cfg.fpn is not None: in_channels = cfg.fpn.num_features
            else: in_channels = self.backbone.channels[self.proto_src]
            in_channels += self.num_grids

            # The include_last_relu=false here is because we might want to change it to another function
            self.proto_net, cfg.mask_dim = make_net(in_channels, cfg.mask_proto_net, include_last_relu=False)

            if cfg.mask_proto_bias:
                cfg.mask_dim += 1


        self.selected_layers = cfg.backbone.selected_layers
        src_channels = self.backbone.channels

        if cfg.use_maskiou:
            self.maskiou_net = FastMaskIoUNet()

        if cfg.fpn is not None:
            # Some hacky rewiring to accomodate the FPN
            self.fpn = FPN([src_channels[i] for i in self.selected_layers])
            self.selected_layers = list(range(len(self.selected_layers) + cfg.fpn.num_downsample))
            src_channels = [cfg.fpn.num_features] * len(self.selected_layers)


        self.prediction_layers = nn.ModuleList()
        cfg.num_heads = len(self.selected_layers)

        for idx, layer_idx in enumerate(self.selected_layers):
            # If we're sharing prediction module weights, have every module's parent be the first one
            parent = None
            if cfg.share_prediction_module and idx > 0:
                parent = self.prediction_layers[0]

            pred = PredictionModule(src_channels[layer_idx], src_channels[layer_idx],
                                    aspect_ratios = cfg.backbone.pred_aspect_ratios[idx],
                                    scales        = cfg.backbone.pred_scales[idx],
                                    parent        = parent,
                                    index         = idx)
            self.prediction_layers.append(pred)

        # Extra parameters for the extra losses
        if cfg.use_class_existence_loss:
            # This comes from the smallest layer selected
            # Also note that cfg.num_classes includes background
            self.class_existence_fc = nn.Linear(src_channels[-1], cfg.num_classes - 1)
        
        if cfg.use_semantic_segmentation_loss:
            self.semantic_seg_conv = nn.Conv2d(src_channels[0], cfg.num_classes-1, kernel_size=1)

        # For use in evaluation
        self.detect = Detect(cfg.num_classes, bkg_label=0, top_k=cfg.nms_top_k,
            conf_thresh=cfg.nms_conf_thresh, nms_thresh=cfg.nms_thresh)

    def save_weights(self, path):
        """ Saves the model's weights using compression because the file sizes were getting too big. """
        torch.save(self.state_dict(), path)
    
    def load_weights(self, path):
        """ Loads weights from a compressed save file. """
        state_dict = torch.load(path)

        # For backward compatability, remove these (the new variable is called layers)
        for key in list(state_dict.keys()):
            if key.startswith('backbone.layer') and not key.startswith('backbone.layers'):
                del state_dict[key]
        
            # Also for backward compatibility with v1.0 weights, do this check
            if key.startswith('fpn.downsample_layers.'):
                if cfg.fpn is not None and int(key.split('.')[2]) >= cfg.fpn.num_downsample:
                    del state_dict[key]
        self.load_state_dict(state_dict)

    def init_weights(self, backbone_path):
        """ Initialize weights for training. """
        # Initialize the backbone with the pretrained weights.
        self.backbone.init_backbone(backbone_path)

        conv_constants = getattr(nn.Conv2d(1, 1, 1), '__constants__')
        
        # Quick lambda to test if one list contains the other
        def all_in(x, y):
            for _x in x:
                if _x not in y:
                    return False
            return True

        # Initialize the rest of the conv layers with xavier
        for name, module in self.named_modules():
            # See issue #127 for why we need such a complicated condition if the module is a WeakScriptModuleProxy
            # Broke in 1.3 (see issue #175), WeakScriptModuleProxy was turned into just ScriptModule.
            # Broke in 1.4 (see issue #292), where RecursiveScriptModule is the new star of the show.
            # Note that this might break with future pytorch updates, so let me know if it does
            is_script_conv = False
            if 'Script' in type(module).__name__:
                # 1.4 workaround: now there's an original_name member so just use that
                if hasattr(module, 'original_name'):
                    is_script_conv = 'Conv' in module.original_name
                # 1.3 workaround: check if this has the same constants as a conv module
                else:
                    is_script_conv = (
                        all_in(module.__dict__['_constants_set'], conv_constants)
                        and all_in(conv_constants, module.__dict__['_constants_set']))
            
            is_conv_layer = isinstance(module, nn.Conv2d) or is_script_conv

            if is_conv_layer and module not in self.backbone.backbone_modules:
                nn.init.xavier_uniform_(module.weight.data)

                if module.bias is not None:
                    if cfg.use_focal_loss and 'conf_layer' in name:
                        if not cfg.use_sigmoid_focal_loss:
                            # Initialize the last layer as in the focal loss paper.
                            # Because we use softmax and not sigmoid, I had to derive an alternate expression
                            # on a notecard. Define pi to be the probability of outputting a foreground detection.
                            # Then let z = sum(exp(x)) - exp(x_0). Finally let c be the number of foreground classes.
                            # Chugging through the math, this gives us
                            #   x_0 = log(z * (1 - pi) / pi)    where 0 is the background class
                            #   x_i = log(z / c)                for all i > 0
                            # For simplicity (and because we have a degree of freedom here), set z = 1. Then we have
                            #   x_0 =  log((1 - pi) / pi)       note: don't split up the log for numerical stability
                            #   x_i = -log(c)                   for all i > 0
                            module.bias.data[0]  = np.log((1 - cfg.focal_loss_init_pi) / cfg.focal_loss_init_pi)
                            module.bias.data[1:] = -np.log(module.bias.size(0) - 1)
                        else:
                            module.bias.data[0]  = -np.log(cfg.focal_loss_init_pi / (1 - cfg.focal_loss_init_pi))
                            module.bias.data[1:] = -np.log((1 - cfg.focal_loss_init_pi) / cfg.focal_loss_init_pi)
                    else:
                        module.bias.data.zero_()
    
    def train(self, mode=True):
        super().train(mode)

        if cfg.freeze_bn:
            self.freeze_bn()

    def freeze_bn(self, enable=False):
        """ Adapted from https://discuss.pytorch.org/t/how-to-train-with-frozen-batchnorm/12106/8 """
        for module in self.modules():
            if isinstance(module, nn.BatchNorm2d):
                module.train() if enable else module.eval()

                module.weight.requires_grad = enable
                module.bias.requires_grad = enable
    
    def forward(self, x):
        """ The input should be of size [batch_size, 3, img_h, img_w] """
        _, _, img_h, img_w = x.size()
        cfg._tmp_img_h = img_h
        cfg._tmp_img_w = img_w
        
        with timer.env('backbone'):
            outs = self.backbone(x)

        if cfg.fpn is not None:
            with timer.env('fpn'):
                # Use backbone.selected_layers because we overwrote self.selected_layers
                outs = [outs[i] for i in cfg.backbone.selected_layers]
                outs = self.fpn(outs)

        proto_out = None
        if cfg.mask_type == mask_type.lincomb and cfg.eval_mask_branch:
            with timer.env('proto'):
                proto_x = x if self.proto_src is None else outs[self.proto_src]
                
                if self.num_grids > 0:
                    grids = self.grid.repeat(proto_x.size(0), 1, 1, 1)
                    proto_x = torch.cat([proto_x, grids], dim=1)

                proto_out = self.proto_net(proto_x)
                proto_out = cfg.mask_proto_prototype_activation(proto_out)

                if cfg.mask_proto_prototypes_as_features:
                    # Clone here because we don't want to permute this, though idk if contiguous makes this unnecessary
                    proto_downsampled = proto_out.clone()

                    if cfg.mask_proto_prototypes_as_features_no_grad:
                        proto_downsampled = proto_out.detach()
                
                # Move the features last so the multiplication is easy
                proto_out = proto_out.permute(0, 2, 3, 1).contiguous()

                if cfg.mask_proto_bias:
                    bias_shape = [x for x in proto_out.size()]
                    bias_shape[-1] = 1
                    proto_out = torch.cat([proto_out, torch.ones(*bias_shape)], -1)


        with timer.env('pred_heads'):
            pred_outs = { 'loc': [], 'conf': [], 'mask': [], 'priors': [] }

            if cfg.use_mask_scoring:
                pred_outs['score'] = []

            if cfg.use_instance_coeff:
                pred_outs['inst'] = []
            
            for idx, pred_layer in zip(self.selected_layers, self.prediction_layers):
                pred_x = outs[idx]

                if cfg.mask_type == mask_type.lincomb and cfg.mask_proto_prototypes_as_features:
                    # Scale the prototypes down to the current prediction layer's size and add it as inputs
                    proto_downsampled = F.interpolate(proto_downsampled, size=outs[idx].size()[2:], mode='bilinear', align_corners=False)
                    pred_x = torch.cat([pred_x, proto_downsampled], dim=1)

                # A hack for the way dataparallel works
                if cfg.share_prediction_module and pred_layer is not self.prediction_layers[0]:
                    pred_layer.parent = [self.prediction_layers[0]]

                p = pred_layer(pred_x)
                
                for k, v in p.items():
                    pred_outs[k].append(v)

        for k, v in pred_outs.items():
            pred_outs[k] = torch.cat(v, -2)

        if proto_out is not None:
            pred_outs['proto'] = proto_out

        if self.training:
            # For the extra loss functions
            if cfg.use_class_existence_loss:
                pred_outs['classes'] = self.class_existence_fc(outs[-1].mean(dim=(2, 3)))

            if cfg.use_semantic_segmentation_loss:
                pred_outs['segm'] = self.semantic_seg_conv(outs[0])

            return pred_outs
        else:
            if cfg.use_mask_scoring:
                pred_outs['score'] = torch.sigmoid(pred_outs['score'])

            if cfg.use_focal_loss:
                if cfg.use_sigmoid_focal_loss:
                    # Note: even though conf[0] exists, this mode doesn't train it so don't use it
                    pred_outs['conf'] = torch.sigmoid(pred_outs['conf'])
                    if cfg.use_mask_scoring:
                        pred_outs['conf'] *= pred_outs['score']
                elif cfg.use_objectness_score:
                    # See focal_loss_sigmoid in multibox_loss.py for details
                    objectness = torch.sigmoid(pred_outs['conf'][:, :, 0])
                    pred_outs['conf'][:, :, 1:] = objectness[:, :, None] * F.softmax(pred_outs['conf'][:, :, 1:], -1)
                    pred_outs['conf'][:, :, 0 ] = 1 - objectness
                else:
                    pred_outs['conf'] = F.softmax(pred_outs['conf'], -1)
            else:

                if cfg.use_objectness_score:
                    objectness = torch.sigmoid(pred_outs['conf'][:, :, 0])
                    
                    pred_outs['conf'][:, :, 1:] = (objectness > 0.10)[..., None] \
                        * F.softmax(pred_outs['conf'][:, :, 1:], dim=-1)
                    
                else:
                    pred_outs['conf'] = F.softmax(pred_outs['conf'], -1)

            return self.detect(pred_outs, self)

整理不易,欢迎一键三连!!!


送你们一条美丽的--分割线--

🌷🌷🍀🍀🌾🌾🍓🍓🍂🍂🙋🙋🐸🐸🙋🙋💖💖🍌🍌🔔🔔🍉🍉🍭🍭🍋🍋🍇🍇🏆🏆📸📸⛵⛵⭐⭐🍎🍎👍👍🌷🌷

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1012452.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构——顺序表】线性表很难嘛?这篇文章能让你轻松掌握顺序表

线性表 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…。线性表在逻辑上是线性结构,也就是说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通…

创建一个简单的外卖订餐系统

在今天的快节奏生活中,外卖订餐系统已经成为了人们日常生活中不可或缺的一部分。这些系统通过在线点餐和配送服务,为用户提供了便捷的用餐体验。在本文中,我们将创建一个简单的外卖订餐系统,使用Python和Flask框架构建后端&#x…

浅析安防监控系统/AI视频智能分析算法:河道水文水位超标算法应用

传统的水位水尺刻度尺位监测中,所采用的人工读数方式,效率较为低下且 人工成本较高,不利于作业流程的数字化。尽管感应器检测会自动对水位的模拟输入进行筛选,但是由于成本、使用场景要求高、后续日常维护复杂等多种因素&#xff…

电脑文件找回怎么做?文件恢复,就用这3招!

“着急!大家伙有什么比较简单的电脑文件找回方法吗?我对电脑不太熟悉,在操作的时候有些文件不知道是被删除了还是丢失了,现在非常需要找回这些丢失的文件!” 其实,在使用电脑的过程中,很多电脑用…

学Python的漫画漫步进阶 -- 第十二步

学Python的漫画漫步进阶 -- 第十二步 十二、文件读写12.1 打开文件12.2 关闭文件12.2.1 在finally代码块中关闭文件12.2.2 在with as代码块中关闭文件 12.3 读写文本文件12.4 动动手——复制文本文件12.5 读写二进制文件12.6 动动手——复制二进制文件12.7 练一练12.8 文件读写…

万物目标识别——Detic使用图像级别的监督信号来进行目标检测模型推理(C++/Python)

一、目标识别 1.1 传统目标识别算法 传统目标检测通常将分类(确定物体属于哪个类别)和定位(确定物体的位置,通常使用边界框bbox表示)任务耦合在一起。这要求训练数据集中包含每个物体的类别标签以及其对应的bbox位置…

【Proteus仿真】【STM32单片机】智能手环

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 系统运行后,OLED显示温度、心率、加速度极其阈值; 可按下K3键进入阈值设置模式,K1和K2调节对应阈值,K4确定;当检测体温、心率、加速度超出阈值范…

通讯协议介绍CoAP 协议解析

目录 1 通讯协议 2 TCP/IP 网络模型 2.1 TCP协议 2.1.1 TCP 连接过程 2.1.2 TCP 断开连接 2.1.3 TCP协议特点 2.2 UDP协议 2.2.1 UDP 协议特点 3 应用层协议简介 3.1 HTTP 协议 3.2 CoAP 协议 3.3 MQTT 协议 4 CoAP 协议详解 4.1 REST 风格 4.2 CoAP 首部分析 4…

网店怎么进行有效推广?可以试试软文推广

商家在为自己的网店制定推广方案时,不管是从渠道、手段、客户群体哪个方面出发都会面临挑战。传统推广方式成本过高,而宣传效果不一定明显,我们可以试试利用软文推广,成本较低而且推广效果明显。接下来媒介盒子就告诉大家&#xf…

四川玖璨电子商务有限公司:短视频运营理解

短视频运营是一种通过策划、执行和管理短视频内容以达到品牌目标的一项工作。在如今面临信息爆炸的时代,短视频已经成为了吸引用户注意力的一种重要方式。作为一种新兴媒体形式,短视频拥有跨时空、生动有趣、内容丰富的特点,因此得到了越来越…

智能遥测终端机RTU的好处介绍

智能遥测终端机RTU是一种具有高度智能化复合功能的遥测装置,它通过数据采集、通信传输和自动控制等技术,实现对被监测系统的远程监控、数据分析、故障诊断和远程控制。它在工业自动化领域的广泛应用,给自动化程度的提高、成本的下降和生产效率…

Linux 内存泄漏检测的基本原理

一、mtrace分析内存泄露 mtrace(memory trace),是 GNU Glibc 自带的内存问题检测工具,它可以用来协助定位内存泄露问题。 它的实现源码在glibc源码的malloc目录下,其基本设计原理为设计一个函数 void mtrace ()&…

开学季ipad手写笔哪款好?平价电容笔牌子排行

随着新学期的临近,随着Apple Pencil的火爆,出现了很多新款的平板电脑的电容笔,也开始在国内上市,有些是品质很高,有些是价位很实惠,而且大部分人都能接受。但是,也存在不少性价比很低的产品。本…

uniapp-video自定义视频封面

uniapp官方文档&#xff1a;video | uni-app官网uni-app,uniCloud,serverlesshttps://uniapp.dcloud.net.cn/uni-app-x/component/video.html#video 主要使用到的是poster属性&#xff0c;详细属性可点击上方api进行查看 <video id"myVideo" class"xwlogo&q…

Go基础语法:概述

概述 1 背景 产生原因 Go是Google开发的一种静态、强类型、编译型、并发型&#xff0c;并具有垃圾回收功能的类C编程语言。2009以开源项目的形式发布&#xff0c;2012年发布1.0稳定版本&#xff0c;距今已经十年了。 Go语言之父Pike提到&#xff1a;Go语言是以C为原型&…

Kubernetes源码阅读环境搭建

参考博文&#xff1a;Kubernetes 源码剖析-环境准备 安装Go语言 wget https://studygolang.com/dl/golang/go1.14.10.linux-amd64.tar.gz下载源代码 mkdir /goinstall创建一个存放go语言的编译器等组件存放的目录。 tar -zxf go1.14.10.linux-amd64.tar.gz -C /goinstall…

Vulhub靶场环境搭建

在Ubantu系统上搭建靶场环境 一、ubantu系统准备 1.更新安装列表 sudo apt-get update 2.安装docker.io sudo apt install docker.io 查看是否安装成功 docker -v 3.安装pip 检查pip是否安装 pip -V 安装pip apt install python3-pip 或者 apt install pip 再次检查pip…

Arcgis提取点数据经纬度

Arcgis提取点数据经纬度 现已打开tiff影像和采样点的shape文件。目标是提取采样点的经纬度信息然后导出。 打开数据管理工具-要素-添加XY坐标 在点的图层上右击打开属性表时&#xff0c;经纬度信息已经添加到属性表中。 在属性表的左上角中点击导出&#xff0c;导出为文本文…

SpringMVC之自定义注解

目录 一.什么是Java注解 1.简介 2.注解的分类 3.JDK元注解 二.自定义注解 1.自定义注解的分类 1.1.标记Annotation: 1.2.元数据Annotation: 2.如何使用自定义注解 3.案例演示 3.1 获取类、方法及属性上的注解值 3.2Inherited 的使用 3.3获取类属性上的注解属性值 3.…

模电课设:用Multisim设计和分析差分放大电路

1 课设内容 1&#xff09;设计一个差分放大器电路&#xff1b; 2&#xff09;用电流源替换发射极电阻&#xff0c;看看会发生什么&#xff1f; 3&#xff09;差分放大器电路特性之差模传输特性。 2 模型搭建 1&#xff09;设计一个差分放大器电路。 差分放大器电路是由对称…