查看全课大纲(第 93 / 93 节)
  1. 1.计算机视觉概述
  2. 2.计算机视觉应用场景
  3. 3.困难与挑战
  4. 4.开源库介绍
  5. 5.图像显示与存储
  6. 6.CLAHE
  7. 7.腐蚀膨胀与开闭运算
  8. 8.滤波与边缘填充
  9. 9.各种滤波
  10. 10.图像金字塔
  11. 11.傅里叶变换
  12. 12.短时傅里叶变换与小波变换
  13. 13.颜色特征与颜色直方图
  14. 14.几何特征_边缘
  15. 15.几何特征-角点与斑点
  16. 16.局部特征-SIFT特征描述子
  17. 17.局部特征-SURF特征描述子
  18. 18.局部特征-ORB特征描述子
  19. 19.其他特征描述子
  20. 20.传统图像分割技术
  21. 21.GraphCut
  22. 22.GrabCut
  23. 23.人脸检测的传统方法
  24. 24.行人检测的传统方法HOG+SVM
  25. 25.行人检测DPM
  26. 26.人工神经网络的架构
  27. 27.目标函数与梯度下降
  28. 28.误差反向传播
  29. 29.可手算的神经网络
  30. 30.改进目标函数与克服梯度消散
  31. 31.神经网络之传统神经网络与深度网络的差异
  32. 32.各种梯度下降算法
  33. 33.如何选择合适的梯度下降算法
  34. 34.避免过适应
  35. 35.CNN的架构
  36. 36.CNN的误差反向传播_卷积层
  37. 37.CNN的误差反向传播_池化层
  38. 38.分类所用的数据集
  39. 39.Alexnet详解
  40. 40.VGG详解
  41. 41.GoogLeNet_v1
  42. 42.BatchNormalization
  43. 43.GoogLeNet_v3v4
  44. 44.ResNet
  45. 45.ResNeXt
  46. 46.CNN设计准则
  47. 47.图像检索与推土机距离
  48. 48.基于颜色相似性
  49. 49.基于形状相似性
  50. 50.基于纹理相似性
  51. 51.基于局部特征相似性
  52. 52.DL的二值哈希编码
  53. 53.高维空间中检索KDTree
  54. 54.高维空间中检索LSH
  55. 55.目标识别任务综述
  56. 56.RCNN
  57. 57.SPP-Net
  58. 58.Fast R-CNN
  59. 59.Faster R-CNN
  60. 60.R-CNN系列模型回顾
  61. 61.R-FCN的设计思路
  62. 62.R-FCN的实现
  63. 63.YOLOv1
  64. 64.YOLOv2_9000
  65. 65.YOLOv3
  66. 66.图像分割应用场景与数据集
  67. 67.上采样的实现方式
  68. 68.FCN网络架构的由来
  69. 69.FCN构建细节
  70. 70.DeepLabv1
  71. 71.CRF
  72. 72.DeepLabv2
  73. 73.DeepLabv3
  74. 74.特定的医学影像分割任务
  75. 75.U-Net
  76. 76.3D U-Net
  77. 77.V-Net
  78. 78.DenseNet
  79. 79.病理切片分析任务及数据集
  80. 80.病理切片分析
  81. 81.图说任务及其传统处理方法
  82. 82.深度语言模型与RNN
  83. 83.LSTM及其变种
  84. 84.NIC模型
  85. 85.SAT模型
  86. 86.图说的性能指标
  87. 87.判别模型与生成模型
  88. 88.KL散度与JS散度
  89. 89.VAE
  90. 90.GAN的基本原理
  91. 91.DCGAN与CGAN
  92. 92.Wasserstein GAN
  93. 93.SRGAN

SRGAN

小象实战讲义 · 基于深度学习的计算机视觉

在图像生成领域,我们之前学习的GAN模型(如DCGAN)虽然能生成新的图像,但往往面临分辨率低、细节模糊的问题。想象一下,如果你有一张模糊的老照片,能否通过算法让它变得清晰锐利,甚至“想象”出丢失的细节?这正是超分辨率技术(Super-Resolution, SR)的目标。本节我们将学习SRGAN,一种将生成对抗网络与超分辨率任务相结合的经典模型,它通过引入感知损失,使生成的高分辨率图像在视觉上更加逼真、细节更加丰富。

💡 核心导读

  • 问题定位:理解传统基于均方误差(MSE)的超分辨率方法为何会导致图像模糊,以及SRGAN如何解决这一问题。
  • 网络架构:掌握SRGAN生成器(基于SRResNet的残差结构)和判别器的具体构成与设计思路。
  • 损失函数:深入理解SRGAN的核心——感知损失函数,它由内容损失(VGG Loss)和对抗损失两部分构成。
  • 效果理解:体会SRGAN生成的图像在视觉感知上的优势,理解其“像画家作画”般补充细节的原理。

从模糊到清晰:超分辨率GAN要解决什么问题?

在传统的图像生成任务中,即便是像DCGAN这样改进后的模型,其生成图像的分辨率通常也较低(例如64×64像素)。更重要的是,如果使用均方误差作为训练生成网络的主要损失函数,虽然训练过程相对稳定、收敛较快,但会产生一个严重的副作用:丢失图像的高频细节。

高频细节对应的是图像中物体的边缘、纹理等变化剧烈的部分。丢失这些细节的直接结果,就是生成的图像看起来过于平滑、模糊,缺乏真实感。

SRGAN(Super-Resolution GAN)正是为了解决这个问题而提出的。它的核心目标非常明确:给定一张低分辨率(Low-Resolution, LR)图像,通过一个生成模型,将其转换(或“恢复”)成一张高分辨率(High-Resolution, HR)图像,并且要求生成的结果不仅在像素值上接近真实高分辨率图像,更要在视觉感知上——即轮廓、纹理、细节——具有强烈的真实感。

为了实现这一目标,SRGAN沿用了 Johnson 等人(2016)提出的感知损失(Perceptual Loss) 思想:不再仅仅在像素空间(Pixel Space)比较生成图像与目标图像的差异,而是转向在特征空间(Feature Space) 进行比较。SRGAN的贡献在于把这一感知损失与对抗损失(Adversarial Loss) 结合起来,让生成器与判别器在博弈中共同进化。

简单来说,SRGAN可以看作是在一个强大的超分辨率生成网络(SRResNet)基础上,加上了一个用于判断图像是否“真实”的判别器(Discriminator)而构成的对抗训练框架。

SRGAN的网络架构剖析

作为一种GAN,SRGAN同样由生成器(Generator) 和判别器(Discriminator) 两部分组成。让我们逐一拆解。

生成网络:基于残差结构的细节恢复引擎

SRGAN的生成器是其核心,负责将低分辨率图像“放大”并补充细节。它的主体结构借鉴并改进了ResNet的思想。

输入: 低分辨率图像 I_LR
|
V
[卷积层] K9N64S1 -> [PReLU]
|
V
--- 循环 B 次 ---
|   [残差块] (结构见下)
|---
|
V
[卷积层] K3N64S1 -> [BatchNorm]
|
V
--- (与初始卷积输出相加,构成大残差连接) ---
|
V
[次像素卷积层] K3N256S1 -> [PixelShuffle] -> 上采样×2
|
V
[次像素卷积层] K3N256S1 -> [PixelShuffle] -> 上采样×2
|
V
[输出卷积层] K9N3S1 -> 将 64 通道特征图映射为 3 通道 RGB 图像
|
V
输出: 高分辨率图像 I_SR

关键组件解析:

  1. 残差块(B Residual Blocks):

    • 这是生成网络的主体,由多个结构相同的残差块堆叠而成(原论文中B=16)。
    • 每个残差块内部为:卷积 → 批归一化(Batch Normalization) → PReLU → 卷积 → 批归一化,然后把第二个 BN 的输出与块的输入逐元素相加(第二个卷积之后不接 PReLU)。
    • 块内采用了残差连接:将块的输入直接加到第二个批归一化的输出之后。这种结构有助于缓解深层网络训练中的梯度消失问题,让网络能够学习到更复杂的映射关系。
    • 参数表示:K3N64S1 是一种紧凑的表示法,意为卷积核(Kernel)大小为3×3,输出通道数(N)为64,步长(Stride)为1。
  2. 大残差连接(Global Residual Connection):

    • 在堆叠的残差块之前和之后,各有一个卷积层。网络将初始卷积层的输出,绕过中间所有的残差块,直接与残差块堆栈后的卷积层输出相加。
    • 这构成了一个更大的残差结构,其思想是:网络主要学习低分辨率图像与高分辨率图像之间的残差(即细节差异),而不是学习完整的图像映射,这大大降低了学习难度。
  3. 次像素卷积层(Sub-pixel Convolution Layer):

    • 这是实现分辨率提升(上采样)的关键。
    • 传统上采样方法(如双线性插值)不引入新的信息。次像素卷积层则先通过卷积增加通道数(例如增加到原始通道数的r²倍,r为上采样倍数),然后通过一个像素重排(PixelShuffle) 操作,将多通道的像素信息重新排列到空间维度,从而增大图像尺寸并补充细节。
    • 例如,目标是将图像宽高放大2倍(r=2)。卷积层输出特征图的通道数变为输入的4倍,然后PixelShuffle操作将每4个通道的对应像素重新排列成一个2×2的局部块,从而将特征图尺寸放大2倍,通道数恢复为原始数量。

判别网络:判断“真实感”的裁判

相比于复杂的生成器,SRGAN的判别器结构相对传统和简洁,其本质是一个二分类卷积神经网络。

输入: 图像 (真实HR 或 生成SR)
|
V
--- 循环8次 ---
|   [卷积层] K3N64S1 -> [BatchNorm] -> [LeakyReLU]
|   (后续卷积层通道数递增,如128, 256, 512...)
|---
|
V
[展平操作]
|
V
[全连接层] -> [LeakyReLU]
|
V
[全连接层] -> [Sigmoid]
|
V
输出: 概率标量 (真/假)

判别器由 8 个卷积块组成,每个块包含卷积、批归一化和LeakyReLU激活函数(通道数依次为 64、64、128、128、256、256、512、512,交替使用步长 1 和 2 下采样)。经过多层卷积下采样后,特征图被展平并送入全连接层,最后通过一个Sigmoid函数输出一个0到1之间的概率值,表示判别器认为输入图像是“真实高分辨率图像”的可能性。

判别器的目标是尽可能准确地区分来自数据集的真实高分辨率图像和生成器产生的超分辨率图像。而生成器的目标则是“骗过”判别器,使其对自己的输出给出高分。

SRGAN的损失函数:感知损失的精髓

损失函数是SRGAN的灵魂,它引导着生成器向正确的方向进化。SRGAN生成器的总损失函数称为感知损失(Perceptual Loss),是以下两项的加权和:

lSR=lContentSR⏟内容损失+10−3⋅lGenSR⏟对抗损失l^{SR} = \underbrace{l_{Content}^{SR}}_{\text{内容损失}} + \underbrace{10^{-3} \cdot l_{Gen}^{SR}}_{\text{对抗损失}}

其中,10−310^{-3} 是一个用于平衡两项权重的超参数。

内容损失:在特征空间比较相似性

传统超分辨率方法直接使用均方误差作为损失函数: lMSESR=1WHC∑x=1W∑y=1H∑c=1C(Ix,y,cHR−GθG(ILR)x,y,c)2l_{MSE}^{SR} = \frac{1}{WHC} \sum_{x=1}^{W} \sum_{y=1}^{H} \sum_{c=1}^{C} (I_{x,y,c}^{HR} - G_{\theta_G}(I^{LR})_{x,y,c})^2 其中 GθG(ILR)G_{\theta_G}(I^{LR}) 是生成器输出的超分辨率图像 ISRI^{SR}。W,H,CW, H, C 分别是图像的宽、高和通道数。

MSE损失追求像素级的精确匹配,但正如前文所述,这通常会导致模糊的结果,因为平均化的最优解就是丢失高频细节的平滑图像。

SRGAN提出了基于VGG网络的特征损失(VGG Loss) 作为内容损失: lContentSR=1Wi,jHi,j∑x=1Wi,j∑y=1Hi,j(ϕi,j(IHR)x,y−ϕi,j(GθG(ILR))x,y)2l_{Content}^{SR} = \frac{1}{W_{i,j} H_{i,j}} \sum_{x=1}^{W_{i,j}} \sum_{y=1}^{H_{i,j}} (\phi_{i,j}(I^{HR})_{x,y} - \phi_{i,j}(G_{\theta_G}(I^{LR}))_{x,y})^2

公式解读:

  • ϕi,j\phi_{i,j} 表示一个在ImageNet上预训练好的VGG网络。
  • ii 和 jj 有特定含义:ii 表示第 ii 个最大池化层,jj 表示在该池化层之前的第 jj 个卷积层(激活后);因此 ϕi,j\phi_{i,j} 指的是这一层输出的整组特征图(包含所有通道),而不是某层内的第 jj 个通道。原论文使用的是VGG19网络的 conv5_4 层(即第5个池化层前的第4个卷积层)。
  • Wi,j,Hi,jW_{i,j}, H_{i,j} 是该特征图的宽和高。
  • 这个损失计算的是:真实高分辨率图像和生成器输出的超分辨率图像,分别通过VGG网络提取特征后,在指定的中间特征层上,所有位置(x,y)(x,y)、所有通道的特征值的均方误差。

为什么这样做有效? 预训练的VGG网络已经学会了识别图像中丰富的语义信息(如物体、纹理、边缘)。在特征空间计算差异,意味着我们不再要求生成图像和真实图像在像素值上一模一样,而是要求它们在高级语义和视觉风格上相似。这允许生成器有一定的自由度去“想象”和补充合理的细节,只要这些细节在人类视觉感知上是可信的即可。

对抗损失:驱动生成图像更逼真

对抗损失沿用经典GAN中生成器的损失形式: lGenSR=∑n=1N−log⁡DθD(GθG(ILR))l_{Gen}^{SR} = \sum_{n=1}^{N} -\log D_{\theta_D}(G_{\theta_G}(I^{LR})) 其中 DθD(⋅)D_{\theta_D}(\cdot) 是判别器输出的概率值(认为输入是真实图像的概率)。

这个损失的含义是:生成器希望它生成的超分辨率图像 GθG(ILR)G_{\theta_G}(I^{LR}),能够被判别器 DD 误判为真实图像。即希望 D(G(ILR))D(G(I^{LR})) 的值越接近1越好,因此最小化 −log⁡(D(G(ILR)))-\log(D(G(I^{LR})))。

对抗损失为生成过程注入了“竞争”压力,驱动生成器去生成那些在整体分布上与真实高分辨率图像集难以区分的样本,从而提升图像的全局真实感。

SRGAN的训练与效果

训练数据准备

训练时,我们需要成对的低分辨率和高分辨率图像。

  1. 高分辨率图像:直接来自数据集(如ImageNet)。
  2. 低分辨率图像:SRGAN 原论文(Ledig et al., 2017)的做法是对高分辨率图像用双三次(bicubic)核直接做 4 倍下采样,得到 (ILR,IHR)(I^{LR}, I^{HR}) 图像对。后来 BSRGAN、Real-ESRGAN 等工作才引入“高斯模糊 + 二次降采样”的复合降质管线来模拟真实退化——那是后续改进,不是 SRGAN 的原始设定。

效果与启示

SRGAN生成的图像在视觉感知上取得了突破性进展。与基于MSE的方法产生的模糊图像相比,SRGAN的结果在纹理、边缘等细节上更加清晰锐利。

一个有趣的观察是:如果将SRGAN生成的图像放大到像素级别仔细查看,你可能会发现一些看似不规则的色块或线条。但是,当你以正常的观看距离审视整张图片时,这些“瑕疵”却共同构成了令人信服的细节。这个过程非常类似于油画创作:画家并不会在每一笔都精确复制实物,而是通过不同颜色和笔触的堆叠,在整体上营造出逼真的光影和质感。SRGAN的感知损失正是引导网络学习这种“整体逼真”而非“像素精确”的生成策略。

📝 动手练一练

  1. 概念辨析:SRGAN中的“内容损失”与传统的“均方误差损失”最根本的区别是什么?这种区别如何帮助SRGAN生成更清晰的图像?
👉 点击查看参考答案

根本区别在于比较的空间不同。

  • 均方误差损失在像素空间直接比较生成图像与目标图像每个像素点的数值差异。这迫使生成器寻找一个在平均意义上最接近的“平滑”解,导致高频细节丢失,图像模糊。
  • SRGAN的内容损失(VGG Loss) 在特征空间进行比较。它利用预训练的VGG网络,提取图像的高级语义特征(如纹理、边缘模式),并计算这些特征的差异。这允许生成器不必拘泥于像素级的完全复现,而是可以“想象”和补充符合语义逻辑的合理细节,只要在整体视觉感知上与目标相似即可。因此,它能生成细节更丰富、视觉上更清晰的图像。
  1. 代码思考:以下代码用 OpenCV 和 NumPy 演示“先降质、再下采样”这一预处理思路(注意:SRGAN 原论文用的是 bicubic 直接下采样,这里用高斯模糊只是为了直观展示“模糊程度”对训练难度的影响)。请阅读代码,并回答:如果我们将高斯滤波的核大小(5,5)改为(1,1),会对生成的“低分辨率”图像以及后续SRGAN的训练产生什么影响?
import cv2
import numpy as np

# 假设我们有一张微小的高分辨率“图像”(一个6x6的棋盘格图案,用于演示)
hr_img = np.array([[255, 0, 255, 0, 255, 0],
                   [0, 255, 0, 255, 0, 255],
                   [255, 0, 255, 0, 255, 0],
                   [0, 255, 0, 255, 0, 255],
                   [255, 0, 255, 0, 255, 0],
                   [0, 255, 0, 255, 0, 255]], dtype=np.uint8)

print("原始高分辨率图像 (6x6):")
print(hr_img)

# 步骤1: 高斯滤波 (模拟模糊)
# 使用一个小的高斯核,sigma根据核大小自动计算
blurred = cv2.GaussianBlur(hr_img.astype(np.float32), (5, 5), 0)
print("\n高斯模糊后图像 (6x6, 值已取整):")
print(blurred.astype(np.uint8))

# 步骤2: 下采样 (这里模拟2倍下采样,由于图像小,我们简单隔点取样)
# 实际中会使用cv2.resize进行双线性或双三次插值下采样
lr_img = blurred[::2, ::2]  # 隔行隔列取样
print("\n下采样后的低分辨率图像 (3x3):")
print(lr_img.astype(np.uint8))
原始高分辨率图像 (6x6):
[[255   0 255   0 255   0]
 [  0 255   0 255   0 255]
 [255   0 255   0 255   0]
 [  0 255   0 255   0 255]
 [255   0 255   0 255   0]
 [  0 255   0 255   0 255]]

高斯模糊后图像 (6x6, 值已取整):
[[127 127 127 127 127 127]
 [127 127 127 127 127 127]
 [127 127 127 127 127 127]
 [127 127 127 127 127 127]
 [127 127 127 127 127 127]
 [127 127 127 127 127 127]]

下采样后的低分辨率图像 (3x3):
[[127 127 127]
 [127 127 127]
 [127 127 127]]
👉 点击查看参考答案

将高斯核大小从(5,5)改为(1,1),意味着几乎不进行模糊处理((1,1)的核就是原像素本身)。

  • 对低分辨率图像的影响:生成的lr_img将几乎直接是原始高分辨率图像hr_img的清晰下采样版本,丢失的细节主要来自简单的降采样操作,而没有模拟真实世界中因光学模糊、运动模糊等导致的高频信息丢失。
  • 对SRGAN训练的影响:在这种情况下,训练任务变得“过于简单”。生成器可能只需要学习一个相对简单的插值算法就能很好地从lr_img重建hr_img,因为输入本身包含了很多清晰的结构信息。这会导致:
    1. 模型可能无法很好地学习到如何从真正模糊的低分辨率输入中恢复细节,从而降低其在实际复杂场景下的泛化能力。
    2. 对抗损失和感知损失的作用可能会被削弱,因为像素级的MSE损失可能已经能达到不错的效果。

因此,对后续采用复合降质的真实场景(如 BSRGAN、Real-ESRGAN)来说,合适的模糊核是模拟退化、提升恢复能力的重要一环;SRGAN 原论文用的是 bicubic 直接下采样,不含这一步。

本章小结

本节我们深入学习了SRGAN,一个将生成对抗网络成功应用于图像超分辨率的里程碑式模型。它通过精巧的网络设计和创新的损失函数,突破了传统方法在视觉感知上的瓶颈。

今天,超分辨率更多使用 ESRGAN、SwinIR、Real-ESRGAN 以及扩散模型(如 Stable Diffusion Upscaler);但 SRGAN 提出的“感知损失 + 对抗损失”组合,仍是感知质量优化的经典范式。

📋 行动清单

  • 复述核心思想:能够清晰说明SRGAN为何要使用“感知损失”来代替“均方误差损失”,以及感知损失由哪两部分构成。
  • 解析网络结构:画出SRGAN生成器的简化框图,并标出残差块、大残差连接和次像素卷积层的位置与作用。
  • 理解训练流程:描述SRGAN训练时所需的图像对(I_LR, I_HR)是如何生成的,并理解对抗训练中生成器和判别器的目标分别是什么。

—— 小象教研组