超分辨率重建

意义

客观世界的场景含有丰富多彩的信息,但是由于受到硬件设备的成像条件和成像方式的限制,难以获得原始场景中的所有信息。而且,硬件设备分辨率的限制会不可避免地使图像丢失某些高频细节信息。在当今信息迅猛发展的时代,在卫星遥感、医学影像、多媒体视频等领域中对图像质量的要求越来越高,人们不断寻求更高质量和更高分辨率的图像,来满足日益增长的需求。

空间分辨率的大小是衡量图像质量的一个重要指标,也是将图像应用到实际生活中重要的参数之一。分辨率越高的图像含有的细节信息越多,图像清晰度越高,在实际应用中对各种目标的识别和判断也更加准确。

但是通过提高硬件性能从而提高图像的分辨率的成本高昂。因此,为了满足对图像分辨率的需求,又不增加硬件成本的前提下,依靠软件方法的图像超分辨率重建应运而生。

超分辨率图像重建是指从一系列有噪声、模糊及欠采样的低分辨率图像序列中恢复出一幅高分辨率图像的过程。可以针对现有成像系统普遍存在分辨率低的缺陷,运用某些算法,提高所获得低分辨率图像的质量。因此,超分辨率重建算法的研究具有广阔的发展空间。

方法的具体细节

评价指标
峰值信噪比

峰值信噪比(Peak Signal-to-Noise Ratio), 是信号的最大功率和信号噪声功率之比,来测量被压缩的重构图像的质量,通常以分贝来表示。PSNR指标值越高,说明图像质量越好。

SSIM计算公式如下:

PSNR=10\ast lg\frac{MAX_I^2}{MSE}

MSE表示两个图像之间对应像素之间差值平方的均值。

MAX^2_I表示图像中像素的最大值。对于8bit图像,一般取255。

MSE=\frac{1}{M\ast N} \displaystyle \sum_{i=1}^{N} \sum_{j=1}^{M}(f_{ij}-f'_{ij})^2

f_{ij} 表示图像X在 ij 处的像素值

f'_{ij} 表示图像Y在 ij 处的像素值

结构相似性评价

结构相似性评价(Structural Similarity Index), 是衡量两幅图像相似度的指标,取值范围为0到1。SSIM指标值越大,说明图像失真程度越小,图像质量越好。

SSIM计算公式如下:

L(X,Y)=\frac{2\mu X\mu Y +C_1}{\mu ^2_X + \mu ^2_Y + C_1}

C(X,Y)=\frac{2\sigma X\sigma Y +C_2}{\sigma ^2_X + \sigma ^2_Y + C_2}

S(X,Y)=\frac{\sigma _{XY} + C_3}{\sigma _X \sigma _Y + C_3}

SSIM(X,Y)=L(X,Y) \ast C(X,Y) \ast S(X,Y)

 这两种方式,一般情况下能较为准确地评价重建效果。但是毕竟人眼的感受是复杂丰富的,所以有时也会出现一定的偏差。

EDSR

img

SRResNet在SR的工作中引入了残差块,取得了更深层的网络,而EDSR是对SRResNet的一种提升,其最有意义的模型性能提升是去除掉了SRResNet多余的模块(BN层)

image-20211229150541634

EDSR把批规范化处理(batch normalization, BN)操作给去掉了。

论文中说,原始的ResNet最一开始是被提出来解决高层的计算机视觉问题,比如分类和检测,直接把ResNet的结构应用到像超分辨率这样的低层计算机视觉问题,显然不是最优的。由于批规范化层消耗了与它前面的卷积层相同大小的内存,在去掉这一步操作后,相同的计算资源下,EDSR就可以堆叠更多的网络层或者使每层提取更多的特征,从而得到更好的性能表现。EDSR用L1损失函数来优化网络模型。

1.解压数据集

因为训练时间可能不是很长,所以这里用了BSD100,可以自行更换为DIV2K或者coco

#  !unzip -o /home/aistudio/data/data121380/DIV2K_train_HR.zip -d train
# !unzip -o  /home/aistudio/data/data121283/Set5.zip -d test
 2.定义dataset
import os
from paddle.io import Dataset
from paddle.vision import transforms
from PIL import Image
import random
import paddle
import PIL
import numbers
import numpy as np
from PIL import Image
from paddle.vision.transforms import BaseTransform
from paddle.vision.transforms import functional as F
import matplotlib.pyplot as pltclass SRDataset(Dataset):def __init__(self, data_path, crop_size, scaling_factor):""":参数 data_path: 图片文件夹路径:参数 crop_size: 高分辨率图像裁剪尺寸  (实际训练时不会用原图进行放大,而是截取原图的一个子块进行放大):参数 scaling_factor: 放大比例"""self.data_path=data_pathself.crop_size = int(crop_size)self.scaling_factor = int(scaling_factor)self.images_path=[]# 如果是训练,则所有图像必须保持固定的分辨率以此保证能够整除放大比例# 如果是测试,则不需要对图像的长宽作限定# 读取图像路径for name in os.listdir(self.data_path):self.images_path.append(os.path.join(self.data_path,name))# 数据处理方式self.pre_trans=transforms.Compose([# transforms.CenterCrop(self.crop_size),transforms.RandomCrop(self.crop_size),transforms.RandomHorizontalFlip(0.5),transforms.RandomVerticalFlip(0.5),# transforms.ColorJitter(brightness=0.3, contrast=0.3, hue=0.3),])self.input_transform = transforms.Compose([transforms.Resize(self.crop_size//self.scaling_factor),transforms.ToTensor(),transforms.Normalize(mean=[0.5],std=[0.5]),])self.target_transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(mean=[0.5],std=[0.5]),])def __getitem__(self, i):# 读取图像img = Image.open(self.images_path[i], mode='r')img = img.convert('RGB')img=self.pre_trans(img)lr_img = self.input_transform(img)hr_img = self.target_transform(img.copy())return lr_img, hr_imgdef __len__(self):return len(self.images_path)

测试dataset

# 单元测试train_path='train/DIV2K_train_HR'
test_path='test'
ds=SRDataset(train_path,96,2)
l,h=ds[1]# print(type(l))
print(l.shape)
print(h.shape)l=np.array(l)
h=np.array(h)
print(type(l))
l=l.transpose(2,1,0)
h=h.transpose(2,1,0)
print(l.shape)
print(h.shape)plt.subplot(1, 2, 1)
plt.imshow(((l+1)/2))
plt.title('l')
plt.subplot(1, 2, 2)
plt.imshow(((h+1)/2))
plt.title('h')
plt.show()

定义网络结构

较rsresnet少了归一化层,以及更深的残差块

from paddle.nn import Layer
from paddle import nn
import mathn_feat = 256
kernel_size = 3# 残差块 尺寸不变
class _Res_Block(nn.Layer):def __init__(self):super(_Res_Block, self).__init__()self.res_conv = nn.Conv2D(n_feat, n_feat, kernel_size, padding=1)self.relu = nn.ReLU()def forward(self, x):y = self.relu(self.res_conv(x))y = self.res_conv(y)y *= 0.1# 残差加入y = paddle.add(y, x)return yclass EDSR(nn.Layer):def __init__(self):super(EDSR, self).__init__()in_ch = 3num_blocks = 32self.conv1 = nn.Conv2D(in_ch, n_feat, kernel_size, padding=1)# 扩大self.conv_up = nn.Conv2D(n_feat, n_feat * 4, kernel_size, padding=1)self.conv_out = nn.Conv2D(n_feat, in_ch, kernel_size, padding=1)self.body = self.make_layer(_Res_Block, num_blocks)# 上采样self.upsample = nn.Sequential(self.conv_up, nn.PixelShuffle(2))# 32个残差块def make_layer(self, block, layers):res_block = []for _ in range(layers):res_block.append(block())return nn.Sequential(*res_block)def forward(self, x):out = self.conv1(x)out = self.body(out)out = self.upsample(out)out = self.conv_out(out)return out

看paddle能不能用gpu

import paddle
print(paddle.device.get_device())paddle.device.set_device('gpu:0')

训练,一般4个小时就可以达到一个不错的效果,set5中psnr可以达到27左右,当然这时间还是太少了

import os
from math import log10
from paddle.io import DataLoader
import paddle.fluid as fluid
import warnings
from paddle.static import InputSpecif __name__ == '__main__':warnings.filterwarnings("ignore", category=Warning)  # 过滤报警信息train_path='train/DIV2K_train_HR'test_path='test'crop_size = 96      # 高分辨率图像裁剪尺寸scaling_factor = 2  # 放大比例# 学习参数checkpoint = './work/edsr_paddle'   # 预训练模型路径,如果不存在则为Nonebatch_size = 30    # 批大小start_epoch = 0     # 轮数起始位置epochs = 10000        # 迭代轮数workers = 4         # 工作线程数lr = 1e-4           # 学习率# 先前的psnrpre_psnr=32.35try:model = paddle.jit.load(checkpoint)print('加载先前模型成功')except:print('未加载原有模型训练')model = EDSR()# 初始化优化器scheduler = paddle.optimizer.lr.StepDecay(learning_rate=lr, step_size=1, gamma=0.99, verbose=True)optimizer = paddle.optimizer.Adam(learning_rate=scheduler,parameters=model.parameters())criterion = nn.MSELoss()train_dataset = SRDataset(train_path, crop_size, scaling_factor)test_dataset = SRDataset(test_path, crop_size, scaling_factor)train_loader = DataLoader(train_dataset,batch_size=batch_size,shuffle=True,num_workers=workers,)test_loader = DataLoader(test_dataset,batch_size=batch_size,shuffle=False,num_workers=workers,)for epoch in range(start_epoch, epochs+1):model.train()  # 训练模式:允许使用批样本归一化train_loss=0n_iter_train = len(train_loader)train_psnr=0# 按批处理for i, (lr_imgs, hr_imgs) in enumerate(train_loader):lr_imgs = lr_imgshr_imgs = hr_imgssr_imgs = model(lr_imgs)loss = criterion(sr_imgs, hr_imgs)  optimizer.clear_grad()loss.backward()optimizer.step()train_loss+=loss.item()psnr = 10 * log10(1 / loss.item())train_psnr+=psnrepoch_loss_train=train_loss / n_iter_traintrain_psnr=train_psnr/n_iter_trainprint(f"Epoch {epoch}. Training loss: {epoch_loss_train} Train psnr {train_psnr}DB")model.eval()  # 测试模式test_loss=0all_psnr = 0n_iter_test = len(test_loader)with paddle.no_grad():for i, (lr_imgs, hr_imgs) in enumerate(test_loader):lr_imgs = lr_imgshr_imgs = hr_imgssr_imgs = model(lr_imgs)loss = criterion(sr_imgs, hr_imgs)psnr = 10 * log10(1 / loss.item())all_psnr+=psnrtest_loss+=loss.item()epoch_loss_test=test_loss/n_iter_testepoch_psnr=all_psnr / n_iter_testprint(f"Epoch {epoch}. Testing loss: {epoch_loss_test} Test psnr{epoch_psnr} dB")if epoch_psnr>pre_psnr:paddle.jit.save(model, checkpoint,input_spec=[InputSpec(shape=[1,3,48,48], dtype='float32')])pre_psnr=epoch_psnrprint('模型更新成功')scheduler.step()

测试,需要自己上传一张低分辨率的图片

import paddle
from paddle.vision import transforms
import PIL.Image as Image
import numpy as npimgO=Image.open('img_003_SRF_2_LR.png',mode="r")  #选择自己图片的路径
img=transforms.ToTensor()(imgO).unsqueeze(0)#导入模型
net=paddle.jit.load("./work/edsr_paddle")source = net(img)[0, :, :, :]
source = source.cpu().detach().numpy()  # 转为numpy
source = source.transpose((1, 2, 0))  # 切换形状
source = np.clip(source, 0, 1)  # 修正图片
img = Image.fromarray(np.uint8(source * 255))plt.figure(figsize=(9,9))
plt.subplot(1, 2, 1)
plt.imshow(imgO)
plt.title('input')
plt.subplot(1, 2, 2)
plt.imshow(img)
plt.title('output')
plt.show()img.save('./sr.png')

EDSR_X2效果

双线性插值放大效果

 EDSR_X2放大效果

 双线性插值放大效果

EDSR_X2放大效果

原文: EDSR图像超分重构

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

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

相关文章

导入PIL时报错

在导入PIL时,报以下错误: 查找原因 参考博客 Could not find a version that satisfies the requirement PIL (from versions: ) No matching distributi-CSDN博客,按照wheel后,安装PIL时,报如下的错误。 查找说是python版本与wheel文件版本不同,确认本机python版本 …

Nginx模块开发之http handler实现流量统计(2)

文章目录 一、概述二、Nginx handler模块开发2.1、代码实现2.2、编写config文件2.3、编译模块到Nginx源码中2.4、修改conf文件2.5、执行效果 总结 一、概述 上一篇【Nginx模块开发之http handler实现流量统计(1)】使用数组在单进程实现了IP的流量统计&a…

堆的实现(堆的插入、堆的删除等)超级全

堆的实现(堆的插入、堆的删除等)超级全 文章目录 堆的实现(堆的插入、堆的删除等)超级全一、前期基础知识1.树结构①树的定义②树的相关概念③二叉树④满二叉树和完全二叉树a.满二叉树b.完全二叉树 ⑤二叉树的性质⑥二叉树顺序结构…

每日OJ题_算法_双指针_力扣11. 盛最多水的容器

力扣11. 盛最多水的容器 11. 盛最多水的容器 - 力扣(LeetCode) 难度 中等 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成…

2023 最新 PDF.js 在 Vue3 中的使用

因为自己写业务要定制各种 pdf 预览情况(可能),所以采用了 pdf.js 而不是各种第三方封装库,主要还是为了更好的自由度。 一、PDF.js 介绍 官方地址 中文文档 PDF.js 是一个使用 HTML5 构建的便携式文档格式查看器。 pdf.js 是社区…

人工智能教程(二):人工智能的历史以及再探矩阵

目录 前言 更多矩阵的知识 Pandas 矩阵的秩 前言 在上一章中,我们讨论了人工智能、机器学习、深度学习、数据科学等领域的关联和区别。我们还就整个系列将使用的编程语言、工具等做出了一些艰难的选择。最后,我们还介绍了一点矩阵的知识。在本文中&am…

需求变更导致估算不精准 6大措施

需求变更可能导致估算不精准、项目成本增加、进度延迟等问题,如果不能准确地估算项目,往往会造成资源浪费和开发效率的降低,因此亟需解决因需求变更导致地估算不精准的问题。 一般来说,主要是从以下6个方面入手解决: 1…

【maven】【IDEA】idea中使用maven编译项目,报错java: 错误: 找不到符号 【2】

idea中使用maven编译项目,报错java: 错误: 找不到符号 错误状况展示: 如果报这种错,是因为项目中真的找不到报错的方法或者枚举 字段之类的,但实际是 : 点击 File Path

OSG粒子系统与阴影-雾效模拟(1)

虚拟现实中有很多效果,如雨效、雪效、雾效等,这些都可以通过粒子系统来实现。一个真实的粒子系统的模式能使三维场景达到更好的效果。 本章对OSG粒子系统的使用以及生成自定义粒子系统的方法进行了详细介绍最后还附带说明了阴影的使用方法。在实时的场景…

pairplot

Python可视化 | Seaborn5分钟入门(七)——pairplot - 知乎 (zhihu.com) Seaborn是基于matplotlib的Python可视化库。它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matplotlib的基础上进行了更高级的API封装,从而使得作图更加容易,不需…

红黑树详解

红黑树的概念与性质 前置知识 在学习红黑树之前,最好有二叉查找树和AVL树的基础,因为红黑树本质就是一种特殊的二叉查找树,而红黑树的操作中需要用到AVL树中旋转的相关知识。至于二叉查找树和AVL树,可以参考如下两篇博客&#xf…

Matplotlib图形注释_Python数据分析与可视化

Matplotlib图形注释 添加注释文字、坐标变换 有的时候单单使用图形无法完整清晰的表达我们的信息,我们还需要进行文字进行注释,所以matplotlib提供了文字、箭头等注释可以突出图形中重点信息。 添加注释 为了使我们的可视化图形让人更加容易理解&#…

长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 示例 1: 输入&#x…

MySQL 有多个普通索引时会取哪一个索引?

我们都知道MySQL在查询时底层会进行索引的优化,假设有两个普通索引,且where 后面也根据这两个普通索引查询数据,那么执行查询语句时会使用到那个索引? 为了方便演示,新建users表,新建idx_name、idx_city这两…

前端vue导出PPT,使用pptxgen.js

前言 公司新需求需要导出ppt给业务用,查阅资料后发现也挺简单的,记录一下。 如有不懂的可以留言!!! 1.安装包 npm install pptxgenjs --save2.引入包 在需要使用的文件中引入 import Pptxgenfrom "pptxgenjs&…

Oracle研学-介绍及安装

一 ORACLE数据库特点: 支持多用户,大事务量的事务处理数据安全性和完整性控制支持分布式数据处理可移植性(跨平台,linux转Windows) 二 ORACLE体系结构 数据库:oracle是一个全局数据库,一个数据库可以有多个实例,每个…

nodejs+vue+python+PHP+微信小程序-留学信息查询系统的设计与实现-安卓-计算机毕业设计

1、用户模块: 1)登录:用户注册登录账号。 2)留学查询模块:查询学校的入学申请条件、申请日期、政策变动等。 3)院校排名:查询国外各院校的实力排名。 4)测试功能:通过入学…

python-选择排序

选择排序是一种简单直观的排序算法,它的基本思想是每一轮选择未排序部分的最小元素,然后将其放到已排序部分的末尾。这个过程持续进行,直到整个数组排序完成。(重点:通过位置找元素) 以下是选择排序的详细步骤和 Python 实现&…

HarmonyOS应用开发实战—登录页面【ArkTS】

文章目录 本页面实战效果预览图一.HarmonyOS应用开发1.1HarmonyOS 详解1.2 ArkTS详解二.HarmonyOS应用开发实战—登录页面【ArkTS】2.1 ArkTS页面源码2.2 代码解析2.3 心得本页面实战效果预览图 一.HarmonyOS应用开发 1.1HarmonyOS 详解 HarmonyOS(鸿蒙操作系统)是华为公司…

js粒子效果(一)

效果: 代码: <!doctype html> <html> <head><meta charset"utf-8"><title>HTML5鼠标经过粒子散开动画特效</title><style>html, body {position: absolute;overflow: hidden;margin: 0;padding: 0;width: 100%;height: 1…