基于ECCV2014中的"Learning a Deep Convolutional Network for Image Super-Resolution"一文,用windows+tensorflow实现作者(原文是用caffe实现)的工作。
原文链接如下:http://personal.ie.cuhk.edu.hk/~ccloy/files/eccv_2014_deepresolution.pdfpersonal.ie.cuhk.edu.hkhttp://mmlab.ie.cuhk.edu.hk/projects/SRCNN.htmlmmlab.ie.cuhk.edu.hk
1.SRCNN简介
(1)总述
SRCNN的网络结构仅包含三个卷积层,网络结构十分简单,如下图:
SRCNN首先使用双三次(bicubic)插值将低分辨率图像放大成目标尺寸,接着通过三层卷积网络拟合非线性映射,最后输出高分辨率图像结果。本文中,作者将三层卷积的结构解释成三个步骤:图像块的提取和特征表示,特征非线性映射和最终的重建。
(2)网络设计思路
从稀疏编码得来的,并表述为之前所述的三个步骤如下
Patch extraction: 提取图像Patch,进行卷积提取特征,类似于稀疏编码中的将图像patch映射到低分辨率字典中
Non-linear mapping: 将低分辨率的特征映射为高分辨率特征,类似于字典学习中的找到图像patch对应的高分辨字典
Reconstruction:根据高分辨率特征进行图像重建。类似于字典学习中的根据高分辨率字典进行图像重建
(3)网络结构
第一层为conv层(实现数据读入)
输入:低分辨率补丁
卷积核:c*f1*f1*n1(其中,c为输入图像通道数,文中取YCrCb中Y通道,c=1;f1=9;n1为当前卷积核输出深度取64)
第二层为conv层(实现非线性多个映射)
输入:第一层输入
卷积核:n1*1*1*n2(其中,n1为前一卷积层输出数据深度64,n2为当前层数据输出深度为32)
第三层为conv层(实现重建)
输入:第二层输出
卷积核:n2*f3*f3*c(其中,n2为前一个卷积层输出数据深度,f3=5,c为重建后高分辨率图通道数,和输入保持一致c=1)
(4)训练与测试
训练过程:对高分辨率图像随机选取一些patch,然后进行降采样,然后进行升采样,以此作为输入,并以原始高分辨率图像作为目标,采用逐像素损失为优化目标。
测试过程:首先将图像插值一定的倍数作为输入图像,然后通过网络,输出结果。
2.python(tensorflow)实现
共包含三个部分,主函数main.py、网络结构函数model.py、工具函数utils.py
(1)main.py功能:
定义训练和测试参数(包括:如果采用SGD时的batchSize、学习率、步长stride、训练还是测试模式),此后由设定的参数进行训练或测试。
(2)model.py功能:
定义网络的结构(三个卷积层,以及它们的卷积核大小):
#第一层CNN:对输入图片的特征提取。(9 x 9 x 64卷积核)
#第二层CNN:对第一层提取的特征的非线性映射(1 x 1 x 32卷积核)
#第三层CNN:对映射后的特征进行重建,生成高分辨率图像(5 x 5 x 1卷积核)
训练方式:SGD、Adam等(测试结果SGD的效果更好)
(3)utils.py功能:
存放需要使用的小函数,包括
read_data(path) #读取h5格式数据文件
preprocess(path, scale=3) #对路径下的image裁剪成scale整数倍,再对image缩小1/scale倍后,放大scale倍以得到低分辨率图input_,调整尺寸后的image为高分辨率图label_
prepare_data(sess, dataset) #数据准备
make_data(sess, data, label) #把数据保存成.h5格式
imread(path, is_grayscale=True) #读指定路径的图像
modcrop(image, scale=3) #把图像的长和宽都变成scale的倍数
modcrop_small(image) #把result变为和origin一样的大小
input_setup(sess, config) #读图像集,制作子图并保存为h5文件格式,以及训练和测试操作
源代码如下:
(1)main.py函数
from model import SRCNN
from utils import input_setup
import numpy as np
import tensorflow as tf
import pprint
import os
flags = tf.app.flags
flags.DEFINE_integer("epoch", 2000,"训练多少波")
#flags.DEFINE_integer("batch_size", 128, "The size of batch images [128]")
#一开始将batch size设为128和64,不仅参数初始loss很大,而且往往一段时间后训练就发散
#batch中每个样本产生梯度竞争可能比较激烈,所以导致了收敛过慢
#后来改回了128
flags.DEFINE_integer("batch_size", 128, "batch size")
flags.DEFINE_integer("image_size", 33, "图像使用的尺寸")
flags.DEFINE_integer("label_size", 21, "label_制作的尺寸")
#学习率文中设置为 前两层1e-4 第三层1e-5
#SGD+指数学习率10-2作为初始
flags.DEFINE_float("learning_rate", 1e-2, "学习率")
flags.DEFINE_integer("c_dim", 1, "图像维度")
flags.DEFINE_integer("scale", 3, "sample的scale大小")
#stride训练采用14,测试采用21
flags.DEFINE_integer("stride", 21 , "步长为14或者21")
flags.DEFINE_string("checkpoint_dir", "checkpoint", "checkpoint directory名字")
flags.DEFINE_string("sample_dir", "sample", "sample directory名字")
flags.DEFINE_boolean("is_train", False, "True for training, False for testing")#测试
#flags.DEFINE_boolean("is_train", True, "True for training, False for testing")#训练