精华内容
下载资源
问答
  • 语义分割

    2021-03-26 19:35:21
    语义分割 图像分割分成二个大类即语义分割和实例分割。因为我的研究方向是语义分割方向,所以我现在更的想法就是分享一下我对于语义分割的看法与自己每天看的语义分割论文。其中主要是自己每天会看的顶会论文和GAN...

    语义分割

    图像分割分成二个大类即语义分割和实例分割。因为我的研究方向是语义分割方向,所以我现在更的想法就是分享一下我对于语义分割的看法与自己每天看的语义分割论文。其中主要是自己每天会看的顶会论文和GAN方面的论文、
    语义分割简单来说就是将不同的物件与物件所处的场景分割开来,同时对于同一物件,还给予了不同的标注。

    2021CVPR论文GitHub
    图像分割模型的基本架构包括编码器与解码器。编码器通过卷积核提取图像特征。解码器负责输出包含物体轮廓的分割。其中最常见的网络是u-net和DeepLab 。
    U-Net 最初是一个用于分割生物医学图像的卷积神经网络。它的架构由两部分组成,左侧是提取路径,右侧是扩展路径。提取路径用来捕获上下文,扩展路径用来精准定位。提取路径由两个 33 的卷积组成。卷积后经过 ReLU 激活和用于降采样的 22 最大池化计算。
    在 DeepLab 架构网络带有上采样滤波器的卷积被用于密集预测型任务。多尺度的物体分割是通过空洞空间金字塔池化(atrous spatial pyramid pooling)完成的。最后,使用 DCNN 来提升物体边界的定位精准度。通过在上采样滤波器过程中插入 0 或对输入特征图稀疏采样,来实现空洞卷积。
    损失函数
    就我个人看最近的语义分割文章来看,对于损失函数来说用的较多的损失函数是最小交叉熵和最大均方误差这二个损失函数。
    最小交叉熵
    最小交叉熵是衡量二个分布之间距离的刻度,当交叉熵最小的时候说明二个分布的距离,交叉熵大就说明二个分布的距离越大。
    H(p,q)=xp(x)logq(x) H(p, q)=-\sum_{x} p(x) \log q(x)
    这里我们要注意的是,p和q的交叉熵与q和p的交叉熵是不一样的。其中p是预测值,q是预测值。
    最大均方误差
    均方误差的意思是从一个样本当中的输出与期望的差值的平方的平均值。
    MES(y,y)=i=1n(yiyi)2n M E S\left(y, y^{\prime}\right)=\frac{\sum_{i=1}^{n}\left(y_{i}-y_{i}^{\prime}\right)^{2}}{n}
    在回归问题上采用最大均方误差作为损失函数的较多。
    个人感受
    1.特殊的卷积(1)Astrous Convolutions(扩张卷积)空洞卷积(dilated convolution)是针对图像语义分割问题中下采样会降低图像分辨率、丢失信息而提出的一种卷积思路。利用添加空洞扩大感受野,让原本3x3的卷积核,在相同参数量和计算量下拥有5x5(dilated rate =2)或者更大的感受野,从而无需下采样。扩张卷积又名空洞卷积(atrous convolutions),向卷积层引入了一个称为 “扩张率(dilation rate)”的新参数,该参数定义了卷积核处理数据时各值的间距。换句话说,相比原来的标准卷积,扩张卷积多了一个hyper-parameter(超参数)称之为dilation rate(扩张率),指的是kernel各点之前的间隔数量,【正常的convolution 的 dilatation rate为 1】。
    (2)深度可分离卷积SeparableConv2D实现整个深度分离卷积过程,即深度方向的空间卷积 (分别作用于每个输入通道)+ 输出通道混合在一起的逐点卷积。DepthwiseConv2D仅仅实现前半部分的空间卷积 (分别作用于每个输入通道)。(3)可变形卷积卷积神经网络(CNNs)由于其固定的几何结构而固有地局限于模型几何变换。可变形卷积和可变形RoI池。两者都是基于模块中的增加空间采样位置的想法,其中带有额外的偏移量并学习目标任务的偏移量,不需要额外的监督。新的模块可以很容易地取代现有CNN中的普通对等体,并且可以很容易地通过标准的反向传播来进行端到端的训练,从而产生可变形卷积网络。
    2.空间金字塔池化等下采样技术。如上述模型中的ASPP模块及JPU模块,并且可以以此技术来相互组合达到更好的效果。
    3.CRF(条件随机场)在基于深度学习的语义图像分割体系结构,CRF是一个有用的后处理模块,但是主要缺点是不能将其用作端到端体系结构的一部分。在标准CRF模型中,可以表示成对电位用加权高斯函数的和。但是由于精确的极小化是否考虑了CRF分布的平均场近似用一个简单的产品版本来表示发行版独立的边际分布。它的平均场近似原生形式不适合反向传播。4.Loss函数的更改(1)二分类大名鼎鼎的focal loss,focal loss的提出是在目标检测领域,为了解决正负样本比例严重失衡的问题。是由log loss改进而来的。

    展开全文
  • 本教程利用MATLAB进行图像语义分割,从语义分割概念、模型搭建、图像标记、模型测试完整的展示了MATLAB语义分割的全过程。(本博主提供一对一技术支持服务,有需要的同学可以私信我哦)
  • 憨批的语义分割12——Keras 搭建自己的Unet语义分割平台注意事项学习前言什么是Unet模型代码下载Unet实现思路一、预测部分1、主干网络介绍2、加强特征提取结构3、利用特征获得预测结果二、训练部分1、训练文件详解2...

    注意事项

    这是重新构建了的Unet语义分割网络,主要是文件框架上的构建,还有代码的实现,和之前的语义分割网络相比,更加完整也更清晰一些。建议还是学习这个版本的Unet。

    学习前言

    重置一下我最喜欢的Unet。
    在这里插入图片描述

    什么是Unet模型

    Unet是一个优秀的语义分割模型,其主要执行过程与其它语义分割模型类似。

    Unet可以分为三个部分,如下图所示:

    第一部分是主干特征提取部分,我们可以利用主干部分获得一个又一个的特征层,Unet的主干特征提取部分与VGG相似,为卷积和最大池化的堆叠。利用主干特征提取部分我们可以获得五个初步有效特征层,在第二步中,我们会利用这五个有效特征层可以进行特征融合。

    第二部分是加强特征提取部分,我们可以利用主干部分获取到的五个初步有效特征层进行上采样,并且进行特征融合,获得一个最终的,融合了所有特征的有效特征层

    第三部分是预测部分,我们会利用最终获得的最后一个有效特征层对每一个特征点进行分类,相当于对每一个像素点进行分类。
    在这里插入图片描述

    代码下载

    Github源码下载地址为:
    https://github.com/bubbliiiing/unet-keras

    Unet实现思路

    一、预测部分

    1、主干网络介绍

    在这里插入图片描述
    Unet的主干特征提取部分由卷积+最大池化组成,整体结构与VGG类似。

    本文所采用的主干特征提取网络为VGG16,这样也方便使用imagnet上的预训练权重。

    VGG是由Simonyan 和Zisserman在文献《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷积神经网络模型,其名称来源于作者所在的牛津大学视觉几何组(Visual Geometry Group)的缩写。

    该模型参加2014年的 ImageNet图像分类与定位挑战赛,取得了优异成绩:在分类任务上排名第二,在定位任务上排名第一。
    它的结构如下图所示:
    在这里插入图片描述
    这是一个VGG16被用到烂的图,但确实很好的反应了VGG16的结构。

    当我们使用VGG16作为主干特征提取网络的时候,我们只会用到两种类型的层,分别是卷积层最大池化层

    当输入的图像大小为512x512x3的时候,具体执行方式如下:
    1、conv1:进行两次[3,3]的64通道的卷积,获得一个[512,512,64]的初步有效特征层,再进行2X2最大池化,获得一个[256,256,64]的特征层。
    2、conv2:进行两次[3,3]的128通道的卷积,获得一个[256,256,128]的初步有效特征层,再进行2X2最大池化,获得一个[128,128,128]的特征层。
    3、conv3:进行三次[3,3]的256通道的卷积,获得一个[128,128,256]的初步有效特征层,再进行2X2最大池化,获得一个[64,64,256]的特征层。
    4、conv4:进行三次[3,3]的512通道的卷积,获得一个[64,64,512]的初步有效特征层,再进行2X2最大池化,获得一个[32,32,512]的特征层。
    5、conv5:进行三次[3,3]的512通道的卷积,获得一个[32,32,512]的初步有效特征层。

    在这里插入图片描述

    from keras import layers
    
    def VGG16(img_input):
        # Block 1
        x = layers.Conv2D(64, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block1_conv1')(img_input)
        x = layers.Conv2D(64, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block1_conv2')(x)
        feat1 = x
        x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)
    
        # Block 2
        x = layers.Conv2D(128, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block2_conv1')(x)
        x = layers.Conv2D(128, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block2_conv2')(x)
        feat2 = x
        x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)
    
    
        # Block 3
        x = layers.Conv2D(256, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block3_conv1')(x)
        x = layers.Conv2D(256, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block3_conv2')(x)
        x = layers.Conv2D(256, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block3_conv3')(x)
        feat3 = x
        x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
    
        # Block 4
        x = layers.Conv2D(512, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block4_conv1')(x)
        x = layers.Conv2D(512, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block4_conv2')(x)
        x = layers.Conv2D(512, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block4_conv3')(x)
        feat4 = x
    
        x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
    
        # Block 5
        x = layers.Conv2D(512, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block5_conv1')(x)
        x = layers.Conv2D(512, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block5_conv2')(x)
        x = layers.Conv2D(512, (3, 3),
                          activation='relu',
                          padding='same',
                          name='block5_conv3')(x)
        feat5 = x
        return feat1, feat2, feat3, feat4, feat5
    

    2、加强特征提取结构

    在这里插入图片描述
    Unet所使用的加强特征提取网络是一个U的形状。

    利用第一步我们可以获得五个初步的有效特征层,在加强特征提取网络这里,我们会利用这五个初步的有效特征层进行特征融合特征融合的方式就是对特征层进行上采样并且进行堆叠

    为了方便网络的构建与更好的通用性,我们的Unet和上图的Unet结构有些许不同,在上采样时直接进行两倍上采样再进行特征融合,最终获得的特征层和输入图片的高宽相同。

    具体示意图如下:
    在这里插入图片描述

    import numpy as np
    from keras.models import *
    from keras.layers import *
    from nets.vgg16 import VGG16
    
    def Unet(input_shape=(256,256,3), num_classes=21):
        inputs = Input(input_shape)
        feat1, feat2, feat3, feat4, feat5 = VGG16(inputs) 
          
        channels = [64, 128, 256, 512]
    
        P5_up = UpSampling2D(size=(2, 2))(feat5)
        P4 = Concatenate(axis=3)([feat4, P5_up])
        P4 = Conv2D(channels[3], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P4)
        P4 = Conv2D(channels[3], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P4)
    
        P4_up = UpSampling2D(size=(2, 2))(P4)
        P3 = Concatenate(axis=3)([feat3, P4_up])
        P3 = Conv2D(channels[2], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P3)
        P3 = Conv2D(channels[2], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P3)
    
        P3_up = UpSampling2D(size=(2, 2))(P3)
        P2 = Concatenate(axis=3)([feat2, P3_up])
        P2 = Conv2D(channels[1], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P2)
        P2 = Conv2D(channels[1], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P2)
    
        P2_up = UpSampling2D(size=(2, 2))(P2)
        P1 = Concatenate(axis=3)([feat1, P2_up])
        P1 = Conv2D(channels[0], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P1)
        P1 = Conv2D(channels[0], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P1)
    
        P1 = Conv2D(num_classes, 1, activation="softmax")(P1)
    
        model = Model(inputs=inputs, outputs=P1)
        return model
    

    3、利用特征获得预测结果

    利用1、2步,我们可以获取输入进来的图片的特征,此时,我们需要利用特征获得预测结果。

    利用特征获得预测结果的过程为:
    利用一个1x1卷积进行通道调整,将最终特征层的通道数调整成num_classes。
    在这里插入图片描述

    import numpy as np
    from keras.models import *
    from keras.layers import *
    from nets.vgg16 import VGG16
    
    def Unet(input_shape=(256,256,3), num_classes=21):
        inputs = Input(input_shape)
        feat1, feat2, feat3, feat4, feat5 = VGG16(inputs) 
          
        channels = [64, 128, 256, 512]
    
        P5_up = UpSampling2D(size=(2, 2))(feat5)
        P4 = Concatenate(axis=3)([feat4, P5_up])
        P4 = Conv2D(channels[3], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P4)
        P4 = Conv2D(channels[3], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P4)
    
        P4_up = UpSampling2D(size=(2, 2))(P4)
        P3 = Concatenate(axis=3)([feat3, P4_up])
        P3 = Conv2D(channels[2], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P3)
        P3 = Conv2D(channels[2], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P3)
    
        P3_up = UpSampling2D(size=(2, 2))(P3)
        P2 = Concatenate(axis=3)([feat2, P3_up])
        P2 = Conv2D(channels[1], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P2)
        P2 = Conv2D(channels[1], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P2)
    
        P2_up = UpSampling2D(size=(2, 2))(P2)
        P1 = Concatenate(axis=3)([feat1, P2_up])
        P1 = Conv2D(channels[0], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P1)
        P1 = Conv2D(channels[0], 3, activation='relu', padding='same', kernel_initializer='he_normal')(P1)
    
        P1 = Conv2D(num_classes, 1, activation="softmax")(P1)
    
        model = Model(inputs=inputs, outputs=P1)
        return model
    

    二、训练部分

    1、训练文件详解

    我们使用的训练文件采用VOC的格式。
    语义分割模型训练的文件分为两部分。
    第一部分是原图,像这样:
    在这里插入图片描述
    第二部分标签,像这样:
    在这里插入图片描述
    原图就是普通的RGB图像,标签就是灰度图或者8位彩色图。

    原图的shape为[height, width, 3],标签的shape就是[height, width],对于标签而言,每个像素点的内容是一个数字,比如0、1、2、3、4、5……,代表这个像素点所属的类别。

    语义分割的工作就是对原始的图片的每一个像素点进行分类,所以通过预测结果中每个像素点属于每个类别的概率与标签对比,可以对网络进行训练。

    2、LOSS解析

    本文所使用的LOSS由两部分组成:
    1、Cross Entropy Loss。
    2、Dice Loss。

    Cross Entropy Loss就是普通的交叉熵损失,当语义分割平台利用Softmax对像素点进行分类的时候,进行使用。

    Dice loss将语义分割的评价指标作为Loss,Dice系数是一种集合相似度度量函数,通常用于计算两个样本的相似度,取值范围在[0,1]。

    计算公式如下:
    在这里插入图片描述
    就是预测结果和真实结果的交乘上2,除上预测结果加上真实结果。其值在0-1之间。越大表示预测结果和真实结果重合度越大。所以Dice系数是越大越好。

    如果作为LOSS的话是越小越好,所以使得Dice loss = 1 - Dice,就可以将Loss作为语义分割的损失了。
    实现代码如下:

    def dice_loss_with_CE(beta=1, smooth = 1e-5, alpha = 0.25, gamma=2.0, threhold=0.5):
        def _dice_loss_with_CE(y_true, y_pred):
            y_pred = K.clip(y_pred, K.epsilon(), 1.0 - K.epsilon())
    
            CE_loss = - y_true[...,:-1] * K.log(y_pred)
            CE_loss = K.mean(K.sum(CE_loss, axis = -1))
    
            tp = K.sum(y_true[...,:-1] * y_pred, axis=[0,1,2])
            fp = K.sum(y_pred         , axis=[0,1,2]) - tp
            fn = K.sum(y_true[...,:-1], axis=[0,1,2]) - tp
    
            score = ((1 + beta ** 2) * tp + smooth) / ((1 + beta ** 2) * tp + beta ** 2 * fn + fp + smooth)
            score = tf.reduce_mean(score)
            dice_loss = 1 - score
            # dice_loss = tf.Print(dice_loss, [dice_loss, focal_loss])
            return CE_loss + dice_loss
        return _dice_loss_with_CE
    

    训练自己的Unet模型

    整个Unet的文件构架为:
    在这里插入图片描述
    在训练模型之前,我们需要首先准备好数据集。
    大家可以下载我上传的voc数据集,也可以根据voc数据集格式进行数据集制作。
    在这里插入图片描述
    如果大家下载的是我上传的voc数据集,那么就不需要运行VOCdevkit文件夹下面的voc2unet.py。
    如果是自己制作的数据集,那么需要运行VOCdevkit文件夹下面的voc2unet.py,从而生成train.txt和val.txt。
    在这里插入图片描述
    生成完成后。
    修改train.py文件下的num_classes,使其为分的类的个数+1。
    在这里插入图片描述
    之后就可以开始训练了。
    在这里插入图片描述

    展开全文
  • 语义分割 这是一个使用从Unreal Engine获得的综合数据集进行语义分割的小项目。 任务是使用插件从Unreal Engine创建合成数据集并识别图像中的对象。 数据集由RGBD(RGB +深度)图像和地面真实情况组成。 环境很简单...
  • 语义分割语义分割评估指标mIOU

    万次阅读 多人点赞 2019-05-22 15:47:33
    语义分割评估指标计算公式可参考:基于深度学习的图像语义分割技术概述之5.1度量标准 mIOU定义 Mean Intersection over Union(MIoU,均交并比):为语义分割的标准度量。其计算两个集合的交集和并集之比,在语义分割...

    语义分割评估指标计算公式可参考:基于深度学习的图像语义分割技术概述之5.1度量标准

    mIOU定义

    Mean Intersection over Union(MIoU,均交并比):为语义分割的标准度量。其计算两个集合的交并比,在语义分割的问题中,这两个集合为真实值(ground truth)和预测值(predicted segmentation)。计算公式如下:
    i表示真实值,j表示预测值pijp_{ij} 表示将i预测为j

    MIoU=1k+1i=0kpiij=0kpij+j=0kpjipii M I o U=\frac{1}{k+1} \sum_{i=0}^{k} \frac{p_{i i}}{\sum_{j=0}^{k} p_{i j}+\sum_{j=0}^{k} p_{j i}-p_{i i}}
    等价于:
    MIoU=1k+1i=0kTPFN+FP+TP M I o U=\frac{1}{k+1} \sum_{i=0}^{k} \frac{TP}{{FN}+{FP}+{TP}}
    先求每个类别的交并比,再平均

    直观理解

    在这里插入图片描述
    MIoU:计算两圆交集(橙色部分)与两圆并集(红色+橙色+黄色)之间的比例,理想情况下两圆重合,比例为1。

    mIOU实现

    步骤一:先求混淆矩阵

    在这里插入图片描述

    步骤二:再求mIOU

    混淆矩阵的每一行再加上每一列,最后减去对角线上的值

    import numpy as np
    
    class IOUMetric:
        """
        Class to calculate mean-iou using fast_hist method
        """
    
        def __init__(self, num_classes):
            self.num_classes = num_classes
            self.hist = np.zeros((num_classes, num_classes))
    
        def _fast_hist(self, label_pred, label_true):
            # 找出标签中需要计算的类别,去掉了背景
            mask = (label_true >= 0) & (label_true < self.num_classes)
            # # np.bincount计算了从0到n**2-1这n**2个数中每个数出现的次数,返回值形状(n, n)
            hist = np.bincount(
                self.num_classes * label_true[mask].astype(int) +
                label_pred[mask], minlength=self.num_classes ** 2).reshape(self.num_classes, self.num_classes)
            return hist
    
        # 输入:预测值和真实值
        # 语义分割的任务是为每个像素点分配一个label
        def ev aluate(self, predictions, gts):
            for lp, lt in zip(predictions, gts):
                assert len(lp.flatten()) == len(lt.flatten())
                self.hist += self._fast_hist(lp.flatten(), lt.flatten())
                
            # miou
            iou = np.diag(self.hist) / (self.hist.sum(axis=1) + self.hist.sum(axis=0) - np.diag(self.hist))
            miou = np.nanmean(iou) 
            
            # -----------------其他指标------------------------------
            # mean acc
            acc = np.diag(self.hist).sum() / self.hist.sum()
            acc_cls = np.nanmean(np.diag(self.hist) / self.hist.sum(axis=1))
    
            freq = self.hist.sum(axis=1) / self.hist.sum()
            fwavacc = (freq[freq > 0] * iou[freq > 0]).sum()
    
            return acc, acc_cls, iou, miou, fwavacc
    

    参考:mIoU源码解析

    展开全文
  • 语义分割 语义分类Hello There! This post is about a road surface semantic segmentation approach. So the focus here is on the road surface patterns, like: what kind of pavement the vehicle is driving on...

    语义分割 语义分类

    Hello There! This post is about a road surface semantic segmentation approach. So the focus here is on the road surface patterns, like: what kind of pavement the vehicle is driving on or if there is any damage on the road, also the road markings and speed-bumps as well and other things that can be relevant for a vehicular navigation task.

    你好! 这篇文章是关于路面语义分割方法的。 因此,这里的重点是路面模式,例如:车辆行驶在哪种路面上或道路上是否有损坏,还有道路标记和减速带以及其他与路面相关的事项车辆导航任务。

    Here I will show you the step-by-step approach based on the preprint paper available at ResearchGate [1]. The Ground Truth and the experiments were made using the RTK dataset [2], with images captured with a low-cost camera, containing images of roads with different types of pavement and different conditions of pavement quality.

    在这里,我将向您展示基于ResearchGate [1]上预印本的分步方法。 地面真相和实验是使用RTK数据集 [2]进行的,其中使用低成本相机捕获的图像包含了具有不同类型路面和不同路面质量条件的道路图像。

    It was fun to work on it and I’m excited to share it, I hope you enjoy it too. 🤗

    进行这项工作很有趣,很高兴与大家分享,希望您也喜欢。 🤗

    介绍 (Introduction)

    The purpose of this approach is to verify the effectiveness of using passive vision (camera) to detect different patterns on the road. For example, to identify if the road surface is an asphalt or cobblestone or an unpaved (dirt) road? This may be relevant for an intelligent vehicle, whether it is an autonomous vehicle or an Advanced Driver-Assistance System (ADAS). Depending on the type of pavement it may be necessary to adapt the way the vehicle is driven, whether for the safety of users or the conservation of the vehicle or even for the comfort of people inside the vehicle.

    该方法的目的是验证使用被动视觉(摄像机)检测道路上不同模式的有效性。 例如,确定路面是沥青路面还是鹅卵石路面还是未铺砌的(污垢)道路? 这可能与智能车辆有关,无论它是自动驾驶汽车还是高级驾驶员辅助系统(ADAS)。 取决于路面的类型,可能出于驾驶员的安全性或车辆的保护,甚至为了车内人员的舒适性,需要调整车辆的行驶方式。

    Another relevant factor of this approach is related to the detection of potholes and water-puddles, which could generate accidents, damage the vehicles and can be quite common in developing countries. This approach can also be useful for departments or organizations responsible for maintaining highways and roads.

    此方法的另一个相关因素与坑洼和水坑的检测有关,坑坑和水坑可能会导致事故,损坏车辆,并且在发展中国家非常普遍。 这种方法对于负责维护公路和公路的部门或组织也很有用。

    To achieve these objectives, Convolutional Neural Networks (CNN) were used for the semantic segmentation of the road surface, I’ll talk more about that in next sections.

    为了实现这些目标,将卷积神经网络(CNN)用于路面的语义分割,我将在下一节中进一步讨论。

    地面真相 (Ground Truth)

    To train the neural network and to test and validate the results, a Ground Truth (GT) was created with 701 images from the RTK dataset. This GT is available on the dataset page and is composed by the following classes:

    为了训练神经网络并测试和验证结果,使用来自RTK数据集中的701张图像创建了地面真实(GT)。 此GT在数据集页面上可用,并且由以下类组成:

    Image for post
    GT classes [1]
    GT班[1]
    Image for post
    GT Samples [1]
    GT样品[1]

    方法和设置 (The approach and setup)

    Everything done here was done using Google Colab. Which is a free Jupyter notebook environment and give us free access to GPUs and is super easy to use, also very helpful for organization and configuration. It was also used the fastai [3], the amazing deep learning library. To be more precise, the step-by-step that I will present was very much based on one of the lessons given by Jeremy Howard on one the courses about deep learning, in this case lesson3-camvid.

    此处完成的所有操作均使用Google Colab完成。 这是一个免费的Jupyter笔记本环境,可让我们免费访问GPU,而且超级易用,对于组织和配置也非常有帮助。 它还使用了fastai [3],这是一个了不起的深度学习库。 更准确地说,我将逐步讲解的步骤很大程度上是基于杰里米·霍华德(Jeremy Howard)在有关深度学习的课程(在本例中为lesson3-camvid)的课程中提供的课程之一

    The CNN architecture used was the U-NET [4], which is an architecture designed to perform the task of semantic segmentation in medical images, but successfully applied to many other approaches. In addition, ResNet [5] based encoder and a decoder are used. The experiments for this approach were done with resnet34 and resnet50.

    所使用的CNN体​​系结构是U-NET [4],该体系结构旨在执行医学图像中的语义分割任务,但已成功应用于许多其他方法。 另外,使用基于ResNet [5]的编码器和解码器。 使用resnet34和resnet50完成了此方法的实验。

    For the data augmentation step, standard options from the fastai library were used, with horizontal rotations and perspective distortion being applied. With fastai it is possible to take care to make the same variations made in the data augmentation step for both the original and mask (GT) images.

    对于数据增强步骤,使用来自fastai库的标准选项,并应用了水平旋转和透视变形。 使用fastai时 ,可能要注意对原始图像和蒙版(GT)图像在数据扩充步骤中进行相同的更改。

    A relevant point, which was of great importance for the definition of this approach, is that the classes of the GT are quite unbalanced, having much larger pixels of background or surface types (eg.: asphalt, paved or unpaved) than the other classes. Unlike an image classification problem, where perhaps replicating certain images from the dataset could help to balance the classes, in this case, replicating an image would imply further increasing the difference between the number of pixels from the largest to the smallest classes. Then, in the defined approach weights were used in the classes for balancing. 🤔

    对于此方法的定义而言,非常重要的一点是,GT的类别非常不平衡,与其他类别相比,背景或表面类型(例如:沥青,已铺设或未铺设)的像素要大得多。 与图像分类问题不同,在图像分类问题中,也许从数据集中复制某些图像可以帮助平衡类别,在这种情况下,复制图像将意味着从最大类别到最小类别的像素数之间的差进一步增大。 然后,在定义的方法中,将权重用于类中以进行平衡。 🤔

    Based on different experiments, it was realized that just applying the weights is not enough, because when improving the accuracy of the classes that contain a smaller amount of pixels, the classes that contain a larger amount of pixels (eg.: asphalt, paved and unpaved) lost quality in the accuracy results.

    根据不同的实验,我们认识到仅应用权重是不够的,因为当提高包含较少像素数量的类的准确性时,包含较大像素数量的类(例如:沥青,铺砌的和未铺砌)在准确性结果中损失了质量。

    The best accuracy values, considering all classes, without losing much quality for the detection of surface types, was with the following configuration: first training a model without using weights, generating a model with good accuracy for the types of surface, then, use that previously trained model as a basis for the next model that uses the proportional weights for the classes. And that’s it!

    在考虑所有类别的前提下,最好的精度值在不损失检测表面类型的质量的情况下,采用以下配置:首先在不使用权重的情况下训练模型,为表面类型生成具有良好精度的模型,然后使用先前训练的模型,作为使用比例权重的下一个模型的基础。 就是这样!

    You can check the complete code, that I will comment on throughout this post, on GitHub:

    您可以在GitHub上查看完整的代码,以便在本文中进行评论:

    一步步 (Step-by-Step)

    Are you ready?

    你准备好了吗?

    https://giphy.com/https://giphy.com/的 gif

    Cool, so we start by our initial settings, importing the fastai library and the pathlib module. Let’s call this as Step 1.

    太酷了,因此我们从初始设置开始,导入fastai库和pathlib模块。 我们称其为“ 步骤1”

    第1步-初始设置 (Step 1 — Initial settings)

    Road Surface Semantic Segmentation.ipynb路面语义分割

    As we’ll use our dataset from google drive, we need to mount it, so in the next cell type:

    由于我们将使用Google驱动器中的数据集,因此需要对其进行挂载,因此在下一个单元格类型中:

    Road Surface Semantic Segmentation.ipynb路面语义分割

    You’ll see something like the next image, click on the link and you’ll get an authorization code, so just copy and paste the authorization code in the expected field.

    您将看到类似下图的内容,单击链接,您将获得授权码,因此只需将授权码复制并粘贴到期望的字段中即可。

    Image for post
    From author
    来自作者

    Now just access your Google Drive as a file system. This is the start of Step 2, loading our data.

    现在,只需将您的Google云端硬盘作为文件系统访问即可。 这是第2步的开始,即加载我们的数据。

    第2步-准备数据 (Step 2 — Preparing the data)

    Road Surface Semantic Segmentation.ipynb路面语义分割

    Where “image” is the folder containing the original images. The “labels” is the folder containing the masks that we’ll use for our training and validation, these images are 8-bit pixels after a colormap removal process. In “colorLabels” I’ve put the original colored masks, which we can use later for visual comparison. The “valid.txt” file contains a list of images names randomly selected for validation. Finally, the “codes.txt” file contains a list with classes names.

    其中“ image ”是包含原始图像的文件夹。 “ labels ”是一个文件夹,其中包含我们将用于训练和验证的蒙版,这些图像是在去除色图后的8位像素。 在“ colorLabels ”中,我放置了原始的彩色蒙版,以后可以将其用于视觉比较。 “ valid.txt ”文件包含随机选择用于验证的图像名称列表。 最后,“ codes.txt ”文件包含带有类名称的列表。

    Image for post
    From author
    来自作者
    Road Surface Semantic Segmentation.ipynb路面语义分割
    Image for post
    From author
    来自作者

    Now, we define the paths for the original images and for the GT mask images, enabling access to all images in each folder to be used later.

    现在,我们定义原始图像和GT遮罩图像的路径,从而可以访问每个文件夹中的所有图像以供以后使用。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    We can see an example, image 139 from the dataset.

    我们可以看到一个示例,数据集中的图像139。

    Image for post
    From author
    来自作者

    Next, as shown in fastai lesson, we use a function to infer the mask filename from the original image, responsible for the color coding of each pixel.

    接下来,如fastai课程中所示,我们使用一个函数来从原始图像中推断遮罩文件名,该文件名负责每个像素的颜色编码。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    步骤3 —第一步—不加重量 (Step 3 — First Step — Without weights)

    Here we are at the Step 3. Let’s create the DataBunch for training our first model using data block API. Defining where our images come from, which images will be used for validation and and the masks corresponding to each original image. For the data augmentation, the fastai library also gives options, but here we’ll use only the default options with get_transforms(), which consists of randomly horizontal rotations and the perspective warping. Remember to set tfm_y=True in the transform call to ensure that the transformations for the data augmentation in the dataset are the same for each mask and its original image. Imagine if we rotated the original image, but the mask corresponding to that image was not rotated, what a mess it would be! 😵

    现在我们进入第3步 。 让我们创建一个DataBunch来使用数据块API训练我们的第一个模型。 定义图像的来源,将用于验证的图像以及与每个原始图像相对应的蒙版。 对于数据扩充, fastai库还提供了选项,但是在这里,我们将仅将默认选项与get_transforms() ,该选项由随机的水平旋转和透视变形组成。 请记住在转换调用中设置tfm_y=True ,以确保每个蒙版及其原始图像的数据集中数据扩充的转换都相同。 想象一下,如果我们旋转了原始图像,但是与该图像相对应的蒙版没有旋转,那将是多么混乱! 😵

    Road Surface Semantic Segmentation.ipynb路面语义分割

    We continue using the lesson3-camvid example from the fastai course, to define the accuracy metric and the weight decay. I’ve used the resnet34 model since I didn’t have much of a difference using resnet50 in this approach with this dataset. We can find the learning rate using lr_find(learn), which in my case I’ve defined as 1e-4.

    我们继续使用lesson3-camvidfastai当然例如,要定义精度指标和权衰减。 我使用过resnet34模型,因为在此方法中使用resnet50与该数据集没有太大区别。 我们可以使用lr_find(learn)找到学习率,在我的情况下,我将其定义为1e-4

    Road Surface Semantic Segmentation.ipynb路面语义分割
    Image for post
    From author
    来自作者

    Next we run the fit_one_cycle() for 10 times to check how our model is doing.

    接下来,我们运行fit_one_cycle() 10次​​以检查模型的运行情况。

    Road Surface Semantic Segmentation.ipynb路面语义分割
    Image for post
    From author
    来自作者

    Using the confusion matrix we can see how good (or bad) the model is for each class until now…

    使用混淆矩阵,我们可以看到到目前为止每个班级的模型好坏。

    Road Surface Semantic Segmentation.ipynb路面语义分割
    Image for post
    From author
    来自作者

    Don’t forget to save the model we’ve trained until now.

    别忘了保存我们到目前为止训练的模型。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    Now we just train the model over more epochs to improve the learning, and remember to save our final model. The slice keyword is used to take a start and a stop value, so in the first layers begin the training with the start value and this will change until the stop value when reaching the end of the training process.

    现在,我们只是在更多的时期内训练模型以改善学习效果,并记住保存最终模型。 slice关键字用于获取起始值和终止值,因此在第一层中,以起始值开始训练,并且在到达训练过程结束时,它将更改直到终止值。

    Road Surface Semantic Segmentation.ipynb路面语义分割
    Image for post
    From author
    来自作者

    This is our first model, without weights, which works fine for road surfaces but doesn’t work for the small classes.

    这是我们的第一个没有配重的模型,该模型在路面上可以正常使用,但不适用于小班级。

    Image for post
    From author
    来自作者

    步骤4-第二部分-配重 (Step 4 — Second Part — With weights)

    We’ll use the first model in our next Step. This part is almost exactly the same as the Step 3, since the databunch, we just need to remember to load our previous model.

    在下一步中,我们将使用第一个模型。 这部分与第3步几乎完全相同,因为数据绑定,我们只需要记住加载先前的模型即可。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    And, before we start the training process, we need to put weight in the classes. I defined these weights in order to try to be proportional to how much each class appears in the dataset (number of pixels). * I ran a python code with OpenCV just to count the number of pixels in each class over the GT’s 701 images, to get a sense of the proportion of each class… 😓

    并且,在我们开始培训过程之前,我们需要在课堂上加倍权重。 我定义了这些权重,以便尝试与每个类在数据集中出现的数量(像素数)成正比。 *我用OpenCV运行了一个python代码,只是为了计算GT 701图像中每个类别的像素数,以了解每个类别的比例……😓

    Road Surface Semantic Segmentation.ipynb路面语义分割

    The remainder is exactly like step three presented before. What changes are the results obtained. 😬

    其余部分与前面介绍的第三步完全一样。 得到的结果有什么变化。 😬

    Image for post
    From author
    来自作者

    Now, it looks like we have a more reasonable result for all classes. Remember to save it!

    现在,对于所有类来说,我们似乎都有一个更合理的结果。 记住要保存!

    Road Surface Semantic Segmentation.ipynb路面语义分割

    结果 (Results)

    Finally, let’s see our images, right? Before anything, it will be better to save our results, or our test images.

    最后,让我们看看我们的图像,对不对? 首先,最好保存我们的结果或测试图像。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    But, wait! The images all look completely black, where are my results??? 😱 Calm down, these are the results, just without color map, if you open one of these images on the entire screen, with high brightness, you can see the small variations, “Eleven Shades of Grey” 🙃. So let’s color our results to be more presentable? Now we’ll use OpenCV and create a new folder to save our colored results.

    可是等等! 图像全部看起来都是黑色的,我的结果在哪里??? 😱冷静一下,这些就是结果,只是没有颜色图,如果在整个屏幕上以高亮度打开这些图像之一,则可以看到小的变化,即“十一色灰色”。 因此,让我们对结果进行上色以使其更具表现力吗? 现在,我们将使用OpenCV并创建一个新文件夹来保存彩色结果。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    So we create a function to identify each variation and to colorize each pixel.

    因此,我们创建了一个函数来识别每个变化并为每个像素着色。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    Next, we read each image, call the function and save our final result.

    接下来,我们读取每个图像,调用函数并保存最终结果。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    But, this process could take more time than necessary, using the %timeit we achieve a performance as:

    但是,使用%timeit ,此过程可能会花费不必要的时间,我们可以达到以下性能:

    Image for post
    From author
    来自作者

    Imagine if we need to test with more images? We can speed up this step using Cython. So, let’s put a pinch of Cython on that!

    想像一下是否需要测试更多图像? 我们可以使用Cython加快此步骤。 因此,让我们在上面放一点Cython!

    https://giphy.com/https://giphy.com/的 gif

    So, we edit our function to identify each variation and to colorize each pixel, but this time, using Cython.

    因此,我们编辑函数以识别每个变化并为每个像素着色,但是这次使用Cython。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    And we just read each image and call the function and save our final result as we did before.

    然后,我们只需读取每个图像并调用函数,然后像以前一样保存最终结果。

    Road Surface Semantic Segmentation.ipynb路面语义分割

    And voila! Now we have a performance as:

    瞧! 现在我们的表现为:

    Image for post
    From author
    来自作者

    Much better, right?

    好多了吧?

    一些结果样本 (Some results samples)

    In the image below are some results. In the left column are the original images, in the middle column the GT and in the right column the result with this approach.

    在下图中是一些结果。 左图是原始图像,中间栏是GT,右图是这种方法的结果。

    Image for post
    Adapted from [1]
    改编自[1]

    带有结果的视频 (Video with the results)

    讨论(让我们谈谈) (Discussion (Let’s talk about it))

    Identifying road surface conditions is important in any scenario, based on this the vehicle or driver can adapt and make a decision that can make the driving safer, more comfortable and more efficient. This is particularly relevant in developing countries that may have even more situations of road maintenance problems or a reasonable number of unpaved roads.

    在任何情况下,识别路面状况都很重要,基于此,车辆或驾驶员可以做出调整,并做出可以使驾驶更加安全,舒适和高效的决定。 这在可能存在更多道路维护问题或相当数量的未铺砌道路的发展中国家中尤其重要。

    This approach looks promising for dealing with environments with variations in the road surface. This can also be useful for highway analysis and maintenance departments, in order to automate part of their work in assessing road quality and identifying where maintenance is needed.

    对于处理路面变化的环境,这种方法看起来很有希望。 这对于高速公路分析和养护部门也很有用,以便使他们在评估道路质量和确定需要维护的地方的工作自动化。

    However, some points were identified and analyzed as subject to improvement.

    但是,发现并改进了一些要点。

    For the segmentation GT, it may be interesting to divide some classes into more specific classes, such as the Cracks class, used for different damages regardless of the type of road. Thus having variations of Cracks for each type of surface, because different surfaces have different types of damage. Also divide this class into different classes, categorizing different damage in each new class.

    对于分段GT,将某些类别划分为更具体的类别(例如“裂缝”类别)可能会很有趣,例如,无论道路类型如何,“裂纹”类别都会用于不同的损坏。 因此,由于不同类型的表面具有不同类型的损坏,因此每种类型的表面都有不同的裂纹。 还要将此类别分为不同的类别,在每个新类别中将不同的损害分类。

    That’s all for now. Feel free to reach out to me. 🤘

    目前为止就这样了。 请随时与我联系。 🤘

    致谢 (Acknowledgements)

    This experiment is part of a project on visual perception for vehicular navigation from LAPiX (Image Processing and Computer Graphics Lab).

    该实验是LAPiX (图像处理和计算机图形实验室)的车辆导航视觉感知项目的一部分。

    If you are going to talk about this approach, please cite as:

    如果您要谈论这种方法 ,请引用为:

    @article{rateke:2020_3,author = {Thiago Rateke and Aldo von Wangenheim},title = {Road surface detection and differentiation considering surface damages},year = {2020},eprint = {2006.13377}, archivePrefix = {arXiv}, primaryClass = {cs.CV},}

    @article {rateke:2020_3, 作者 = {Thiago Rateke和Aldo von Wangenheim}, 标题 = {考虑到表面损坏的路面检测和区分}, 年份 = {2020}, eprint = {2006.13377}, archivePrefix = {arXiv}, primaryClass = {cs.CV},}

    也可以看看 (See Also)

    翻译自: https://towardsdatascience.com/road-surface-semantic-segmentation-4d65b045245

    语义分割 语义分类

    展开全文
  • 憨批的语义分割13——Pytorch 搭建自己的Unet语义分割平台注意事项学习前言什么是Unet模型代码下载Unet实现思路一、预测部分1、主干网络介绍2、加强特征提取结构3、利用特征获得预测结果二、训练部分1、训练文件详解...
  • datawhale语义分割-Task3 语义分割模型发展 本章主要讲解的是语义分割网络模型的发展:FCN 、SegNet、Unet、DeepLab、RefineNet、PSPNet、GAN语义分割。 3 语义分割模型发展 语义分割(全像素语义分割)作为经典的...
  • 语义分割论文

    2019-02-27 11:01:49
    都是我自己在知网上下载的语义分割论文,特别适合语义分割的入门学习,可以了解语义分割的训练与检测流程。
  • 语义分割系列(一) 何为语义分割 我们在基于深度学习的计算机视觉领域所进行的任务大致可以分为三类:图像分类、目标检测以及图像分割。 图像分割还能进一步分为语义分割和实例分割,我们这里只讨论语义分割。 ...
  • 憨批的语义分割9——Pytorch 搭建自己的PSPNet语义分割平台学习前言什么是PSPNet模型PSPNet实现思路一、预测部分1、主干网络介绍2、加强特征提取结构3、利用特征获得预测结果二、训练部分1、训练文件详解2、LOSS解析...
  • 语义分割综述

    2019-10-15 12:19:12
    语义分割
  • 语义分割】综述——一文搞定语义分割

    万次阅读 多人点赞 2019-02-19 10:05:00
    本文记录了博主阅读的关于语义分割(Semantic Segmentation)的综述类文章的笔记,更新于2019.02.15。 文章目录参考文献网址A 2017 Guide to Semantic Segmentation with Deep Learning什么是语义分割(Semantic ...
  • 自己制作语义分割语义分割数据集

    万次阅读 多人点赞 2018-05-30 16:42:48
    制作语义分割数据集大致需要(1)使用labelme对数据进行标注,生成对应图片的json格式。(2)执行label下的labelme_json_to_dataset.py文件,生成图片对应文件夹。(3)通过第二步生成的文件夹,生成语义图片。(4)...
  • 小菊的语义分割????——语义分割科普Semantic Segmentation什么是语义分割? 什么是语义分割语义分割其实就是像素级的分类任务。假设我们看到这样一幅图: 我们一眼就能看到这是一只狗正趴在地上,那如果我们把...
  • 1 语义分割数据集的笔记 1.1Pascal VOC data sets Pascal VOC是一个语义分割的数据集; 官方链接:http://host.robots.ox.ac.uk/pascal/VOC/
  • Pytorch深度学习实战教程。包含语义分割基础与环境搭建、UNet语义分割网、UNet模型训练。了解UNet语义分割网、以及用Unet网络对自己的数据训练模型
  • 憨批的语义分割10——语义分割评价指标mIOU的计算学习前言什么是mIOUPSPNet实现思路一、预测部分1、主干网络介绍2、加强特征提取结构3、利用特征获得预测结果二、训练部分1、训练文件详解2、LOSS解析训练自己的...
  • 语义分割(Semantic Segmentation)方法

    万次阅读 多人点赞 2019-01-02 18:04:09
    语义分割方面的资源:https://github.com/mrgloom/awesome-semantic-segmentation 1. 什么是语义分割 语义分割是当今计算机视觉领域的关键问题之一。从宏观上看,语义分割是一项高层次的任务,...
  • 对比对象蒙版提案的无监督语义分割 此回购包含我们论文的Pytorch实现: , , 和 。 :trophy: SOTA用于无监督的语义分割。 有关更多信息,请查看基准的网站。 内容 介绍 在没有监督的情况下,能够学习图像的密集...
  • 语义分割综述---一文了解语义分割

    千次阅读 2019-06-09 20:51:51
    语义分割 语义分割方法在处理图像时,具体到像素级别,也就是说,该方法会将图像中每个像素分配到某个对象类别。相关模型要具有像素级的密集预测能力。目前用于语义分割研究的两个最重要数据集是VOC2012和MSCOCO。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,152
精华内容 4,060
关键字:

语义分割