文章目录
-
- 一、目的
- 二、研究背景
- 三、存在的问题
- 四、研究现状
- 五、总结算法创新点和核心代码
-
- SRCNN
- ESPCN
- VDSR
- DRCN
- DRRN
- EDSR
- SRGAN
- ESRGAN
- RDN
- WDSR
- LapSRN
- RCAN
- SAN
- IGNN
- SwinIR
- 六、结论与讨论 (个人理解)
-
- 图像超分的困境
- 图像超分的未来
- 其他
一、目的
- 提高图像分辨率;
- 丰富图像的细节纹理。
二、研究背景
- :图像分辨率一般较低,不能满足高分辨率的视觉要求。 4K 高清显示逐渐普及,但许多成像设备拍摄的照片和老电影的像素分辨率远低于 4K。
- :医疗器械采集的图像分辨率通常较低,高分辨率的医学图像有利于发现小病变。
- :卫星或飞机与遥感成像对象之间的距离较远,受传感器技术和成像设备成本的限制,图像分辨率低,导致目标模糊,不利于图像分析。
- :公共监控系统的摄像头受成本限制,分辨率往往较低,分辨率较低的图片或视频不利于后续的人脸识别、车牌识别和目标结构特征识别 。
- :为了降低大量数据对传输带宽的压力,图像或视频数据在传输过程中会被压缩,如降低图像的分辨率。然而,人们对这些图像或视频的清晰度要求很高,因此在接收端需要使用图像超分辨率技术来提高分辨率,并尽可能重建原始的高清图像或视频。
三、存在的问题
- :实际解决图像超分辨率重建问题的最大挑战是准确估计退化模型。退化模型的估计是在重建图像超分辨率的同时,从低分辨率图像中估计运动信息、模糊信息和噪声信息。事实上,由于缺乏数据,很难仅仅从低分辨率图像中估计退化模型。以前,大多数学者专注于如何设计准确的图像先验, 而忽略了退化模型对结果的影响。虽然许多实践取得了良好的重建结果,但自然图像的性能并不令人满意,这是由于自然图像的退化模型与算法中假设的模型不一致,这也是现有成熟算法无法推广的主要原因。
- :计算复杂性和稳定性是限制图像超分辨率重建算法无法广泛应用的因素。现有的算法基本上是通过牺牲计算代价来提高重建结果的质量, 特别是当放大倍数较大时,计算量平方倍增加,导致图像超分处理非常耗时, 因此缺乏实际应用的价值。最近,一些学者专注于如何快速、良好地实现图像超分辨率重建。虽然现有的方法可以重建高质量的图像,但当输入图像不满足算法假设的模型时,就会产生错误的细节。特别是当学习数据集不完整时,由于缺乏知识,仅仅依靠学习模型的泛化能力来预测丢失的高频细节是不可避免的。因此,到目前为止,现有的图像超分辨率重建算法还没有很强的稳定性。
- :在现有的图像超分辨率重建算法中,图像分辨率重建算法中。事实上,消费级相机在最后一步输出图像时需要压缩图像。此外,由于传输条件和存储空间的限制,互联网上的图像也被压缩。图像压缩对超分辨率重建的影响在于改变图像的退化模型,而图像的退化模型在超分辨率重建中起着非常重要的作用。例如,当图像被压缩时,降质图像 噪声不仅包括加性噪声,还包括与图像内容相关的乘性噪声。此外,基于超分辨率重建的大多数成像模型都是连续的,不考虑数字量化因素。然而,实际处理的图像是数字的,在量化过程中不可避免地会引入量化误差,这将影响图像的退化模型。
- :目前,最常用的超分辨率评价指标是峰值信噪比 (Peak Signal Noise Ratio, PSNR)、均方误差 (Mean Square Error, MSE) 与结构相似 (Structural SIMilarity, SSIM)。这些指标需要使用真实的高分辨率图像作为参考,以评估重建图像和真实图像之间的相似性。相似度越高,重建结果越好,反之亦然。然而,这些评价指标并不能充分反映重建的效果。在实验比较中,重建图像的主观评价往往较高,客观评价较低。此外,当超分辨率重建自然图像时,很难获得真实的参考图像,这些评价指标在面对这种情况时失去了作用。因此,研究与主观评价一致的图像客观评价指标是有意义的。
四、研究现状
- 基于插值:常用的插值方法包括最近的相邻插值、双线插值和双三次插值。虽然这些方法简单有效,但假设图像是连续的,没有引入更有效的信息。重建结果的边缘和轮廓往往模糊,纹理恢复效果差,性能有限。
- 基于重建:这种方法将图像超分辨率重建视为优化重建误差的问题,通过引入先验知识获得局部最优解。基于重建的常见算法包括集投影法 (Projection onto Convex Set, POCS)、 最大后验概率法 (Maximum A Posterior estimation, MAP)、贝叶斯分析方法 (Bayesian Analysis, BA)、迭代反投影法 (Iterative Back Projection, IBP) 等。虽然这种方法通过引入先验信息来增加图像超分辨率重建过程的约束,但它获得了良好的重建效果。虽然这种方法通过引入先验信息来增加图像超分辨率重建过程的约束,但它获得了良好的重建效果。但这些算法存在明显的收敛性不理想等问题。
- 基于学习:卷积神经网络 (Convolutional Neural Network, CNN) 由于其优秀的细节表征能力已广泛应用于图像超分辨率重建研究 Transformer 在图像超分辨率领域也取得了成功。能够隐藏地学习图像的先验知识,并利用所学的先验知识生成效果更好的超分辨率图像。 这种方法的经典包括 SRCNN、ESPCN、VDSR、DRCN、DRRN、EDSR、SRGAN、ESRGAN、RDN、WDSR、LapSRN、RCAN、SAN、IGNN、SwinIR等。基于学习的图像超分辨率重建算法在重建结果上远远优于传统算法,但由于对硬件设备和处理时间的要求较高,这些算法实际应用较少。
五、总结算法创新点和核心代码
SRCNN
:https://arxiv.org/abs/1501.00092 : MatLab http://mmlab.ie.cuhk.edu.hk/projects/SRCNN.html TensorFlow https://github.com/tegg89/SRCNN-Tensorflow Pytorch https://github.com/fuyongXu/SRCNN_Pytorch_1.0 Keras https://github.com/jiantenggei/SRCNN-Keras
- :基于深度学习的图像超分辨率重建开山作品。对于低分辨率图像,首先使用双三次插值 (bicubic) 该方法将其转换为真实高分辨率图像的大小。将插值图像作为卷积神经网络的输入,最终重建高分辨率图像。
- :与传统方法相比,SRCNN 重建后的图像质量更高。
- :(1) 依赖图像区域信息;(2) 训练收敛速度太慢(3) 网络只适用于单一尺度输入。
- :
import torch.nn as nn
class SRCNN(nn.Module):
def __init__(self, inputChannel, outputChannel):
super(SRCNN, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(inputChannel, 64, kernel_size=9, padding=9 // 2),
nn.ReLU(inplace=True),
nn.Conv2d(64, 32, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(32, outputChannel, kernel_size=5, padding=5 // 2),
)
def forward(self, x):
out = self.conv(x)
return out
ESPCN
:https://arxiv.org/abs/1609.05158 : MatLab https://github.com/wangxuewen99/Super-Resolution/tree/master/ESPCN TensorFlow https://github.com/drakelevy/ESPCN-TensorFlow Pytorch https://github.com/leftthomas/ESPCN
- :在末端直接使用亚像素卷积的方式来进行上采样。
- :(1) 只在模型末端进行上采样,可以使得在低分辨率空间保留更多的纹理区域,在视频超分中也可以做到实时。(2) 模块末端直接使用亚像素卷积的方式来进行上采样,相比于显示的将低分插值到高分,这种上采样方式可以获得更好的重建效果。
- :只考虑上采样的问题,对于如何学习更加丰富的特征信息和利用没有太多研究。
- :亚像素卷积实际上并不涉及到卷积运算,是一种高效、快速、无参 的像素重排列的上采样方式。由于处理速度很快,其直接用在视频超分中也可以做到实时。因此这种上采样的方式很多时候都成为上采样的首选,经常用在低级计算机视觉领域。
- :
import math
import torch
from torch import nn
class ESPCN(nn.Module):
def __init__(self, scale_factor, num_channels=1):
super(ESPCN, self).__init__()
self.first_part = nn.Sequential(
nn.Conv2d(num_channels, 64, kernel_size=5, padding=5//2),
nn.Tanh(),
nn.Conv2d(64, 32, kernel_size=3, padding=3//2),
nn.Tanh(),
)
self.last_part = nn.Sequential(
nn.Conv2d(32, num_channels * (scale_factor ** 2), kernel_size=3, padding=3 // 2),
nn.PixelShuffle(scale_factor)
)
self._initialize_weights()
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
if m.in_channels == 32:
nn.init.normal_(m.weight.data, mean=0.0, std=0.001)
nn.init.zeros_(m.bias.data)
else:
nn.init.normal_(m.weight.data, mean=0.0, std=math.sqrt(2/(m.out_channels*m.weight.data[0][0].numel())))
nn.init.zeros_(m.bias.data)
def forward(self, x):
x = self.first_part(x)
x = self.last_part(x)
return x
VDSR
:https://arxiv.org/abs/1511.04587 : MatLab (1) https://cv.snu.ac.kr/research/VDSR/ (2) https://github.com/huangzehao/caffe-vdsr TensorFlow https://github.com/Jongchan/tensorflow-vdsr Pytorch https://github.com/twtygqyy/pytorch-vdsr
- :(1) 使用足够深的神经网络; (2) 引入残差学习; (3) 更高的学习率; (4) 提出多尺度超分模型。
- :(1) VDSR 加深网络深度使得网络感受野更大, 更好地利用了更大区域的上下文信息。(2) 残差学习加速网络收敛,同时进行高低级别特征信息的融合;(3) 更高的学习率可以加速网络的收敛;(4) VDSR 通过让参数在所有预定义的尺度因子中共享,经济地解决了不同放大尺度的问题。
- :过大的学习率可能造成梯度的爆炸,所以提出梯度裁减的方法来避免。
- :
import torch
import torch.nn as nn
from math import sqrt
class Conv_ReLU_Block(nn.Module):
def __init__(self):
super(Conv_ReLU_Block, self).__init__()
self.conv = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1, bias=False)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
return self.relu(self.conv(x))
class VDSR(nn.Module):
def __init__(self):
super(VDSR, self).__init__()
self.residual_layer = self.make_layer(Conv_ReLU_Block, 18)
self.input = nn.Conv2d(in_channels=1, out_channels=64, kernel_size=3, stride=1, padding=1, bias=False)
self.output = nn.Conv2d(in_channels=64, out_channels=1, kernel_size=3, stride=1, padding=1, bias=False)
self.relu = nn.ReLU(inplace=True)
for m in self.modules():
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, sqrt(2. / n))
def make_layer(self, block, num_of_layer):
layers = []
for _ in range(num_of_layer):
layers.append(block())
return nn.Sequential(*layers)
def forward(self, x):
residual = x
out = self.relu(self.input(x))
out = self.residual_layer(out)
out = self.output(out)
out = torch.add(out, residual)
return out
DRCN
:https://arxiv.org/pdf/1511.04491.pdf : MatLab https://cv.snu.ac.kr/research/DRCN/ TensorFlow (1) https://github.com/nullhty/DRCN_Tensorflow (2) https://github.com/jiny2001/deeply-recursive-cnn-tf Pytorch https://github.com/fungtion/DRCN Keras https://github.com/ghif/drcn
- :(1) 提出了深度递归卷积网络,用相同的循环层来替代不同的卷积层;(2) 提出循环监督和使用跳跃连接。
- :(1) 增大网络的感受野;(2) 避免深度网络的梯度消失 / 爆炸问题。
- :
import torch.nn as nn
class DRCN(nn.Module):
def __init__(self, n_class):
super(DRCN, self).__init__()
# convolutional encoder
self.enc_feat = nn.Sequential()
self.enc_feat.add_module('conv1', nn.Conv2d(in_channels=1, out_channels=100, kernel_size=5,
padding=2))
self.enc_feat.add_module('relu1', nn.ReLU(True))
self.enc_feat.add_module('pool1', nn.MaxPool2d(kernel_size=2, stride=2))
self.enc_feat.add_module('conv2', nn.Conv2d(in_channels=100, out_channels=150, kernel_size=5,
padding=2))
self.enc_feat.add_module('relu2', nn.ReLU(True))
self.enc_feat.add_module('pool2', nn.MaxPool2d(kernel_size=2, stride=2))
self.enc_feat.add_module('conv3', nn.Conv2d(in_channels=150, out_channels=200, kernel_size=3,
padding=1))
self.enc_feat.add_module('relu3', nn.ReLU(True))
self.enc_dense = nn.Sequential()
self.enc_dense.add_module('fc4', nn.Linear(in_features=200 * 8 * 8, out_features=1024))
self.enc_dense.add_module('relu4', nn.ReLU(True))
self.enc_dense.add_module('drop4', nn.Dropout2d())
self.enc_dense.add_module('fc5', nn.Linear(in_features=1024, out_features=1024))
self.enc_dense.add_module('relu5', nn.ReLU(True))
# label predict layer
self.pred = nn.Sequential()
self.pred.add_module('dropout6', nn.Dropout2d())
self.pred.add_module('predict6', nn.Linear(in_features=1024, out_features=n_class))
# convolutional decoder
self.rec_dense = nn.Sequential()
self.rec_dense.add_module('fc5_', nn.Linear(in_features=1024, out_features=1024))
self.rec_dense.add_module('relu5_', nn.ReLU(True))
self.rec_dense.add_module('fc4_', nn.Linear(in_features=1024, out_features=200 * 8 * 8))
self.rec_dense.add_module('relu4_', nn.ReLU(True))
self.rec_feat = nn.Sequential()
self.rec_feat.add_module('conv3_', nn.Conv2d(in_channels=200, out_channels=150,
kernel_size=3, padding=1))
self.rec_feat.add_module('relu3_', nn.ReLU(True))
self.rec_feat.add_module('pool3_', nn.Upsample(scale_factor=2))
self.rec_feat.add_module('conv2_', nn.Conv2d(in_channels=150, out_channels=100,
kernel_size=5, padding=2))
self.rec_feat.add_module('relu2_', nn.ReLU(True))
self.rec_feat.add_module('pool2_', nn.Upsample(scale_factor=2))
self.rec_feat.add_module('conv1_', nn.Conv2d(in_channels=100, out_channels=1,
kernel_size=5, padding=2))
def forward(self, input_data):
feat = self.enc_feat(input_data)
feat = feat.view(-1, 200 * 8 * 8)
feat_code = self.enc_dense(feat)
pred_label = self.pred(feat_code)
feat_encode = self.rec_dense(feat_code)
feat_encode = feat_encode.view(-1, 200, 8, 8)
img_rec = self.rec_feat(feat_encode)
return pred_label, img_rec
DRRN
:https://openaccess.thecvf.com/content_cvpr_2017/html/Tai_Image_Super-Resolution_via_CVPR_2017_paper.html : MatLab https://github.com/tyshiwo/DRRN_CVPR17 TensorFlow https://github.com/LoSealL/VideoSuperResolution Pytorch https://github.com/Major357/DRRN-pytorch
- :(1) 比 VDSR 更深的网络;(2) 递归学习; (3) 残差学习。
- :(1) 越深的网络一般可以得到更好的重建效果;(2) 相当于增加网络深度,权重共享来减少参数量;(3) 避免发生梯度消失 / 爆炸问题。
- :
import torch import torch.nn as nn from math import sqrt class DRRN(nn.Module): def __init__(self): super(DRRN, self).__init__() self.input = nn.Conv2d(in_channels=1, out_channels=128, kernel_size=3, stride=1, padding=1, bias=False) self.conv1 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1, bias=False) self.conv2 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1, bias=False) self.output = nn.Conv2d(in_channels=128, out_channels=1, kernel_size=3, stride=1, padding=1, bias=False) self.relu = nn.ReLU(inplace=True) for m in self.modules(): if isinstance(m, nn.Conv2d): n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels m.weight.data.normal_(0, sqrt(2. / n)) def forward(self, x): residual = x inputs = self.input(self.relu(x)) out = inputs for _ in range(25): out = self.conv2(self.relu(self.conv1(self.relu(out)))) out = torch.add(out, inputs) out = self.output 标签:
8b型高稳定性传感器ibp传感器mos环振式数字加速度传感器