精华内容
下载资源
问答
  • 附代码 SegNet
    2022-02-18 12:18:57

    参考链接:https://blog.csdn.net/zhuzemin45/article/details/79709874
    代码链接:https://github.com/delta-onera/segnet_pytorch/blob/master/segnet.py

    SegNet和FCN,DeConv思路十分相似,只是Encoder,Decoder(Upsampling)使用的技术不一致。此外SegNet的编码器部分使用的是VGG16的前13层卷积网络,每个编码器层都对应一个解码器层,最终解码器的输出被送入soft-max分类器以独立的为每个像素产生类概率。上采样处采用了Unpool进行上采样。

    在这里插入图片描述

    代码:

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    from collections import OrderedDict
    
    class SegNet(nn.Module):
        def __init__(self,input_nbr,label_nbr):
            super(SegNet, self).__init__()
    
            batchNorm_momentum = 0.1
    
            self.conv11 = nn.Conv2d(input_nbr, 64, kernel_size=3, padding=1)
            self.bn11 = nn.BatchNorm2d(64, momentum= batchNorm_momentum)
            self.conv12 = nn.Conv2d(64, 64, kernel_size=3, padding=1)
            self.bn12 = nn.BatchNorm2d(64, momentum= batchNorm_momentum)
    
            self.conv21 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
            self.bn21 = nn.BatchNorm2d(128, momentum= batchNorm_momentum)
            self.conv22 = nn.Conv2d(128, 128, kernel_size=3, padding=1)
            self.bn22 = nn.BatchNorm2d(128, momentum= batchNorm_momentum)
    
            self.conv31 = nn.Conv2d(128, 256, kernel_size=3, padding=1)
            self.bn31 = nn.BatchNorm2d(256, momentum= batchNorm_momentum)
            self.conv32 = nn.Conv2d(256, 256, kernel_size=3, padding=1)
            self.bn32 = nn.BatchNorm2d(256, momentum= batchNorm_momentum)
            self.conv33 = nn.Conv2d(256, 256, kernel_size=3, padding=1)
            self.bn33 = nn.BatchNorm2d(256, momentum= batchNorm_momentum)
    
            self.conv41 = nn.Conv2d(256, 512, kernel_size=3, padding=1)
            self.bn41 = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
            self.conv42 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn42 = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
            self.conv43 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn43 = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
    
            self.conv51 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn51 = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
            self.conv52 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn52 = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
            self.conv53 = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn53 = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
    
            self.conv53d = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn53d = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
            self.conv52d = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn52d = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
            self.conv51d = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn51d = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
    
            self.conv43d = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn43d = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
            self.conv42d = nn.Conv2d(512, 512, kernel_size=3, padding=1)
            self.bn42d = nn.BatchNorm2d(512, momentum= batchNorm_momentum)
            self.conv41d = nn.Conv2d(512, 256, kernel_size=3, padding=1)
            self.bn41d = nn.BatchNorm2d(256, momentum= batchNorm_momentum)
    
            self.conv33d = nn.Conv2d(256, 256, kernel_size=3, padding=1)
            self.bn33d = nn.BatchNorm2d(256, momentum= batchNorm_momentum)
            self.conv32d = nn.Conv2d(256, 256, kernel_size=3, padding=1)
            self.bn32d = nn.BatchNorm2d(256, momentum= batchNorm_momentum)
            self.conv31d = nn.Conv2d(256,  128, kernel_size=3, padding=1)
            self.bn31d = nn.BatchNorm2d(128, momentum= batchNorm_momentum)
    
            self.conv22d = nn.Conv2d(128, 128, kernel_size=3, padding=1)
            self.bn22d = nn.BatchNorm2d(128, momentum= batchNorm_momentum)
            self.conv21d = nn.Conv2d(128, 64, kernel_size=3, padding=1)
            self.bn21d = nn.BatchNorm2d(64, momentum= batchNorm_momentum)
    
            self.conv12d = nn.Conv2d(64, 64, kernel_size=3, padding=1)
            self.bn12d = nn.BatchNorm2d(64, momentum= batchNorm_momentum)
            self.conv11d = nn.Conv2d(64, label_nbr, kernel_size=3, padding=1)
    
    
        def forward(self, x):
    
            # Stage 1
            x11 = F.relu(self.bn11(self.conv11(x)))
            x12 = F.relu(self.bn12(self.conv12(x11)))
            x1p, id1 = F.max_pool2d(x12,kernel_size=2, stride=2,return_indices=True)
    
            # Stage 2
            x21 = F.relu(self.bn21(self.conv21(x1p)))
            x22 = F.relu(self.bn22(self.conv22(x21)))
            x2p, id2 = F.max_pool2d(x22,kernel_size=2, stride=2,return_indices=True)
    
            # Stage 3
            x31 = F.relu(self.bn31(self.conv31(x2p)))
            x32 = F.relu(self.bn32(self.conv32(x31)))
            x33 = F.relu(self.bn33(self.conv33(x32)))
            x3p, id3 = F.max_pool2d(x33,kernel_size=2, stride=2,return_indices=True)
    
            # Stage 4
            x41 = F.relu(self.bn41(self.conv41(x3p)))
            x42 = F.relu(self.bn42(self.conv42(x41)))
            x43 = F.relu(self.bn43(self.conv43(x42)))
            x4p, id4 = F.max_pool2d(x43,kernel_size=2, stride=2,return_indices=True)
    
            # Stage 5
            x51 = F.relu(self.bn51(self.conv51(x4p)))
            x52 = F.relu(self.bn52(self.conv52(x51)))
            x53 = F.relu(self.bn53(self.conv53(x52)))
            x5p, id5 = F.max_pool2d(x53,kernel_size=2, stride=2,return_indices=True)
    
    
            # Stage 5d
            x5d = F.max_unpool2d(x5p, id5, kernel_size=2, stride=2)
            x53d = F.relu(self.bn53d(self.conv53d(x5d)))
            x52d = F.relu(self.bn52d(self.conv52d(x53d)))
            x51d = F.relu(self.bn51d(self.conv51d(x52d)))
    
            # Stage 4d
            x4d = F.max_unpool2d(x51d, id4, kernel_size=2, stride=2)
            x43d = F.relu(self.bn43d(self.conv43d(x4d)))
            x42d = F.relu(self.bn42d(self.conv42d(x43d)))
            x41d = F.relu(self.bn41d(self.conv41d(x42d)))
    
            # Stage 3d
            x3d = F.max_unpool2d(x41d, id3, kernel_size=2, stride=2)
            x33d = F.relu(self.bn33d(self.conv33d(x3d)))
            x32d = F.relu(self.bn32d(self.conv32d(x33d)))
            x31d = F.relu(self.bn31d(self.conv31d(x32d)))
    
            # Stage 2d
            x2d = F.max_unpool2d(x31d, id2, kernel_size=2, stride=2)
            x22d = F.relu(self.bn22d(self.conv22d(x2d)))
            x21d = F.relu(self.bn21d(self.conv21d(x22d)))
    
            # Stage 1d
            x1d = F.max_unpool2d(x21d, id1, kernel_size=2, stride=2)
            x12d = F.relu(self.bn12d(self.conv12d(x1d)))
            x11d = self.conv11d(x12d)
    
            return x11d
    
        def load_from_segnet(self, model_path):
            s_dict = self.state_dict()# create a copy of the state dict
            th = torch.load(model_path).state_dict() # load the weigths
            # for name in th:
                # s_dict[corresp_name[name]] = th[name]
            self.load_state_dict(th)
    
    更多相关内容
  • SegNet-PyTorch

    2021-05-16 23:39:07
    SegNet-PyTorch 该项目是的SegNet的实现,您可以通过访问作者提供的演示来找到更多详细信息。 环境 Ubuntu的:16.04 火炬:0.4.0 的Python:3.6.1 运行项目 sh run.sh
  • 该演示演示了如何准备用于训练的像素标签数据,以及如何基于VGG-16创建,训练和评估SegNet 将血涂片图像分为 3 类——血液寄生虫、血细胞和背景。深度学习是医学成像中最强大的方法之一。在这个演示中,我们将介绍...
  • 语义分割:基于restnet50的segnet迁移学习,模型的训练,与使用;
  • 语义分割网络经典:FCN与SegNet 全文目录 1、FCN 概述 编码和解码过程 2、SegNet 概述: 特征上采样与融合细节 代码地址 将图像中每个像素分配到某个对象类别,相关模型要具有像素级的密集预测能力。 01 FCN ...
  • caffe-segnet:SegNet的实现

    2021-05-11 13:42:08
    Caffe SegNet 这是的修改版本,支持 如SegNet中所述:用于图像分割的深度卷积编码器/解码器体系结构Vijay Badrinarayanan,Alex Kendall和Roberto Cipolla,PAMI 2017 [ ] 更新后的版本: 此版本支持cudnn v2加速...
  • keras-segnet, 利用keras框架实现SegNet模型 keras-segnet使用 keras 实现 SegNet -like体系结构。当前版本的不支持在SegNet文章中提出的索引转移,所以它基本上是一个通用的编码器解码网络。 在 index-based-...
  • 发表SegNet网络的论文为:Badrinarayanan V, Kendall A, Cipolla R.SegNet: A Deep Convolutional Encoder-Decoder Architecture for SceneSegmentation[J]. IEEE Transactions on Pattern Analysis & ...
  • Segnet网络结构

    2018-10-26 12:17:38
    Segnet网络结构
  • 基于segnet的语义分割

    2019-01-13 21:20:40
    基于segnet模型的对cityscapes数据集的语义分割代码实现
  • SegNet-tensorflow+dataset

    2018-04-13 17:15:18
    segnet的tensorflow实现以及CamVid数据集(包含training、val、test)的下载。
  • 【Keras】基于SegNet和U-Net的遥感图像语义分割-附件资源
  • 文中选用深度学习中的SegNet语义分割模型进行算法改进,提出了一种基于稀疏约束SegNet的高分辨率遥感影像建筑 物提取算法。首先对SegNet模型加入正则项和Dropout,大大降低了模型过拟合现象的发生;其 次为了模型...
  • 惊人的语义分割 ...SegNet- 贝叶斯SegNet- PSPNet- RefineNet- PAN- DeepLabV3- DeepLabV3Plus- DenseASPP- BiSegNet- 基本型号 该项目支持以下这些主干模型,您可以根据需要选择合适的基本模型。
  • 该存储库包含用于CamVid数据集的多类语义分割的多个深度学习模型(U-Net,FCN32和SegNet)的实现。 实施tensorflow 2.0 Aplha GPU软件包 包含用于图像分类/检测/分段的通用计算机视觉项目目录创建和图像处理管道
  • segnet-cudnn7-caffe-pascal

    2022-03-20 16:30:31
    segnet权重
  • SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation tensorflow源代码+数据集
  • SegNet_ResNet_resnet语义分割_segnet_语义分割resnet_迁移学习_源码.zip
  • caffe-segnet-segnet-cleaned

    2018-05-12 16:13:36
    segnet
  • SegNet: A Deep Convolutional Encoder-Decoder Architecture for Scene Segmentation
  • SegNet+dataset

    2018-06-04 17:18:21
    SegNet+dataset SegNet+dataset SegNet+dataset SegNet+dataset
  • Segnet是用于语义像素级分割的深层全卷积神经网络体系结构。 这是实现(除了Upsampling层,在论文中,纸张使用了尚未在keras中实现的基于索引的upsampling(我正在研究),但这不应该使差异很大)。 您可以直接从...
  • segnet-tutorial-master

    2019-04-30 11:47:55
    一种实时进行语义分割的网络,可以用于自动驾驶
  • SegNet算法详解

    千次阅读 2021-12-31 11:29:40
    SegNet论文详解 本文提出了一种用于语义分割的深度全卷积神经网络结构SegNet,其核心由一个编码器网络和一个对应的解码器网络以及一个像素级分类层组成。 本文的创新在于: 解码器使用在对应编码器的最大池化步骤中...

    SegNet论文详解

    SegNet算法Pytorch实现:https://github.com/codecat0/CV/tree/main/Semantic_Segmentation/SegNet

    本文提出了一种用于语义分割的深度全卷积神经网络结构SegNet,其核心由一个编码器网络和一个对应的解码器网络以及一个像素级分类层组成

    本文的创新在于:
    解码器使用在对应编码器的最大池化步骤中计算的池化索引来执行非线性上采样,这与反卷积相比,减少了参数量和运算量,而且消除了学习上采样的需要。
    在这里插入图片描述

    1. 网络结构

    在这里插入图片描述

    1.1 编码器

    1. Conv层
      • 通过卷积提取特征,其中使用的是same padding的卷积,不会改变特征图的尺寸
    2. BN层
      • 起到归一化的作用
    3. ReLU层
      • 起到激活函数的作用
    4. Pooling层
      • max pooling层,同时会记录最大值的索引位置

    1.2 解码器

    1. Upsampling层
      在这里插入图片描述

      • 对输入的特征图放大两倍,然后把输入特征图的数据根据编码器pooling层的索引位置放入,其他位置为0
    2. Conv层

      • 通过卷积提取特征,其中使用的是same padding的卷积,不会改变特征图的尺寸
    3. BN层

      • 起到归一化的作用
    4. ReLU层

      • 起到激活函数的作用

    1.3 像素级分类层

    输出每一个像素点在所有类别概率,其中最大的概率类别为该像素的预测值

    2. Pytorch实现

    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    
    class Encoder(nn.Module):
        def __init__(self, in_channels):
            super(Encoder, self).__init__()
    
            batchNorm_momentum = 0.1
    
            self.encode1 = nn.Sequential(
                nn.Conv2d(in_channels, 64, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(64, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(64, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
            )
    
            self.encode2 = nn.Sequential(
                nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(128, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(128, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
            )
    
            self.encode3 = nn.Sequential(
                nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(256, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(256, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
            )
    
            self.encode4 = nn.Sequential(
                nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(512, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(512, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
            )
    
            self.encode5 = nn.Sequential(
                nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(512, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(512, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
            )
    
        def forward(self, x):
            idx = []
    
            x = self.encode1(x)
            x, id1 = F.max_pool2d_with_indices(x, kernel_size=2, stride=2, return_indices=True)
            idx.append(id1)
    
            x = self.encode2(x)
            x, id2 = F.max_pool2d_with_indices(x, kernel_size=2, stride=2, return_indices=True)
            idx.append(id2)
    
            x = self.encode3(x)
            x, id3 = F.max_pool2d_with_indices(x, kernel_size=2, stride=2, return_indices=True)
            idx.append(id3)
    
            x = self.encode4(x)
            x, id4 = F.max_pool2d_with_indices(x, kernel_size=2, stride=2, return_indices=True)
            idx.append(id4)
    
            x = self.encode5(x)
            x, id5 = F.max_pool2d_with_indices(x, kernel_size=2, stride=2, return_indices=True)
            idx.append(id5)
    
            return x, idx
    
    
    class Decoder(nn.Module):
        def __init__(self, out_channels):
            super(Decoder, self).__init__()
    
            batchNorm_momentum = 0.1
    
            self.decode1 = nn.Sequential(
                nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(512, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(512, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True)
            )
    
            self.decode2 = nn.Sequential(
                nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(512, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(512, 256, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(256, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True)
            )
    
            self.decode3 = nn.Sequential(
                nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(256, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(256, 128, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(128, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True)
            )
    
            self.decode4 = nn.Sequential(
                nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(128, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(128, 64, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(64, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True)
            )
    
            self.decode5 = nn.Sequential(
                nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1, bias=False),
                nn.BatchNorm2d(64, momentum=batchNorm_momentum),
                nn.ReLU(inplace=True),
    
                nn.Conv2d(64, out_channels, kernel_size=3, stride=1, padding=1)
            )
    
        def forward(self, x, idx):
            x = F.max_unpool2d(x, idx[4], kernel_size=2, stride=2)
    
            x = self.decode1(x)
            x = F.max_unpool2d(x, idx[3], kernel_size=2, stride=2)
    
            x = self.decode2(x)
            x = F.max_unpool2d(x, idx[2], kernel_size=2, stride=2)
    
            x = self.decode3(x)
            x = F.max_unpool2d(x, idx[1], kernel_size=2, stride=2)
    
            x = self.decode4(x)
            x = F.max_unpool2d(x, idx[0], kernel_size=2, stride=2)
    
            x = self.decode5(x)
    
            return x
    
    
    class SegNet(nn.Module):
        # https://arxiv.org/abs/1511.00561
        def __init__(self, num_classes):
            super(SegNet, self).__init__()
    
            self.encode = Encoder(in_channels=3)
            self.decode = Decoder(out_channels=num_classes)
    
        def forward(self, x):
            x, idx = self.encode(x)
            x = self.decode(x, idx)
            return x
    
    
    if __name__ == '__main__':
        input = torch.randn(1, 3, 384, 544)
        model = SegNet(num_classes=2)
        output = model(input)
        print(output.shape)
    
    展开全文
  • SegNet 网络

    千次阅读 2021-11-09 16:59:39
    Q1:seq2seq A1:就是根据一个输入序列x,来生成另一个输出序列y Q2:padding的三种方式 A2:padding有三种模式:... (5)Bayesian SegNet就是在SegNet基础上网络结构增加dropout,增加后处理操作,本质是一种模型集成。

    Q1:seq2seq

    A1:就是根据一个输入序列x,来生成另一个输出序列y

    Q2:padding的三种方式

    A2:padding有三种模式:full,same,valid,其实这三种不同模式是对卷积核移动范围的不同限制

    假设设 image的大小是7x6,filter的大小是3x3

    1.Full mode

     橙色部分为image, 蓝色部分为filter。full模式的意思是,从filter和image刚相交开始做卷积,白色部分为填0。filter的运动范围如图所示。

     2. same mode

    当filter的中心(K)与image的边角重合时,开始做卷积运算,可见filter的运动范围比full模式小了一圈。注意:这里的same还有一个意思,卷积之后输出的feature map尺寸保持不变(相对于输入图片)。当然,same模式不代表完全输入输出尺寸一样,也跟卷积核的步长有关系。same模式也是最常见的模式,因为这种模式可以在前向传播的过程中让特征图的大小保持不变,调参师不需要精准计算其尺寸变化(因为尺寸根本就没变化)。

    3.vaild mode

    当filter全部在image里面的时候,进行卷积运算,可见filter的移动范围较same更小了。

     

     

    Encoder-Decoder模型

     Encoder-Decoder Based Models是非常经典的一种图像分割模型(FNC网络,严格来说,其实也是这种模式)。模型通常由两部分组成,即Encoder部分和Decoder 部分Encoder会通过convolutional layers对image进行下采样,使得图片size减小,而channel增加。常见使用的下采样网络有:vgg-16、ResNet。通过去掉下采样网络的fn层,只保留卷积层,从而达到对图片下采样(Encoder)的目的Decoder 有两种方法:使用deconv对图片上采样,从而将Encoder的特征图Decoder 为像素分割图;对特征图进行unpooling后,做same卷积
    更直观的理解就是,Encoder负责将一张图片的每个像素点,通过复杂的计算过程,映射到某一个高维分布上,而Decoder则是负责将这个高维分布,映射到给定的类别区域。中间的高维分布,是我们不可见的,但神经网络却可以很好的使用它。正是这种借助中间的高维分布的思想,搭建起来了原图像到像素级分类图像的桥梁,实现了end-to-end的训练过程。

    SegNet网络

    从主干模型中提取出卷积了多次,具有一定特征的层(典型的是长宽经过4次压缩之后的层),然后利用upsamepling2D函数进行三次上采样,得到输出层(语意分割的结果)

    1.网络架构

    网络结构:

    SegNet网络结构如图所示,Input为输入图片,Output为输出分割的图像,不同颜色代表不同的分类。语义分割的重要性就在于不仅告诉你图片中某个东西是什么,而且告知你他在图片的位置。我们可以看到是一个对称网络,由中间绿色pooling层与红色upsampling层作为分割,左边是卷积提取高维特征,并通过pooling使图片变小,SegNet作者称为Encoder,右边是反卷积(在这里反卷积与卷积没有区别)与upsampling,通过反卷积使得图像分类后特征得以重现,upsampling使图像变大,SegNet作者称为Decoder,最后通过Softmax,输出不同分类的最大值。这就是大致的SegNet过程,

     2.Encoder

    Ecoder端是使用Vgg16,总计使用了Vgg16的13个卷积层,如下图所示,encoder在最大池化操作时记录了最大值所在位置(索引),用于之后在decoder中使用那些存储的索引来对相应特征图进行去池化操作,这样在上采样阶段就无需学习。这有助于保持高频信息的完整性,但当对低分辨率的特征图进行去池化时,它也会忽略邻近的信息。上采样后得到的是一个稀疏特征图,再通过普通的卷积得到稠密特征图,再重复上采样。最后再用激活函数得到onehot 分类结果。
    Encoder过程中,通过卷积提取特征,SegNet使用的卷积为same卷积,即卷积后保持图像原始尺寸;在Decoder过程中,同样使用same卷积,不过卷积的作用是为upsampling变大的图像丰富信息,使得在Pooling过程丢失的信息可以通过学习在Decoder得到。SegNet中的卷积与传统CNN的卷积并没有区别。

     

     3.Pooling&Upsampling(Decoder):

    Pooling在CNN中是使得图片缩小一半的手段,通常有max与mean两种Pooling方式,下图所示的是max Pooling。max Pooling是使用一个2x2的filter,取出这4个权重最大的一个,原图大小为4x4,Pooling之后大小为2x2,原图左上角黄色的四个数,最后只剩最大的0.8,这就是max的意思。 

    在SegNet中的Pooling与其他Pooling多了一个index功能(该文章亮点之一),每次Pooling,都会保存通过max选出的权值在2x2 filter中的相对位置,对于上图的0.8来说,0.8在黄色2x2 filter中的位置为(0,1)(index从0开始),绿色的0.9的index为(1,0)。同时,从网络框架图可以看到绿色的pooling与红色的upsampling通过pool indices相连,实际上是pooling后的indices输出到对应的upsampling(因为网络是对称的,所以第1次的pooling对应最后1次的upsamping,如此类推)。 
            Upsamping就是Pooling的逆过程(index在Upsampling过程中发挥作用),Upsamping使得图片变大2倍。我们清楚的知道Pooling之后,每个filter会丢失了3个权重,这些权重是无法复原的,但是在Upsamping层中可以得到在Pooling中相对Pooling filter的位置。所以Upsampling中先对输入的特征图放大两倍,然后把输入特征图的数据根据Pooling indices放入,下图所示,Unpooling对应上述的Upsampling,switch variables对应Pooling indices。

     对比FCN可以发现SegNet在Unpooling时用index信息,直接将数据放回对应位置,后面再接Conv训练学习。这个上采样不需要训练学习(只是占用了一些存储空间)。反观FCN则是用transposed convolution策略,即将feature 反卷积后得到upsampling,这一过程需要学习,同时将encoder阶段对应的feature做通道降维,使得通道维度和upsampling相同,这样就能做像素相加得到最终的decoder输出. 

    左边是SegNet的upsampling过程,就是把feature map的值 abcd, 通过之前保存的max-pooling的坐标映射到新的feature map中,其他的位置置零.

    右边是FCN的upsampling过程,就是把feature map, abcd进行一个反卷积,得到的新的feature map和之前对应的encoder feature map 相加.

    SegNet的分割精度略好于FCN
     

     4.Deconvolution

     pooling&Upsampling示意图中右边的Upsampling可以知道,2x2的输入,变成4x4的图,但是除了被记住位置的Pooling indices,其他位置的权值为0,因为数据已经被pooling走了。因此,SegNet使用的反卷积在这里用于填充缺失的内容,因此这里的反卷积与卷积是一模一样,在网络框架图中跟随Upsampling层后面的是也是卷积层。

    5.Output:

     在网络框架中,SegNet,最后一个卷积层会输出所有的类别(包括other类),网络最后加上一个softmax层,由于是end to end, 所以softmax需要求出所有每一个像素在所有类别最大的概率,最为该像素的label,最终完成图像像素级别的分类。

    总结


    (1)编码器部分的特征如果可以被很好的保存,例如本文的pooling操作,保存了其索引,可以取得很好的分割效果,尤其是在边缘部分。

    (2)SegNet效率很高,因为它只存储特征映射的最大池索引,并在其解码器网络中使用它们来获得良好的性能。

    (3)本文的pooling操作可以解决推断过程中内存消耗大的问题。

    (4)对于给定的编码器,使用更大的解码器可以提升分割的精度。

    (5)Bayesian SegNet就是在SegNet基础上网络结构增加dropout,增加后处理操作,本质是一种模型集成。
     

    展开全文
  • SegNet

    2020-09-13 11:49:45
    (无relu) 分类:soft-max分类器对应像素处概率最大的分类标签 3.1解码器变体 SegNet与fcn 的比较 SegNet使用最大池化索引对特征图进行上采样(无需学习),并与可训练的解码器滤波器组卷积。FCN通过学习对输入特征图...

    摘要

    This core trainable segmentation engine consists of an encoder network, a corresponding decoder network followed by a pixel-wise classification layer.
    (由编码器网络、相应的解码器网络和随后的像素分类层组成)
    The architecture of the encoder network is topologically identical to the 13 convolutional layers in the VGG16 network .
    (编码器网络的架构在拓扑上与VGG16网络中的13个卷积层相同)
    The role of the decoder network is to map the low resolution encoder feature maps to full input resolution feature maps for pixel-wise classification.
    (解码器网络的作用是将低分辨率编码器特征图映射到全输入分辨率特征图,以便按像素分类)
    The novelty of SegNet lies is in the manner in which the decoder upsamples its lower resolution input feature map(s)
    (SegNet的新颖性在于解码器对其较低分辨率的输入特征映射进行上采样的方式)

    Specifically, the decoder uses pooling indices computed in the max-pooling step of the corresponding encoder to perform non-linear upsampling. This eliminates the need for learning to upsample. The upsampled maps are sparse and are then convolved with trainable filters to produce dense feature maps.
    (步骤:解码器使用在相应编码器的max-pooling步骤中计算的pooling索引来执行非线性上采样。这消除了学习上采样的需要。上采样的特征图是稀疏的,然后与可训练的滤波器卷积以产生密集的特征地图)

    1介绍

    The encoder network in SegNet is topologically identical to the convolutional layers in VGG16 . We remove the fully connected layers of VGG16 . The key component of SegNet is the decoder network which consists of a hierarchy of decoders one corresponding to each encoder. Of these, the appropriate decoders use the max-pooling indices received from the corresponding encoder to perform non-linear upsampling of their input feature maps.
    (SegNet中的编码器网络在拓扑上与VGG16中的卷积层相同。我们去掉了VGG16的完全连接层。SegNet的关键组成部分是解码器网络,它由一系列解码器组成,每个解码器对应一个编码器。其中,适当的解码器使用从相应编码器接收的最大池化索引来执行其输入特征图的非线性上采样。)

    2相关综述

    3网络架构

    编码–解码–逐像素分类
    在这里插入图片描述
    编码器部分:将VGG16去掉由全连接层转化过来的卷积层,保留13层。编码器特征图与filter bank产生特征图,然后进行批归一,ReLU(逐像素),最大池化(窗口2*2,步长为2)(即,以因子2进行下采样)-------下采样会损失细节,故在下采样之前从特征图中捕获并存储边界信息----该论文提出,仅存储最大索引(max-pooling indices)
    解码器部分:相应解码器用来自对应的编码器的最大池化索引进行上采样,以生成稀疏特征图,然后与解码器组的filter bank卷积以产生密集特征图,然后批归一。(无relu)
    分类:soft-max分类器对应像素处概率最大的分类标签

    3.1解码器变体
    SegNet与fcn 的比较
    在这里插入图片描述
    SegNet使用最大池化索引对特征图进行上采样(无需学习),并与可训练的解码器滤波器组卷积。FCN通过学习对输入特征图进行去卷积进行上采样,并添加相应的编码器特征图以产生解码器输出。该特征图是相应编码器中的最大池化层(包括子采样)的输出。
    请注意,在FCN中没有可训练的解码器滤波器。
    3.2 训练
    3.3分析
    We can now summarize the above analysis with the following general points.

    1. The best performance is achieved when encoder feature maps are stored in full. This is reflected in the semantic contour delineation metric (BF) most clearly.
    2. When memory during inference is constrained, then compressed forms of encoder feature maps (dimensionality reduction, max-pooling indices) can be stored and used with an appropriate decoder (e.g. SegNet type) to improve performance.
    3. Larger decoders increase performance for a given encoder network.

    4基准/标杆

    4.1道路场景分割
    4.2室内场景

    5讨论与未来工作

    6总结

    展开全文
  • SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation
  • SegNet论文理解

    千次阅读 2022-01-17 01:41:43
    Segnet:A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation 文章来源:2016 TPAMI SegNet论文地址:https://arxiv.org/abs/1511.00561 一、背景 SegNet网络是在部分FCN的基础之上进行改进...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,008
精华内容 1,203
关键字:

segnet