【CV】第 8 章:语义分割和神经风格迁移

   大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流

个人主页-Sonhhxg_柒的博客_CSDN博客 

欢迎各位→点赞 + 收藏⭐️ + 留言​

系列专栏 - 机器学习【ML】 自然语言处理【NLP】  深度学习【DL】

 foreword

✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。

如果你对这个系列感兴趣的话,可以关注订阅哟

文章目录

用于语义分割的 TensorFlow DeepLab 概述

Spatial Pyramid Pooling(空间金字塔池化)

Atrous convolution(空洞卷积)

Encoder-decoder network

编码器模块

解码器模块

DeepLab 中的语义分割——示例

谷歌 Colab、谷歌云 TPU 和 TensorFlow

使用 DCGAN 生成人工图像

Generator(生成器)

 Discriminator(鉴别器)

训练

使用 DCGAN 进行图像修复

TensorFlow DCGAN – 示例

使用 OpenCV 进行图像修复

了解神经风格迁移

概括


深度神经网络的应用不仅限于在图像中寻找对象(我们在前几章中已经了解)——它还可以用于将图像分割成空间区域,从而生成人造图像并从一个图像中转移风格图像到另一个。

在本章中,我们将使用 TensorFlow Colab 来执行所有这些任务。语义分割预测图像的每个像素是否属于某个类别。这是一种有用的图像叠加技术。您将了解 TensorFlow DeepLab,以便您可以对图像执行语义分割。深度卷积生成对抗网络DCGAN ) 是强大的工具,用于生成人脸和手写数字等人工图像。它们也可用于图像修复。我们还将讨论如何使用 CNN 将风格从一张图像转移到另一张图像。

在本章中,我们将介绍以下主题:

  • 用于语义分割的 TensorFlow DeepLab 概述
  • 使用 DCGAN 生成人工图像
  • 使用 OpenCV 进行图像修复
  • 了解神经风格迁移

用于语义分割的 TensorFlow DeepLab 概述

语义分割是在像素级别理解和分类图像内容的任务。与对象检测不同,在多个对象类别上绘制一个矩形边界框(类似于我们对 YOLOV3 的了解),语义分割学习整个图像并将封闭对象的类别分配给图像中的相应像素。因此,语义分割可以比对象检测更强大。语义分割的基础架构基于编码器-解码器网络,其中编码器创建一个高维特征向量并在不同层次上聚合它,而解码器在神经网络的不同层次上创建一个语义分割掩码。编码器使用传统的 CNN,而解码器使用反池化、反卷积和上采样。DeepLab 是谷歌推出的一种特殊类型的语义分割,它使用 Atrous Convolution、空间金字塔池化而不是常规的最大池化和编码器-解码器网络。DeepLabV3+ 是由 Liang-Chieh Chen、Yukun Zhu、George Papandreou、Florian Schro 和 Hartwig Adam在他们的论文Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation ( https://arxiv.org/abs/1802.02611 ) 中介绍。

DeepLab 于 2015 年从 V1 开始,并于 2019 年迅速移至 V3+。不同 DeepLab 版本的比较如下表所示:

DeepLab V1

DeepLab V2

DeepLab V3

DeepLab V3+

Paper

使用深度卷积网络和完全连接的 CRF 进行语义图像分割,2015

DeepLab:使用深度卷积网络、Atrous 卷积和完全连接的 CRF 进行语义图像分割, 2017

重新思考用于语义图像分割的 Atrous 卷积, 2017

用于语义图像分割的具有 Atrous 可分离卷积的编码器-解码器, 2018

作者

Liang-Chieh Chen、George Papandreou、Iasonas Kokkinos、Kevin Murphy 和 Alan L. Yuille

Liang-Chieh Chen、George Papandreou、Iasonas Kokkinos、Kevin Murphy 和 Alan L. Yuille

Liang-Chieh Chen、George Papandreou、Florian Schroff 和 Hartwig Adam

Liang-Chieh Chen, Yukun Zhu, George Papandreou, Florian Schro, and Hartwig Adam

关键概念

Atrous 卷积,全连接条件随机场CRF )

Atrous 空间金字塔池化ASPP )

ASPP、图像级特征和批量标准化

ASPP 和编码器/解码器模块

DeepLabV3+ 使用空间金字塔池SPP ) 的概念来定义其架构。

Spatial Pyramid Pooling(空间金字塔池化)

我们在第 5 章,神经网络架构和模型中介绍的大部分 CNN模型,需要固定的输入图像大小,这限制了输入图像的纵横比和比例。固定大小约束不是来自卷积操作;相反,它来自需要固定输入大小的全连接层。卷积操作从 CNN 不同层中图像的边缘、角落和不同形状生成特征图。不同层的特征图是不同的,并且是图像内形状的函数。作为输入大小的函数,它们不会发生很大变化。SPP 替换了最后一个池化层,就在全连接层之前,它由平行排列的空间 bin 组成,其大小与输入图像大小成正比,但其总数固定为全连接层的数量。

DeepLabV3 的架构基于两种类型的神经网络——Atrous 卷积和编码器-解码器网络。

Atrous convolution(空洞卷积)

 我们在第 4 章“图像深度学习”中介绍了卷积的概念,但没有深入探讨各种类型的 Atrous 卷积。空洞卷积,也称为空洞卷积,增加了卷积的视野。传统的 CNN 使用最大池化和步幅来快速减小层的大小,但这样做也降低了特征图的空间分辨率。Atrous 卷积是一种用来解决这个问题的方法。它通过使用 Atrous 值修改步幅来实现这一点,从而有效地改变过滤器的值字段,如下图所示:

【CV】第 8 章:语义分割和神经风格迁移_第1张图片

上图显示了速率 = 2 的 Atrous 卷积。与深度卷积相比,它跳过了每个其他单元格。实际上,如果我们应用 stride = 2,则 3 x 3 内核是 5 x 5 内核。与简单的深度较小的特征图相比,Atrous 卷积增加了视野并捕获了边界信息(与最大池化相比,其中对象边界缺失),从而产生丰富的图像上下文。由于其在每个后续层中保持视野相同的特性,Atrous 卷积用于图像分割。

DeepLabV3 执行几个并行的 Atrous 卷积,所有这些都以不同的速率运行,就像我们之前描述的空间池化层概念一样。上图说明了 Atrous 卷积和并行模块彼此相邻堆叠以形成 SPP。与传统卷积相比,最终特征向量的深度和宽度比原始图像减小,Atrous 卷积保留了图像大小。因此,图像的更精细的细节不会丢失。这在构建具有丰富图像上下文的分割图时很有帮助。

Encoder-decoder network

编码器是一种神经网络,它获取图像并生成特征向量。解码器与编码器相反;它采用特征向量并从中生成图像。编码器和解码器一起训练以优化组合损失函数。

编码器-解码器网络导致编码器路径中的计算速度更快,因为不必在编码器路径中扩展特征并且在解码器路径中恢复尖锐对象。编码器-解码器网络包含一个编码器模块,用于捕获更高的语义信息,例如图像中的形状。它通过逐渐减少特征图来做到这一点。另一方面,解码器模块保留了空间信息和更清晰的图像分割。

编码器和解码器主要使用多尺度的 1 x 1 和 3 x 3 Atrous 卷积。让我们更详细地看一下它们。

编码器模块

编码器模块的主要特点如下:

  • Atrous 卷积提取特征。
  • 输出步幅是输入图像的分辨率与最终输出分辨率的比值。其典型值为 16 或 8,这会导致更密集的特征提取。
  • 在最后两个块中使用速率为 2 和 4 的 Atrous 卷积。
  • ASPP 模块用于在多个尺度上应用卷积操作

解码器模块

解码器模块的主要特点如下:

  • 1 x 1 卷积用于减少来自编码器模块的低级特征图的通道。
  • 3 x 3 卷积用于获得更清晰的分割结果。
  • 上采样 4。

DeepLab 中的语义分割——示例

使用 TensorFlow 训练 DeepLab 的详细代码可以在以下由 TensorFlow 管理的 GitHub 页面找到:https ://github.com/tensorflow/models/tree/master/research/deeplab 。

Google Colab 包含基于多个预训练模型的内置 DeepLab Python 代码。这可以在https://colab.research.google.com/github/tensorflow/models/blob/master/research/deeplab/deeplab_demo.ipynb找到。

谷歌 Colab、谷歌云 TPU 和 TensorFlow

在深入示例代码的细节之前,我们先了解一下谷歌机器学习的一些基本特性,所有这些特性都是免费提供的,这样我们就可以开发出强大的计算机视觉和机器学习代码:

  • Google Colab:您可以从 Google Drive 中打开 Google Colab,如以下屏幕截图所示。如果您是第一次使用它,您必须点击新建,然后点击更多才能将 Google Colab 安装到您的云端硬盘。Google Colab 让您无需安装即可打开 Jupyter Notebook。它还内置了 TensorFlow,这意味着使用已包含的所有 TensorFlow 依赖项要容易得多:

【CV】第 8 章:语义分割和神经风格迁移_第2张图片

前面的屏幕截图显示了 Google Colab 文件夹相对于 Google Drive 的位置。它使您可以处理.ipynb文件,然后存储它们。

  • Google Cloud TPU:这是一个张量处理单元。它允许您更快地运行您的神经网络代码。进入 Google Colab Notebook 后,您可以为 Python.ipynb文件激活 TPU,如以下屏幕截图所示:
【CV】第 8 章:语义分割和神经风格迁移_第3张图片

 如前面的屏幕截图所示,打开 Cloud TPU 将有助于加快您处理神经网络的训练和预测阶段的速度。

Google Colab DeepLab 笔记本包含三个示例图像,还为您提供了获取 URL 的选项,以便您可以加载自定义图像。当您获取图像的 URL 时,请确保该 URL.jpg位于末尾。从互联网上提取的许多图像没有此扩展名,程序会说找不到它。如果您有自己想要使用的图像,请将它们存储在您的 GitHub 页面上,然后下载 URL。以下屏幕截图显示了基于以下内容接收到的输出mobilenetv2_coco_voctrainaug:

【CV】第 8 章:语义分割和神经风格迁移_第4张图片

前面的屏幕截图显示了四个不同的图像——停放的自行车、繁忙的纽约街道、城市道路和带家具的房间。在所有情况下,检测都非常好。需要注意的是,该模型只检测了以下 20 个类,外加一个背景类:background , plane , bike , bird , boat , bottle , bus , car , cat , chair , cow , Diningtable , dog , horse , motorbike , person ,盆栽沙发火车电视。以下屏幕截图显示了使用不同模型运行的相同四个图像,即xception_coco_voctrainval:

【CV】第 8 章:语义分割和神经风格迁移_第5张图片

与 MobileNet 模型相比,对象对异常模型的预测显示出更大的改进。与 MobileNet 模型相比,异常模型已清楚地检测到自行车、人类和桌子的分割。

MobileNet 是一种用于手机和边缘设备的高效神经网络模型。它使用深度卷积而不是普通卷积。有关 MobileNet 和深度卷积的详细了解,请参阅第 11 章,边缘深度学习与 GPU/CPU 优化

使用 DCGAN 生成人工图像

在第 5 章,神经网络架构和模型中,我们了解了 DCGAN。它们由生成器模型和判别器模型组成。生成器模型接收代表图像特征的随机向量,并通过 CNN 运行以生成人工图像G(z)。因此,生成器模型返回生成新图像及其类别的绝对概率G(z) 。鉴别器(D)网络是一个二元分类器。它从样本概率、图像分布(p-data)和来自生成器的人工图像中获取真实图像,以生成概率P(z),即最终图像是从真实图像分布中采样的。因此,鉴别器模型返回最终图像的类别来自给定分布的条件概率。

鉴别器将生成真实图像的概率信息提供给生成器,生成器使用该信息来改进其预测,以创建人造图像G(z)。随着训练的进行,生成器在创建可以欺骗判别器的人造图像方面变得更好,而判别器将发现更难区分真实图像和人造图像。这两个模型相互对立——因此得名对抗网络。当判别器无法再将真实图像与人工图像分开时,模型就会收敛。

GAN 训练遵循判别器和生成器训练几个时期的替代模式,然后重复直到达到收敛。在每个训练周期中,其他组件保持固定,即我们训练生成器时,判别器保持固定,训练判别器时,生成器保持固定,以尽量减少生成器和判别器相互追逐的机会.

前面的描述应该已经为您提供了对 GAN 的高级理解。但是,为了编写 GAN,我们需要更多地了解模型架构。让我们开始吧。

Generator(生成器)

 DCGAN的生成器网络架构如下图所示:

【CV】第 8 章:语义分割和神经风格迁移_第6张图片

从上图中,我们可以看到以下内容:

  • 所有具有步幅但没有最大池化的卷积网络都允许网络在生成器中学习自己的上采样。请注意,最大池化被跨步卷积取代。
  • 第一层从鉴别器中获取概率 P(z),通过矩阵乘法连接到下一个卷积层。这意味着没有使用正式的全连接层。然而,网络服务于它的目的。
  • 我们对所有层应用批量归一化来重新调整输入,除了生成器输出层以提高学习的稳定性。

 Discriminator(鉴别器)

DCGAN的判别器网络架构如下图所示:

【CV】第 8 章:语义分割和神经风格迁移_第7张图片

从上图中,我们可以看到以下内容:

  • 所有具有步幅但没有最大池化的卷积网络都允许网络在鉴别器中学习自己的下采样。
  • 我们消除了全连接层。最后一个卷积层被展平并直接连接到单个 sigmoid 输出。
  • 我们对除鉴别器输入层以外的所有层应用批量归一化,以提高学习的稳定性。

训练

训练时要考虑的主要特征如下:

  • 激活:Tanh
  • 小批量大小为 128 的随机梯度下降SGD )
  • 泄漏 ReLU:斜率 = 0.2
  • 学习率为 0.0002 的 Adam 优化器
  • 0.5 的动量项:0.9 的值会导致振荡

下图显示了 DCGAN 在训练阶段的损失项:

【CV】第 8 章:语义分割和神经风格迁移_第8张图片

当生成器接收到随机输入时开始训练,生成器损失被定义为它产生假输出的能力。鉴别器损失被定义为它区分真实输出和假输出的能力。梯度用于更新生成器和判别器。在训练过程中,生成器和判别器同时进行训练。训练过程通常只要我们需要同时训练两个模型。请记住,两个模型彼此同步。

使用 DCGAN 进行图像修复

图像修复是根据来自相邻点的信息填充图像或视频的缺失部分的过程。图像修复工作流程涉及以下步骤:

  1. 有一个缺少部分的图像。
  2. 收集相应缺失部分的像素信息。这称为图层蒙版。
  3. 向神经网络输入步骤 1 和 2 中描述的图像,以确定需要填充图像的哪个部分。这意味着神经网络首先处理具有缺失部分的图像,然后处理层掩码。
  4. 输入图像经过类似的 DCGAN,如前所述(卷积和反卷积)。图层掩码允许网络仅关注基于其相邻像素数据的缺失部分,并丢弃已经完成的图像部分。生成器网络生成假图像,而鉴别器网络确保最终绘画尽可能真实。

TensorFlow DCGAN – 示例

TensorFlow.org 有一个很好的图像修复示例,您可以在 Google Colab 或您自己的本地机器上运行它。该示例可以在 Google Colab 中运行,网址为https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/tutorials/generation/dcgan.ipynb#scrollTo=xjjkT9KAK6H7。

此示例显示了基于 MNIST 数据集训练 GAN,然后生成人工数字。使用的模型与我们在前面几节中描述的相似。

使用 OpenCV 进行图像修复

OpenCV提供了两种图像修复方法,如下:

  • cv.INPAINT_TELEA是基于 Alexandru Telea 在 2004 年的论文An Image Inpainting Technique Based on the Fast Marching Method。该方法用邻域中所有已知像素的归一化加权和来替换要修复的邻域中的像素。对靠近该点和边界轮廓的那些像素给予更多的权重。一旦一个像素被修复,它使用快速移动方法移动到下一个最近的像素:
import numpy as np 
import cv2 as cv 
img = cv.imread('/home/.../krishmark.JPG') 
mask = cv.imread('/home/.../markonly.JPG',0) 
dst = cv.inpaint(img,mask,3,cv.INPAINT_TELEA) 
cv.imshow('dst',dst) 
cv.waitKey(0) 
cv.destroyAllWindows()
  • cv.INPAINT_NS基于Bertalmio、Marcelo、Andrea L. Bertozzi 和 Guillermo Sapiro 在 2001年的论文Navier-Stokes、流体动力学和图像和视频修复。它在匹配边界处的梯度向量的同时连接具有相同强度的点修复区域。此方法使用流体动力学算法:
import numpy as np 
import cv2 as cv 
img = cv.imread('/home/.../krish_black.JPG') 
mask = cv.imread('/home/.../krish_white.JPG',0) 
dst = cv.inpaint(img,mask,3,cv.INPAINT_NS) 
cv.imshow('dst',dst) 
cv.waitKey(0) 
cv.destroyAllWindows()

最终输出如下图所示:

【CV】第 8 章:语义分割和神经风格迁移_第9张图片

正如我们所看到的,两个预测都部分成功,但没有完全删除该行。

了解神经风格迁移

神经风格转移是一种技术,您可以通过匹配内容图像和样式图像的特征分布来混合内容图像和样式图像,以生成与内容图像相似但以样式图像的样式进行艺术绘制的最终图像。风格迁移可以在 TensorFlow 中以两种不同的方式完成:

  • 使用 TensorFlow Hub 中的预训练模型。这是您上传图像和样式的地方,该工具包将生成您的样式输出。您可以在https://colab.research.google.com/github/tensorflow/hub/blob/master/examples/colab/tf2_arbitrary_image_stylization.ipynb上传您的图片。请注意,TensorFlow Hub 是许多预训练网络的来源。
  • 通过训练神经网络来开发自己的模型。为此,请按照下列步骤操作:
    1. 选择 VGG19 网络——它有五个卷积 (Conv2D) 网络,每个 Conv2D 有四层,然后是全连接层。
    2. 通过 VGG19 网络加载您的内容图像。
    3. 预测前五个卷积。
    4. 加载没有顶层的 VGG19 模型(类似于我们在第 6 章,使用迁移学习的视觉搜索中所做的)并列出层的名称。
    5. VGG19 中的卷积层进行特征提取,而全连接层执行分类任务。如果没有顶层,网络将只有前五个卷积层。从前面的章节我们知道,初始层传达原始图像的输入像素,而最终层捕获图像的定义特征和模式。
    6. 通过这样做,图像的内容由中间特征图表示——在这种情况下,这是第五个卷积块。
    7. 最大平均差异 ( MMD ) 用于比较两个向量。 在他们关于Demystifying Neural Style Transfer的原始论文中,Yanghao Li、Naiyan Wang、Jiaying Liu 和 Xiaodi Hou 表明,匹配图像特征图的 gram 矩阵相当于最小化特征向量的 MMD。图像的风格由风格化图像的特征图的 gram 矩阵表示。gram矩阵为我们提供了特征向量之间的关系,并由点积表示。这也可以被认为是特征向量与整个图像的平均值之间的相关性。
    8. 总损失 = 风格损失 + 内容损失。损失计算为输出图像相对于目标图像的均方误差的加权和。
gram 矩阵是向量 G = I i T I j的内积的矩阵。这里,I i和 I j是原始图像和样式化图像的特征向量。内积表示向量的协方差,表示相关性。这可以用样式来表示。

以下代码输入一个 VGG 模型并从模型中提取样式和内容层:

vgg = tf.keras.applications.VGG19(include_top=False, weights='imagenet') 
vgg.trainable = False 
for layer in vgg.layers: 
print(layer.name)

以下结果显示了卷积块及其序列:

input_2
 block1_conv1
 block1_conv2
 block1_pool
 block2_conv1
 block2_conv2
 block2_pool
 block3_conv1
 block3_conv2
 block3_conv3
 block3_conv4
 block3_pool
 block4_conv1
 block4_conv2
 block4_conv3
 block4_conv4
 block4_pool
 block5_conv1
 block5_conv2
 block5_conv3
 block5_conv4
 block5_pool

我们将使用我们从前面的输出生成的卷积结果来开发内容层和样式层,如以下代码所示:

#Content layer:
content_layers = ['block5_conv2']
#Style layer:
style_layers = ['block1_conv1','block2_conv1','block3_conv1', 'block4_conv1', 'block5_conv1']
style_outputs = [vgg.get_layer(name).output for name in style_layers]
content_outputs = [vgg.get_layer(name).output for name in content_layers]
vgg.input = style_image*255

输入的四个维度分别是batch size、图像宽度、图像高度和图像通道数。255 乘数将图像强度转换为 0 到 255 的比例:

model = tf.keras.Model([vgg.input], outputs)

如前所述,这种风格可以用 gram 矩阵表示。在 TensorFlow 中,gram 矩阵可以表示为tf.linalg.einsum。

因此,我们可以编写以下内容:

for style_output in style_outputs:
    gram_matrix = tf.linalg.einsum(‘bijc,bijd->bcd’,style_outputs,style_outputs)/tf.cast(tf.shape(style_outputs[1]*style_outputs[2]))

损失计算如下:

style_loss = tf.add_n([tf.reduce_mean((style_outputs[name]-style_targets[name])**2) for name in style_outputs.keys()]) 
style_loss *= style_weight / num_style_layers 

content_loss = tf.add_n([tf .reduce_mean((content_outputs[name]-content_targets[name])**2) for name in content_outputs.keys()]) 
content_loss *= content_weight / num_content_layers 
loss = style_loss + content_loss

最终代码可以从https://www.tensorflow.org/tutorials/generation/style_transfer的 TensorFlow 教程中获得。代码结构如here所述。我在下面的图像上运行它,输出如下:

【CV】第 8 章:语义分割和神经风格迁移_第10张图片

 请注意图像输出如何从沙漠中的少量石粒过渡到完全充满石头,同时保持沙漠的一些结构。最后一次迭代(迭代 1,000 次)确实展示了一种艺术融合。

概括

在本章中,我们学习了如何使用 TensorFlow 2.0 和 Google Colab 来训练神经网络来执行许多复杂的图像处理任务,例如语义分割、图像修复、生成人工图像和神经风格迁移。我们了解了生成网络和判别网络的功能,以及如何以平衡的方式同时训练神经网络以创建假输出图像。我们还学习了如何使用 Atrous 卷积、空间池化和编码器-解码器网络来开发语义分割。最后,我们使用 Google Colab 训练神经网络来执行神经风格迁移。

在下一章中,我们将使用神经网络进行活动识别。

你可能感兴趣的:(深度学习,计算机视觉,人工智能)