MATLAB环境下基于深度学习VDSR的单图像超分辨率重建
之前主要研究现代信号处理的,深度学习嘛,一个大号/深层的,现代的,黑箱的,信号/图像处理器,所以,我刚才说了,作为一个研究现代信号处理的,顺便搞些深度学习也是顺理成章的。该算法可能在一维信号时频谱超分辨率重建方面有用,之前做过一些相关的东西。程序运行环境为MATLAB R2018A。
代码下载链接
https://mianbaoduo.com/o/bread/Y5mXmp5x
进入正题,本文主要讲解如何训练一个所谓的Very-Deep Super-Resolution (VDSR) 深层网络,然后使用 VDSR 网络从单低分辨率图像中估计高分辨率图像。关于VDSR网络,见文章末尾参考文献。
超分辨率重建是从低分辨率图像创建高分辨率图像的过程,本例考虑单图像超分辨率 (single image super-resolution。SISR),其目标是从一张低分辨率图像中恢复为一张高分辨率图像。SISR具有一定的难度,因为高频图像内容通常无法从低分辨率图像中恢复。如果没有高频信息,高分辨率图像的质量就会受到限制。此外,SISR是一个所谓的病态问题,因为低分辨率图像可以产生几种可能的高分辨率图像。
VDSR网络
VDSR是一种卷积神经网络,旨在执行单图像超分辨率重建。VDSR网络学习低分辨率和高分辨率图像之间的映射。理论上这种映射是存在的,因为低分辨率和高分辨率图像具有相似的图像内容,并且主要在高频细节上有所不同。
VDSR采用残差学习策略,即网络通过学习估计残差图像。残差图像是高分辨率参考图像和低分辨率图像之间的差异,后者使用双三次插值进行升级以匹配参考图像的大小。残差图像包含有关图像的高频细节的信息。
VDSR网络根据彩色图像的亮度检测残差图像。图像的亮度通道 Y 通过红色、绿色和蓝色像素值的线性组合来表示每个像素的亮度。相比之下,图像的两个色度通道 Cb 和 Cr 是表示色差信息的红色、绿色和蓝色像素值的不同线性组合。VDSR仅使用亮度通道进行训练,因为人类的感知对亮度变化比对颜色变化更敏感。
如下用英文表述较为方便:
在 VDSR 网络通过学习估计残差图像后,可以将估计的残差图像添加到上采样的低分辨率图像,然后将图像转换回 RGB 色彩空间来重建高分辨率图像。
尺度因子将参考图像的大小与低分辨率图像的大小相关联。随着尺度因子的增加,SISR变得更加病态,因为低分辨率图像会丢失有关高频图像内容的更多信息。VDSR通过使用较大的感受野receptive field来解决这个问题。 下载训练数据和测试数据
下载 IAPR TC-12 Benchmark,其中包含 20000 张自然图像,、包括人物,动物,城市等。可以使用downloadIAPRTC12Data函数来下载数据,数据文件的大小约为 1.8 GB。
本文将使用 IAPR TC-12 Benchmark的一小部分数据来训练网络,所有图像均为 32 位 JPEG 彩色图像。 定义用于训练的Mini-Batch Datastore
Mini-batch datastore 用于将训练数据输送到网络,本文通过vdsrImagePatch类自定义实现。vdsrImagePatch从低分辨率图像中提取图像块,并以不同的尺度因子升级图像块。每个mini-batch 包含 64 个大小为 41 x 41 像素的图像块,在训练期间将从图像中的随机位置提取所有图像块。要训练多尺度因子网络,将"尺度因子"设置为 [2 3 4]。 miniBatchSize = 64; scaleFactors = [2 3 4]; source = vdsrImagePatchDatastore(trainImages,... "MiniBatchSize",miniBatchSize,... "PatchSize",41,... "BatchesPerImage",1,... "ScaleFactor",scaleFactors); vdsrImagePatchDatastore向网络提供小批量数据,对datastore执行读取操作以浏览数据 inputBatch = read(source); summary(inputBatch)
设置VDSR层
本例使用MATLAB神经网络工具箱中的 41 个层定义 VDSR 网络,包括:
· imageInputLayer - Image input layer
· convolutional2dLayer - 2-D convolution layer for convolutional neural networks
· reluLayer - Rectified linear unit (ReLU) layer
· regressionLayer - Regression output layer for a neural network
第一层,图像输入层,对图像块进行操作,图像块的大小基于网络感受野,网络感受野是影响网络中最顶层响应的空间图像区域。对于深度为D的网络,感受野是(2D + 1)x(2D + 1)。由于 VDSR 是一个 20 层网络,因此感受野和图像块大小为 41 x 41。图像输入层接受具有一个通道的图像,因为 VDSR 仅使用亮度通道进行训练。 networkDepth = 20; firstLayer = imageInputLayer([41 41 1],"Name","InputLayer","Normalization","none");
图像输入层后跟一个 2-D 卷积层,其中包含 64 个大小为 3 x 3 的滤波器。mini-batch大小决定了滤波器的数量。每个卷积层后面都有一个ReLU层,便于引入非线性。 convolutionLayer = convolution2dLayer(3,64,"Padding",1, ... "Name","Conv1"); convolutionLayer.Weights = sqrt(2/(9*64))*randn(3,3,1,64); convolutionLayer.Bias = zeros(1,1,64);
ReLU 层 relLayer = reluLayer("Name","ReLU1");
中间层包含 18 个交替的卷积和ReLU 层。每个卷积层包含 64 个大小为 3 x 3 x 64 的滤波器。 middleLayers = [convolutionLayer relLayer]; for layerNumber = 2:networkDepth-1 conv2dLayer = convolution2dLayer(3,64,... "Padding",[1 1],... "Name",["Conv" num2str(layerNumber)]);
权重初始化 conv2dLayer.Weights = sqrt(2/(9*64))*randn(3,3,64,64); conv2dLayer.Bias = zeros(1,1,64); relLayer = reluLayer("Name",["ReLU" num2str(layerNumber)]); middleLayers = [middleLayers conv2dLayer relLayer]; end
倒数第二层是一个卷积层,具有一个大小为 3x3x64 的滤波器·,用于重建图像。 conv2dLayer = convolution2dLayer(3,1,... "NumChannels",64,... "Padding",[1 1],... "Name",["Conv" num2str(networkDepth)]); conv2dLayer.Weights = sqrt(2/(9*64))*randn(3,3,64,1); conv2dLayer.Bias = zeros(1,1,1);
最后一层是回归层,回归层计算残差图像和网络预测之间的均方误差。 finalLayers = [conv2dLayer regressionLayer("Name","FinalRegressionLayer")];
连接所有层以形成 VDSR 网络 layers = [firstLayer middleLayers finalLayers];指定训练参数
使用具有动量 (SGDM) 优化的随机梯度下降来训练网络,学习速率最初设置为 0.1,然后每 20 个 epoch 降低 10 倍。 maxEpochs = 100; epochIntervals = 1; initLearningRate = 0.1; learningRateFactor = 0.1; l2reg = 0.0001; options = trainingOptions("sgdm",... "Momentum",0.9,... "InitialLearnRate",initLearningRate,... "LearnRateSchedule","piecewise",... "LearnRateDropPeriod",10,... "LearnRateDropFactor",learningRateFactor,... "L2Regularization",l2reg,... "MaxEpochs",maxEpochs,... "MiniBatchSize",miniBatchSize,... "GradientThresholdMethod","l2norm",... "GradientThreshold",0.01);训练网络
使用trainNetwork函数训练 VDSR 网络 modelDateTime = datestr(now,"dd-mmm-yyyy-HH-MM-SS"); net = trainNetwork(source,layers,options); save(["trainedVDSR-" modelDateTime "-Epoch-" num2str(maxEpochs*epochIntervals) "ScaleFactors-" num2str(234) ".mat"],"net","options");
使用 VDSR 网络执行单图像超分辨率重建
使用 VDSR 网络执行单图像超分辨率 (SISR)重建的步骤如下:
· 从高分辨率参考图像创建采样的低分辨率图像。
· 使用双三次插值对低分辨率图像执行 SISR,这是一种不依赖于深度学习的传统图像处理解决方案。
· 使用 VDSR 网络对低分辨率图像执行 SISR。
· 使用双三次插值和 VDSR 直观地比较重建的高分辨率图像
· 评估超分辨率图像的质量。 创建低分辨率图像
创建一个低分辨率图像,该图像将使用深度学习的超分辨率重建结果与使用传统图像处理技术(如双三次插值)重建的结果进行比较。 exts = {".jpg",".png"}; fileNames = {"sherlock.jpg","car2.jpg","fabric.png","greens.jpg","hands1.jpg","kobi.png",... "lighthouse.png","micromarket.jpg","office_4.jpg","onion.png","pears.png","yellowlily.jpg",... "indiancorn.jpg","flamingos.jpg","sevilla.jpg","llama.jpg","parkavenue.jpg",... "peacock.jpg","car1.jpg","strawberries.jpg","wagon.jpg"}; filePath = [fullfile(matlabroot,"toolbox","images","imdata") filesep]; filePathNames = strcat(filePath,fileNames); testImages = imageDatastore(filePathNames,"FileExtensions",exts);
显示若干测试图像 montage(testImages)
选择其中一个图像作为超分辨率的参考图像 indx = 1; % 图像索引 Ireference = readimage(testImages,indx); Ireference = im2double(Ireference); imshow(Ireference) title("High-Resolution Reference Image")
设置尺度因子为 0.25 ,创建高分辨率参考图像的低分辨率版本。 scaleFactor = 0.25; Ilowres = imresize(Ireference,scaleFactor,"bicubic"); imshow(Ilowres) title("Low-Resolution Image")
使用双三次插值提高图像分辨率
在没有深度学习的情况下提高图像分辨率的标准方法是使用双三次插值。使用双三次插值放大低分辨率图像,以便生成的高分辨率图像与参考图像的大小相同。 [nrows,ncols,np] = size(Ireference); Ibicubic = imresize(Ilowres,[nrows ncols],"bicubic"); imshow(Ibicubic) title("High-Resolution Image Obtained Using Bicubic Interpolation")
使用VDSR 网络提高图像的分辨率
回想一下,VDSR仅使用图像的亮度通道进行训练,因为人类感知对亮度变化比对颜色变化更敏感。
使用 rgb2ycbr 函数将低分辨率图像从 RGB 色彩空间转换为亮度 (Iy) 和色度(Icb 和 Icr)通道。 Iycbcr = rgb2ycbcr(Ilowres); Iy = Iycbcr(:,:,1); Icb = Iycbcr(:,:,2); Icr = Iycbcr(:,:,3);
使用双三次插值放大亮度和两个色度通道。上采样色度通道(Icb_bicubic和Icr_bicubic)无需进一步处理。 Iy_bicubic = imresize(Iy,[nrows ncols],"bicubic"); Icb_bicubic = imresize(Icb,[nrows ncols],"bicubic"); Icr_bicubic = imresize(Icr,[nrows ncols],"bicubic");
将Iy_bicubic输入VDSR网络,观察最后一层(回归层)的激活。网络的输出是所需的残差图像。 Iresidual = activations(net,Iy_bicubic,41); Iresidual = double(Iresidual); imshow(Iresidual,[]) title("Residual Image from VDSR")
将残差图像加到亮度分量中,以获得高分辨率的VDSR亮度分量。 Isr = Iy_bicubic + Iresidual;
将高分辨率 VDSR 亮度分量与颜色分量连接,并使用 ycbcr2rgb 函数将图像转换为 RGB 色彩空间,则得到VDSR的最终高分辨率彩色图像。 Ivdsr = ycbcr2rgb(cat(3,Isr,Icb_bicubic,Icr_bicubic)); imshow(Ivdsr) title("High-Resolution Image Obtained Using VDSR")
定量比较
为了更直观的理解高分辨率图像,使用格式为 [x y width height]的向量roi来指定感兴趣区域 (ROI), x 和 y 为ROI的坐标,width和height为ROI的宽度和高度。 roi = [320 30 480 400];
将高分辨率图像裁剪到此 ROI区域,显示结果 montage({imcrop(Ibicubic,roi),imcrop(Ivdsr,roi)}) title("High-Resolution Results Using Bicubic Interpolation (Left) vs. VDSR (Right)");
结果显示VDSR高分辨率图像具有更清晰的细节和更清晰的边缘。
利用图像质量度量定量比较双三次插值的高分辨率图像与 VDSR高分辨率图像。
计算图像的峰值信噪比(PSNR),PNSR 值越大,通常表示图像质量越好 bicubicPSNR = psnr(Ibicubic,Ireference) vdsrPSNR = psnr(Ivdsr,Ireference)
bicubicPSNR = 38.4747
vdsrPSNR = 39.4473
计算每图像的结构相似性指数 (SSIM),SSIM 评估图像的三个特征的视觉冲击:亮度、对比度和结构信息,SSIM 值越接近 1,测试图像与参考图像的一致性越好 bicubicSSIM = ssim(Ibicubic,Ireference) vdsrSSIM = ssim(Ivdsr,Ireference)
bicubicSSIM = 0.9861
vdsrSSIM = 0.9878
使用自然图像质量评估(NIQE),NIQE的设计思路是基于构建一系列的用于衡量图像质量的特征,并且将这些特征用于拟合一个多元的高斯模型,NIQE实际上是衡量一张待测图像在多元分布上的差异。NIQE评分越小,表示感知质量越好。 bicubicNIQE = niqe(Ibicubic) vdsrNIQE = niqe(Ivdsr)
bicubicNIQE = 5.1719
vdsrNIQE = 4.7463
计算尺度因子为 2、3 和 4 的整组测试图像的平均 PSNR 和 SSIM值,可以使用辅助函数superResolutionMetric计算平均指标。 superResolutionMetrics(net,testImages,scaleFactors);
Results for Scale factor 2
Average PSNR for Bicubic = 31.809683
Average PSNR for VDSR = 32.915853
Average SSIM for Bicubic = 0.938194
Average SSIM for VDSR = 0.953473
Results for Scale factor 3
Average PSNR for Bicubic = 28.170441
Average PSNR for VDSR = 28.802722
Average SSIM for Bicubic = 0.884381
Average SSIM for VDSR = 0.898248
Results for Scale factor 4
Average PSNR for Bicubic = 27.010839
Average PSNR for VDSR = 28.087250
Average SSIM for Bicubic = 0.861604
Average SSIM for VDSR = 0.882349
对于每个尺度因子,与双三次插值相比,VDSR 具有更好的指标分数。
参考文献
[1] Kim, J., J. K. Lee, and K. M. Lee. "Accurate Image Super-Resolution Using Very Deep Convolutional Networks." Proceedings of the IEEE® Conference on Computer Vision and Pattern Recognition. 2016, pp. 1646-1654.
[2] Grubinger, M., P. Clough, H. Müller, and T. Deselaers. "The IAPR TC-12 Benchmark: A New Evaluation Resource for Visual Information Systems." Proceedings of the OntoImage 2006 Language Resources For Content-Based Image Retrieval. Genoa, Italy. Vol. 5, May 2006, p. 10.
[3] He, K., X. Zhang, S. Ren, and J. Sun. "Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification." Proceedings of the IEEE International Conference on Computer Vision, 2015, pp. 1026-1034.