基于SRCNN的表情包超分辨率(附tensorflow实现)

SRCNN原理


基于SRCNN的表情包超分辨率(附tensorflow实现)_第1张图片

  如上图所示,SRCNN作为深度学习在超分辨率上的第一个应用,仅仅用了简单的三层CNN(但是效果已经很好了),原作者将这三层分别表示为:

  • 第一层CNN:对输入图片的特征提取。(9 x 9 x 64卷积核)
  • 第二层CNN:对第一层提取的特征的非线性映射(1 x 1 x 35卷积核)
  • 第三层CNN:对映射后的特征进行重建,生成高分辨率图像(5 x 5 x 1卷积核)。
  • 注:最原始的SRCNN输入不是低分辨率图像,而是低分辨率双立方插值后的图片

实现过程遇到的问题以及解决办法


  • 采用亮度通道训练,最后测试生成的图片变成偏紫色。

      一开始,我采用了论文说的只训练YCbCr模式的Y通道,具体流程就是:训练的时候输入BRG模式的图片,再转化为YCbCr模式,但是只将Y通道通过CNN网络,最后输出的结果再和另外两个合成生成心得YCbCr模式图片,最后再转回BGR模式,将最终生成的BGR模式图片与输入的BRG模式图片计算MSE loss,进行梯度下降训练网络。具体流程如下图:

    基于SRCNN的表情包超分辨率(附tensorflow实现)_第2张图片

      但是,比较奇怪的是loss明明已经比较好的收敛了,最后生成的图片却都带了某种颜色。。。具体原因我查了好久也没查到,可能是我opencv用得有点问题吧。

      最后,我干脆直接使用三通道图片训练(直接输入shape == (num,width, height, channel) 的图片进行训练),但是发现loss下降不是很理想,查了网上一些博客后,发现也有人碰到了这些问题,大致原因是SRCNN的参数比较难训练,所以导致三通道的训练比较难进行,可以采用单通道训练。于是我干脆粗暴的将三通道分别训练,最后再合成,最终效果也还算可以吧,但是只能勉强达到双立方插值的效果,并没有明显的改进(就是下面碰到的第二个问题),总之,最终改进的网络结构大致如下图:

    基于SRCNN的表情包超分辨率(附tensorflow实现)_第3张图片

  • loss收敛不到较优值,导致生成图片比双立方插值的效果都差。

      这个我也查了好久的资料,最后没解决办法,只能上github上找别人源码看一看做法大概有什么不同,惊喜的是,我这一翻,发现他们对数据集的预处理和我比较不同,我是直接取400x400的图片(作为label),进行压缩再进行双立方插值,以此作为input,最后minimize label与input的MSE;而他们是从一对随意shape的图片中sample出一定大小的图片(有的是80x80)作为原始图片,和我的400X400比,变得比较小,而且也不用进行数据集的预处理。我想了想,可能用比较小的patch训练生成的结果会比较不那么平滑。于是我就试了试,发现loss收敛大概到了原来的十分之一!最后测试了一下,生成的结果的确比较理想,和双立方插值比,效果的确比较好。

最终效果


test dataset部分图片效果:

基于SRCNN的表情包超分辨率(附tensorflow实现)_第4张图片

局限性


  可以看出,SRCNN生成的图片,虽然边缘比双立方插值锐利一点,但是还是相对原图模糊,这个和选择的loss有一定的关系,mean square error这个衡量方式,往往会让图片相对平滑,预测会相对“中庸”(在之后的论文提出了其他改进的loss,这里不展开叙述)。如下图所述:

基于SRCNN的表情包超分辨率(附tensorflow实现)_第5张图片

reference:深度学习在单图像超分辨率上的应用:SRCNN、Perceptual loss、SRResNet

代码地址


代码地址: 基于SRCNN的表情包超分辨率

你可能感兴趣的:(机器学习)