ESPCN:使用高效的亚像素卷积神经网络实现实时单图像和视频超分辨率

ESPCN:使用高效的亚像素卷积神经网络实现实时单图像和视频超分辨率

Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network

使用高效的亚像素卷积神经网络实现实时单图像和视频超分辨率

https://arxiv.org/abs/1609.05158

https://github.com/mrshao520/ReproductionCode/tree/main/ESPCN

CVPR 2016

Abstract

  • 问题:超分辨率在HR空间中执行,这是次优的,并增加了计算复杂度。
  • 方法:提出了第一个能够在单个 K2 GPU 上对 1080p 视频进行实时 SR 的卷积神经网络 (CNN)
    • 提出了一种新颖的 CNN 架构,其中特征图是在 LR 空间中提取的
    • 引入了一个高效的亚像素卷积层,该层学习一系列放大滤波器,以将最终的 LR 特征图放大到 HR 输出中
  • 结果:降低了计算复杂度,并且比以前基于CNN的方法快了一个数量级
  • 主要贡献
    • 上采样由网络的最后一层处理。这意味着每个LR图像都直接输入网络,并通过LR空间中的非线性卷积进行特征提取。由于输入分辨率降低,我们可以有效地使用较小的卷积层来集成相同的信息,同时保持给定的上下文区域。分辨率和过滤器尺寸的减小大大降低了计算和内存的复杂性,足以实现实时高清视频的超分辨率。
    • 对于具有L层的网络,我们学习\(n_{L-1}\)个特征图的\(n_{L-1}\)个上采样过滤器,而不是输入图像的一个上采样过滤器。另外,不使用显式插值过滤器意味着网络隐式的学习SR所需的处理。相比较第一层的单一固定的上采样过滤器,网络能够学习更好更复杂的LR到HR的映射。

1. 简介

全局SR问题假设LR数据是HR数据的低通滤波(模糊)、下采样和噪声版本。这是一个非常不适定的问题,因为在不可逆低通滤波和子采样操作期间会丢失高频信息。此外,SR操作实际上是从LR到HR空间的一对多映射,可以有多个解决方案,其中确定正确的解决方案并非易事。许多SR技术的一个关键假设是许多高频数据是冗余的,因此可以从低频分量准确地重建。因此,SR是一个推理问题,因此依赖于我们的相关图像统计模型。

许多方法假设多个图像可用作于具有不同视角的同一场景的LR实例,即具有独特的先验仿射变换。这些方法可以归类于超分辨率方法,以及通过附加信息约束不适定问题并尝试反转下采过程来利用显式冗余。然而,这些方法通常需要计算复杂的图像配准和融合阶段,其准确性直接影响结果的准确性。另一种可替代的方法是单图像超分辨率(signal image super-resulotion SISR)技术。这些技术试图学习存在于自然数据中的隐式冗余, 以恢复从单个LR图像中丢失的HR信息。这通常以图像的局部空间相关性和视频中的附加时间相关性的形式出现。在这种情况下,需要重构约束形式的先验信息来限制重构的解空间。

所提出的高效亚像素卷积神经网络(ESPCN),具有两个用于提取特征图的卷积层,以及一个聚合LR空间的特征图并一步构建SR图像的亚像素卷积层。

1.1 相关工作

  • 稀疏编码
  • 神经网络

1.2 动机和贡献

当SR上采样比例因子为3时,不同方法的精度和速度之间的权衡图。结果显示了在2.0GHz时钟的单个CPU内核上运行的来自Set14的图像的平均PSNR和运行时间。

  • 要将LR图像超分辨率到HR空间,需要提高LR图像的分辨率以在某个点与HR图像的分辨率相匹配。
  1. 图像分辨率在网络中间逐渐增加。
  2. 在网络的第一层之前或者在网络的第一层中,增加图像的分辨率。
    • 这种方法有一些问题:
      • 第一,在图像增强步骤之前增加LR图像的分辨率将增加计算的复杂度,这对于卷积网络尤其有问题,其中处理速度直接取决于输入图像的分辨率
      • 第二,经常用于完成该任务的插值法,例如双三次插值,不会带来额外的信息去解决不适定重建问题

仅在网络的最末端增加从LR到HR的分辨率,并从LR特征图超分辨率HR数据。这样就无需在更大的 HR 分辨率下执行大部分 SR 操作。为此,我们提出了一种高效的亚像素卷积层来学习图像和视频超分辨率的放大操作。

2. 方法

下采样:我们首先使用高斯滤波器对\(\mathbf{I^{HR}}\)卷积,从而模拟相机的点扩散函数,然后将图像缩小r倍。r 也被称为放大比率。

为避免在将\(\mathbf{I^{LR}}\)输入网络之前将其放大,在我们的架构中,我们首先将\(l\)层卷积神经网络直接应用于LR图像,然后应用亚像素卷积层来放大LR特征图以生成\(\mathbf{I^{SR}}\)

对于由\(L\)层组成的网络,前\(L - 1\)层可以描述如下:

\[f^{1}(\mathbf{I^{LR};W_{1},b_{1}}) = \phi(W_{1} * \mathbf{I^{LR}} + b_{1}) \\ \]

\[f^{l}(\mathbf{I^{LR};W_{1:l},b_{1:l}}) = \phi(W_{l} * f^{l-1}(\mathbf{I^{LR}}) + b_{l}) \]

  • \(l \epsilon (1, L-1)\):层数
  • \(W_{l}\):权重,大小为\(n_{l-1} \times n_{l} \times k_{l} \times k_{l}\)的2D卷积层
    • \(n_{0} = c\),c是图像通道数
    • \(n_{l}\)\(l\)层特征的数量
    • \(k_{l}\)\(l\)层过滤器的大小
  • \(b_{l}\):偏差,长度为\(n_{l}\)的向量
  • \(\phi\):非线性函数(激活函数)
  • \(f^{l}\)\(\mathbf{LR}\)特征图转换成\(\mathbf{HR}\)图像\(\mathbf{I^{SR}}\)

2.1 反卷积层

添加反卷积层是从最大池化(max-pooling)和其他图像下采样层恢复分辨率的流行选择。这种方法已成功应用于可视化激活以及使用网络的高级特征生成语义分割。SRCNN中使用的双三次插值是反卷积层的一个特例

反卷积层:每个输入像素与步长\(r\)的卷积层相乘,并对所的输出窗口求和。

2.2 高效的亚像素卷积层

在ImageNet上训练的第一层过滤器,上采样因子为3。过滤器根据其差异进行排序。

上采样LR图像的另一种方法是在LR空间中使用小步幅\(\frac{1}{r}\)进行卷积,这可以通过插值,穿孔,非池化简单地实现将LR空间映射到HR空间,然后在HR空间中 进行步长为1的卷积。这些实现将计算成本增加了\(r^{2}\)倍,因为卷积发生在HR空间中。

另外,在LR空间中,利用卷积操作,具有大小为\(k_{s}\)、权重间隔为\(\frac{1}{r}\)的过滤器\(W_{s}\)与步长为\(\frac{1}{r}\)的卷积层将激活\(W_{s}\)的不同部分。落在像素之间的权重根本没有被激活,并不需要被计算。激活模式的数量正好是\(r^{2}\)。根据其位置,每个激活模式最多有\(\lceil \frac{k_{s}}{r} \rceil ^{2}\)个被激活的权重。在图像上的过滤器卷积期间,这些模式定期的被激活,具体取决于不同的亚像素位置:\(mod(x, r),\ mod(y, r)\),其中\(x, y\)是HR空间中的输出像素的坐标。在这篇论文,我们提出了一种有效的方法去实现上述操作,当\(mod(k_{s},r) = 0\)时:

\[\mathbf{I^{SR}} = f^{L}(\mathbf{I^{LR}}) = ps(W_{L} * f^{L-1}(\mathbf{I^{LR}}) + b_{L}) \]

  • \(ps\):是一个周期性的重排列操作,将 $H \times W \times C \cdot r^{2} $ 张量的元素重新排列为形状为 \(rH \times rW \times C\) 的张量

从数学上将,该操作可以用以下方式描述:

\[PS(T)_{x,y,c} = T_{\lfloor x/r \rfloor,\lfloor y/r \rfloor, C \cdot r \cdot mod(y,r) + C \cdot mode(x,r) + c} \]

因此,卷积核\(W_{L}\)的形状为\(n_{L-1} \times r^{2}C \times k_{L} \times k_{L}\)。请注意,我们不会对最后一层的卷积输出使用非线性映射。很容易看出来,当\(k_{L}=\frac{k_{s}}{r}\)以及\(mod(k_{s}, r) = 0\)时,LR中间中的亚像素卷积等同于过滤器\(W_{s}\)。我们将新层称为亚像素卷积层,将网络称为高效的亚像素卷积层(ESPCN)。最后一层直接从LR特征图生成HR图像,每个特征图都有一个上采样过滤器。

给定一个由HR图像实例组成的训练集\(\mathbf{I_{n}^{HR}},\ n=1 \dots N\),我们生成相应的LR图像\(\mathbf{I^{LR}_{n}},\ n=1 \dots N\),并计算重建图像的像素均方误差(MSE)作为损失函数训练目标。

\[ℓ(W_{1:L}, b_{1:L}) = \frac{1}{r^{2}HW} \sum^{rH}_{x=1} \sum^{rW}_{x=1}(\mathbf{I^{HR}_{x, y}}-f^{L}_{x, y}(\mathbf{I^{LR}}))^{2} \]

值得注意的是,在训练阶段可以避免执行上述的周期性打乱操作。我们可以预先打乱训练数据去匹配\(ps\)之前的输出层,而不是将输出作为层的一部分进行打乱。因此,我们提出的层,与反卷积层相比在训练阶段快\(log_{2}r^{2}\)倍,与在卷积之前进行上采样的实现快了\(r^{2}\)倍。

在 ImageNet 上训练的最后一层过滤器,放大系数为 3:(a) 显示来自 SRCNN 9-5-5 模型的权重,(b) 显示来自 ESPCN 的权重(ImageNet elu)模型和(c)在应用于 \(ps\) 操作后(b)的权重应用于\(r^{2}\)通道。过滤器按默认顺序排列。

2.3 代码

import torch
import torch.nn as nn
import torch.nn.functional as F 

class ESPCNModel_tanh(nn.Module):
    def __init__(self, upscale_factor) -> None:
        super().__init__()
        self.conv1 = nn.Conv2d(1, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
        self.conv2 = nn.Conv2d(64, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        # n x 32 x h x w ===> n x 9 x h x w
        self.conv3 = nn.Conv2d(32, 1 * (upscale_factor ** 2), kernel_size=(3, 3), 
                               stride=(1, 1), padding=(1, 1))
        # n x 9 x h x w ===> n x 1 x 3h x 3w
        self.pixel_shuffle= nn.PixelShuffle(upscale_factor)
        
    def forward(self, x):
        x = F.tanh(self.conv1(x))
        x = F.tanh(self.conv2(x))
        x = F.sigmoid(self.pixel_shuffle(self.conv3(x)))
        
        return x

class ESPCNModel_relu(nn.Module):
    def __init__(self, upscale_factor) -> None:
        super().__init__()
        self.conv1 = nn.Conv2d(1, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
        self.conv2 = nn.Conv2d(64, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
        # n x 32 x h x w ===> n x 9 x h x w
        self.conv3 = nn.Conv2d(32, 1 * (upscale_factor ** 2), kernel_size=(3, 3), 
                               stride=(1, 1), padding=(1, 1))
        # n x 9 x h x w ===> n x 1 x 3h x 3w
        self.pixel_shuffle= nn.PixelShuffle(upscale_factor)
        
    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        x = F.sigmoid(self.pixel_shuffle(self.conv3(x)))
        
        return x
    
if __name__== "__main__":
    model = ESPCNModel_tanh(upscale_factor=3)
    print(model)
    
    pixel_shuffle = nn.PixelShuffle(3)
    input = torch.randn(2, 18, 4, 4) # n c h w
    print(f'input: {input}')
    # c_in=9   h_in=4   w_in=4
    # c_out = c_in / upscale^2
    # h_out = h_in * upscale    w_out = w_in * upscale
    output = pixel_shuffle(input)
    print(output.size()) # torch.Size([1, 1, 12, 12])
    print(f'output: {output}')

3. 实验

3.1 数据集

3.2 实施细节

对于ESPCN,我们在评估中设置 \(l = 3,\ (f_{1},n_{1})=(5, 64),\ (f_{2}, n_{2})=(3,32)\ and\ f_{3}=3\),(即卷积层数为3,f 为卷积核大小,n 为卷积核个数)。在训练阶段,从训练的真实有效的图片\(\mathbf{I^{HR}}\)中提取大小为\(17r \times 17r\)像素的子图像,其中\(r\)是上采样系数。

为了合成低分辨率样本图片\(I^{LR}\),我们使用高斯滤波器模糊\(I^{HR}\)并通过上采样系数对其进行子采样。从\(\mathbf{I^{HR}}\)中按照步长为 \((17 - \sum mod(f,2)) \times r\)提取测试集图片,从\(\mathbf{I^{LR}}\)中按照步长为 \((17-\sum mod(f,2))\)提取训练集图片。

根据我们的实验,我们选择tanh而不是relu作为最终模型的激活函数。

在 100 个 epoch 后观察到成本函数没有改善后,训练停止。初始学习率设置为0.01,最终学习率设置为0.0001,并在成本函数的改进小于阈值 μ 时逐步更新。最后一层的学习速度比慢 10 倍。在 K2 GPU 上对 91 张图像进行训练大约需要三个小时,对来自 ImageNet [的图像进行 7 天的放大因子 3。我们使用 PSNR 作为性能指标来评估我们的模型。

Dataset Scale ESPCN(91 relu) SRCNN(ImageNet) ESPCNN(ImageNet relu) ESPCNN(VOC2012 tanh) ESPCNN(VOC2012 relu)
Set 5 3 32.39 32.52 33.00 30.45 30.31
Set 14 3 28.97 29.14 29.42 27.26 27.19
posted @ 2025-03-23 19:50  致郁系游戏  阅读(259)  评论(0)    收藏  举报