[关闭]
@Team 2019-03-01T08:05:04.000000Z 字数 4280 阅读 874

ESRGAN-进击的超分辨率复原

github:https://github.com/xinntao/ESRGANhttps://github.com/xinntao/BasicS

arxiv:https://arxiv.org/pdf/1809.00219v2.pdf

当超分辨率复原碰上GAN

前言

超分辨率成像(Super-resolution imaging,缩写SR),是一种提高影片分辨率的技术。在一些称为“光学SR”的SR技术中,系统的衍射极限被超越;而在其他所谓的“几何SR”中,数位感光元件的分辨率因而提高。超分辨率成像技术用于一般图像处理和超高分辨率显微镜。

生成对抗网络(英语:**G**enerative **A**dversarial **N**etwork,简称GAN)是非监督式学习的一种方法,通过让两个神经网络相互博弈的方式进行学习。该方法由伊恩·古德费洛等人于2014年提出。[1]

生成对抗网络由一个生成网络与一个判别网络组成。生成网络从潜在空间(latent space)中随机采样作为输入,其输出结果需要尽量模仿训练集中的真实样本。判别网络的输入则为真实样本或生成网络的输出,其目的是将生成网络的输出从真实样本中尽可能分辨出来。而生成网络则要尽可能地欺骗判别网络。两个网络相互对抗、不断调整参数,最终目的是使判别网络无法判断生成网络的输出结果是否真实。[2][1][3]

关于GAN:我我之前写过一篇:手把手教你用keras搭建GAN

直入主题

ESRGAN的全名叫 Enhanced Super-Resolution Generative Adversarial Networks,发表于ECCV2018,它是基于SRGAN改进而来到,相比于SRGAN它在三个方面进行了改进

  1. 改进了网络结构,对抗损失,感知损失
  2. 引入Residual-in-Residu Dense Block(RRDB)
  3. 使用激活前的VGG特征来改善感知损失

在开始讲这个ESRGAN的具体实现之前,我先来看一下他和他的前辈SRGAN的对比效果:

屏幕快照 2019-03-01 上午1.23.31

image-20190301013829937

我们可以从上图看出,

  1. ESRGAN在锐度和边缘信息上优于SRGAN,且去除了"伪影"
  2. 从PI和PMSE两个指标来看,ESRGAN也可以当之无愧地称得上是超分辨率复原任务中的the State-of-the-Art

庖丁解牛

RRDB,对residual blocks的改进:

我们可以看出这个残差块是很传统的Conv-BN-relu-Conv-BN的结构,而作者在文章中是这么说到的:

We empirically observe that BN layers tend to bring artifacts. These artifacts,
namely BN artifacts, occasionally appear among iterations and different settings,
violating the needs for a stable performance over training. In this section, we
present that the network depth, BN position, training dataset and training loss
have impact on the occurrence of BN artifacts and show corresponding visual

什么意思呢?就是说作者认为SRGAN之所以会产生伪影,就是因为使用了Batchnormalization,所以作者做出了去除BN的改进

image-20190301143914007

而且我们再来看,SRGAN的残差块是顺序连接的,而作者可能哎,受denseNet的启发,他就把这些残差块用密集连接的方式连在一起.那么他的生成器里的特征提取部分最终变成了这样子:

image-20190301144350837

既然我们知道他的网络结构是这样子设计的,那么他的实现其实就很简单:

  1. class RRDB_Net(nn.Module):
  2. def __init__(self, in_nc, out_nc, nf, nb, gc=32, upscale=4, norm_type=None, act_type='leakyrelu', \
  3. mode='CNA', res_scale=1, upsample_mode='upconv'):
  4. super(RRDB_Net, self).__init__()
  5. n_upscale = int(math.log(upscale, 2))
  6. if upscale == 3:
  7. n_upscale = 1
  8. fea_conv = B.conv_block(in_nc, nf, kernel_size=3, norm_type=None, act_type=None)
  9. rb_blocks = [B.RRDB(nf, kernel_size=3, gc=32, stride=1, bias=True, pad_type='zero', \
  10. norm_type=norm_type, act_type=act_type, mode='CNA') for _ in range(nb)]
  11. LR_conv = B.conv_block(nf, nf, kernel_size=3, norm_type=norm_type, act_type=None, mode=mode)
  12. if upsample_mode == 'upconv':
  13. upsample_block = B.upconv_blcok
  14. elif upsample_mode == 'pixelshuffle':
  15. upsample_block = B.pixelshuffle_block
  16. else:
  17. raise NotImplementedError('upsample mode [%s] is not found' % upsample_mode)
  18. if upscale == 3:
  19. upsampler = upsample_block(nf, nf, 3, act_type=act_type)
  20. else:
  21. upsampler = [upsample_block(nf, nf, act_type=act_type) for _ in range(n_upscale)]
  22. HR_conv0 = B.conv_block(nf, nf, kernel_size=3, norm_type=None, act_type=act_type)
  23. HR_conv1 = B.conv_block(nf, out_nc, kernel_size=3, norm_type=None, act_type=None)
  24. self.model = B.sequential(fea_conv, B.ShortcutBlock(B.sequential(*rb_blocks, LR_conv)),\
  25. *upsampler, HR_conv0, HR_conv1)
  26. def forward(self, x):
  27. x = self.model(x)

对损失函数的改进

说到损失函数啊,我们之前在SRGAN的文章里我也介绍过,这个判别器它判断的是你输入的图片是"真的"高清图像,还是"假的"高清图像,而且作者他就提出一种新的思考模式,就是说我的判别器是来估计真实图像相对来说比fake图像更逼真的概率。

怎么来理解这句话呢?

image-20190301145004428

具体而言,作者把标准的判别器换成Relativistic average Discriminator(RaD),所以判别器的损失函数定义为:

image-20190301151447125

对应的生成器的对抗损失函数为:

image-20190301151456042求MSE的操作是通过对中的所有数据求平均得到的,是原始低分辨图像经过生成器以后的图像,由于对抗的损失包含了,所以生成器受益于对抗训练中的生成数据和实际数据的梯度,这种调整会使得网络学习到更尖锐的边缘和更细节的纹理。

因为作者放放出来的代码比较emmmmmm,没找到具体的训练部分哎……

对感知损失的改进

我们之前看SRGAN的时候看到哎,它是用来一个训练好的VGG16来给出超分辨率复原所需要的特征,作者通过对损失域的研究发现,激活前的特征,这样会克服两个缺点。

Perceptual
loss is previously defined on the activation layers of a pre-trained deep network,
where the distance between two activated features is minimized. Contrary to
the convention, we propose to use features before the activation layers, which
will overcome two drawbacks of the original design.

  1. 激活后的特征是非常稀疏的,特别是在很深的网络中。这种稀疏的激活提供的监督效果是很弱的,会造成性能低下;
  2. 使用激活后的特征会导致重建图像与GT的亮度不一致。

image-20190301154741733

与此同时,作者还在loss函数中加入了,也就是损失,最终损失函数由三部分组成:

image-20190301153434204

网络插值

为了平衡感知质量和PSNR等评价值,作者提出了一个灵活且有效的方法---网络插值。具体而言,作者首先基于PSNR方法训练的得到的网络G_PSNR,然后再用基于GAN的网络G_GAN进行整合

image-20190301153806957

image-20190301154824312

它的具体实现就是:

  1. for k, v_PSNR in net_PSNR.items():
  2. v_ESRGAN = net_ESRGAN[k]
  3. net_interp[k] = (1 - alpha) * v_PSNR + alpha * v_ESRGAN

具体实现部分

ESRGAN可以实现放大4倍的效果

首先要训练一个基于PSRN指标的模型,如何根据这个模型的权重进行生成器的初始化.

作者使用了Adam作为优化器(β1 = 0.9, β2 = 0.999.)进行交替训练.

生成器有16个residual block和23个RRDB

实验效果

笔者自己也动手跑了这个代码,就放出一个买家秀给各位看官老爷看看

image-20190301155506110

总结:

文章提出的ESRGAN在SRGAN的基础上做出了改进,在大的框架上没有改动,但是通过各种各样的小技巧,也确实有不错的效果提升,而且很重要滴是作者很良心滴开源了代码,复现的要求也不是很难,作为一份不错的the State-of-the-Art,朋友们如果也是在超分辨率复原这一块做研究或者说想做应用,也是很有参考价值的.

笔者才学疏浅,斗胆浅写一二,如果你喜欢的话请点个赞写个评论哟,感谢您的支持.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注