超分辨率重建

意義

客觀世界的場景含有豐富多彩的信息,但是由于受到硬件設備的成像條件和成像方式的限制,難以獲得原始場景中的所有信息。而且,硬件設備分辨率的限制會不可避免地使圖像丟失某些高頻細節信息。在當今信息迅猛發展的時代,在衛星遙感、醫學影像、多媒體視頻等領域中對圖像質量的要求越來越高,人們不斷尋求更高質量和更高分辨率的圖像,來滿足日益增長的需求。

空間分辨率的大小是衡量圖像質量的一個重要指標,也是將圖像應用到實際生活中重要的參數之一。分辨率越高的圖像含有的細節信息越多,圖像清晰度越高,在實際應用中對各種目標的識別和判斷也更加準確。

但是通過提高硬件性能從而提高圖像的分辨率的成本高昂。因此,為了滿足對圖像分辨率的需求,又不增加硬件成本的前提下,依靠軟件方法的圖像超分辨率重建應運而生。

超分辨率圖像重建是指從一系列有噪聲、模糊及欠采樣的低分辨率圖像序列中恢復出一幅高分辨率圖像的過程。可以針對現有成像系統普遍存在分辨率低的缺陷,運用某些算法,提高所獲得低分辨率圖像的質量。因此,超分辨率重建算法的研究具有廣闊的發展空間。

方法的具體細節

評價指標
峰值信噪比

峰值信噪比(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.pswp.cn/news/167912.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167912.shtml
英文地址,請注明出處:http://en.pswp.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版本 …

C++ 指針進階:動態分配內存

工作原理 malloc 是 stdlib.h 庫中的函數,聲明為 void *__cdecl malloc(size_t _Size); 原理: malloc 函數沿空閑鏈表(位于內存 堆空間 中)申請一塊滿足需求的內存塊,將所需大小的內存塊分配給用戶剩下的返回到鏈表上; 并返回指向該內存區的首地址的指針,意該指針的類型…

ElasticSearch之cat allocation API

查看各節點上各個shard的硬件使用情況,命令樣例如下: curl -X GET "https://localhost:9200/_cat/allocation?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"執行結果如下&#x…

MyBatis常見面試題總結

MyBatis常見面試題總結 #{} 和 ${} 的區別是什么? ${}是 Properties 文件中的變量占位符,它可以用于標簽屬性值和 sql 內部,屬于靜態文本替換,比如${driver}會被靜態替換為com.mysql.jdbc. Driver。 #{}是 sql 的參數占位符&…

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…

音視頻項目—基于FFmpeg和SDL的音視頻播放器解析(二十二)

介紹 在本系列,我打算花大篇幅講解我的 gitee 項目音視頻播放器,在這個項目,您可以學到音視頻解封裝,解碼,SDL渲染相關的知識。您對源代碼感興趣的話,請查看基于FFmpeg和SDL的音視頻播放器 如果您不理解本…

MySQL 排序和分組怎么做?

文章目錄 前言MySQL 排序語法在命令提示符中使用 ORDER BY 子句在PHP腳本中使用 ORDER BY 子句 MySQL 分組GROUP BY 語法實例演示使用 WITH ROLLUP 后言 前言 hello world歡迎來到前端的新世界 😜當前文章系列專欄:Mysql 🐱?👓博…

Cookie的基本使用

JavaScript Cookie(JavaScript 的 Cookie)是一種在Web瀏覽器中存儲和檢索用戶信息的機制。它允許網站在用戶計算機上存儲小型數據片段,以便在之后的會話中使用這些數據。Cookie通常用于持久化用戶首選項、跟蹤用戶行為和提供個性化體驗。 通…

堆的實現(堆的插入、堆的刪除等)超級全

堆的實現(堆的插入、堆的刪除等)超級全 文章目錄 堆的實現(堆的插入、堆的刪除等)超級全一、前期基礎知識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…

vue打包上傳服務器的總結筆記

經歷了3個小時教訓,還是自己總結一下吧,致未來傻x的自己。 第一步,打開b站。搜索【vue打包】找到一個視頻教程 前端Vue項目打包部署實戰教程_嗶哩嗶哩_bilibili 這步是在看不懂下面操作的情況下用的 第一步:找到nginx的配置文件…

需求變更導致估算不精準 6大措施

需求變更可能導致估算不精準、項目成本增加、進度延遲等問題,如果不能準確地估算項目,往往會造成資源浪費和開發效率的降低,因此亟需解決因需求變更導致地估算不精準的問題。 一般來說,主要是從以下6個方面入手解決: 1…

【maven】【IDEA】idea中使用maven編譯項目,報錯java: 錯誤: 找不到符號 【2】

idea中使用maven編譯項目,報錯java: 錯誤: 找不到符號 錯誤狀況展示: 如果報這種錯,是因為項目中真的找不到報錯的方法或者枚舉 字段之類的,但實際是 : 點擊 File Path

OSG粒子系統與陰影-霧效模擬(1)

虛擬現實中有很多效果,如雨效、雪效、霧效等,這些都可以通過粒子系統來實現。一個真實的粒子系統的模式能使三維場景達到更好的效果。 本章對OSG粒子系統的使用以及生成自定義粒子系統的方法進行了詳細介紹最后還附帶說明了陰影的使用方法。在實時的場景…

(HAL庫版)freeRTOS移植STMF103

正點原子關于freeRTOS的教程是比較好的,可惜移植的是標準庫,但是我學的是Hal庫,因為開發速度更快,從最后那個修改SYSTEM文件夾的地方開始替換為下面的內容就可以了 5.修改Systick中斷、SVC中斷、PendSV中斷 將SVC中斷、P…

pairplot

Python可視化 | Seaborn5分鐘入門(七)——pairplot - 知乎 (zhihu.com) Seaborn是基于matplotlib的Python可視化庫。它提供了一個高級界面來繪制有吸引力的統計圖形。Seaborn其實是在matplotlib的基礎上進行了更高級的API封裝,從而使得作圖更加容易,不需…

紅黑樹詳解

紅黑樹的概念與性質 前置知識 在學習紅黑樹之前,最好有二叉查找樹和AVL樹的基礎,因為紅黑樹本質就是一種特殊的二叉查找樹,而紅黑樹的操作中需要用到AVL樹中旋轉的相關知識。至于二叉查找樹和AVL樹,可以參考如下兩篇博客&#xf…

oracle安裝的肘腋之疾小合集

#臨時空間指定 export TMP/tmp export TMPDIR/tmp #圖形化顯示框不全 java問題,使用系統自帶的jre ./runInstaller -jreLoc/usr/local/jdk1.7.0_80/ #ins30131 Failed to access the temporary location 給/tmp/CVU*加x權限 #linux桌面太小 xrandr -s 1440x900_60…