https://medium.com/nanonets/how-to-do-image-segmentation-using-deep-learning-c673cc5862ef
如今,语义分割是计算机视觉领域的关键问题之一。纵观全局,语义分割是为完整场景理解铺平道路的高级任务之一。场景理解作为核心计算机视觉问题的重要性突出表现在越来越多的应用程序通过从图像推断知识而滋养。其中一些应用包括自动驾驶车辆,人机交互,虚拟现实等。随着近年来深度学习的普及,许多语义分割问题正在使用深层架构解决,最常见的是卷积神经网络,超越其他方法在准确性和效率方面有很大差距。
什么是语义分割?
语义分割是从粗略推理到精细推理的自然步骤:
- 的起源可位于分类,其由进行预测为一个整体的输入。
- 下一步是定位/检测,它不仅提供类,还提供有关这些类的空间位置的附加信息。
- 最后,语义分割通过使密集预测推断每个像素的标签来实现细粒度推理,从而每个像素用其封闭对象矿石区域的类别标记。
语义分割的一个例子(来源:https://blog.goodaudience.com/using-convolutional-neural-networks-for-image-segmentation-a-quick-intro-75bd68779225)
值得回顾一些对计算机视觉领域做出重大贡献的标准深度网络,因为它们经常被用作语义分割系统的基础:
- AlexNet:多伦多开创性的深度CNN赢得了2012年ImageNet竞赛,测试准确度为84.6%。它由5个卷积层组成,最大池化,ReLU为非线性,3个完全卷积层和丢失。
- VGG-16:这款牛津大学的模型以92.7%的准确率赢得了2013年ImageNet大赛。它使用一堆卷积层,在第一层中具有小的感受野,而不是具有大的感受野的少数层。
- GoogLeNet:这个Google的网络赢得了2014年ImageNet竞赛,准确率为93.3%。它由22层和一个新引入的构建块组成,称为初始模块。该模块由网络中的网络层,池化操作,大型卷积层和小型卷积层组成。
- ResNet:这款微软的模型以96.4%的准确率赢得了2016年ImageNet竞赛。由于其深度(152层)和残余块的引入而众所周知。剩余块通过引入标识跳过连接来解决训练真正深层架构的问题,以便层可以将其输入复制到下一层。
CNN架构(来源:https://www.semanticscholar.org/paper/An-Analysis-of-Deep-Neural-Network-Models-for-Canziani-Paszke/28ee688947cf9d31fc48f07a0497cd75200a9485)
现有的语义分割方法是什么?
一般语义分段架构可以广泛地被认为是编码器网络,后面是解码器网络:
- 的编码器通常是为预训练的分类网络等VGG / RESNET随后由解码器网络。
- 解码器的任务是将由编码器学习的判别特征(较低分辨率)语义地投影到像素空间(较高分辨率)上以获得密集分类。
与深度网络的最终结果是唯一重要的分类不同,语义分割不仅需要在像素级别进行区分,而且还需要将在编码器的不同阶段学习的判别特征投影到像素空间上的机制。不同的方法采用不同的机制作为解码机制的一部分。让我们探讨三种主要方法:
1 - 基于区域的语义分割
基于区域的方法通常遵循“使用识别的分割”流水线,其首先从图像中提取自由形态区域并描述它们,然后是基于区域的分类。在测试时,基于区域的预测被转换为像素预测,通常通过根据包含它的最高得分区域标记像素。
R-CNN架构
R-CNN (具有CNN特征的区域)是基于区域的方法的一个代表性工作。它基于对象检测结果执行语义分割。具体而言,R-CNN首先利用选择性搜索来提取大量的对象提议,然后为每个提议计算CNN特征。最后,它使用类特定的线性SVM对每个区域进行分类。与主要用于图像分类的传统CNN结构相比,R-CNN可以解决更复杂的任务,如物体检测和图像分割,甚至成为这两个领域的重要基础。此外,R-CNN可以构建在任何CNN基准结构之上,例如AlexNet,VGG,GoogLeNet和ResNet。
对于图像分割任务,R-CNN为每个区域提取了两种类型的特征:全区域特征和前景特征,并发现当将它们连接在一起作为区域特征时,它可以带来更好的性能。由于使用高度辨别力的CNN特征,R-CNN实现了显着的性能改进。但是,它也会受到分段任务的一些缺点:
- 该功能与分段任务不兼容。
- 该特征不包含足够的空间信息以用于精确的边界生成。
- 生成基于段的提议需要时间,并且会极大地影响最终的性能。
由于这些瓶颈,最近的研究已被提出来解决这些问题,包括SDS,Hypercolumns,Mask R-CNN。
2 - 基于完全卷积网络的语义分割
原始的完全卷积网络(FCN)学习从像素到像素的映射,而不提取区域提议。FCN网络管道是传统CNN的扩展。主要思想是使经典CNN作为输入任意大小的图像。CNN仅限于特定尺寸输入接受和生成标签的限制来自固定的完全连接的层。与它们相反,FCN只有卷积和汇集层,使它们能够对任意大小的输入进行预测。
FCN架构
该特定FCN中的一个问题是通过传播几个交替的卷积和池化层,输出特征图的分辨率被下采样。因此,FCN的直接预测通常是低分辨率的,导致相对模糊的对象边界。已经提出了各种更先进的基于FCN的方法来解决该问题,包括SegNet,DeepLab-CRF和扩张卷积。
3 - 弱监督语义分割
语义分割中的大多数相关方法依赖于具有像素分割掩模的大量图像。然而,手动注释这些掩模非常耗时,令人沮丧且商业上昂贵。因此,最近提出了一些弱监督方法,这些方法致力于通过利用带注释的边界框来实现语义分割。
Boxsup培训
例如,Boxsup使用边界框注释作为监督来训练网络并迭代地改进用于语义分割的估计掩模。简单它是否将弱监督限制视为输入标签噪声问题,并将递归训练作为去噪策略进行探讨。像素级标签解释了多实例学习框架内的分段任务,并添加了一个额外的图层来约束模型,为图像级分类的重要像素分配更多权重。
用全卷积网络进行语义分割
在本节中,让我们逐步实现最流行的语义分割架构 - 全卷积网络(FCN)。我们将使用Python 3中的TensorFlow库以及其他依赖项(如Numpy和Scipy)来实现它。
在本练习中,我们将使用FCN标记图像中道路的像素。我们将与Kitti Road Dataset合作进行道路/车道检测。这是Udacity的自动驾驶汽车纳米学位课程的一个简单练习,你可以在这个GitHub回购中了解更多有关设置的信息。
Kitti Road Dataset Training Sample(来源:http://www.cvlibs.net/datasets/kitti/eval_road_detail.php?result = 3748e213cf8e0100b7a26198114b3cdc7caa3aff )
以下是FCN架构的主要功能:
- FCN从VGG16传输知识以执行语义分段。
- 使用1x1卷积将VGG16的完全连接层转换为完全卷积层。该过程以低分辨率产生类存在热图。
- 使用转置卷积(用双线性插值滤波器初始化)完成这些低分辨率语义特征映射的上采样。
- 在每个阶段,通过添加来自VGG16中较低层的较粗但较高分辨率的特征图的特征,进一步细化上采样过程。
- 在每个卷积块之后引入跳过连接,以使后续块从先前合并的特征中提取更抽象的,类显着的特征。
FCN有3个版本(FCN-32,FCN-16,FCN-8)。我们将按照以下详细步骤实施FCN-8:
- 编码器:预训练的VGG16用作编码器。解码器从VGG16的第7层开始。
- FCN第8层:VGG16的最后一个完全连接层被1x1卷积取代。
- FCN第9层: FCN第8层上采样2次以匹配VGG 16 第4层的尺寸,使用带参数的转置卷积:(kernel =(4,4),stride =(2,2),paddding ='same ')。之后,在VGG16的第4层和FCN第9层之间添加了跳过连接。
- FCN第10层: FCN第9层上采样2次以匹配VGG16 第3层的维度,使用带参数的转置卷积:(kernel =(4,4),stride =(2,2),paddding ='same' )。之后,在VGG 16的第3层和FCN第10层之间添加跳过连接。
- FCN Layer-11: FCN Layer-10上采样4次以匹配输入图像大小的尺寸,因此我们使用带参数的转置卷积来获取实际图像并且深度等于类的数量:(kernel =(16,16) ,stride =(8,8),paddding ='same')。
FCN-8架构(来源:https://www.researchgate.net/figure/Illustration-of-the-FCN-8s-network-architecture-as-proposed-in-20-In-our-method-the_fig1_305770331)
步骤1
我们首先将预先训练的VGG-16模型加载到TensorFlow中。接受TensorFlow会话和VGG文件夹的路径(可在此处下载),我们从VGG模型返回张量元组,包括图像输入,keep_prob(控制丢失率),第3层,第4层和图层7。
VGG16功能
第2步
现在我们专注于使用VGG模型中的张量为FCN创建图层。给定VGG层输出的张量和要分类的类的数量,我们返回该输出的最后一层的张量。特别是,我们将1x1卷积应用于编码器层,然后通过跳过连接和上采样将解码器层添加到网络。
图层功能
第3步
下一步是优化我们的神经网络,即建立TensorFlow损失函数和优化器操作。这里我们使用交叉熵作为我们的损失函数,使用Adam作为我们的优化算法。
优化功能
第4步
这里我们定义train_nn函数,它接收重要的参数,包括时期数,批量大小,损失函数,优化器操作,输入图像的占位符,标签图像,学习率。对于培训过程,我们还将keep_probability设置为0.5,将learning_rate设置为0.001。为了跟踪进度,我们还在培训期间打印出损失。
第5步
最后,是时候训练我们的网了!在这个运行函数中,我们首先使用load_vgg,layers和optimize函数构建我们的网络。然后我们使用train_nn函数训练网络并保存记录的推理数据。
运行功能
关于我们的参数,我们选择epochs = 40,batch_size = 16,num_classes = 2和image_shape =(160,576)。在进行2次试验,辍学= 0.5和辍学= 0.75后,我们发现第二次试验产生更好的结果,平均损失更好。
培训样本结果
要查看完整代码,请查看以下链接:https://gist.github.com/khanhnamle1994/e2ff59ddca93c0205ac4e566d40b5e88