使用 ESPCN 模型进行超分辨率图像处理

前言

使用 ESPCN (Efficient Sub-Pixel CNN) 模型对低分辨率的图像,进行超分辨率处理。

效果展示

lowres 表示低分辨率图像,highres 表示高分辨率图像,prediction 表示模型预测的高分辨率图像,可以看出模型在生成高分辨率图像过程中确实发挥了作用。

image.png

image.png

image.png

PSNR of low resolution image and high resolution image is 25.4162
PSNR of predict and high resolution is 26.8309

image.png

image.png

image.png

PSNR of low resolution image and high resolution image is 24.5984
PSNR of predict and high resolution is 26.2234

模型原理

SRCNNDRCN 中,低分辨率图像都是先通过上采样插值得到与高分辨率图像同样的大小再作为网络输入,这意味着卷积操作在较高的分辨率上进行,相比于在低分辨率的图像上计算卷积会降低效率ESPCN 提出一种在低分辨率图像上直接计算卷积得到高分辨率图像的高效率方法。

image.png

ESPCN 的核心概念是亚像素卷积层(sub-pixel convolutional layer)。如上图所示,网络的输入是原始低分辨率图像,通过若干卷积层以后,得到的特征图像大小与输入图像一样,但是特征通道为 r^2 。将每个像素的 r^2 个通道重新排列成一个 r x r 的区域,对应于高分辨率图像中的一个 r x r 大小的子块,从而大小为r^2 x H x W 的特征图像被重新排列成 1 x rH x rW 大小的高分辨率图像。这个变换虽然被称作 sub-pixel convolution , 但实际上并没有卷积操作。总之亚像素卷积层包含两个过程,分别是普通的卷积层和后面的排列像素的步骤。

通过使用 sub-pixel convolution , 图像从低分辨率到高分辨率放大的过程,插值函数被隐含地包含在前面的卷积层中,可以自动学习到。只在最后一层对图像大小做变换,前面的卷积运算由于在低分辨率图像上进行,因此效率会较高。

数据处理

  • 我自己生成了一批数据,我这里是放在了 D:\pythonProject\HKYModel\data2 目录之下。
  • 因为数据集中已经分好了训练集测试集,所以直接使用函数进行本地数据的读取即可得到 train_dsvalid_ds
  • train_dsvalid_ds 中的图片都做归一化操作
root_dir = "D:\pythonProject\HKYModel\BSR\BSDS500\data"
crop_size = 300
upscale_factor = 3
input_size = crop_size // upscale_factor
batch_size = 8
train_ds = image_dataset_from_directory(root_dir, batch_size=batch_size, image_size=(crop_size, crop_size), validation_split=0.2,  subset="training", seed=1337,  label_mode=None)
valid_ds = image_dataset_from_directory(root_dir, batch_size=batch_size,  image_size=(crop_size, crop_size),  validation_split=0.2, subset="validation",  seed=1337, label_mode=None)
def scaling(input_image):input_image = input_image / 255.return input_image
train_ds = train_ds.map(scaling)
valid_ds = valid_ds.map(scaling)
  • process_input 函数接受输入图像和输入大小作为参数,并且将输入图像转换为 YUV 颜色空间。YUV 颜色空间包含了亮度(Y)和色度(U、V)信息。tf.image.rgb_to_yuv 函数用于将 RGB 彩色图像转换为 YUV 颜色空间。接着确定最后一个维度的索引。这个索引被用来沿着颜色通道轴(通常是最后一个维度)拆分输入张量,得到 Y、U、V 三个通道的张量。我们从拆分后的张量中只提取亮度通道 Y,并使用 tf.image.resize 函数将其调整为指定的输入大小,调整大小的方法是 "area"
  • process_target 函数也是类似的,它也将输入图像转换为 YUV 颜色空间,并提取出亮度通道 Y。但不同的是,它并没有调整图像的大小,只是返回了亮度通道 Y。
dataset = os.path.join(root_dir, "images")
test_path = os.path.join(dataset, "test")
test_img_paths = sorted([os.path.join(test_path, fname) for fname in os.listdir(test_path) if fname.endswith(".jpg")])
def process_input(input, input_size):input = tf.image.rgb_to_yuv(input)last_dimension_axis = len(input.shape) - 1y, u, v = tf.split(input, 3, axis=last_dimension_axis)return tf.image.resize(y, [input_size, input_size], method="area")
def process_target(input):input = tf.image.rgb_to_yuv(input)last_dimension_axis = len(input.shape) - 1y, u, v = tf.split(input, 3, axis=last_dimension_axis)return y
train_ds = train_ds.map(lambda x: (process_input(x, input_size), process_target(x))).prefetch(buffer_size=32)
valid_ds = valid_ds.map(lambda x: (process_input(x, input_size), process_target(x))).prefetch(buffer_size=32)

模型

  • DepthToSpace 类继承自 layers.Layer,表示一个深度转换空间的层,用于实现深度转换空间操作。 get_config 方法用于获取层的配置信息。这个方法被调用以保存层的配置,以便在需要序列化模型时可以重新创建相同的层实例。call 方法实现了层的前向传播逻辑,在这个方法中,它接受一个输入张量 input,然后执行深度转换空间操作。具体地,它首先获取输入张量的形状信息,然后按照 block_size 分块重排张量,并最终返回转换后的张量。

  • get_model 函数用于创建一个 Keras 模型。在这个函数中,它接受两个参数:upscale_factorchannelsupscale_factor 表示上采样因子,channels 表示输入图像的通道数。在模型中,它使用了一系列的卷积层构建了一个深度卷积神经网络。然后,通过 DepthToSpace 层来实现深度转换空间操作,以实现图像的上采样。最后,通过 keras.Model 类构建了一个 Keras 模型,指定了输入和输出,返回了这个模型。

class DepthToSpace(layers.Layer):def __init__(self, block_size):super().__init__()self.block_size = block_sizedef get_config(self):config = super().get_config()config.update({"block_size": self.block_size})return configdef call(self, input):batch, height, width, depth = ops.shape(input)depth = depth // (self.block_size**2)x = ops.reshape(input, [batch, height, width, self.block_size, self.block_size, depth])x = ops.transpose(x, [0, 1, 3, 2, 4, 5])x = ops.reshape(x, [batch, height * self.block_size, width * self.block_size, depth])return x
def get_model(upscale_factor=3, channels=1):conv_args = {"activation": "relu",  "kernel_initializer": "orthogonal", "padding": "same"}inputs = keras.Input(shape=(None, None, channels))x = layers.Conv2D(512, 5, **conv_args)(inputs)x = layers.Conv2D(256, 3, **conv_args)(x)x = layers.Conv2D(64, 3, **conv_args)(x)x = layers.Conv2D(channels * (upscale_factor**2), 3, **conv_args)(x)outputs = DepthToSpace(upscale_factor)(x)return keras.Model(inputs, outputs)

训练

  • 自定义回调函数类 ESPCNCallback ,在每个 epoch 开始时调用 on_epoch_begin 方法,它初始化了一个列表 self.psnr,用于存储每个 epoch 的峰值信噪比(PSNR)。在每个 epoch 结束时调用 on_epoch_end 方法。它计算了当前 epoch 的平均 PSNR ,并打印输出。每隔 20 个 epoch 就利用模型生成了一个预测图像,并通过 plot_results 函数绘制了这个预测图像,用于观察模型的生成效果。在每个测试集的 batch 结束时调用on_test_batch_end 方法,它计算了当前 batch 的 PSNR ,并将其添加到 self.psnr 列表中。
  • 另外创建了两个额外的 Keras 回调函数:early_stopping_callback 用于在训练过程中实施 early stopping 策略,如果在连续 5 个 epoch 中损失没有降低,则停止训练;model_checkpoint_callback 用于在训练过程中保存模型的最佳参数。
  • 使用 Adam 优化器和均方误差作为损失函数。
  • 使用 model.fit 函数进行模型的训练。指定了训练数据集 train_ds,并设置了训练的 epochs 数目为 200,并且设置了之前定义的回调函数作为回调参数。
class ESPCNCallback(keras.callbacks.Callback):def __init__(self):super().__init__()self.test_img = get_lowres_image(load_img(test_img_paths[0]), upscale_factor)def on_epoch_begin(self, epoch, logs=None):self.psnr = []def on_epoch_end(self, epoch, logs=None):print("Mean PSNR for epoch: %.2f" % (np.mean(self.psnr)))if epoch % 20 == 0:prediction = upscale_image(self.model, self.test_img)plot_results(prediction, "epoch-" + str(epoch), "prediction")def on_test_batch_end(self, batch, logs=None):self.psnr.append(10 * math.log10(1 / logs["loss"]))early_stopping_callback = keras.callbacks.EarlyStopping(monitor="loss", patience=5)
model_checkpoint_callback = keras.callbacks.ModelCheckpoint(filepath="ESPCN/checkpoint.keras", save_weights_only=False, monitor="loss",  mode="min", save_best_only=True, )
model = get_model(upscale_factor=upscale_factor, channels=1)
model.summary()
callbacks = [ESPCNCallback(), early_stopping_callback, model_checkpoint_callback]
model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.001), loss=keras.losses.MeanSquaredError())
model.fit(train_ds, epochs=200, callbacks=callbacks, validation_data=valid_ds, verbose=2)

日志打印:

Epoch 1/200
2024-03-06 16:14:17.804215: I tensorflow/stream_executor/cuda/cuda_dnn.cc:384] Loaded cuDNN version 8100
Mean PSNR for epoch: 22.44
50/50 - 5s - loss: 0.0226 - val_loss: 0.0058 - 5s/epoch - 105ms/step
Epoch 2/200
Mean PSNR for epoch: 23.57
50/50 - 1s - loss: 0.0064 - val_loss: 0.0043 - 1s/epoch - 21ms/step
...
Epoch 29/200
Mean PSNR for epoch: 26.75
50/50 - 1s - loss: 0.0025 - val_loss: 0.0022 - 996ms/epoch - 20ms/step
Epoch 30/200
Mean PSNR for epoch: 26.53
50/50 - 1s - loss: 0.0025 - val_loss: 0.0023 - 992ms/epoch - 20ms/step
Epoch 31/200
Mean PSNR for epoch: 26.18
50/50 - 1s - loss: 0.0025 - val_loss: 0.0023 - 987ms/epoch - 20ms/step

那么,我们该如何学习大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

一、大模型全套的学习路线

学习大型人工智能模型,如GPT-3、BERT或任何其他先进的神经网络模型,需要系统的方法和持续的努力。既然要系统的学习大模型,那么学习路线是必不可少的,下面的这份路线能帮助你快速梳理知识,形成自己的体系。

L1级别:AI大模型时代的华丽登场

L2级别:AI大模型API应用开发工程

L3级别:大模型应用架构进阶实践

L4级别:大模型微调与私有化部署

一般掌握到第四个级别,市场上大多数岗位都是可以胜任,但要还不是天花板,天花板级别要求更加严格,对于算法和实战是非常苛刻的。建议普通人掌握到L4级别即可。

以上的AI大模型学习路线,不知道为什么发出来就有点糊,高清版可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

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

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

相关文章

力扣hot100:155. 最小栈(栈,辅助栈存储相关信息)

LeetCode:155. 最小栈 1、尝试单调栈 看到这题说,要常数时间内检索最小元素的栈,想到了单调栈,递增单调栈确实能维护最小值,但是这个最小值是存在一定意义的,即如果后面出现了最小值,那么前面…

光电管道液位传感器与电容式液位开关相比

如今,随着检测液位技术的不断发展,检测液位的方法也越来越多,比如浮球开关、电容式液位传感器、管道式液位传感器等等,那么光电管道液位传感器与电容式液位开关相比,有哪些优势? 光电管道液位传感器采用先…

论文高级图表绘制(Python语言,局部放大图)

本文将通过一个具体的示例,展示如何使用Python语言和Matplotlib库来绘制高级图表,包括局部放大图的制作。适用于多条曲线绘制在同一个图表中,但由于数据量过大,导致曲线的细节看不清,需要对细节进行局部放大。如下图: 环境准备 首先,确保你的Python环境中已经安装了以…

页面加载性能分析中,如何确定哪些资源是关键的,哪些可以延迟加载?

在页面加载性能分析中,确定哪些资源是关键的,哪些可以延迟加载,可以通过以下步骤进行: 使用 Performance 面板: 在 Chrome DevTools 的 Performance 面板中记录页面加载过程。分析记录结果,查看哪些资源加载…

基于SSM+Jsp的高校信息资源共享平台

开发语言:Java框架:ssm技术:JSPJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包…

页面加载性能分析时,有哪些常见的性能瓶颈需要特别注意?

在进行页面加载性能分析时,以下是一些常见的性能瓶颈,需要特别注意: 长页面加载时间: 页面加载时间超过行业标准或用户期望,导致用户流失。 高 CPU 使用率: 某些脚本或操作导致 CPU 使用率飙升,…

基于STM32开发的智能家居监控系统

目录 引言环境准备智能家居监控系统基础代码实现:实现智能家居监控系统 4.1 传感器数据读取4.2 电器设备控制4.3 实时数据监控与分析4.4 用户界面与数据可视化应用场景:家庭安全监控与管理问题解决方案与优化收尾与总结 1. 引言 随着智能家居技术的发…

C++的MQTT开发:使用Paho的C++接口实现消息发布、订阅、连接RabbitMQ

C Paho实现MQTT消息发布功能 要使用paho的cpp接口实现发布MQTT消息的功能,需要进行以下步骤: 安装paho库:首先从paho官方网站下载并安装paho的C库。可以从https://www.eclipse.org/paho/clients/cpp/ 下载适合操作系统的版本。 创建MQTT客户…

FM151A,FM171B和利时工控

FM151A,FM171B和利时工控,DCS系统应该具备以下特点:1.系统具备开放的体系结构,可以提供多层的开放数据接口;FM151A,FM171B和利时工控。2.系统应具备强大的处理功能,中型分布式控制系统大型数据采集监控系统功能。FM151…

[数据集][目标检测]室内积水检测数据集VOC+YOLO格式761张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):761 标注数量(xml文件个数):761 标注数量(txt文件个数):761 标注类别…

Spark Python环境搭建与优化:深入剖析四个方面、五个方面、六个方面及七个关键要点

Spark Python环境搭建与优化:深入剖析四个方面、五个方面、六个方面及七个关键要点 在大数据处理领域,Apache Spark凭借其出色的性能和灵活性备受瞩目。而要在Python中利用Spark的强大功能,首先需要搭建一个稳定且高效的Spark Python环境。本…

使用小黄鸟(HttpCanary)、VMOS Pro虚拟机对手机APP进行抓包(附带软件)

老规矩先看,效果图: 文章很详细,希望可以耐心看完,保证可以学会抓包,不再走冤枉路,小编在之前看过太多类似文章,折腾了太久才搞懂的,写这篇文章就是不想希望你们像小编一样再花时间…

C++ 20新特性之三向比较运算符

概述 在C中&#xff0c;如果需要对两个自定义类的对象进行比较&#xff0c;我们通常要单独定义6个比较运算符&#xff1a;、!、<、<、>、>。这不仅繁琐&#xff0c;还很容易出错&#xff0c;特别是当比较逻辑复杂时&#xff0c;稍有不慎就会引发不一致的比较结果。…

最新的ffmepg.js前端VUE3实现视频、音频裁剪上传功能

package.json "dependencies": {"ffmpeg/ffmpeg": "^0.12.10","ffmpeg/util": "^0.12.1" }vue3组件代码 根据需要更改 <script setup lang"ts"> import { FFmpeg } from ffmpeg/ffmpeg; import { fetchF…

mac无法读取windows分区怎么办 苹果硬盘怎么读取

对于Mac电脑用户但有Windows系统使用需求的&#xff0c;我们可以通过Boot Camp启动转换助理安装Windows分区这个方案来解决&#xff0c;不过因为两个系统的磁盘格式不同&#xff0c;相应的也会产生一些问题&#xff0c;例如无法正常读取windows分区。下面本文就详细说明mac无法…

在Java中使用SeleniumAPI,超详细

Java中 Selenium相关操作 1 定位元素 1.1 css选择器定位元素 就是定位到页面的元素&#xff0c;本质上就是一个一个的语法 下面举几个具体的例子&#xff1a; 类选择器 按照给定的 class 属性的值&#xff0c;选择所有匹配的元素。 语法&#xff1a;.classname 例子&am…

Sass详细介绍

Sass&#xff08;Syntactically Awesome Stylesheets&#xff09;是一种CSS预处理器&#xff0c;用于增强CSS的功能和灵活性。以下是对Sass的详细介绍&#xff0c;采用分点表示和归纳的方式&#xff1a; 1. Sass的概述 Sass是一种CSS预处理器&#xff0c;它扩展了CSS的语法和…

力扣1358.包含所有三种字符的子字符串数目

力扣1358.包含所有三种字符的子字符串数目 遍历左端点 找到最小的子字符串 res n - j(右边全部) class Solution {public:int numberOfSubstrings(string s) {unordered_map<char,int> cnt;int n s.size(),res0,count3;for(int i0,j0;j<n;j){if(!cnt.count(s[j])…

Python如何巧妙回应:深入解析Python的回应策略与技巧

Python如何巧妙回应&#xff1a;深入解析Python的回应策略与技巧 在编程的世界里&#xff0c;Python以其简洁、易读和强大的功能库赢得了众多开发者的青睐。然而&#xff0c;当我们与Python程序进行交互时&#xff0c;如何巧妙地回应其输出或错误信息&#xff0c;成为了提高编…

数字签名及其作用

一、技术难点 数字签名作为信息安全领域的关键技术之一&#xff0c;其技术难点主要体现在以下几个方面&#xff1a; 算法选择&#xff1a;不同的数字签名算法具有不同的安全性、效率和应用场景。如RSA、ECDSA、DSA等算法各有优劣&#xff0c;如何根据实际需求选择合适的算法是…