【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)

【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(代码详解)

  • 一、简介
  • 二、用于图像压缩的CNN自动编码器
    • 1. 导入库
    • 2. 加载MNIST数据
    • 3. 预处理图像数据
    • 4. 探索性数据分析
    • 5. 模型创建
    • 6. 训练模型
    • 7. 可视化结果
  • 三、用于图像降噪的CNN自动编码器
    • 1. 导入库
    • 2. 加载数据集
    • 3. 预处理图像数据
    • 4. 为图像添加噪声
    • 5. 探索性数据分析
    • 6. 模型创建
    • 7. 训练模型
    • 8. 可视化结果
  • 四、总结

一、简介

自动编码器:
  自动编码器(Autoencoder)是一种无监督学习算法,用于数据的降维和特征提取。它由一个编码器和一个解码器组成,可以通过将输入数据压缩成低维表示,然后再将其解压缩回原始数据空间来重构输入数据。
  自动编码器的目标是尽可能地减小重构误差,使得解码器能够生成与输入数据相似的输出。为了达到这个目标,编码器将输入数据映射到潜在空间(也称为编码空间)中的低维表示,而解码器则将该低维表示映射回原始数据空间。
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第1张图片

  自动编码器的训练过程通常使用无监督学习的方法,即仅使用输入数据作为训练样本,而没有对应的标签。训练过程中,编码器和解码器的参数通过最小化重构误差来进行优化。重构误差可以使用均方差(Mean Squared Error)或其他适当的损失函数来度量。
  自动编码器可以应用于多种任务,包括数据降维、特征提取、数据去噪、异常检测等。在数据降维任务中,自动编码器可以将高维数据压缩到低维表示,以便可视化或更高效地处理数据。在特征提取任务中,自动编码器可以学习到输入数据的有用特征表示,从而提高后续任务的性能。在数据去噪任务中,自动编码器可以通过学习重构干净数据来过滤掉输入数据中的噪声。在异常检测任务中,自动编码器可以学习正常数据的表示,然后用于检测与正常模式不符的异常数据。

卷积神经网络(CNN):
  卷积神经网络(Convolutional Neural Network,CNN)是一种广泛应用于计算机视觉和图像处理任务的神经网络模型。与传统的全连接神经网络相比,CNN在处理具有网格结构的数据(如图像)时表现出色。
  CNN的核心思想是通过卷积层、池化层和全连接层等组件来实现特征提取和分类。下面是CNN的主要组成部分:

  1. 卷积层(Convolutional Layer):卷积层是CNN的核心。它使用一组可学习的滤波器(卷积核)对输入数据进行卷积操作,从而提取输入数据的局部特征。每个滤波器通过滑动窗口的方式在输入数据上进行卷积操作,生成一系列的特征映射(Feature Map)。
  2. 激活函数(Activation Function):在卷积层之后,一般会应用一个非线性的激活函数,如ReLU(Rectified Linear Unit),来引入非线性特性。激活函数的作用是增加网络的表达能力,并且有助于提取非线性特征。
  3. 池化层(Pooling Layer):池化层用于降低特征映射的空间尺寸,减少参数数量,并提取主要特征。常用的池化操作是最大池化(Max Pooling),它从每个局部区域中选择最大值作为池化结果。池化操作还可以提高网络的平移不变性,使得网络对输入的微小位置变化具有鲁棒性。
  4. 全连接层(Fully Connected Layer):在经过多个卷积层和池化层之后,得到的特征映射被拉平成一维向量,并通过一个或多个全连接层进行分类或回归操作。全连接层的每个神经元与上一层的所有神经元相连,参数量较大。

  在CNN中,通过堆叠多个卷积层、激活函数、池化层和全连接层,可以逐渐提取出输入数据的高层次特征表示,从而实现对图像内容的理解和识别。

CNN自动编码器:
  CNN自动编码器是将卷积神经网络(CNN)与自动编码器(Autoencoder)结合的模型。它可以用于图像降噪、图像去噪、特征提取等任务。
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第2张图片
  CNN自动编码器的结构与传统的自动编码器类似,但在编码器和解码器中使用了卷积层和反卷积层(也称为转置卷积层)来处理图像数据的空间结构。以下是CNN自动编码器的一般结构:

  1. 编码器(Encoder):编码器由一系列的卷积层、池化层和激活函数组成。卷积层用于提取输入图像的特征,通过逐渐减小空间维度和增加通道数,将输入图像压缩成低维的特征表示。通常在编码器的最后一层添加一个全连接层,将特征映射转换为更低维的表示。
  2. 解码器(Decoder):解码器是编码器的逆过程,由一系列的反卷积层和激活函数组成。反卷积层(转置卷积层)用于将低维的特征表示映射回原始图像的空间维度和通道数。最后一层的激活函数通常使用sigmoid或tanh函数来保证解码器输出的像素值在合适的范围内。
  3. 损失函数(Loss Function):常用的损失函数是均方差(Mean Squared Error),它衡量解码器输出与原始图像之间的重构误差。优化目标是最小化重构误差,使得解码器能够生成与输入图像相似的输出。

  通过训练CNN自动编码器,可以学习到输入图像的有用特征表示,并通过解码器重构图像。编码器部分可以作为特征提取器使用,而解码器部分可以用于生成新的图像样本。
  CNN自动编码器在图像处理任务中具有广泛的应用,例如图像降噪,它可以学习到图像的清晰结构并去除噪声;图像去噪,它可以学习到干净图像的表示,并通过解码器生成去噪后的图像;特征提取,它可以学习到图像的有用特征表示,可以用于后续的图像分类、目标检测等任务。

二、用于图像压缩的CNN自动编码器

  图像压缩是通过减少图像数据的冗余性和信息损失来减小图像文件的大小的过程。CNN(卷积神经网络)自动编码器是一种有效的方法,可用于图像压缩和重建。
  CNN自动编码器由编码器和解码器两部分组成。编码器将输入图像逐渐压缩到一个较低维度的表示,而解码器则将该低维度表示恢复到原始图像的尺寸。
⚙️自动编码器的流程:
  *️⃣ 输入图像 -> 编码器 -> 压缩表示 -> 解码器 -> 重构输入图像

  • 自动编码器需要一个输入数据样本,这里我们考虑的是一个图像,并将其输入到编码器网络中。
  • 编码器网络由若干层组成,通常包括卷积层、池化层和全连接层。这些层逐步减少空间维度,从输入数据中提取有意义的特征。
  • 编码器网络的最后一层产生输入数据的压缩表示。
  • 编码阶段的压缩表示被传递到解码器网络中。
  • 解码器网络与编码器网络是对称的,由全连接层、上采样层和有时转置的卷积层组成。它采用压缩的表示方法,并逐渐增加空间维度,以重建原始输入数据。
  • 解码器网络的最后一层生成重构的输出,其目的是与原始输入数据密切相似。

▶️ 以下是用于图像压缩的CNN自动编码器的python代码在jupyter notebook中的实现:

1. 导入库

import numpy as np
import matplotlib.pyplot as plt
from keras import Sequential
from keras.layers import Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.datasets import mnist

代码详解:

  • import numpy as np: 导入了numpy库,并将其命名为np,这是一个常用的科学计算库,用于处理数组和矩阵等数值运算。
  • import matplotlib.pyplot as plt: 导入了matplotlib.pyplot模块,并将其命名为plt,它是matplotlib库中的一个子模块,用于绘制图形和可视化数据。
  • from keras import Sequential: 从keras库中导入了Sequential类,Sequential类是用于构建深度神经网络模型的基本模块。
  • from keras.layers import Dense, Conv2D, MaxPooling2D, UpSampling2D: 从keras.layers模块中导入了DenseConv2DMaxPooling2DUpSampling2D等类,这些类用于构建神经网络的各种层。
  • from keras.datasets import mnist: 从keras.datasets模块导入了mnist模块,mnist模块提供了加载手写数字数据集MNIST的功能。

  这段代码导入了所需的库和模块,为后续的代码提供了必要的功能和工具。

2. 加载MNIST数据

(x_train, _), (x_test, _) = mnist.load_data()

代码详解:
  这行代码加载了MNIST手写数字数据集,并将数据集分为训练集和测试集:
  MNIST数据集是一个经典的机器学习数据集,包含了一系列的手写数字图像。这里使用的mnist.load_data()函数是keras库中的一个功能,用于从网络下载并加载MNIST数据集。
具体来说,这行代码执行的操作如下:

  • 从MNIST数据集中加载训练数据集,赋值给x_train
  • 同时从MNIST数据集中加载测试数据集,赋值给x_test

  在这之后,你可以使用x_trainx_test来访问训练集和测试集的图像数据,进行后续的处理和分析。

3. 预处理图像数据

对图像数据进行归一化:

x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255

代码详解:
  这段代码对图像数据进行了归一化处理。在机器学习和深度学习中,对输入数据进行归一化是一种常见的预处理步骤。归一化可以将数据缩放到一个特定的范围内,通常是[0, 1]或[-1, 1]之间。这有助于提高模型的训练效果和收敛速度。
  这段代码执行了以下操作:

  • x_train = x_train.astype('float32'): 将x_train的数据类型转换为float32,这是为了进行后续的除法运算。
  • x_test = x_test.astype('float32'): 将x_test的数据类型转换为float32,同样是为了进行后续的除法运算。
  • / 255: 将每个像素的数值除以255,将像素值缩放到[0, 1]的范围内。由于MNIST图像的像素值范围是0到255,所以除以255可以实现这一目的。

  通过执行这些操作,x_trainx_test中的图像数据被归一化到了[0, 1]的范围内,可以更好地用于神经网络的训练和评估。

重塑输入图像数据:

x_train = x_train.reshape(len(x_train), 28, 28, 1)
x_test = x_test.reshape(len(x_test), 28, 28, 1)
x_test.shape

运行结果:
在这里插入图片描述

代码详解:
  这段代码对训练集和测试集的图像数据进行了形状重塑操作。在深度学习中,特别是在使用卷积神经网络(CNN)处理图像数据时,通常要求输入数据的形状符合特定的要求。对于MNIST数据集中的图像数据,CNN通常要求其形状为(样本数, 图像高度, 图像宽度, 通道数)

  • x_train = x_train.reshape(len(x_train), 28, 28, 1): 将x_train的形状从(样本数, 图像高度, 图像宽度)重塑为(样本数, 28, 28, 1),其中28是图像的高度和宽度,1表示图像的通道数,这里是灰度图像,所以通道数为1。
  • x_test = x_test.reshape(len(x_test), 28, 28, 1): 将x_test的形状从(样本数, 图像高度, 图像宽度)重塑为(样本数, 28, 28, 1),同样的操作,将图像的高度、宽度和通道数设置为28、28和1。

  最后,代码通过x_test.shape打印出了x_test的形状。由于前面对x_test进行了形状重塑,所以输出的形状为(样本数, 图像高度, 图像宽度, 通道数),即(10000, 28, 28, 1)。表示测试集中共有10000个样本,每个样本的图像大小为28x28,通道数为1。

4. 探索性数据分析

查看输入图像的样子:

# 随机选择一个图像的索引
index = np.random.randint(len(x_test))
# 显示图像
plt.imshow(x_test[index].reshape(28,28))
plt.gray()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第3张图片
代码详解:
  这段代码的作用是随机选择一张测试集中的图像,并使用灰度图像进行可视化。下面是对代码逐行的解释:

  • index = np.random.randint(len(x_test)): 使用np.random.randint()函数随机生成一个介于0和测试集长度之间的整数,将其赋值给index变量。这样就可以随机选择一个图像的索引。
  • plt.imshow(x_test[index].reshape(28,28)): 使用plt.imshow()函数显示被选择的图像。x_test[index]表示从测试集中选择的图像数据,.reshape(28, 28)将图像数据的形状重塑为28x28的二维数组,以适应imshow()函数的要求。
  • plt.gray(): 使用plt.gray()函数将显示的图像设置为灰度图像。

  通过执行这段代码,你可以看到随机选择的图像以灰度形式显示在屏幕上。下面是随机查看的其他的图像:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第4张图片
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第5张图片

5. 模型创建

使用Keras构建的自动编码器(autoencoder)模型:

model = Sequential([
                    # 编码器网络
                    Conv2D(32, 3, activation='relu', padding='same', input_shape=(28, 28, 1)),
                    MaxPooling2D(2, padding='same'),
                    Conv2D(16, 3, activation='relu', padding='same'),
                    MaxPooling2D(2, padding='same'),
                    # 解码器网络
                    Conv2D(16, 3, activation='relu', padding='same'),
                    UpSampling2D(2),
                    Conv2D(32, 3, activation='relu', padding='same'),
                    UpSampling2D(2),
                    # 输出层
                    Conv2D(1, 3, activation='sigmoid', padding='same')
])

model.compile(optimizer='adam', loss='binary_crossentropy')
model.summary()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第6张图片
代码详解:
  这段代码定义了一个使用Keras构建的自动编码器(autoencoder)模型,并对模型进行了编译和概要(summary)打印。

  • model = Sequential([...]): 创建一个Sequential模型对象,并用方括号内的列表来定义模型的层结构。在这个自动编码器模型中,包含了编码器网络和解码器网络,它们通过共享权重来实现数据的压缩和重构。编码器网络和解码器网络之间的中间部分就是数据的潜在表示(latent representation)。
  • Conv2D(32, 3, activation='relu', padding='same', input_shape=(28, 28, 1)): 添加一个卷积层作为编码器网络的第一层。这个卷积层有32个过滤器,每个过滤器的大小为3x3,使用ReLU激活函数,并采用"same"填充方式。input_shape=(28, 28, 1)指定了输入数据的形状为28x28的灰度图像。
  • MaxPooling2D(2, padding='same'): 添加一个最大池化层,大小为2x2,采用"same"填充方式。最大池化层用于降低特征图的尺寸,并提取主要特征。
  • Conv2D(16, 3, activation='relu', padding='same'): 添加另一个卷积层作为编码器网络的第二层,具有16个过滤器,大小为3x3,使用ReLU激活函数,并采用"same"填充方式。
  • MaxPooling2D(2, padding='same'): 添加第二个最大池化层,大小为2x2,采用"same"填充方式。
  • Conv2D(16, 3, activation='relu', padding='same'): 添加一个卷积层作为解码器网络的第一层,具有16个过滤器,大小为3x3,使用ReLU激活函数,并采用"same"填充方式。
  • UpSampling2D(2): 添加一个上采样层,将特征图的尺寸扩大两倍。
  • Conv2D(32, 3, activation='relu', padding='same'): 添加另一个卷积层作为解码器网络的第二层,具有32个过滤器,大小为3x3,使用ReLU激活函数,并采用"same"填充方式。
  • UpSampling2D(2): 添加第二个上采样层,将特征图的尺寸再次扩大两倍。
  • Conv2D(1, 3, activation='sigmoid', padding='same'): 添加输出层,这是解码器网络的最后一层。它具有1个过滤器,大小为3x3,使用Sigmoid激活函数,并采用"same"填充方式。输出层的目标是重构输入图像。
  • model.compile(optimizer='adam', loss='binary_crossentropy'): 编译模型,指定优化器为Adam,损失函数为二元交叉熵(binary_crossentropy)。自动编码器的目标是通过最小化重构误差来学习数据的有效表示。
  • model.summary(): 打印模型的概要信息,包括每一层的名称、输出形状和参数数量等。概要信息提供了对模型结构的整体概览。

  综上这段代码定义了一个基本的自动编码器模型,并将其编译为可训练的模型。通过打印模型概要,你可以查看模型的层结构和参数数量等重要信息。

6. 训练模型

model.fit(x_train, x_train, epochs=20, batch_size=256, validation_data=(x_test, x_test))

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第7张图片
代码详解:
  这段代码用于训练自动编码器模型。

  • model.fit(x_train, x_train, epochs=20, batch_size=256, validation_data=(x_test, x_test)): 使用fit()函数进行模型的训练。参数解释如下:
  • x_train: 训练集的输入数据,这里是图像数据。
  • x_train: 训练集的目标数据,这里与输入数据相同,即重构输入图像。
  • epochs=20: 迭代次数,指定模型训练的轮数,每轮遍历整个训练集。
  • batch_size=256: 批处理大小,指定每个批次中的样本数量。在每个批次中,模型会根据输入数据进行前向传播和反向传播,并更新权重。
  • validation_data=(x_test, x_test): 验证数据,用于在每个训练轮次结束时评估模型的性能。这里使用测试集作为验证数据,同时将测试集作为目标数据进行重构误差的计算。

  运行结果显示了每个训练轮次所耗费的时间以及每个训练轮次模型的训练误差(loss)和验证误差(val_loss),这两个重要的指标是用于评估模型的性能和训练的进展情况。下面是对这两个指标的介绍:

  • loss: 训练误差,表示模型在每个训练批次中的平均损失值。它是模型在训练数据上的表现,用于衡量模型对训练数据的拟合程度。训练误差的目标是尽量减小,使模型能够更好地拟合训练数据。
  • val_loss: 验证误差,表示模型在每个训练轮次结束时,在验证数据上的平均损失值。它是模型在未参与训练的数据上的表现,用于衡量模型的泛化能力。验证误差的目标是尽量减小,使模型能够在未见过的数据上有良好的表现。

  通常情况下,正如运行结果所示,随着训练的进行,训练误差和验证误差都会逐渐减小,这意味着模型在训练数据和验证数据上的性能都在改善。然而,如果出现训练误差持续下降而验证误差开始增大的情况,这可能表明模型出现了过拟合现象,即在训练数据上过度拟合而无法很好地泛化到新数据。
  通过执行这段代码,模型将使用训练集进行训练,并在每个训练轮次结束时使用测试集进行性能评估。模型会根据给定的损失函数(二元交叉熵)来计算重构误差,并通过优化器(Adam)来更新模型的权重。训练过程将重复进行指定的轮数(20轮),直到模型收敛或达到指定的训练轮次。通过观察训练误差和验证误差的变化趋势,可以帮助判断模型的训练状态和性能。如运行结果所示,如果训练误差和验证误差都能够持续减小且收敛到一个较小的值,那么模型的训练是成功的,并且在训练数据和验证数据上都有良好的性能。

7. 可视化结果

进行预测:

pred = model.predict(x_test)

运行结果:
在这里插入图片描述
代码详解:
  这行代码用于使用训练好的自动编码器模型对测试集进行预测。

  • pred = model.predict(x_test): 使用predict()函数对测试集进行预测。将测试集x_test作为输入,模型将对每个输入图像进行预测,并生成相应的输出图像。预测结果将存储在pred变量中。

  通过执行这行代码,模型将使用测试集作为输入,通过自动编码器进行图像重构,并生成预测结果。预测结果pred将包含与输入图像对应的重构图像。可以使用这些重构图像来评估模型在测试集上的性能,或进行其他进一步的分析和可视化。

随机选择原始图像并显示结果:

# 随机选择原始的图像
index = np.random.randint(len(x_test))
# 显示原始图像
plt.imshow(x_test[index].reshape(28,28))
plt.gray()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第8张图片
代码详解:
  这段代码用于从测试集中随机选择一张图像,并对其进行可视化。

  • index = np.random.randint(len(x_test)): 使用np.random.randint()函数生成一个随机整数,范围在0到测试集长度之间(不包括测试集长度本身)。这个整数被赋值给index变量,表示所选择的图像在测试集中的索引位置。
  • plt.imshow(x_test[index].reshape(28,28)): 使用plt.imshow()函数显示所选择的图像。x_test[index]表示从测试集中选择的图像数据,.reshape(28, 28)将图像数据的形状重塑为28x28的二维数组,以适应imshow()函数的要求。
  • plt.gray(): 使用plt.gray()函数将显示的图像设置为灰度图像。

  通过执行这段代码,你可以看到随机选择的图像以灰度形式显示在屏幕上。每次运行代码,都会随机选择不同的图像进行显示。

可视化可视化经过自动编码器压缩和解压后的图像:

plt.imshow(pred[index].reshape(28,28))
plt.gray()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第9张图片
代码详解:
  这段代码用于可视化经过自动编码器压缩和解压后的图像。

  • plt.imshow(pred[index].reshape(28,28)): 使用plt.imshow()函数显示经过自动编码器预测的图像。pred[index]表示从预测结果中选择的图像数据,.reshape(28, 28)将图像数据的形状重塑为28x28的二维数组,以适应imshow()函数的要求。

  通过执行这段代码,你可以看到经过自动编码器压缩和解压后的图像以灰度形式显示在屏幕上。这样可以直观地比较原始图像和自动编码器生成的图像之间的差异。这有助于评估自动编码器的性能和图像重构质量。

创建并排显示原始图像和预测压缩图像的子图:

index = np.random.randint(len(x_test))
plt.figure(figsize=(10, 4))
# 显示原图
ax = plt.subplot(1, 2, 1)
plt.imshow(x_test[index].reshape(28,28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# 显示压缩图像
ax = plt.subplot(1, 2, 2)
plt.imshow(pred[index].reshape(28,28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第10张图片
代码详解:
  这段代码用于同时显示原始图像和经过自动编码器压缩和解压后的图像。

  • index = np.random.randint(len(x_test)): 使用np.random.randint()函数生成一个随机整数,范围在0到测试集长度之间(不包括测试集长度本身)。这个整数被赋值给index变量,表示所选择的图像在测试集中的索引位置。
  • plt.figure(figsize=(10, 4)): 使用plt.figure()函数创建一个图像窗口,设置图像窗口的大小为(10, 4)。
  • ax = plt.subplot(1, 2, 1): 使用plt.subplot()函数创建一个子图,设置子图的位置为(1, 2, 1),表示将原始图像显示在第一个子图位置。
  • plt.imshow(x_test[index].reshape(28,28)): 使用plt.imshow()函数显示原始图像。x_test[index]表示从测试集中选择的原始图像数据,.reshape(28, 28)将图像数据的形状重塑为28x28的二维数组,以适应imshow()函数的要求。
  • plt.gray(): 使用plt.gray()函数将显示的图像设置为灰度图像。
  • ax.get_xaxis().set_visible(False): 使用ax.get_xaxis().set_visible(False)函数将子图的x轴刻度标签隐藏。
  • ax.get_yaxis().set_visible(False): 使用ax.get_yaxis().set_visible(False)函数将子图的y轴刻度标签隐藏。
  • ax = plt.subplot(1, 2, 2): 使用plt.subplot()函数创建第二个子图,设置子图的位置为(1, 2, 2),表示将压缩后的图像显示在第二个子图位置。
  • plt.imshow(pred[index].reshape(28,28)): 使用plt.imshow()函数显示压缩后的图像。pred[index]表示从预测结果中选择的图像数据,.reshape(28, 28)将图像数据的形状重塑为28x28的二维数组,以适应imshow()函数的要求。
  • plt.gray(): 使用plt.gray()函数将显示的图像设置为灰度图像。
  • ax.get_xaxis().set_visible(False): 使用ax.get_xaxis().set_visible(False)函数将子图的x轴刻度标签隐藏。
  • ax.get_yaxis().set_visible(False): 使用ax.get_yaxis().set_visible(False)函数将子图的y轴刻度标签隐藏。
  • plt.show(): 使用plt.show()函数显示图像窗口,同时显示原始图像和压缩后的图像。

  通过执行这段代码,你可以看到一个图像窗口,其中包含了两个子图。第一个子图显示原始图像,第二个子图显示经过自动编码器压缩和解压后的图像。这样可以直观地比较两者之间的差异。每次运行代码,都会显示不同的图像,因为index变量是随机选择的。图像窗口的大小为(10, 4),可以根据需要进行调整。

  到目前为止,我们已经了解了自动编码器如何用于图像压缩。接下来我们将看到如何使用自动编码器对图像进行降噪。

三、用于图像降噪的CNN自动编码器

1. 导入库

import numpy as np
import matplotlib.pyplot as plt
from keras import Sequential
from keras.layers import Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.datasets import mnist

2. 加载数据集

(x_train, _), (x_test, _) = mnist.load_data()

3. 预处理图像数据

对图像数据进行归一化:

x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255

重塑输入图像数据:

x_train = x_train.reshape(len(x_train), 28, 28, 1)
x_test = x_test.reshape(len(x_test), 28, 28, 1)
x_test.shape

4. 为图像添加噪声

在训练和测试图像中添加随机噪声:

noise_factor = 0.6
x_train_noisy = x_train + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_train.shape)
x_test_noisy = x_test + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_test.shape)

代码详解:

  • noise_factor = 0.6: 定义噪声因子,表示噪声的强度。这里设置为0.6,意味着添加的噪声将是原始图像的0.6倍大小。
  • x_train_noisy = x_train + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_train.shape): 使用np.random.normal()函数生成服从正态分布的随机噪声,并将其加到训练集的图像数据上。loc=0.0表示正态分布的均值为0,scale=1.0表示正态分布的标准差为1,size=x_train.shape表示生成的随机噪声的形状与训练集图像数据的形状相同。然后,将生成的随机噪声乘以噪声因子,并加到训练集图像数据上。
  • x_test_noisy = x_test + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_test.shape): 同样地,使用相同的过程对测试集的图像数据添加噪声。

  通过执行这段代码,我们将训练集和测试集的图像数据分别与随机生成的噪声相加,从而添加了噪声。这种噪声添加操作可以用于训练和评估去噪自编码器等模型,以提高模型对噪声图像的处理能力。

对添加了噪声的图像数据进行值范围的裁剪:

x_train_noisy = np.clip(x_train_noisy, 0., 1.)
x_test_noisy = np.clip(x_test_noisy, 0., 1.)

代码详解:
  这段代码将添加了噪声的图像数据进行值范围的裁剪,将所有像素值限制在0到1之间。

  • x_train_noisy = np.clip(x_train_noisy, 0., 1.): 使用np.clip()函数对训练集的噪声图像数据进行裁剪操作。np.clip()函数可以将数组中的值限制在指定的范围内。这里将噪声图像数据的像素值限制在0到1之间。
  • x_test_noisy = np.clip(x_test_noisy, 0., 1.): 同样地,对测试集的噪声图像数据进行值范围的裁剪操作。

  通过执行这段代码,我们将添加了噪声的图像数据的像素值限制在0到1的范围内。这种操作可以确保输入数据的像素值在合理的范围内,以便更好地适应模型的训练和处理要求。

5. 探索性数据分析

查看原始图像:

# 随机选择一个图像作为索引
index = np.random.randint(len(x_test))
# 可视化图像
plt.imshow(x_test[index].reshape(28,28))
plt.gray()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第11张图片
代码详解:
  这段代码随机选择一个测试集中的图像,并将其可视化。

  • index = np.random.randint(len(x_test)): 使用np.random.randint()函数生成一个随机整数作为索引,范围为从0到测试集样本数量减1。这样可以随机选择一个图像作为索引。
  • plt.imshow(x_test[index].reshape(28,28)): 使用plt.imshow()函数将选择的图像数据以灰度图像的形式进行可视化。x_test[index]表示选择的图像数据,.reshape(28,28)将图像数据的形状重新调整为28x28的二维形状,以便适应imshow函数的要求。
  • plt.gray(): 将图像显示设置为灰度模式。

  通过执行这段代码,你可以随机选择一个测试集中的图像,并将其以灰度图像的形式显示出来。这样可以帮助你观察和了解所选择的图像的内容和特征。

查看带有噪声的相同图像:

# 随机选择一个图像作为索引
index = np.random.randint(len(x_test))
# 可视化图像
plt.imshow(x_test_noisy[index].reshape(28,28))
plt.gray()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第12张图片
代码详解:
  这段代码随机选择一个添加了噪声的测试集图像,并将其可视化。

  • index = np.random.randint(len(x_test)): 使用np.random.randint()函数生成一个随机整数作为索引,范围为从0到测试集样本数量减1。这样可以随机选择一个图像作为索引。
  • plt.imshow(x_test_noisy[index].reshape(28,28)): 使用plt.imshow()函数将选择的添加了噪声的测试集图像数据以灰度图像的形式进行可视化。x_test_noisy[index]表示选择的图像数据,.reshape(28,28)将图像数据的形状重新调整为28x28的二维形状,以便适应imshow()函数的要求。
  • plt.gray(): 将图像显示设置为灰度模式。

  通过执行这段代码,你可以随机选择一个添加了噪声的测试集图像,并将其以灰度图像的形式显示出来。这样可以帮助你观察和了解所选择的图像在添加噪声后的效果和特征变化。

其他带噪声的图像:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第13张图片
  通过查看这些图像发现我们很直接通过带噪声的图像难识别其原始图像。

6. 模型创建

model = Sequential([
                    # 编码器网络
                    Conv2D(32, 3, activation='relu', padding='same', input_shape=(28, 28, 1)),
                    MaxPooling2D(2, padding='same'),
                    Conv2D(16, 3, activation='relu', padding='same'),
                    MaxPooling2D(2, padding='same'),
                    # 解码器网络
                    Conv2D(16, 3, activation='relu', padding='same'),
                    UpSampling2D(2),
                    Conv2D(32, 3, activation='relu', padding='same'),
                    UpSampling2D(2),
                    # 输出层
                    Conv2D(1, 3, activation='sigmoid', padding='same')
])

model.compile(optimizer='adam', loss='binary_crossentropy')
model.summary()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第14张图片
代码详解:
  这段代码定义了一个基于卷积神经网络的自编码器模型,并进行了编译和打印模型概述。

  • model = Sequential([...]): 创建一个Sequential模型对象,用于构建神经网络模型。模型中的每一层都按照顺序添加到模型中。
  • Conv2D(32, 3, activation='relu', padding='same', input_shape=(28, 28, 1)): 添加一个卷积层,该层具有32个过滤器(即输出通道数为32),过滤器的大小为3x3,使用ReLU激活函数,填充方式为“same”,并指定输入的形状为28x28的灰度图像(通道数为1)。
  • MaxPooling2D(2, padding='same'): 添加一个最大池化层,该层使用2x2的池化窗口进行下采样,填充方式为“same”。
  • Conv2D(16, 3, activation='relu', padding='same'): 添加另一个卷积层,该层具有16个过滤器,过滤器的大小为3x3,使用ReLU激活函数,填充方式为“same”。
  • MaxPooling2D(2, padding='same'): 添加另一个最大池化层,使用2x2的池化窗口进行下采样,填充方式为“same”。
  • Conv2D(16, 3, activation='relu', padding='same'): 添加一个卷积层,该层具有16个过滤器,过滤器的大小为3x3,使用ReLU激活函数,填充方式为“same”。
  • UpSampling2D(2): 添加一个上采样层,使用2x2的上采样窗口进行上采样。
  • Conv2D(32, 3, activation='relu', padding='same'): 添加另一个卷积层,该层具有32个过滤器,过滤器的大小为3x3,使用ReLU激活函数,填充方式为“same”。
  • UpSampling2D(2): 添加另一个上采样层,使用2x2的上采样窗口进行上采样。
  • Conv2D(1, 3, activation='sigmoid', padding='same'): 添加输出层,该层具有1个过滤器(输出通道数为1),过滤器的大小为3x3,使用Sigmoid激活函数,填充方式为“same”。
  • model.compile(optimizer='adam', loss='binary_crossentropy'): 编译模型,使用Adam优化器和二元交叉熵损失函数。
  • model.summary(): 打印模型的概述信息,包括每一层的名称、输出形状和参数数量等。

  通过执行这段代码,我们定义了一个基于卷积神经网络的自编码器模型,并编译和打印了模型的概述信息。这个自编码器模型由编码器网络和解码器网络组成,可以用于图像去噪任务。

7. 训练模型

model.fit(x_train_noisy, x_train, epochs=20, batch_size=256, validation_data=(x_test_noisy, x_test))

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第15张图片
代码详解:
  这段代码使用带有噪声的训练集数据对模型进行训练,并使用未经过噪声处理的测试集数据进行验证。

  • model.fit(x_train_noisy, x_train, epochs=20, batch_size=256, validation_data=(x_test_noisy, x_test)): 使用fit()函数对模型进行训练。x_train_noisy是带有噪声的训练集输入,x_train是对应的无噪声的训练集目标。epochs=20表示进行20轮的训练,batch_size=256表示每个批次的样本数量为256。validation_data=(x_test_noisy, x_test)表示使用未经过噪声处理的测试集数据作为验证数据。

  通过执行这段代码,模型将使用带有噪声的训练集数据进行训练,目标是通过自编码器模型学习恢复无噪声的原始图像。在训练过程中,将计算训练集和验证集的损失值,并更新模型的权重参数,以提高模型对图像去噪的能力。

8. 可视化结果

使用训练好的模型对带有噪声的测试集数据进行预测,生成恢复的去噪图像:

pred = model.predict(x_test_noisy)

运行结果:
在这里插入图片描述
代码详解:

  • pred = model.predict(x_test_noisy): 使用predict()函数对带有噪声的测试集数据进行预测,得到恢复的图像。x_test_noisy是带有噪声的测试集输入。

  通过执行这段代码,模型将对带有噪声的测试集数据进行预测,并生成恢复的去噪图像。预测的结果存储在pred变量中,每个样本对应一个去噪的图像。这样可以通过对比去噪的图像与带噪声的图像,评估模型的去噪效果。

随机选择带噪声图像并显示它:

index = np.random.randint(len(x_test))
plt.imshow(x_test_noisy[index].reshape(28,28))
plt.gray()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第16张图片
代码详解:

  • index = np.random.randint(len(x_test)): 使用np.random.randint()函数生成一个随机整数作为索引,范围为从0到测试集样本数量减1。这样可以随机选择一个图像作为索引。
  • plt.imshow(x_test_noisy[index].reshape(28,28)): 使用plt.imshow()函数将选择的带有噪声的测试集图像数据以灰度图像的形式进行可视化。x_test_noisy[index]表示选择的图像数据,.reshape(28,28)将图像数据的形状重新调整为28x28的二维形状,以便适应imshow()函数的要求。
  • plt.gray(): 将图像显示设置为灰度模式。

  通过执行这段代码,随机选择了一个带有噪声的测试集图像,并将其以灰度图像的形式显示出来。这样可以帮助你观察和了解所选择的图像的噪声效果和特征变化。

可视化降噪后的图像:

plt.imshow(pred[index].reshape(28,28))
plt.gray()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第17张图片
代码详解:

  • plt.imshow(pred[index].reshape(28,28)): 使用plt.imshow()函数将选择的去噪后的图像数据以灰度图像的形式进行可视化。pred[index]表示选择的去噪后的图像数据,.reshape(28,28)将图像数据的形状重新调整为28x28的二维形状,以便适应imshow()函数的要求。
  • plt.gray(): 将图像显示设置为灰度模式。

  通过执行这段代码,将去噪后的图像以灰度图像的形式显示出来。这样可以帮助你观察和了解去噪后的图像的特征和效果。

创建子图,将原始和预测的去噪图像并排显示:

index = np.random.randint(len(x_test))
plt.figure(figsize=(10, 4))
# 可视化带噪声图像
ax = plt.subplot(1, 2, 1)
plt.imshow(x_test_noisy[index].reshape(28,28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
# 可视化降噪后图像
ax = plt.subplot(1, 2, 2)
plt.imshow(pred[index].reshape(28,28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()

运行结果:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第18张图片
代码详解:
  这段代码将原始图像和去噪后的图像进行对比,并以一行两列的形式显示在同一张图中。

  • index = np.random.randint(len(x_test)): 使用np.random.randint()函数生成一个随机整数作为索引,范围为从0到测试集样本数量减1。这样可以随机选择一个图像作为索引。
  • plt.figure(figsize=(10, 4)): 创建一个大小为10x4的图像窗口,用于显示原始图像和压缩后的图像。
  • ax = plt.subplot(1, 2, 1): 创建一个子图,位置为1行2列中的第1个位置。用于显示原始图像。
  • plt.imshow(x_test_noisy[index].reshape(28,28)): 使用plt.imshow()函数将选择的带有噪声的测试集图像数据以灰度图像的形式显示在子图中。x_test_noisy[index]表示选择的图像数据,.reshape(28,28)将图像数据的形状重新调整为28x28的二维形状,以便适应imshow()函数的要求。
  • plt.gray(): 将图像显示设置为灰度模式。
  • ax.get_xaxis().set_visible(False): 隐藏x轴刻度和标签。
  • ax.get_yaxis().set_visible(False): 隐藏y轴刻度和标签。
  • ax = plt.subplot(1, 2, 2): 创建一个子图,位置为1行2列中的第2个位置。用于显示压缩后的图像。
  • plt.imshow(pred[index].reshape(28,28)): 使用plt.imshow()函数将选择的去噪后的图像数据以灰度图像的形式显示在子图中。pred[index]表示选择的去噪后的图像数据,.reshape(28,28)将图像数据的形状重新调整为28x28的二维形状,以便适应imshow()函数的要求。
  • plt.gray(): 将图像显示设置为灰度模式。
  • ax.get_xaxis().set_visible(False): 隐藏x轴刻度和标签。
  • ax.get_yaxis().set_visible(False): 隐藏y轴刻度和标签。
  • plt.show(): 显示图像窗口。

  通过执行这段代码,你将在同一张图中同时显示带噪声的图像和去噪后的图像,以便进行对比和观察它们的区别。图像的大小为10x4,左边的子图显示带噪声的图像,右边的子图显示去噪后的图像。

  查看其他组的对比:
【深度学习项目】用于图像压缩和去噪的深度 CNN 自动编码器(详细报告+代码详解)_第19张图片

四、总结

  在这个项目教程中,我们探讨了深度CNN自动编码器如何用于图像压缩和去噪。   深度CNN自动编码器结合了CNN的空间特征提取能力和自动编码器的重建能力来学习输入数据的有效表示。它可以用于学习紧凑和有意义的表征是至关重要的各种应用。在这里,我们已经看到了自动编码器在图像压缩和去噪方面的应用。
  在图像压缩的自动编码器架构中使用深度CNN的优势在于,它可以捕捉空间依赖性并从输入图像中提取有意义的特征。编码器网络中的卷积层进行局部特征提取,捕捉精细的细节和模式。解码器网络使用转置的卷积层对压缩后的表示进行上采样,并以更好的分辨率重建图像。与传统方法相比,深度CNN架构有助于在压缩过程中保留重要的图像特征并确保更高质量的重建。
  与图像压缩类似,自动编码器中的深度CNN架构在图像去噪方面也很有优势,因为它可以捕捉复杂的空间模式并提取层次特征。网络中的卷积层可以识别噪声模式并抑制它们,使解码器网络能够重建一个更干净的图像版本。
  总之,深度CNN自动编码器是一种强大的方法,适用于图像压缩和去噪任务。它可以在潜伏空间中学习有效的图像表征,允许在降低内存或带宽要求的情况下进行图像压缩。此外,它还能有效地去除损坏图像中的噪声,使重建的图像更干净、质量更高。

⭐️ 往期机器学习/深度学习项目推荐:
1️⃣【机器学习项目】使用 PyTorch 预测汽车价格(详细报告+代码详解)
2️⃣【机器学习/数据分析大项目】黑色星期五销售预测(详细报告+代码详解)
3️⃣【机器学习项目】使用机器学习算法预测航班价格(详细报告+代码详解)

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