【图像处理】使用自动编码器进行图像降噪(改进版)

news2024/11/24 8:59:17

阿里雷扎·凯沙瓦尔兹

一、说明

        自动编码器是一种学习压缩和重建输入数据的神经网络。它由一个将数据压缩为低维表示的编码器和一个从压缩表示中重建原始数据的解码器组成。该模型使用无监督学习进行训练,旨在最小化输入和重建输出之间的差异。自动编码器可用于降维、数据去噪和异常检测等任务。它们在处理未标记数据时非常有效,并且可以从大型数据集中学习有意义的表示。

二、自动编码器的工作原理

        网络提供原始图像x,以及它们的噪声版本x~。网络尝试重建其输出 x',使其尽可能接近原始图像 x。通过这样做,它学会了如何对图像进行去噪。

如图所示,编码器模型将输入转换为小型密集表示形式。解码器模型可以看作是能够生成特定特征的生成模型。

编码器和解码器网络通常都是作为一个整体进行训练的。损失函数惩罚网络创建与原始输入 x 不同的输出 x'

通过这样做,编码器学会了保留潜在空间限制所需的尽可能多的相关信息,并巧妙地丢弃不相关的部分,例如噪声。解码器学习获取压缩的潜在信息并将其重建为完整的无错误输入。

三、如何实现自动编码器

        让我们实现一个自动编码器来对手写数字进行降噪。输入是一个 28x28 灰度缩放的图像,构建一个 128 个元素的矢量。

        编码器层负责将输入图像转换为潜在空间中的压缩表示。它由一系列卷积层和全连接层组成。这种压缩表示包含捕获其底层模式和结构的输入图像的基本特征。ReLU用作编码器层中的激活函数。它应用逐元素激活函数,将负输入的输出设置为零,并保持正输入不变。在编码器层中使用ReLU的目标是引入非线性,允许网络学习复杂的表示并从输入数据中提取重要特征。

        代码中的解码器层负责从潜在空间中的压缩表示重建图像。它反映了编码器层的结构,由一系列完全连接和转置卷积层组成。解码器层从潜在空间获取压缩表示,并通过反转编码器层执行的操作来重建图像。它使用转置卷积层逐渐对压缩表示进行上采样,并最终生成与输入图像具有相同尺寸的输出图像。Sigmoid 和 ReLU 激活用于解码器层。Sigmoid 激活将输入值压缩在 0 到 1 之间,将每个神经元的输出映射到类似概率的值。在解码器层中使用 sigmoid 的目标是生成 [0, 1] 范围内的重建输出值。由于此代码中的输入数据表示二进制图像,因此 sigmoid 是重建像素值的合适激活函数。

        通过在编码器层和解码器层使用适当的激活函数,自动编码器模型可以有效地学习将输入数据压缩到低维潜在空间中,然后从潜在空间重建原始输入数据。激活函数的选择取决于所解决问题的具体要求和特征。

二进制交叉熵用作损失函数,Adam 用作最小化损失函数的优化器。“binary_crossentropy”损失函数通常用于二元分类任务,适用于在这种情况下重建二元图像。它衡量预测输出与真实目标输出之间的相似性。“adam”优化器用于在训练期间更新模型的权重和偏差。Adam(自适应矩估计的缩写)是一种优化算法,它结合了 RMSprop 优化器和基于动量的优化器的优点。它单独调整每个权重参数的学习率,并使用梯度的第一和第二时刻来有效地更新参数。

通过使用二进制交叉熵作为损失函数和Adam优化器,自动编码器模型旨在最小化重建误差并优化模型的参数,以生成输入数据的准确重建。

第 1 部分:导入库和模块

import numpy as np
 import matplotlib.pyplot as plt
from tensorflow.keras.datasets import mnist
 from tensorflow.keras.layers import input, dense, reshape, flatten, Conv2D, Conv2DTranspose
 from tensorflow.keras.models import model from tensorflow.keras.optimizers   import Adam

from tensorflow.keras.callbacks import EarlyStop

在这一部分中,导入了必要的库和模块。

  • numpy(导入为 )是用于数值运算的库。np
  • matplotlib.pyplot(导入为 )是用于打印的库。plt
  • mnist从 导入以加载 MNIST 数据集。tensorflow.keras.datasets
  • 从 和 导入各种层和模型。tensorflow.keras.layerstensorflow.keras.models
  • 优化程序是从 导入的。Adamtensorflow.keras.optimizers
  • 回调是从 导入的。EarlyStoppingtensorflow.keras.callbacks

第 2 部分:加载和预处理数据集

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

在这一部分中,加载 MNIST 数据集并将其拆分为训练集和测试集。相应的标签将被忽略,并且不会分配给任何变量。

第 3 部分:预处理数据集

x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
x_train = np.expand_dims(x_train, axis=-1)
x_test = np.expand_dims(x_test, axis=-1)

在这一部分中,数据集被预处理:

  • 和 中图像的像素值通过除以 0.1 归一化为 255 到 0 的范围。x_trainx_test
  • 输入数据的维度使用 展开以包括通道维度。这对于卷积运算是必需的。np.expand_dims

第 4 部分:向训练集添加随机噪声

noise_factor = 0.5
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)
x_train_noisy = np.clip(x_train_noisy, 0., 1.)
x_test_noisy = np.clip(x_test_noisy, 0., 1.)

在这一部分中,随机噪声被添加到训练集中:

  • 选择0.5的噪声系数来控制噪声量。
  • 使用平均值为 0、标准差为 1 的随机噪声样本生成,然后按噪声因子进行缩放。np.random.normal
  • 噪声训练集和测试集是通过将噪声添加到原始数据中获得的。
  • 对像素值进行裁剪,以确保它们保持在 0 到 1 的有效范围内。

第 5 部分:创建自动编码器模型

input_shape = (28, 28, 1)
latent_dim = 128

# Encoder
inputs = Input(shape=input_shape)
x = Conv2D(32, kernel_size=3, strides=2, activation='relu', padding='same')(inputs)
x = Conv2D(64, kernel_size=3, strides=2, activation='relu', padding='same')(x)
x = Flatten()(x)
latent_repr = Dense(latent_dim)(x)

# Decoder
x = Dense(7 * 7 * 64)(latent_repr)
x = Reshape((7, 7, 64))(x)
x = Conv2DTranspose(32, kernel_size=3, strides=2, activation='relu', padding='same')(x)
decoded = Conv2DTranspose(1, kernel_size=3, strides=2, activation='sigmoid', padding='same')(x)

# Autoencoder model
autoencoder = Model(inputs, decoded)

在这一部分中,自动编码器模型是使用编码器-解码器架构创建的:

  • input_shape定义为 ,表示输入图像的形状。(28, 28, 1)
  • latent_dim设置为 128,这决定了潜在空间的维数。
  • 编码器层定义:
  • 将使用指定的 .input_shape
  • 添加了两个分别具有 32 和 64 个过滤器的卷积层,内核大小为 3x3,步幅为 2,激活和填充设置为 。'relu''same'
  • 卷积层的输出使用 .Flatten()
  • 通过将扁平输出传递到带有神经元的完全连接层来获得潜在表示。Denselatent_dim
  • 解码器层定义:
  • 添加带有神经元的层以匹配编码器中最后一个特征图的形状。Dense7 * 7 * 64
  • 输出将调整为 使用 .(7, 7, 64)Reshape
  • 添加了两个转置卷积层:
  • 第一层有 32 个过滤器,内核大小为 3x3,步幅为 2,激活和填充设置为 。'relu''same'
  • 第二层有 1 个筛选器,内核大小为 3x3,步幅为 2,激活和填充设置为 。'sigmoid''same'
  • 通过指定输入和输出层来创建模型。autoencoder

第 6 部分:编译自动编码器模型

autoencoder.compile(optimizer=Adam(lr=0.0002), loss='binary_crossentropy')

在这一部分中,编译了自动编码器模型:

  • 优化器的学习率为 0.0002。Adam
  • 损失函数设置为 。'binary_crossentropy'

第 7 部分:添加提前停止

early_stopping = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True)

在这一部分中,创建了一个提前停止回调:

  • 它监视验证丢失 ()。'val_loss'
  • 如果验证损失连续 5 个 epoch 没有改善,则停止训练。
  • 恢复训练期间模型的最佳权重。

第 8 部分:训练自动编码器

epochs = 20
batch_size = 128

history = autoencoder.fit(x_train_noisy, x_train, validation_data=(x_test_noisy, x_test),
                          epochs=epochs, batch_size=batch_size, callbacks=[early_stopping])

在这一部分中,对自动编码器模型进行了训练:

  • 纪元数设置为 100,批大小设置为 128。
  • 训练数据以 提供,验证数据以 提供。(x_train_noisy, x_train)(x_test_noisy, x_test)
  • 训练过程以指定的周期数、批大小和提前停止回调执行。
  • 训练历史记录存储在变量中。history

第 9 部分:去噪测试图像并显示结果

denoised_test_images = autoencoder.predict(x_test_noisy)

# Display original, noisy, and denoised images
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
    # Original images
    ax = plt.subplot(3, n, i + 1)
    plt.imshow(x_test[i].reshape(28, 28), cmap='gray')
    plt.title("Original")
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # Noisy images
    ax = plt.subplot(3, n, i + 1 + n)
    plt.imshow(x_test_noisy[i].reshape(28, 28), cmap='gray')
    plt.title("Noisy")
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # Denoised images
    ax = plt.subplot(3, n, i + 1 + n + n)
    plt.imshow(denoised_test_images[i].reshape(28, 28), cmap='gray')
    plt.title("Denoised")
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()

在这一部分中:

  • 通过使用该方法将噪声测试图像通过训练的自动编码器来获得去噪测试图像。predict
  • 原始、噪点和去噪图像使用 .matplotlib.pyplot
  • 将创建一个包含三行的图形来显示图像。
  • 对于每一行,为每个图像创建一个子图。
  • 原始图像、噪点图像和去噪图像显示在单独的子图中。
  • 为每个子图设置轴标签和标题。
  • 结果图使用 表示。plt.show()

四、结果

深度学习
自动编码器
词典

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/784152.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

宋浩线性代数笔记(二)矩阵及其性质

更新线性代数第二章——矩阵,本章为线代学科最核心的一章,知识点多而杂碎,务必仔细学习。 重难点在于: 1.矩阵的乘法运算 2.逆矩阵、伴随矩阵的求解 3.矩阵的初等变换 4.矩阵的秩 (去年写的字,属实有点ugl…

Android 之 Canvas API 详解 (Part 2) 剪切方法合集

本节引言: 本节继续带来Android绘图系列详解之Canvas API详解(Part 2),今天要讲解的是Canvas 中的ClipXxx方法族!我们可以看到文档中给我们提供的Clip方法有三种类型: clipPath( ),clipRect( ),clipRegion(…

Mybatis的基本操作--增删改查

目录 查看数据 无参数 一个参数 多个参数 添加数据 修改数据 删除数据 查看数据 分三种情况:无参,有一个参数,有多个参数的情况。 (这里的详细操作步骤是博主的上一篇博客写的:初识Mybatis,并创建第…

2023年VSCode插件最新推荐(54款)

本文介绍前端开发领域常用的一些VSCode插件,插件是VSCode最重要的组成部分之一,本文列出了我自己在以往工作经验中积累的54款插件,个人觉得这些插件是有用或有趣的,根据它们的作用,我粗略的把它们分成了代码管理、文本…

css实现纹理条纹,波点背景效果

css实现纹理条纹,波点背景效果 本文目录 css实现纹理条纹,波点背景效果效果一:水平条纹效果二:竖向条纹效果三:斜条纹效果四:网格效果五:象棋盘1效果六:象棋盘2效果七:红…

代码重构的时机与方法

🐱 个人主页:不叫猫先生,公众号:前端舵手 🙋‍♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步…

机器人制作开源方案 | 智能垃圾桶

1. 功能说明 智能垃圾桶是一种利用物联网技术和智能感知能力的智能设备,旨在提高垃圾分类和处理的效率。通常具备以下特点和功能: ① 智能感知:智能垃圾桶配备各种传感器,如压力传感器、红外线传感器等,可以实时感知…

Flutter实现点击头像更新头像的功能,本地相册选取和调用相机两种方式的实现

文章目录 需求实现的效果如图代码实现代码分析用InkWell包住了我们的头像,这样来监听点击头像的事件用showDialog弹出提示框让用户选择是从相册里选择头像还是使用相机来拍照用image_picker实现从设备的相册或相机中选择图片或拍照 需求 Flutter实现点击头像更新头…

数字孪生管控系统,智慧园区楼宇合集

智慧园区是指将物联网、大数据、人工智能等技术应用于传统建筑和基础设施,以实现对园区的全面监控、管理和服务的一种建筑形态。通过将园区内设备、设施和系统联网,实现数据的传输、共享和响应,提高园区的管理效率和运营效益,为居…

【java】【基础8】入门结业-ATM系统实战

目录 一、ATM项目技术 二、能达成的能力 三、开始编码 3.1 系统架构搭建、欢迎页设计 3.1.1 Account 3.1.2 ATM 3.1.3 Test 3.2 开户功能实现 3.2.1 修改AccountgetUserName() 3.2.2 ATM 开户操作 3.2.3 ATM为新用户生成一个随机卡号​编辑 3.3 登录功能实现 3.4 操作页…

登录和注册页面 - 验证码功能的实现

目录 1. 生成验证码 2. 将本地验证码发布成 URL 3. 后端返回验证码的 URL 给前端 4. 前端将用户输入的验证码传给后端 5. 后端验证验证码 1. 生成验证码 使用hutool 工具生成验证码. 1.1 添加 hutool 验证码依赖 <!-- 验证码 --> <dependency><groupId…

Linux——信号量、环形队列

Linux——信号量和环形队列 文章目录 Linux——信号量和环形队列概念信号量的PV原语线程申请信号量失败将会被挂起 信号量函数sem_init初始化信号量sem_destroy销毁信号量sem_wait等待信号量sem_post发布信号量 基于环形队列的生产者消费者模型代码实现 概念 临界资源&#xf…

Qt - 信号和槽

文章目录 信号和槽自定义信号和槽代码实现teacher 类申明信号方法student 添加槽并处理绑定信号和槽 当自定义信号和槽出现重载设置按钮点击 信号可以连接信号断开信号 disconnectQt4版本写法Lambda 表达式函数对象参数操作符重载函数参数可修改标示符函数返回值是函数体 总结拓…

【C++修炼之路】继承

&#x1f451;作者主页&#xff1a;安 度 因 &#x1f3e0;学习社区&#xff1a;StackFrame &#x1f4d6;专栏链接&#xff1a;C修炼之路 文章目录 一、概念及定义二、基类和派生类对象赋值转换三、继承中的作用域四、派生类的默认成员函数五、继承与友元六、继承与静态成员七…

2023最新谷粒商城笔记之Sentinel概述篇(全文总共13万字,超详细)

Sentinel概述 服务流控、熔断和降级 什么是熔断 当扇出链路的某个微服务不可用或者响应时间太长时&#xff0c;会进行服务的降级&#xff0c;**进而熔断该节点微服务的调用&#xff0c;快速返回错误的响应信息。**检测到该节点微服务调用响应正常后恢复调用链路。A服务调用B服…

服务器被挂病毒记录(redis入侵)

前言 今天正在快乐的打着游戏&#xff0c;突然一个浙江的电话&#xff1a; 好家伙&#xff0c;我那可怜的1核2g的服务器说在跑挖矿程序&#xff0c;苍天啊&#xff0c;大地呀&#xff0c;我那1核2g的服务器有啥跑呢&#xff0c;别难为这小家伙了。 解决过程&#xff1a; 1…

【学会动态规划】地下城游戏(10)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后&#xff1a; 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟我…

计算机网络复习(路由器、交换机、广域网配置~)

文章目录 子网划分路由器和交换机的配置&#xff08;基础知识&#xff09;IOS基础IOS使用技巧Cisco设备的启动Cisco设备的配置途径配置文件的备份与恢复管理网络环境配置Telnet网络测试 配置路由表路由简介路由表简介路由的分类配置静态路由动态路由协议VLAN间的路由路由信息协…

Redis追本溯源(二)数据结构:String、List、Hash、Set、Zset底层数据结构原理

文章目录 一、String底层——sds&#xff08;Simple Dynamic String&#xff09;1.sds相比C语言字符串的优点2.结构3.扩容4.缩容 二、List底层——quickList、zipList1.quickList及其优化过程&#xff08;1&#xff09;quickList大致结构&#xff08;2&#xff09;引入zipList进…