精华内容
下载资源
问答
  • DeepLabv3+

    千次阅读 2020-01-14 11:41:05
    DeepLabv3+ 引言 语义分割中的DCNN主要有两种结构:空间金字塔池化SPP和编码器-解码器encoder-decoder SPP通过多种感受野池化不同分辨率的特征来挖掘上下文信息。 Encoder-decoder逐步重构空间信息来更好的捕捉...

    DeepLabv3+

    引言

    语义分割中的DCNN主要有两种结构:空间金字塔池化SPP和编码器-解码器encoder-decoder

    SPP通过多种感受野池化不同分辨率的特征来挖掘上下文信息。

    Encoder-decoder逐步重构空间信息来更好的捕捉物体的边缘。

    在这里插入图片描述DeepLabv3+对DeepLabv3进行了拓展,在encoder-decoder结构上采用SPP模块。encoder提取丰富的语义信息,decoder恢复精细的物体边缘。encoder允许在任意分辨率下采用空洞卷积。

    DeepLabv3+贡献

    • 提出一个encoder-decoder结构,其包含DeepLabv3作为encoder和高效的decoder模块。
    • encoderdecoder结构中可以通过空洞卷积来平衡精度和运行时间,现有的encoder-decoder结构是不可行的。
    • 在语义分割任务中采用Xception模型并采用depthwise separable convolution,从而更快更有效。

    相关工作

    SPP

    收集多尺度信息。
    PSPNet、DeepLab

    Encoder-decoder

    encoder逐渐减小feature map并提取高层语义信息。
    decoder逐渐恢复空间信息。

    Depthwise separable convolution

    深度可分离卷积或group convolution,在保持性能前提下,有效降低了计算量和参数量。

    方法

    Encoder-Decoder
    空洞卷积:
    该部分见DeepLabv2

    在这里插入图片描述

    深度可分离卷积:
    深度可分离卷积将标准卷积分解为depthwise conv后跟一个pointwise conv,有效地降低了计算复杂度。
    depthwise conv对每个输入通道分别进行spatial conv。
    pointwise conv合并depthwise conv的输出。
    我们提出atrous separable conv,其在保持性能前提下,有效降低了计算量和参数量。

    DeepLabv3作为encoder:
    令outputstride等于输入图像分辨率和输出分辨率的比值。
    图像分类任务,最终的feature map通常比输入图像分辨率小32倍,因此outputstride=32。
    语义分割任务,令outputstride=16or8,通过移除最后1or2个blocks并应用空洞卷积(rate=2or4

    )来密集提取特征。

    在我们的encoder-decoder结构中,采用DeepLabv3最后的feature map作为encoder的输出,包含256
    个通道并富含语义信息。此外,可以通过空洞卷积以任意分辨率提取特征,取决于计算量。

    decoder:
    在这里插入图片描述
    DeepLabv3以factor=16上采样。
    DeepLabv3+首先以factor=4上采样,然后和尺寸相同的低层特征相拼接。低层特征采用1×1卷积降维,因为低层特征维度一般比较高(256or512),将占较大权重(我们的模型只有256),使得训练变困难。拼接之后,我们采用3×3的卷积来细化特征,然后再以factor=4双线性插值。

    改进 Aligned Xception
    Xception模型用于图像分类任务,Aligned Xception用于物体检测任务,我们对Xception做了一些变化使其可用于语义分割任务。
    1)更多的层,为了计算量和内存,不对Entry flow网络结构进行修改。
    2)所有池化层替换为depthwise separable conv,以便采用 atrous separable conv提取任意分辨率的特征。
    3)类似于MobileNet,在每个3×3后添加额外的BN和ReLU。

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

    展开全文
  • deeplabV3+

    2020-07-24 10:27:00
    deeplabV3+ deeplabV3+主要运用了Encoder-Decoder结构 主要包括三个结构: 1.backbone 2.aspp 3.deconder 其中前两项称为Encoder 上图对于整个过程画的特别清楚,自我感觉很容易进行理解。 deeplabV3 运用了膨胀...

    deeplabV3+

    deeplabV3+主要运用了Encoder-Decoder结构
    主要包括三个结构:
    1.backbone
    2.aspp
    3.deconder
    其中前两项称为Encoder

    在这里插入图片描述
    上图对于整个过程画的特别清楚,自我感觉很容易进行理解。

    deeplabV3 运用了膨胀卷积,在保证图像大小不变的情况下,增大了图片的感受野。
    在这里插入图片描述

    Backbone 我采用的resnet101, 如上图所示,在图像缩小为16倍后,运用膨胀卷积在保证图片大小不变,感受野却继续增大。(注意:语义分割中,更深的层数决定图像的轮廓,浅层的深度显示的是物体的细节。)但是如果图像尺寸缩小的太小,在还原的过程中会导致信息缺失,因此膨胀卷积很好地解决了这一问题。
    如最上方的一张图最后backbone一共有两个输出部分,一个是最后一层的输出,另一个是从中间层进行输出(中间层截取的是图像1/4处,进行计算可以得到)。为什么呢?
    因为全局特征或上下文之间的互相作用有助于做语义分割

    采用Aspp结构(带膨胀卷积的空间金字塔池化),作用:捕捉多尺度的空间信息,并把不定长的输入变为定长的输入
    在backbone最后输出的结果采用不同的膨胀率进行卷积经过试验分别是采用1x1 卷积和三个3x3膨胀率分别为6,12,18。滤波器数量为256。并加上图像集特征,即先对原图做GAP,然后在进行卷积融合。如下图所示。
    在这里插入图片描述
    最后就是Decoder,按照第一幅图的流程就可打得到最后结果。

    展开全文
  • 憨批的语义分割5——DeeplabV3+模型解析以及训练自己的DeeplabV3+模型(划分斑马线)学习前言模型部分什么是DeeplabV3+模型DeeplabV3+模型的代码实现1、主干模型Xception。2、DeeplabV3+的Decoder解码部分代码测试...

    学习前言

    DeeplabV3是一个比较新的模型了,他不仅比较新,而且参数量较大,本篇BLOG将会从整体上对DeeplabV3+进行一个分解……如果想要先有语义分割的基础,可以看我的博文憨批的语义分割2——训练自己的segnet模型(划分斑马线)

    在这里插入图片描述

    模型部分

    想要看视频教程的可以去这里Keras 搭建自己的语义分割模型https://www.bilibili.com/video/av75562599/

    什么是DeeplabV3+模型

    DeeplabV3+被认为是语义分割的新高峰,主要是因为这个模型的效果非常的好呀。
    DeepLabv3+主要在模型的架构上作文章,为了融合多尺度信息,其引入了语义分割常用的encoder-decoder形式。在 encoder-decoder 架构中,引入可任意控制编码器提取特征的分辨率,通过空洞卷积平衡精度和耗时。
    听起来很懵对吧,其实DeeplabV3的主要结构可以由下面这幅图得到。
    在这里插入图片描述
    由这幅图我们可以发现,其实deeplabV3+模型仍然是两个部分,一个部分是Encoder,一个部分是Decoder。

    • 重点哈重点哈重点哈
    • 重点哈重点哈重点哈!
    • 重点哈重点哈重点哈!!!

    其实deeplabV3+与我们之前介绍的pspnet、segnet、unet相比,其最大的特点就是引入了空洞卷积,在不损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。如下就是空洞卷积的一个示意图,所谓空洞就是特征点提取的时候会跨像素

    在这里插入图片描述

    空洞卷积的目的其实也就是提取更有效的特征,所以它位于Encoder网络中用于特征提取。

    我们再来仔细看看Encoder的结构。
    在这里插入图片描述
    其具有两个核心点:
    1、在主干DCNN深度卷积神经网络里使用串行的Atrous Convolution。串行的意思就是一层又一层,普通的深度卷积神经网络的结构就是串行结构。
    2、在图片经过主干DCNN深度卷积神经网络之后的结果分为两部分,一部分直接传入Decoder,另一部分经过并行的Atrous Convolution,分别用不同rate的Atrous Convolution进行特征提取,再进行合并,再进行1x1卷积压缩特征。

    我们再来看看Decoder的结构。
    在这里插入图片描述
    Decoder看起来就简单多了,其输入有两部分,一部分是DCNN的输出,一部分是DCNN输出经过并行空洞卷积后的结果。
    这两个结果经过一定的处理后Concat在一起,在DeeplabV3中,Upsample的方式是双线性插值。

    然后就得到最后的结果啦~

    DeeplabV3+模型的代码实现

    DeeplabV3+模型的代码分为两部分。

    1、主干模型Xception。

    该部分用于特征提取,其结构是优化改进后的Xception,其相比一般的Xception最大的特点是引入了空洞卷积神经网络学习小记录22——Xception模型的复现详解

    from keras.models import Model
    from keras import layers
    from keras.layers import Input
    from keras.layers import Lambda
    from keras.layers import Activation
    from keras.layers import Concatenate
    from keras.layers import Add
    from keras.layers import Dropout
    from keras.layers import BatchNormalization
    from keras.layers import Conv2D
    from keras.layers import DepthwiseConv2D
    from keras.layers import ZeroPadding2D
    from keras.layers import GlobalAveragePooling2D
    
    
    def _conv2d_same(x, filters, prefix, stride=1, kernel_size=3, rate=1):
        # 计算padding的数量,hw是否需要收缩
        if stride == 1:
            return Conv2D(filters,
                          (kernel_size, kernel_size),
                          strides=(stride, stride),
                          padding='same', use_bias=False,
                          dilation_rate=(rate, rate),
                          name=prefix)(x)
        else:
            kernel_size_effective = kernel_size + (kernel_size - 1) * (rate - 1)
            pad_total = kernel_size_effective - 1
            pad_beg = pad_total // 2
            pad_end = pad_total - pad_beg
            x = ZeroPadding2D((pad_beg, pad_end))(x)
            return Conv2D(filters,
                          (kernel_size, kernel_size),
                          strides=(stride, stride),
                          padding='valid', use_bias=False,
                          dilation_rate=(rate, rate),
                          name=prefix)(x)
    
    
    def SepConv_BN(x, filters, prefix, stride=1, kernel_size=3, rate=1, depth_activation=False, epsilon=1e-3):
        # 计算padding的数量,hw是否需要收缩
        if stride == 1:
            depth_padding = 'same'
        else:
            kernel_size_effective = kernel_size + (kernel_size - 1) * (rate - 1)
            pad_total = kernel_size_effective - 1
            pad_beg = pad_total // 2
            pad_end = pad_total - pad_beg
            x = ZeroPadding2D((pad_beg, pad_end))(x)
            depth_padding = 'valid'
        
        # 如果需要激活函数
        if not depth_activation:
            x = Activation('relu')(x)
    
        # 分离卷积,首先3x3分离卷积,再1x1卷积
        # 3x3采用膨胀卷积
        x = DepthwiseConv2D((kernel_size, kernel_size), strides=(stride, stride), dilation_rate=(rate, rate),
                            padding=depth_padding, use_bias=False, name=prefix + '_depthwise')(x)
        x = BatchNormalization(name=prefix + '_depthwise_BN', epsilon=epsilon)(x)
        if depth_activation:
            x = Activation('relu')(x)
    
        # 1x1卷积,进行压缩
        x = Conv2D(filters, (1, 1), padding='same',
                   use_bias=False, name=prefix + '_pointwise')(x)
        x = BatchNormalization(name=prefix + '_pointwise_BN', epsilon=epsilon)(x)
        if depth_activation:
            x = Activation('relu')(x)
    
        return x
    
    
    def _xception_block(inputs, depth_list, prefix, skip_connection_type, stride,
                        rate=1, depth_activation=False, return_skip=False):
    
        residual = inputs
        for i in range(3):
            residual = SepConv_BN(residual,
                                  depth_list[i],
                                  prefix + '_separable_conv{}'.format(i + 1),
                                  stride=stride if i == 2 else 1,
                                  rate=rate,
                                  depth_activation=depth_activation)
            if i == 1:
                skip = residual
        if skip_connection_type == 'conv':
            shortcut = _conv2d_same(inputs, depth_list[-1], prefix + '_shortcut',
                                    kernel_size=1,
                                    stride=stride)
            shortcut = BatchNormalization(name=prefix + '_shortcut_BN')(shortcut)
            outputs = layers.add([residual, shortcut])
        elif skip_connection_type == 'sum':
            outputs = layers.add([residual, inputs])
        elif skip_connection_type == 'none':
            outputs = residual
        if return_skip:
            return outputs, skip
        else:
            return outputs
    
    
    
    def Xception(inputs,alpha=1,OS=16):
        if OS == 8:
            entry_block3_stride = 1
            middle_block_rate = 2  # ! Not mentioned in paper, but required
            exit_block_rates = (2, 4)
            atrous_rates = (12, 24, 36)
        else:
            entry_block3_stride = 2
            middle_block_rate = 1
            exit_block_rates = (1, 2)
            atrous_rates = (6, 12, 18)
    
        # 256,256,32
        x = Conv2D(32, (3, 3), strides=(2, 2),
                    name='entry_flow_conv1_1', use_bias=False, padding='same')(inputs)
        x = BatchNormalization(name='entry_flow_conv1_1_BN')(x)
        x = Activation('relu')(x)
    
        # 256,256,64
        x = _conv2d_same(x, 64, 'entry_flow_conv1_2', kernel_size=3, stride=1)
        x = BatchNormalization(name='entry_flow_conv1_2_BN')(x)
        x = Activation('relu')(x)
    
        # 256,256,128 -> 256,256,128 -> 128,128,128
        x = _xception_block(x, [128, 128, 128], 'entry_flow_block1',
                            skip_connection_type='conv', stride=2,
                            depth_activation=False)
        
        # 128,128,256 -> 128,128,256 -> 64,64,256
        # skip = 128,128,256
        x, skip1 = _xception_block(x, [256, 256, 256], 'entry_flow_block2',
                                    skip_connection_type='conv', stride=2,
                                    depth_activation=False, return_skip=True)
    
        x = _xception_block(x, [728, 728, 728], 'entry_flow_block3',
                            skip_connection_type='conv', stride=entry_block3_stride,
                            depth_activation=False)
        for i in range(16):
            x = _xception_block(x, [728, 728, 728], 'middle_flow_unit_{}'.format(i + 1),
                                skip_connection_type='sum', stride=1, rate=middle_block_rate,
                                depth_activation=False)
    
        x = _xception_block(x, [728, 1024, 1024], 'exit_flow_block1',
                            skip_connection_type='conv', stride=1, rate=exit_block_rates[0],
                            depth_activation=False)
        x = _xception_block(x, [1536, 1536, 2048], 'exit_flow_block2',
                            skip_connection_type='none', stride=1, rate=exit_block_rates[1],
                            depth_activation=True)
        return x,atrous_rates,skip1
    

    2、DeeplabV3+的Decoder解码部分

    这一部分对应着上面DeeplabV3+模型中的Decoder部分。(并行空洞卷积也在这一部分里面~)
    其关键就是把获得的特征重新映射到比较大的图中的每一个像素点,用于每一个像素点的分类。

    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function
    
    import tensorflow as tf
    from nets.Xception import Xception
    from keras.models import Model
    from keras import layers
    from keras.layers import Input
    from keras.layers import Lambda
    from keras.layers import Activation
    from keras.layers import Softmax,Reshape
    from keras.layers import Concatenate
    from keras.layers import Add
    from keras.layers import Dropout
    from keras.layers import BatchNormalization
    from keras.layers import Conv2D
    from keras.layers import DepthwiseConv2D
    from keras.layers import ZeroPadding2D
    from keras.layers import GlobalAveragePooling2D
    from keras.utils.data_utils import get_file
    from keras import backend as K
    from keras.activations import relu
    from keras.applications.imagenet_utils import preprocess_input
    
    def SepConv_BN(x, filters, prefix, stride=1, kernel_size=3, rate=1, depth_activation=False, epsilon=1e-3):
        # 计算padding的数量,hw是否需要收缩
        if stride == 1:
            depth_padding = 'same'
        else:
            kernel_size_effective = kernel_size + (kernel_size - 1) * (rate - 1)
            pad_total = kernel_size_effective - 1
            pad_beg = pad_total // 2
            pad_end = pad_total - pad_beg
            x = ZeroPadding2D((pad_beg, pad_end))(x)
            depth_padding = 'valid'
        
        # 如果需要激活函数
        if not depth_activation:
            x = Activation('relu')(x)
    
        # 分离卷积,首先3x3分离卷积,再1x1卷积
        # 3x3采用膨胀卷积
        x = DepthwiseConv2D((kernel_size, kernel_size), strides=(stride, stride), dilation_rate=(rate, rate),
                            padding=depth_padding, use_bias=False, name=prefix + '_depthwise')(x)
        x = BatchNormalization(name=prefix + '_depthwise_BN', epsilon=epsilon)(x)
        if depth_activation:
            x = Activation('relu')(x)
    
        # 1x1卷积,进行压缩
        x = Conv2D(filters, (1, 1), padding='same',
                   use_bias=False, name=prefix + '_pointwise')(x)
        x = BatchNormalization(name=prefix + '_pointwise_BN', epsilon=epsilon)(x)
        if depth_activation:
            x = Activation('relu')(x)
    
        return x
    
    def Deeplabv3(input_shape=(512, 512, 3), classes=21, alpha=1.,OS=16):
    
        img_input = Input(shape=input_shape)
    
        # x=32, 32, 2048
        x,atrous_rates,skip1 = Xception(img_input,alpha,OS=OS)
    
        # 全部求平均后,再利用expand_dims扩充维度,1x1
        b4 = GlobalAveragePooling2D()(x)
    
        b4 = Lambda(lambda x: K.expand_dims(x, 1))(b4)
        b4 = Lambda(lambda x: K.expand_dims(x, 1))(b4)
        
        # 压缩filter
        b4 = Conv2D(256, (1, 1), padding='same',
                    use_bias=False, name='image_pooling')(b4)
        b4 = BatchNormalization(name='image_pooling_BN', epsilon=1e-5)(b4)
        b4 = Activation('relu')(b4)
    
        size_before = tf.keras.backend.int_shape(x)
        # 直接利用resize_images扩充hw
        # b4 = 64,64,256
        b4 = Lambda(lambda x: tf.image.resize_images(x, size_before[1:3]))(b4)
        # 调整通道
        b0 = Conv2D(256, (1, 1), padding='same', use_bias=False, name='aspp0')(x)
        b0 = BatchNormalization(name='aspp0_BN', epsilon=1e-5)(b0)
        b0 = Activation('relu', name='aspp0_activation')(b0)
    	
    	# 并行空洞卷积
        # rate值与OS相关,SepConv_BN为先3x3膨胀卷积,再1x1卷积,进行压缩
        # 其膨胀率就是rate值
        # rate = 6 (12)
        b1 = SepConv_BN(x, 256, 'aspp1',
                        rate=atrous_rates[0], depth_activation=True, epsilon=1e-5)
        # rate = 12 (24)
        b2 = SepConv_BN(x, 256, 'aspp2',
                        rate=atrous_rates[1], depth_activation=True, epsilon=1e-5)
        # rate = 18 (36)
        b3 = SepConv_BN(x, 256, 'aspp3',
                        rate=atrous_rates[2], depth_activation=True, epsilon=1e-5)
    
        # 其实实际的意义就是对Xception的输出结果进行
        x = Concatenate()([b4, b0, b1, b2, b3])
    
    
        # 利用conv2d压缩
        x = Conv2D(256, (1, 1), padding='same',
                   use_bias=False, name='concat_projection')(x)
        x = BatchNormalization(name='concat_projection_BN', epsilon=1e-5)(x)
        x = Activation('relu')(x)
        x = Dropout(0.1)(x)
    
        # skip1.shape[1:3] 为 128,128
        # skip1 128, 128, 256
        x = Lambda(lambda xx: tf.image.resize_images(x, skip1.shape[1:3]))(x)
                                                        
        # 128, 128, 48
        dec_skip1 = Conv2D(48, (1, 1), padding='same',
                            use_bias=False, name='feature_projection0')(skip1)
        dec_skip1 = BatchNormalization(
            name='feature_projection0_BN', epsilon=1e-5)(dec_skip1)
        dec_skip1 = Activation('relu')(dec_skip1)
        # 128,128,304
        x = Concatenate()([x, dec_skip1])
        x = SepConv_BN(x, 256, 'decoder_conv0',
                        depth_activation=True, epsilon=1e-5)
        x = SepConv_BN(x, 256, 'decoder_conv1',
                        depth_activation=True, epsilon=1e-5)
    
    
        x = Conv2D(classes, (1, 1), padding='same')(x)
        
        size_before3 = tf.keras.backend.int_shape(img_input)
        x = Lambda(lambda xx:tf.image.resize_images(xx,size_before3[1:3]))(x)
    
        x = Reshape((-1,classes))(x)
        x = Softmax()(x)
    
        inputs = img_input
        model = Model(inputs, x, name='deeplabv3plus')
    
        return model
    

    代码测试

    将上面两个代码分别保存为Xception.py和deeplab.py。按照如下方式存储:
    在这里插入图片描述
    此时我们运行test.py的代码:

    from nets.deeplab import Deeplabv3
    model = Deeplabv3(classes=2,OS=16)
    model.summary()
    

    如果没有出错的话就会得到如下的结果:
    在这里插入图片描述
    这个模型很大呀,不过提取的特征很有用噢。

    训练部分

    训练的是什么

    虽然把代码贴上来大家就会点运行然后就可以训练自己的模型,但是我还是想要大家知道,语义分割模型训练的是什么。

    1、训练文件详解

    这个要从训练文件讲起。

    语义分割模型训练的文件分为两部分。
    第一部分是原图,像这样:
    在这里插入图片描述
    第二部分标签,像这样:
    在这里插入图片描述
    当你们看到这个标签的时候你们会说,我靠,你给我看的什么辣鸡,全黑的算什么标签,其实并不是这样的,这个标签看起来全黑,但是实际上在斑马线的部分其RGB三个通道的值都是1。

    其实给你们换一个图你们就可以更明显的看到了。
    这是voc数据集中语义分割的训练集中的一幅图:
    在这里插入图片描述
    这是它的标签。
    在这里插入图片描述
    为什么这里的标签看起来就清楚的多呢,因为在voc中,其一共需要分21类,所以火车的RGB的值可能都大于10了,当然看得见。

    所以,在训练集中,如果像本文一样分两类,那么背景的RGB就是000,斑马线的RGB就是111,如果分多类,那么还会存在222,333,444这样的。这说明其属于不同的类。

    2、LOSS函数的组成

    关于loss函数的组成我们需要看两个loss函数的组成部分,第一个是预测结果。

        x = Conv2D(classes, (1, 1), padding='same')(x)
        
        size_before3 = tf.keras.backend.int_shape(img_input)
        x = Lambda(lambda xx:tf.image.resize_images(xx,size_before3[1:3]))(x)
    
        x = Reshape((-1,classes))(x)
        x = Softmax()(x)
    
        inputs = img_input
        model = Model(inputs, x, name='deeplabv3plus')
    

    首先将其filter层的数量改为nclasses,利用tf.image.resize_images得到最后的输出为[416,416,nclasses]。之后利用Softmax估计属于每一个种类的概率。

    其最后预测y_pre其实就是每一个像素点属于哪一个种类的概率

    第二个是真实值,真实值是这样处理的。

    # 从文件中读取图像
    img = Image.open(r".\dataset2\png" + '/' + name)
    img = img.resize((int(WIDTH/4),int(HEIGHT/4)))
    img = np.array(img)
    seg_labels = np.zeros((int(HEIGHT/4),int(WIDTH/4),NCLASSES))
    for c in range(NCLASSES):
        seg_labels[: , : , c ] = (img[:,:,0] == c ).astype(int)
    seg_labels = np.reshape(seg_labels, (-1,NCLASSES))
    Y_train.append(seg_labels)
    

    其将png图先进行resize,resize后其大小与预测y_pre的hw相同,然后读取每一个像素点属于什么种类,并存入。

    其最后真实y_true其实就是每一个像素点确实属于哪个种类

    最后loss函数的组成就是y_true和y_pre的交叉熵。

    训练代码

    大家可以在我的github上下载完整的代码。
    https://github.com/bubbliiiing/Semantic-Segmentation
    数据集的链接为:
    链接:https://pan.baidu.com/s/1uzwqLaCXcWe06xEXk1ROWw
    提取码:pp6w

    1、文件存放方式

    如图所示:
    在这里插入图片描述
    其中img和img_out是测试文件。

    2、训练文件

    训练文件如下:

    from nets.deeplab import Deeplabv3
    from keras.utils.data_utils import get_file
    from keras.optimizers import Adam
    from keras.callbacks import TensorBoard, ModelCheckpoint, ReduceLROnPlateau, EarlyStopping
    from PIL import Image
    import keras
    from keras import backend as K
    import numpy as np
    
    ALPHA = 1.0
    WEIGHTS_PATH_X = "https://github.com/bonlime/keras-deeplab-v3-plus/releases/download/1.1/deeplabv3_xception_tf_dim_ordering_tf_kernels.h5"
                        
    NCLASSES = 2
    HEIGHT = 416
    WIDTH = 416
    
    def generate_arrays_from_file(lines,batch_size):
        # 获取总长度
        n = len(lines)
        i = 0
        while 1:
            X_train = []
            Y_train = []
            # 获取一个batch_size大小的数据
            for _ in range(batch_size):
                if i==0:
                    np.random.shuffle(lines)
                name = lines[i].split(';')[0]
                # 从文件中读取图像
                img = Image.open(r".\dataset2\jpg" + '/' + name)
                img = img.resize((WIDTH,HEIGHT))
                img = np.array(img)
                img = img/255
                X_train.append(img)
    
                name = (lines[i].split(';')[1]).replace("\n", "")
                # 从文件中读取图像
                img = Image.open(r".\dataset2\png" + '/' + name)
                img = img.resize((int(WIDTH),int(HEIGHT)))
                img = np.array(img)
                seg_labels = np.zeros((int(HEIGHT),int(WIDTH),NCLASSES))
                for c in range(NCLASSES):
                    seg_labels[: , : , c ] = (img[:,:,0] == c ).astype(int)
                seg_labels = np.reshape(seg_labels, (-1,NCLASSES))
                Y_train.append(seg_labels)
    
                # 读完一个周期后重新开始
                i = (i+1) % n
            yield (np.array(X_train),np.array(Y_train))
    
    def loss(y_true, y_pred):
        crossloss = K.binary_crossentropy(y_true,y_pred)
        loss = K.sum(crossloss)/HEIGHT/WIDTH
        return loss
    
    if __name__ == "__main__":
        log_dir = "logs/"
        # 获取model
        model = Deeplabv3(classes=2,input_shape=(HEIGHT,WIDTH,3))
        # model.summary()
    
        weights_path = get_file('deeplabv3_xception_tf_dim_ordering_tf_kernels.h5',
                                        WEIGHTS_PATH_X,
                                        cache_subdir='models')
        model.load_weights(weights_path,by_name=True)
    
        # 打开数据集的txt
        with open(r".\dataset2\train.txt","r") as f:
            lines = f.readlines()
    
        # 打乱行,这个txt主要用于帮助读取数据来训练
        # 打乱的数据更有利于训练
        np.random.seed(10101)
        np.random.shuffle(lines)
        np.random.seed(None)
    
        # 90%用于训练,10%用于估计。
        num_val = int(len(lines)*0.1)
        num_train = len(lines) - num_val
    
        # 保存的方式,1世代保存一次
        checkpoint_period = ModelCheckpoint(
                                        log_dir + 'ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5',
                                        monitor='val_loss', 
                                        save_weights_only=True, 
                                        save_best_only=True, 
                                        period=1
                                    )
        # 学习率下降的方式,val_loss 1次不下降就下降学习率继续训练
        reduce_lr = ReduceLROnPlateau(
                                monitor='val_loss', 
                                factor=0.5, 
                                patience=3, 
                                verbose=1
                            )
        # 是否需要早停,当val_loss一直不下降的时候意味着模型基本训练完毕,可以停止
        early_stopping = EarlyStopping(
                                monitor='val_loss', 
                                min_delta=0, 
                                patience=10, 
                                verbose=1
                            )
    
        # 交叉熵
        model.compile(loss = loss,
                optimizer = Adam(lr=1e-3),
                metrics = ['accuracy'])
                
        batch_size = 1
        print('Train on {} samples, val on {} samples, with batch size {}.'.format(num_train, num_val, batch_size))
        
        # 开始训练
        model.fit_generator(generate_arrays_from_file(lines[:num_train], batch_size),
                steps_per_epoch=max(1, num_train//batch_size),
                validation_data=generate_arrays_from_file(lines[num_train:], batch_size),
                validation_steps=max(1, num_val//batch_size),
                epochs=50,
                initial_epoch=0,
                callbacks=[checkpoint_period, reduce_lr])
    
        model.save_weights(log_dir+'last1.h5')
    

    3、预测文件

    预测文件如下:

    from nets.deeplab import Deeplabv3
    from PIL import Image
    import numpy as np
    import random
    import copy
    import os
    
    
    class_colors = [[0,0,0],[0,255,0]]
    NCLASSES = 2
    HEIGHT = 416
    WIDTH = 416
    
    
    model = model = Deeplabv3(classes=2,input_shape=(HEIGHT,WIDTH,3))
    model.load_weights("logs/ep006-loss0.023-val_loss0.030.h5")
    imgs = os.listdir("./img")
    
    for jpg in imgs:
    
        img = Image.open("./img/"+jpg)
        old_img = copy.deepcopy(img)
        orininal_h = np.array(img).shape[0]
        orininal_w = np.array(img).shape[1]
    
        img = img.resize((WIDTH,HEIGHT))
        img = np.array(img)
        img = img/255
        img = img.reshape(-1,HEIGHT,WIDTH,3)
        pr = model.predict(img)[0]
    
        pr = pr.reshape((int(HEIGHT), int(WIDTH),NCLASSES)).argmax(axis=-1)
    
        seg_img = np.zeros((int(HEIGHT), int(WIDTH),3))
        colors = class_colors
    
        for c in range(NCLASSES):
            seg_img[:,:,0] += ( (pr[:,: ] == c )*( colors[c][0] )).astype('uint8')
            seg_img[:,:,1] += ((pr[:,: ] == c )*( colors[c][1] )).astype('uint8')
            seg_img[:,:,2] += ((pr[:,: ] == c )*( colors[c][2] )).astype('uint8')
    
        seg_img = Image.fromarray(np.uint8(seg_img)).resize((orininal_w,orininal_h))
    
        image = Image.blend(old_img,seg_img,0.3)
        image.save("./img_out/"+jpg)
    

    训练结果

    原图:
    在这里插入图片描述
    这么大的模型真的分分钟过拟合,可以给你们看看过拟合后的结果。

    划重点哈!

    • 这是过拟合的画面。
    • 这是过拟合的画面。
    • 这是过拟合的画面。

    想要好的斑马线训练效果建议使用我之前的模型segnet、pspnet此类的,或者使用基于mobilenet的deeplabv3+。
    在这里插入图片描述
    我也训练了基于mobilenetV2的DeeplabV3+模型,效果不错,参数只有200多万个~比segnet还少。
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • deeplabv3+.tar.xz

    2021-02-10 14:23:42
    deeplabv3+.tar.xz
  • 基于深度学习布匹缺陷检测 1 介绍 布匹缺陷可以定义为布匹表面出现的不规则、不连续性、缺陷或不一致性。人工和检测成本高,效率低,引入深度学习自动...DeepLabV3+ 在 stride = 16 的DeepLabv3 模型输出上采样 4x 后

    基于深度学习布匹缺陷检测

    1 介绍

    布匹缺陷可以定义为布匹表面出现的不规则、不连续性、缺陷或不一致性。人工和检测成本高,效率低,引入深度学习自动监测减少成本。

    2 预备知识

    对机器学习有基本了解
    卷积神经网络的基本思想
    理解卷积,最大池化和上采样操作
    了解
    DeeplabV3++的架构理念

    3图像分割

    图像分割就是把图像分成若干个特定的、具有独特性质的区域并提出感兴趣目标的技术和过程。

    4 训练模型

    模型结构
    在这里插入图片描述
    DeepLabV3+ 在 stride = 16 的DeepLabv3 模型输出上采样 4x 后,将 DCNN 中 0.25x 的输出使用11卷积降维后与之连接(concat)再使用33卷积处理后双线性插值上采样 4 倍后得到相对于 DeepLabv3 更精细的结果。
    实现代码如下

    from __future__ import absolute_import, print_function
    
    from collections import OrderedDict
    
    import torch
    import torch.nn as nn
    import torch.nn.functional as F
    
    
    class _ASPP(nn.Module):
        """
        Atrous spatial pyramid pooling with image-level feature
        """
    
        def __init__(self, in_ch, out_ch, rates):
            super(_ASPP, self).__init__()
            self.stages = nn.Module()
            self.stages.add_module("c0", _ConvBnReLU(in_ch, out_ch, 1, 1, 0, 1))
            for i, rate in enumerate(rates):
                self.stages.add_module(
                    "c{}".format(i + 1),
                    _ConvBnReLU(in_ch, out_ch, 3, 1, padding=rate, dilation=rate),
                )
            self.stages.add_module("imagepool", _ImagePool(in_ch, out_ch))
    
        def forward(self, x):
            return torch.cat([stage(x) for stage in self.stages.children()], dim=1)
    
    
    class DeepLabV3Plus(nn.Module):
        """
        DeepLab v3+: Dilated ResNet with multi-grid + improved ASPP + decoder
        """
    
        def __init__(self, n_classes, n_blocks, atrous_rates, multi_grids, output_stride):
            super(DeepLabV3Plus, self).__init__()
    
            # Stride and dilation
            if output_stride == 8:
                s = [1, 2, 1, 1]
                d = [1, 1, 2, 4]
            elif output_stride == 16:
                s = [1, 2, 2, 1]
                d = [1, 1, 1, 2]
    
            # Encoder
            ch = [64 * 2 ** p for p in range(6)]
            self.layer1 = _Stem(ch[0])
            self.layer2 = _ResLayer(n_blocks[0], ch[0], ch[2], s[0], d[0])
            self.layer3 = _ResLayer(n_blocks[1], ch[2], ch[3], s[1], d[1])
            self.layer4 = _ResLayer(n_blocks[2], ch[3], ch[4], s[2], d[2])
            self.layer5 = _ResLayer(n_blocks[3], ch[4], ch[5], s[3], d[3], multi_grids)
            self.aspp = _ASPP(ch[5], 256, atrous_rates)
            concat_ch = 256 * (len(atrous_rates) + 2)
            self.add_module("fc1", _ConvBnReLU(concat_ch, 256, 1, 1, 0, 1))
    
            # Decoder
            self.reduce = _ConvBnReLU(256, 48, 1, 1, 0, 1)
            self.fc2 = nn.Sequential(
                OrderedDict(
                    [
                        ("conv1", _ConvBnReLU(304, 256, 3, 1, 1, 1)),
                        ("conv2", _ConvBnReLU(256, 256, 3, 1, 1, 1)),
                        ("conv3", nn.Conv2d(256, n_classes, kernel_size=1)),
                    ]
                )
            )
    
        def forward(self, x):
            h = self.layer1(x)
            h = self.layer2(h)
            h_ = self.reduce(h)
            h = self.layer3(h)
            h = self.layer4(h)
            h = self.layer5(h)
            h = self.aspp(h)
            h = self.fc1(h)
            h = F.interpolate(h, size=h_.shape[2:], mode="bilinear", align_corners=False)
            h = torch.cat((h, h_), dim=1)
            h = self.fc2(h)
            h = F.interpolate(h, size=x.shape[2:], mode="bilinear", align_corners=False)
            return h
    
    
    try:
        from encoding.nn import SyncBatchNorm
    
        _BATCH_NORM = SyncBatchNorm
    except:
        _BATCH_NORM = nn.BatchNorm2d
    
    _BOTTLENECK_EXPANSION = 4
    
    
    class _ConvBnReLU(nn.Sequential):
        """
        Cascade of 2D convolution, batch norm, and ReLU.
        """
    
        BATCH_NORM = _BATCH_NORM
    
        def __init__(
                self, in_ch, out_ch, kernel_size, stride, padding, dilation, relu=True
        ):
            super(_ConvBnReLU, self).__init__()
            self.add_module(
                "conv",
                nn.Conv2d(
                    in_ch, out_ch, kernel_size, stride, padding, dilation, bias=False
                ),
            )
            self.add_module("bn", _BATCH_NORM(out_ch, eps=1e-5, momentum=0.999))
    
            if relu:
                self.add_module("relu", nn.ReLU())
    
    
    class _Bottleneck(nn.Module):
        """
        Bottleneck block of MSRA ResNet.
        """
    
        def __init__(self, in_ch, out_ch, stride, dilation, downsample):
            super(_Bottleneck, self).__init__()
            mid_ch = out_ch // _BOTTLENECK_EXPANSION
            self.reduce = _ConvBnReLU(in_ch, mid_ch, 1, stride, 0, 1, True)
            self.conv3x3 = _ConvBnReLU(mid_ch, mid_ch, 3, 1, dilation, dilation, True)
            self.increase = _ConvBnReLU(mid_ch, out_ch, 1, 1, 0, 1, False)
            self.shortcut = (
                _ConvBnReLU(in_ch, out_ch, 1, stride, 0, 1, False)
                if downsample
                else lambda x: x  # identity
            )
    
        def forward(self, x):
            h = self.reduce(x)
            h = self.conv3x3(h)
            h = self.increase(h)
            h += self.shortcut(x)
            return F.relu(h)
    
    
    class _ResLayer(nn.Sequential):
        """
        Residual layer with multi grids
        """
    
        def __init__(self, n_layers, in_ch, out_ch, stride, dilation, multi_grids=None):
            super(_ResLayer, self).__init__()
    
            if multi_grids is None:
                multi_grids = [1 for _ in range(n_layers)]
            else:
                assert n_layers == len(multi_grids)
    
            # Downsampling is only in the first block
            for i in range(n_layers):
                self.add_module(
                    "block{}".format(i + 1),
                    _Bottleneck(
                        in_ch=(in_ch if i == 0 else out_ch),
                        out_ch=out_ch,
                        stride=(stride if i == 0 else 1),
                        dilation=dilation * multi_grids[i],
                        downsample=(True if i == 0 else False),
                    ),
                )
    
    
    class _Stem(nn.Sequential):
        """
        The 1st conv layer.
        Note that the max pooling is different from both MSRA and FAIR ResNet.
        """
    
        def __init__(self, out_ch):
            super(_Stem, self).__init__()
            self.add_module("conv1", _ConvBnReLU(3, out_ch, 7, 2, 3, 1))
            self.add_module("pool", nn.MaxPool2d(3, 2, 1, ceil_mode=True))
    
    
    if __name__ == "__main__":
        model = DeepLabV3Plus(
            n_classes=21,
            n_blocks=[3, 4, 23, 3],
            atrous_rates=[6, 12, 18],
            multi_grids=[1, 2, 4],
            output_stride=16,
        )
        model.eval()
        image = torch.randn(1, 3, 513, 513)
    
        print(model)
        print("input:", image.shape)
        print("output:", model(image).shape)
    

    结果如下:
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • DeepLabv3+分析

    2021-04-03 20:23:11
    DeepLabv3+ Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation 原文地址:DeepLabv3+ 注意本文的一作Liang−ChiehChen参与了DeepLab系列,MaskLab和MobileNet系列的工...
  • DeepLabv3Plus-Pytorch DeepLabv3DeepLabv3 +和VOC和Cityscapes上的预训练权重。 可用架构 使用“ --model ARCH_NAME”指定模型体系结构,并使用“ --output_stride OUTPUT_STRIDE”设置输出步幅。 DeepLabV3 ...
  • deeplabV3+_pytorch.zip

    2021-02-09 15:00:46
    deeplabV3+ pytorch版的代码进行了解析,比较详细,有助于大家理解
  • DeepLabv3+是一种非常先进的基于深度学习的图像语义分割方法,可对物体进行像素级分割。 本课程将手把手地教大家使用labelme图像标注工具制作数据集,并使用DeepLabv3+训练自己的数据集,从而能开展自己的图像语义...
  • 【windows10】使用pytorch版本deeplabv3+训练自己数据集

    千次阅读 热门讨论 2020-05-31 16:26:30
    最近工作需要用到语义分割,跑了一个deeplabv3+的模型,deeplabv3+是一个非常不错的语义分割模型,目前使用也比较广泛,目前在网上的教程中大多都是基于tersorflow的deeplabv3+,而博主用的是pytorch,在网上搜索的...
  • 用于blog中实现DeepLabv3+在自己数据集上训练,可直接加载该文件。用于blog中实现DeepLabv3+在自己数据集上训练,可直接加载该文件。
  • DeepLabv3+是一种非常先进的基于深度学习的图像语义分割方法,可对物体进行像素级分割。 本课程将手把手地教大家使用labelme图像标注工具制作数据集,并使用DeepLabv3+训练自己的数据集,从而能开展自己的...
  • DeepLabv3+ 模型详解

    千次阅读 2020-11-20 09:31:07
    DeepLabv3+ 模型详解 文章目录DeepLabv3+ 模型详解1 简介2 Encoder2.1 ResNet-101 as Network Backbone2.1.1 问:在“基础”的卷积神经网络中持续叠加更深的层数会发生什么?2.1.2 问:为什么ResNet中的残差模块会...
  • deeplabv3+复现

    2020-07-13 09:20:02
    deeplabv3+复现实验 1. 数据集 1.1 下载整理 参考:https://blog.csdn.net/github_36923418/article/details/81453519 deeplabv3+中说明,文章使用的数据集是VOC2012,并通过SBD的方法进行了数据增强 VOC2012数据集...
  • DeepLabV3+语义分割实战

    2021-02-11 06:03:15
    DeepLabV3+语义分割实战 语义分割是计算机视觉的一项重要任务,本文使用Jittor框架实现了DeepLabV3+语义分割模型。 DeepLabV3+论文:https://arxiv.org/pdf/1802.02611.pdf 完整代码:...
  • 使用 deeplabv3+ 训练自己的数据集经验总结

    万次阅读 多人点赞 2018-08-22 20:00:31
    deeplabv3+是现今性能最好的语义分割模型之一,本文介绍如何在window环境下安装并运行deeplabv3+。 本文将详细介绍deeplabv3+的环境配置,训练自己的数据,参数调试等内容。 Update: 2018-8-22 环境搭建,数据...
  • DeepLabv3+实现

    千次阅读 2019-04-08 16:32:53
    参考: 官网分割描述 TensorFlow实战:Chapter-9上(DeepLabv3+代码实现)
  • 使用deeplabv3+实现遥感图片的农作物区域分割,包括水稻,小麦,玉米
  • DeeplabV3+学习笔记

    2021-04-24 20:55:09
    DeeplabV3+网络结构 话不多说,先上图: 其主要结构分为两个部分:encoder(编码器)和decoder(解码器) 我们知道,想要解决与对象边界相关的详细信息丢失的问题,我们可以采用空洞卷积、增大感受野的方法来解决;...
  • Deeplabv3 +的Keras实现 Deeplabv3 +的Keras实现 DeepLab是用于语义图像分割的最先进的深度学习模型。 模型基于原始的TF冻结图。 可以将预训练的权重加载到此模型中。 权重直接从原始TF检查点导入。 如何获得标签 ...
  • DeepLabv3+论文

    千次阅读 2019-12-12 09:45:22
    原文地址:DeepLabv3+ 代码复现:TensorFlow 摘要:在深度神经网络中,空间金字塔池化模块或编码解码器结构都常被用于解决语义分割任务。前者的网络能够对多种采样率和多个感受野进行滤波和池化操作来探查传入特征,...
  • deeplabv3+训练自己的数据集 环境:ubuntu 16.04 + TensorFlow 1.9.1 + cuda 9.0 + cudnn 7.0 +python3.6 tensorflow 项目链接 https://github.com/tensorflow/models.git (deeplabv3+) 1、添加依赖库到...
  • deeplabv3+及pytorch实现

    千次阅读 2020-08-25 10:00:07
    deeplab系列 DeepLabV3+ 基本原理及Pytorch版注解 用PyTorch搞定GluonCV预训练模型,这个计算机视觉库真的很好用
  • matlab精度检验代码预训练的DeepLabv3 +网络用于语义分割 该存储库为MATLAB:registered:提供了预训练的DeepLabv3 + [1]语义细分模型。 要求 MATLAB:registered:R2020a或更高版本。 深度学习工具箱:trade_mark:。 ...
  • deeplabv3+训练的ckpt模型Android端部署 接上一篇文章用deeplabV3+训练自己的数据集并导出.pb模型进行可视化测试 一.对deeplabv3+训练的ckpt模型做量化 参考官方文档 修改train.py文件 flags.DEFINE_string('train_...
  • 目录1.deeplabv3+整体结构2.train.py 读源码太痛苦了,各种看不懂。因为刚接触语义分割用了deeplab这个模型,想好好地把源码看一下。读第一遍只能把API查一下,了解函数的作用。这是读的第二遍,把各模块的注释写...
  • DeeplabV3+总结

    千次阅读 2019-10-16 14:25:36
    Abstract 网络中靠前的层可以通过在不同级别(rates ...DeepLabv3+结合以上两种特点.具体是: 通过添加一个简单但是很有效的解码模块去扩展DeepLabv3, 通过物体边界信息改进分割结果. 探索Xecption模型, 将depth...
  • DeepLabV3 +网络把 DeepLabV3 网络作为编码器,利用 atrous convolution 生成任意维度的特征,并采用 ...DeepLabv3+网络模型模块 输入: 包含标记目标图像的 tfrecord 格式数据。 输出: 包含脆性区域目标的二值图。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 838
精华内容 335
关键字:

deeplabv3+