github上有一个很有意思的项目,waifu2x,原理是通过一个训练好的CNN,将低分辨率的图像放大2倍或更多,同时保留足够的细节,使放大后的图像不会过于模糊或失真。该项目是用lua+Touch写的,最近在学习Tensorflow,闲暇之余打算在TF上自己实现一个这样的系统。
1. 网络选择
根据论文Image Super-Resolution Using Deep Convolutional Networks,作者使用了一个3层CNN,是一个非常小的网络,同时为了避免边界效应(bound effect),每一个卷积层都不使用padding,卷积核大小分别为9、1、5,作者也提到,适当增大卷积核的大小,可以提升最后的效果,但也带来了更多的计算量。使用这个网络时,首先需要将低分辨的图像通过bicubic插值到所需的大小,然后再输入网络。对于一个核大小分别为9、3、5的网络,定义如下:
def srcnn_935(patches, name='srcnn'):
with tf.variable_scope(name):
upscaled_patches = tf.image.resize_bicubic(patches, [INPUT_SIZE, INPUT_SIZE], True)
conv1 = conv2d(upscaled_patches, 9, 9, 64, padding='VALID', name='conv1')
relu1 = relu(conv1, name='relu1')
conv2 = conv2d(relu1, 3, 3, 32, padding='VALID', name='conv2')
relu2 = relu(conv2, name='relu2')
return conv2d(relu2, 5, 5, NUM_CHENNELS, padding='VALID', name='conv3')
不过,waifu2x本身没有使用这个网络,而是使用了一个7层的vgg-style网络,按照作者的说法,这个7层网络更便于调整,效果也更好,我也用Tensorflow实现了这个网络,如下:
def vgg7(patches, name='vgg7'):
with tf.variable_scope(name):
upscaled_patches = tf.image.resize_bicubic(patches, [INPUT_SIZE, INPUT_SIZE], True)
conv1 = conv2d(upscaled_patches, 3, 3, 32, padding='VALID', name='conv1')
lrelu1 = leaky_relu(conv1, name='leaky_relu1')
conv2 = conv2d(lrelu1, 3, 3, 32, padding='VALID', name='conv2')
lrelu2 = leaky_relu(conv2, name='leaky_relu2')
conv3 = conv2d(lrelu2, 3, 3, 64, padding='VALID', name='conv3')
lrelu3 = leaky_relu(conv3, name='leaky_relu3')
conv4 = conv2d(lrelu3, 3,