实战训练与源码教程:用Real-ESRGAN对抗生成超分技术实现超高清图像!

news2024/11/24 7:03:17

目录

前言

超分数据如何构造呢?

Real-ESRGAN

1. 高质量细节重建

2. 真实感和自然度

3. 处理真实世界数据

4. 多尺度和多种类型的输入

5. 视觉效果的提升

超分如何退化

1. 模糊处理

2. 噪声处理

3. 压缩失真

4. 训练数据的退化模拟

2.经典退化模型◆退化过程全览

Real esrgan 实践开始

代码环境安装

数据构造

训练Real esrgan网络

第一步是训练real esrnet网络

训练Real esrGan

finetune和生成退化数据


前言

大家好,我是cv君,今天给大家重点介绍一下高质量超分方案Real esrgan,他的方案非常有效,我们可以使用他的方案,自己用高效的生成器来做很多高速、高效的超分。为啥呢?因为他的退化方案不错,他是盲超分算法,盲超分是啥意思呢,就是不知道低分辨率LR和高分辨率图像HR关系的。

超分数据如何构造呢?

    我们在实际生活中,比如你手机是2k的图,你想训练个4倍超分,变成8K分辨率的图,你该怎么构造数据呢?你只有相机拍的2K图,相当于你没有GT咋训练呢,一般情况下,学术界很简单的通过下采样方式,将图像变小成一半或1/4等,这样就得到了小图当LR训练,原图当HR监督,这样就得到了一般的训练数据:DIV2K和Filcker数据等,大量的超分数据,都是这样退化的,那么他们的退化方式是:(双三次)下采样模糊退化,那么网络在学什么呢?学反过来的过程,双三次上采样变清晰进化。这样很明显有个问题:咱实际使用时,输入的图,并不是这么糊(双三次退化后的图像,比较糊,信息丢失严重,尤其是低频都没了),那实际用怎么会好呢?

    所以,数据进化方式出现了:还是举例,你只有相机拍的2K图,如果你想变成8K超分模型,那么是不是我自己用方法构造出一张8K的图即可。咋构造呢,世界上还没有这样的方法吧。——1、用大模型超分,用好一些的超分模型,不就可以变大又清晰了吗,来做GT,这样的好处是,可以得到像素对齐的HR,不会移动图像位置,但是,有个缺点,就是你再用网络学,不就是相当于你的网络在学刚刚这个大超分网络的效果了吗,效果永远无法超越他。所以在这个进化方式完成后,需要对你认为不好的大模型生成的8K图,进行调整,比如你觉得噪声多了,用ps等减小一点,或者是锐度不够,就用ps加锐,注意,加锐可能噪声又会增加。

比如你可以用real-esrgan等模型进行超分你自己的数据集,然后得到高清的大图,这样就得到了LR(你的原图)和HR(其他大模型超分+调整后的图)然后和你的数据进行训练。

    这样获得数据对,还是不够真实,怎样更真实呢,相当于你用两个镜头(一般手机镜头1倍是一个镜头,然后3或者5倍后会切另一个长焦镜头),这样,长焦镜头是光学的力量,是比所有方法都要清晰的。咋做超分数据呢?拿俩相机,(最好焦距是2 、4倍左右)对着同一个地方拍摄,就得到了如下俩图,然后只需要对齐一下数据,即可得到超分的LR和HR:接着对齐数据方式出现了:

如图所示,用105mm焦距的相机和28mm的广角相机,采集同样花圃区域的图像,然后用脚本对齐,或者用手动对齐图像,就得到了HR(105mm长焦的超清晰图像)和用28mm同区域采集到图像(他俩大约差4倍大小,然后稍微缩放成整数,即可训练),光学的力量就是最真实的,那么为啥现在没啥人用呢,数据制造比较麻烦,需要几个真实打算落地的相机,还要不同焦距,有这样的人不多,另外采集完数据,还要对齐,可能焦距不同,还会压缩图像,导致难以对齐,两图像的像素间有偏移,可能难以训练,所以RealSR提供的数据都有像素误差,还专门加了减少像素干扰超分的损失,算一个补丁损失。

    除了这些方法外,还有个方法:模糊核估计,在线退化方法,像Real esrgan,就是在线退化:

Real-ESRGAN

Real-ESRGAN(Real Enhanced Super-Resolution Generative Adversarial Network)在图像超分辨率任务中展现了显著的效果和优势。以下是其主要效果的详细介绍:

1. 高质量细节重建

Real-ESRGAN能够在将低分辨率图像提升至高分辨率时,恢复丰富的细节和纹理。它不仅简单地放大图像,而是利用生成对抗网络的能力来生成具有高真实感的细节。这种方法能够在增强图像的分辨率时保持图像的自然外观,减少由于放大而产生的模糊或伪影。

2. 真实感和自然度

与传统的超分辨率方法相比,Real-ESRGAN特别关注生成图像的真实感。通过对抗训练,生成器不断改进其生成的图像,使其更接近于高分辨率原始图像,从而减少了通常见于超分辨率图像的伪影和不自然的细节。这使得Real-ESRGAN在处理真实世界图像时,能够提供更自然、更细腻的结果。

3. 处理真实世界数据

Real-ESRGAN在处理实际应用中的图像时表现优异,包括模糊、噪声和压缩损失等问题。它比许多传统方法更能够应对这些挑战,提供更加清晰和可用的图像。对于历史照片、低分辨率视频帧和其他高噪声图像,Real-ESRGAN能够有效地恢复图像质量。

4. 多尺度和多种类型的输入

Real-ESRGAN具备处理不同尺度和多种类型输入图像的能力。无论是低分辨率的图像、图像压缩损失、还是具有复杂纹理的图像,它都能提供一致且高质量的超分辨率输出。这使得它在各种应用场景中都能够表现良好,包括图像放大、视频增强和细节恢复等。

5. 视觉效果的提升

通过使用Real-ESRGAN,图像的视觉效果得到了显著提升。生成的高分辨率图像在细节、清晰度和色彩再现方面较传统方法有明显优势。这种提升使得Real-ESRGAN在艺术创作、视觉效果增强和图像质量改进等领域具有广泛的应用潜力。

总的来说,Real-ESRGAN通过深度学习和生成对抗网络的创新,提升了超分辨率图像生成的质量和效果,特别在处理实际图像和复杂情况时表现出色。

超分如何退化

Real-ESRGAN在超分辨率过程中处理图像退化的方式主要包括以下几个方面:

1. 模糊处理

在图像退化中,模糊是常见的问题,通常由拍摄条件、镜头质量等因素造成。Real-ESRGAN通过深度学习模型学习到如何从模糊的低分辨率图像中恢复出清晰的细节。这是通过训练生成器对抗判别器,逐步改进图像细节,减少模糊和恢复清晰度来实现的。

2. 噪声处理

图像在采集和传输过程中可能会受到噪声的干扰。Real-ESRGAN能够通过生成对抗网络的训练,识别并去除噪声,同时保留图像中的重要细节。这种处理使得生成的高分辨率图像不仅更清晰,还具有更好的视觉质量。

3. 压缩失真

低分辨率图像常常经历过压缩,导致细节丢失和伪影。Real-ESRGAN利用对抗训练来学习如何修复这些压缩失真,生成的高分辨率图像能够有效去除压缩带来的伪影,恢复图像的自然细节和纹理。

4. 训练数据的退化模拟

为了使Real-ESRGAN在处理实际退化图像时表现更好,训练过程中会使用模拟退化的低分辨率图像进行训练。这些模拟的退化包括不同类型的模糊、噪声和压缩,从而使模型在面对真实图像时能够表现出更好的恢复能力。

通过这些方法,Real-ESRGAN能够有效处理各种退化情况,使得从低分辨率图像生成的高分辨率图像更接近真实、自然的效果。

上图分别为 双三次上采样、ESRGAN、RealSR 和 Real-ESRGAN 的效果。

2.经典退化模型◆退化过程全览

盲 SR 旨在从具有未知和复杂退化的低分辨率图像中恢复高分辨率图像。通常采用经典退化模型来合成低分辨率输入。通常,首先将真实图像 y 与模糊核 k 进行卷积。然后,执行具有比例因子的下采样操作。低分辨率 x 是通过添加噪声 n 获得的。最后,JPEG压缩也被采用,因为它在真实世界的图像中被广泛使用。

其中 D 表示退化过程,退化实现了将清晰图像 y 模糊为 x 的过程。

Real-ESRGAN 中采用的纯合成数据生成。它利用二阶退化过程来模拟更实际的退化,其中每个退化过程采用经典的退化模型。其中列出了模糊、调整大小、噪声和 JPEG 压缩的详细选择。除此之外模型还使用 sinc 滤波器来合成常见的振铃和超调伪影。

◆K - 高斯滤波

通常将模糊退化建模为具有线性模糊滤波器(内核)的卷积。各向同性和各向异性高斯滤波器是常见的选择。对于内核大小为 2t + 1 的高斯模糊核 k,其 (i, j) ∈ [−t, t] 元素从高斯分布中采样,形式如下:

其中 Σ 是协方差矩阵;C 是空间坐标;N 是归一化常数。协方差矩阵可以进一步表示如下:

其中 σ1 和 σ2 是沿两个主轴的标准差(即协方差矩阵的特征值); θ 是旋转度。当σ1 = σ2时,k 为各向同性高斯模糊核; 否则 k 为各向异性核。

这一步相当于对图像进行了高斯滤波模糊。下图为不同参数下图像的模糊效果:

◆N - 噪声

N 即 Noisy,我们考虑两种常用的噪声类型:1) 加性高斯噪声和 2)泊松噪声。加性高斯噪声的概率密度函数等于高斯分布的概率密度函数。噪声强度由高斯分布的标准差 σ控制。当 RGB 图像的每个通道都有独立的采样噪声时,合成噪声是颜色噪声。我们还通过将相同的采样噪声应用于所有三个通道来合成灰色噪声。泊松噪声遵循泊松分布。它通常用于近似模拟统计量子波动引起的传感器噪声,即在给定曝光水平下感知到的光子数的变化。泊松噪声的强度与图像强度成正比,不同像素的噪声是独立的。

这一步在高斯滤波的基础上为图像增加噪声。下图为不同噪声添加后的效果:

◆ ↓r - Resize

这一步其实代表 Downsampling 即下采样。下采样是合成 SR 中低分辨率图像的基本操作。更一般地说,我们考虑下采样和上采样,即调整大小操作。有几种调整算法——最近邻插值、区域大小调整、双线性插值和双三次插值。不同的调整大小操作会带来不同的效果——有些会产生模糊的结果,而有些可能会产生过锐化的图像,带有超调伪影。为了包含更多样化和复杂的调整大小效果,我们考虑了上述选择的随机调整大小操作。由于最近邻插值引入了错位问题,我们排除了它,只考虑区域、双线性和双三次运算。

↓r

这一步是在高斯滤波后对图像进行下采样。下图为下采样算法和上采样算法的不同组合的影响。图像首先被四倍的比例因子下采样,然后上采样到其原始大小:

◆jpeg - 压缩

JPEG 压缩是一种常用的数字图像有损压缩技术。它首先将图像转换为 YCbCr 颜色空间,并对色度通道进行下采样。然后将图像分成 8 × 8 个块,每个块用二维离散余弦变换 DCT 进行变换,然后对 DCT 系数进行量化。JPEG 压缩通常会引入不愉快的块伪影。压缩图像的质量由质量因子 q ∈ [0, 100] 决定,其中较低的 q 表示更高的压缩比和更差的质量。

上述操作代表对下采样且添加噪声的图像进行 jpeg 压缩。下图为 jpeg 压缩对图像画质的影响:

高阶退化模型

在采用上述经典退化模型来合成训练对时,训练后的模型确实可以处理一些真实样本。然而,它仍然不能解决现实世界中的一些复杂的退化,特别是未知的噪声和复杂的伪影。左侧的真实世界图片在经典退化模型的合成数据训练修正后可以解决,然后右侧更为复杂的真实世界图像的噪声却被放大了:

这是因为合成的低分辨率图像仍然与真实退化图像有很大的差距。因此,我们将经典的退化模型扩展到高阶退化过程,以模拟更实际的退化。经典的退化模型只包含一个固定的基本退化的数量,可以看作是一阶建模。然而,现实生活中的退化过程是相当多样化的,通常包括一系列程序,包括相机的成像系统、图像编辑、互联网传输等。

例如,当我们想要从互联网上恢复低质量的图像下载时,其潜在的退化涉及不同退化过程的复杂组合。具体来说,原始图像可能多年前用手机拍摄,这不可避免地包含相机模糊、传感器噪声、低分辨率和 JPEG 压缩等退化。然后使用锐化和调整大小操作对图像进行编辑,带来超调和模糊伪影。之后,它被上传到一些社交媒体应用程序,这引入了进一步的压缩和不可预测的噪音。随着数字传输也将带来伪影,当图像在互联网上传播多次时,这个过程变得更加复杂。

这种复杂的恶化过程不能用经典的一阶模型建模。因此,我们提出了一个高阶退化模型。n 阶模型涉及 n 个重复退化过程,其中每个退化过程采用具有相同过程但超参数不同的经典退化模型。请注意,这里的“高阶”与数学函数中使用的“高阶”不同。它主要是指同一操作的实现时间。但是我们强调高阶退化过程是关键,这表明并非所有打乱的退化都是必要的。为了使图像分辨率保持在合理的范围内,将式(1)中的下采样操作替换为随机调整大小操作。

根据经验,我们采用了二阶退化过程,因为它可以在保持简单性的同时解决大多数实际情况。下图描述了我们的纯合成数据生成管道的整体管道:

这一系列的 D 就模拟了生活中一张颠沛流体的图片的传递过程。值得注意的是,改进的高阶退化过程并不完美,不能覆盖现实世界中的整个退化空间。相反,它仅通过修改数据合成过程来扩展先前盲 SR 方法的可解退化边界。

环形和超调伪影

环形伪影经常出现在图像中急剧过渡附近的虚假边缘。他们在视觉上看起来像边缘附近的波段或"幽灵"。超调伪影通常与振铃伪影相结合,表现为边缘过渡处的跳跃增加。这些伪影的主要原因是信号在没有高频的情况下是带限的。这些现象非常常见,通常由锐化算法、JPEG压缩等产生。下图显示了一些遭受振铃和超调伪影的真实样本:

上图为存在振铃和超调伪影的真实样本。下图为 sinc 内核的示例 [kernel= 21] 和相应的过滤图像,可以看到图像经过 sinc 内核滤波会出现真实世界类似的振铃和超调伪影的状态。sinc 滤波器,这是一种理想化的滤波器,可以切断高频,以合成训练对的振铃和超调伪影。sinc 滤波器内核可以表示为:

模型在两个地方采用了sinc滤波器:模糊过程和合成的最后一步。last sinc 滤波器和 JPEG 压缩的顺序被随机交换以覆盖更大的退化空间,因为一些图像可能首先被过度锐化(具有过冲伪影),然后具有JPEG压缩;而一些图像可以首先进行JPEG压缩,然后进行锐化操作。

Real esrgan 实践开始

我们可以通过real esrgan官方代码训练,也可以通过basicsr框架实现,为了后续经常使用,我们这里以basicsr框架为例子:

代码环境安装

1、下载basicsr代码

git clone https://github.com/XPixelGroup/BasicSR.git

然后就按照readme 安装即可:

如果有符合版本的torch了,就注释掉

如果自己之前安装过basicsr,就卸载掉,或者重开一个conda环境执行:
在根目录下执行python setup.py develop

如果卡住某个库安装比较慢,就ctrl c,手动自己用清华源安装:-i https;//pypi.tuna.tsinghua.edu.cn/simple

然后再继续setup 

直到成功后,能在pip list里看到basicsr版本号

数据构造

然后就可以了,接下来就是数据构造,我上传了数据和代码,大家可以直接使用,数据可以用div2k也可以多用几个:

Real-ESRGAN/docs/Training_CN.md at master · xinntao/Real-ESRGAN · GitHub

这里面用了3个数据,我们简单些,只用div2k,效果要好,就多用一些。

然后按照readme切割数据成小图,(我们数据切过了,不用再切)

这图就是把原始的div HR和双三次降采样的LR图,同时切割成小图的代码,一块块变小。方便训练,我们的图 就是切割好了的。

训练Real esrgan网络

第一步是训练real esrnet网络

这个就是在先让网络学习超分的过程,是一个正常的网络,学完后,超分分数会高一些,但是还是有些模糊的,因为还没经过Gan网络。这个过程中,学习率稍微高一些。

大家可以调整一下options/train/esrnet X4 的yml,也可以用我的:

要生成个txt,非常简单:

然后呢,就在下面通过这俩来索引图像:txt里写的是文件名,然后前面的话,结合咱dataroot_gt,能拼接成你的图像路径即可。我们只需要HR,不用LR,因为他会在线退化LR。模拟放小、加噪声、加模糊等。

    dataroot_gt: /home/zxx/AF/expandAi/SESR/data/DIV2K/DIV2K_train_HR_Sub
    meta_info: /home/zxx/AF/expandAi/SESR/data/DIV2K/meta_info_DIV2K800sub_GT.txt
# general settings
name: train_RealESRNetx4plus_1000k_B12G4
model_type: RealESRNetModel
scale: 4
num_gpu: auto  # auto: can infer from your visible devices automatically. official: 4 GPUs
manual_seed: 0

# ----------------- options for synthesizing training data in RealESRNetModel ----------------- #
gt_usm: True  # USM the ground-truth

# the first degradation process
resize_prob: [0.2, 0.7, 0.1]  # up, down, keep
resize_range: [0.15, 1.5]
gaussian_noise_prob: 0.5
noise_range: [1, 30]
poisson_scale_range: [0.05, 3]
gray_noise_prob: 0.4
jpeg_range: [30, 95]

# the second degradation process
second_blur_prob: 0.8
resize_prob2: [0.3, 0.4, 0.3]  # up, down, keep
resize_range2: [0.3, 1.2]
gaussian_noise_prob2: 0.5
noise_range2: [1, 25]
poisson_scale_range2: [0.05, 2.5]
gray_noise_prob2: 0.4
jpeg_range2: [30, 95]

gt_size: 256
queue_size: 180

# dataset and data loader settings
datasets:
  train:
    name: DF2K+OST
    type: RealESRGANDataset
    dataroot_gt: /home/zxx/AF/expandAi/SESR/data/DIV2K/DIV2K_train_HR_Sub
    meta_info: /home/zxx/AF/expandAi/SESR/data/DIV2K/meta_info_DIV2K800sub_GT.txt
    io_backend:
      type: disk

    blur_kernel_size: 21
    kernel_list: ['iso', 'aniso', 'generalized_iso', 'generalized_aniso', 'plateau_iso', 'plateau_aniso']
    kernel_prob: [0.45, 0.25, 0.12, 0.03, 0.12, 0.03]
    sinc_prob: 0.1
    blur_sigma: [0.2, 3]
    betag_range: [0.5, 4]
    betap_range: [1, 2]

    blur_kernel_size2: 21
    kernel_list2: ['iso', 'aniso', 'generalized_iso', 'generalized_aniso', 'plateau_iso', 'plateau_aniso']
    kernel_prob2: [0.45, 0.25, 0.12, 0.03, 0.12, 0.03]
    sinc_prob2: 0.1
    blur_sigma2: [0.2, 1.5]
    betag_range2: [0.5, 4]
    betap_range2: [1, 2]

    final_sinc_prob: 0.8

    gt_size: 256
    use_hflip: True
    use_rot: False

    # data loader
    num_worker_per_gpu: 5
    batch_size_per_gpu: 12
    dataset_enlarge_ratio: 1
    prefetch_mode: ~

  # Uncomment these for validation
  # val:
  #   name: validation
  #   type: PairedImageDataset
  #   dataroot_gt: path_to_gt
  #   dataroot_lq: path_to_lq
  #   io_backend:
  #     type: disk

# network structures
network_g:
  type: RRDBNet
  num_in_ch: 3
  num_out_ch: 3
  num_feat: 64
  num_block: 23
  num_grow_ch: 32

# path
path:
  # pretrain_network_g: ~
  pretrain_network_g: /home/zxx/AF/expandAi/BasicSR/experiments/experiments/pretrained_models/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth
  param_key_g: params_ema
  strict_load_g: true
  resume_state: ~

# training settings
train:
  ema_decay: 0.999
  optim_g:
    type: Adam
    lr: !!float 2e-4
    weight_decay: 0
    betas: [0.9, 0.99]

  scheduler:
    type: MultiStepLR
    milestones: [1000000]
    gamma: 0.5

  total_iter: 1000000
  warmup_iter: -1  # no warm up

  # losses
  pixel_opt:
    type: L1Loss
    loss_weight: 1.0
    reduction: mean

# Uncomment these for validation
# validation settings
# val:
#   val_freq: !!float 5e3
#   save_img: True

#   metrics:
#     psnr: # metric name
#       type: calculate_psnr
#       crop_border: 4
#       test_y_channel: false

# logging settings
logger:
  print_freq: 100
  save_checkpoint_freq: !!float 5e3
  use_tb_logger: true
  wandb:
    project: ~
    resume_id: ~

# dist training settings
dist_params:
  backend: nccl
  port: 29500

如果需要验证看得分,就把valid取消注释。

然后下载和使用pre train模型:Real-ESRGAN/docs/Training_CN.md at master · xinntao/Real-ESRGAN · GitHub

这里面有,直接下载一下即可,当然不用也可以,就是拟合慢一些。pretrain_network_g改成自己的路径。打开上面的链接,教程训练。

然后训练完后,生成网络训练好了,就会在保存的路径里得到训好的pth,然后把这个pth路径复制一下,待会要训练gan了

第二步训练Real esrgan 对抗网络

  pretrain_network_g: /home/zxx/AF/expandAi/BasicSR/experiments/experiments/pretrained_models/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth

咱把刚刚训练好的net模型路径改掉我这个

然后可以不验证,验证就把div2k的lr hr都传进来。

完整的gan yml,大家改下路径即可:

# general settings
name: train_RealESRGANx4plus_400k_B12G4
model_type: RealESRGANModel
scale: 4
num_gpu: auto  # auto: can infer from your visible devices automatically. official: 4 GPUs
manual_seed: 0

# ----------------- options for synthesizing training data in RealESRGANModel ----------------- #
# USM the ground-truth
l1_gt_usm: True
percep_gt_usm: True
gan_gt_usm: False

# the first degradation process
resize_prob: [0.2, 0.7, 0.1]  # up, down, keep
resize_range: [0.15, 1.5]
gaussian_noise_prob: 0.5
noise_range: [1, 30]
poisson_scale_range: [0.05, 3]
gray_noise_prob: 0.4
jpeg_range: [30, 95]

# the second degradation process
second_blur_prob: 0.8
resize_prob2: [0.3, 0.4, 0.3]  # up, down, keep
resize_range2: [0.3, 1.2]
gaussian_noise_prob2: 0.5
noise_range2: [1, 25]
poisson_scale_range2: [0.05, 2.5]
gray_noise_prob2: 0.4
jpeg_range2: [30, 95]

gt_size: 256
queue_size: 180

# dataset and data loader settings
datasets:
  train:
    name: DF2K+OST
    type: RealESRGANDataset
    dataroot_gt: /home/zxx/AF/expandAi/SESR/data/DIV2K/DIV2K_train_HR_Sub
    meta_info: /home/zxx/AF/expandAi/SESR/data/DIV2K/meta_info_DIV2K800sub_GT.txt
    io_backend:
      type: disk

    blur_kernel_size: 21
    kernel_list: ['iso', 'aniso', 'generalized_iso', 'generalized_aniso', 'plateau_iso', 'plateau_aniso']
    kernel_prob: [0.45, 0.25, 0.12, 0.03, 0.12, 0.03]
    sinc_prob: 0.1
    blur_sigma: [0.2, 3]
    betag_range: [0.5, 4]
    betap_range: [1, 2]

    blur_kernel_size2: 21
    kernel_list2: ['iso', 'aniso', 'generalized_iso', 'generalized_aniso', 'plateau_iso', 'plateau_aniso']
    kernel_prob2: [0.45, 0.25, 0.12, 0.03, 0.12, 0.03]
    sinc_prob2: 0.1
    blur_sigma2: [0.2, 1.5]
    betag_range2: [0.5, 4]
    betap_range2: [1, 2]

    final_sinc_prob: 0.8

    gt_size: 256
    use_hflip: True
    use_rot: False

    # data loader
    num_worker_per_gpu: 5
    batch_size_per_gpu: 12
    dataset_enlarge_ratio: 1
    prefetch_mode: ~

  # Uncomment these for validation
  val:
    name: validation
    type: PairedImageDataset
    dataroot_gt: /home/zxx/AF/expandAi/SESR/data/DIV2K/DIV2K_valid_HR_Sub
    dataroot_lq: /home/zxx/AF/expandAi/SESR/data/DIV2K/DF2K_valid_LR_bicubic_X4_Sub
    io_backend:
      type: disk

# network structures
network_g:
  type: RRDBNet
  num_in_ch: 3
  num_out_ch: 3
  num_feat: 64
  num_block: 23
  num_grow_ch: 32

network_d:
  type: UNetDiscriminatorSN
  num_in_ch: 3
  num_feat: 64
  skip_connection: True

# path
path:
  # use the pre-trained Real-ESRNet model
  pretrain_network_g: /home/zxx/AF/expandAi/BasicSR/experiments/experiments/pretrained_models/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth
  param_key_g: params_ema
  strict_load_g: true
  resume_state: ~

# training settings
train:
  ema_decay: 0.999
  optim_g:
    type: Adam
    lr: !!float 1e-4
    weight_decay: 0
    betas: [0.9, 0.99]
  optim_d:
    type: Adam
    lr: !!float 1e-4
    weight_decay: 0
    betas: [0.9, 0.99]

  scheduler:
    type: MultiStepLR
    milestones: [400000]
    gamma: 0.5

  total_iter: 400000
  warmup_iter: -1  # no warm up

  # losses
  pixel_opt:
    type: L1Loss
    loss_weight: 1.0
    reduction: mean
  # perceptual loss (content and style losses)
  perceptual_opt:
    type: PerceptualLoss
    layer_weights:
      # before relu
      'conv1_2': 0.1
      'conv2_2': 0.1
      'conv3_4': 1
      'conv4_4': 1
      'conv5_4': 1
    vgg_type: vgg19
    use_input_norm: true
    perceptual_weight: !!float 1.0
    style_weight: 0
    range_norm: false
    criterion: l1
  # gan loss
  gan_opt:
    type: GANLoss
    gan_type: vanilla
    real_label_val: 1.0
    fake_label_val: 0.0
    loss_weight: !!float 1e-1

  net_d_iters: 1
  net_d_init_iters: 0

# Uncomment these for validation
# validation settings
val:
  val_freq: !!float 3e3
  save_img: True

  metrics:
    psnr: # metric name
      type: calculate_psnr
      crop_border: 4
      test_y_channel: false

# logging settings
logger:
  print_freq: 100
  save_checkpoint_freq: !!float 5e3
  use_tb_logger: true
  wandb:
    project: ~
    resume_id: ~

# dist training settings
dist_params:
  backend: nccl
  port: 29500

然后开始训练,训练就去改下路径即可

然后就可以开始训练了(训练net要一天,训练gan也是),训练gan的学习率很小,相当于简单finetune。

network_d:
  type: UNetDiscriminatorSN
  num_in_ch: 3
  num_feat: 64
  skip_connection: True

# path
path:
  # use the pre-trained Real-ESRNet model
  pretrain_network_g: /home/zxx/AF/expandAi/BasicSR/experiments/experiments/pretrained_models/ESRGAN_SRx4_DF2KOST_official-ff704c30.pth
  param_key_g: params_ema
  strict_load_g: true
  resume_state: ~

这里就是D模型,鉴别器:discrimination模型,不断的用鉴别器模型来判断生成的图像是不是真的,不是的话,就增加鉴别损失,最后把损失backward,激励生成模型继续优化。

然后默认是把pretrain_network_g的pth(刚刚训练好的net模型)放过来。

然后训练gan模型就是,用了lr比较小的,慢慢对抗训练

训练完后会得到gan的模型。也要一两天。大家感受下过程即可

finetune和生成退化数据

然后呢,前面提到,咱们real esrgan,你输入一张图,他可以给你输出一张LR图,你就可以得到训练数据了:HR是你原图,LR是gan退化出来的,这样搞个几百张即可训练。

那他是怎么生成退化数据的呢,因为他训练时,会不需要LR的,只需要你给他HR就能训练,咱们上面说过了对吧。

好,那么众所周知,训练超分必定是需要LR 和HR的,就算是real esrgan在线生成,也会生成,把这个结果保存出来即可。他放小、加噪声加模糊的图,就是退化图。

文档里有说怎么弄,应该是用更小学习率训练你的HR,然后保存中间结果做LR吧,也可能是直接网络推理,把中间的退化图保存。

然后我再basicsr里好像没找到怎么把退化的LR图像保存下来的接口?

那很简单,找源码:

如图,我们可以看到他是如何构造LR的,就是把HR拿下来,做一下resize、做一下随机加噪声、做一下随机模糊,然后就得到了小图,self.lq :

# clamp and round
            self.lq = torch.clamp((out * 255.0).round(), 0, 255) / 255.

            # random crop
            gt_size = self.opt['gt_size']
            (self.gt, self.gt_usm), self.lq = paired_random_crop([self.gt, self.gt_usm], self.lq, gt_size,
                                                                 self.opt['scale'])

            # training pair pool
            self._dequeue_and_enqueue()
            # sharpen self.gt again, as we have changed the self.gt with self._dequeue_and_enqueue
            self.gt_usm = self.usm_sharpener(self.gt)
            self.lq = self.lq.contiguous()  # for the warning: grad an

self.lq 是从out变量转来的,那我们看看退化过程,可以看到怎么加的噪声、模糊:

    @torch.no_grad()
    def feed_data(self, data):
        """Accept data from dataloader, and then add two-order degradations to obtain LQ images.
        """
        if self.is_train and self.opt.get('high_order_degradation', True):
            # training data synthesis
            self.gt = data['gt'].to(self.device)
            self.gt_usm = self.usm_sharpener(self.gt)

            self.kernel1 = data['kernel1'].to(self.device)
            self.kernel2 = data['kernel2'].to(self.device)
            self.sinc_kernel = data['sinc_kernel'].to(self.device)

            ori_h, ori_w = self.gt.size()[2:4]

            # ----------------------- The first degradation process ----------------------- #
            # blur
            out = filter2D(self.gt_usm, self.kernel1)
            # random resize
            updown_type = random.choices(['up', 'down', 'keep'], self.opt['resize_prob'])[0]
            if updown_type == 'up':
                scale = np.random.uniform(1, self.opt['resize_range'][1])
            elif updown_type == 'down':
                scale = np.random.uniform(self.opt['resize_range'][0], 1)
            else:
                scale = 1
            mode = random.choice(['area', 'bilinear', 'bicubic'])
            out = F.interpolate(out, scale_factor=scale, mode=mode)
            # add noise
            gray_noise_prob = self.opt['gray_noise_prob']
            if np.random.uniform() < self.opt['gaussian_noise_prob']:
                out = random_add_gaussian_noise_pt(
                    out, sigma_range=self.opt['noise_range'], clip=True, rounds=False, gray_prob=gray_noise_prob)
            else:
                out = random_add_poisson_noise_pt(
                    out,
                    scale_range=self.opt['poisson_scale_range'],
                    gray_prob=gray_noise_prob,
                    clip=True,
                    rounds=False)
            # JPEG compression
            jpeg_p = out.new_zeros(out.size(0)).uniform_(*self.opt['jpeg_range'])
            out = torch.clamp(out, 0, 1)  # clamp to [0, 1], otherwise JPEGer will result in unpleasant artifacts
            out = self.jpeger(out, quality=jpeg_p)

            # ----------------------- The second degradation process ----------------------- #
            # blur
            if np.random.uniform() < self.opt['second_blur_prob']:
                out = filter2D(out, self.kernel2)
            # random resize
            updown_type = random.choices(['up', 'down', 'keep'], self.opt['resize_prob2'])[0]
            if updown_type == 'up':
                scale = np.random.uniform(1, self.opt['resize_range2'][1])
            elif updown_type == 'down':
                scale = np.random.uniform(self.opt['resize_range2'][0], 1)
            else:
                scale = 1
            mode = random.choice(['area', 'bilinear', 'bicubic'])
            out = F.interpolate(
                out, size=(int(ori_h / self.opt['scale'] * scale), int(ori_w / self.opt['scale'] * scale)), mode=mode)
            # add noise
            gray_noise_prob = self.opt['gray_noise_prob2']
            if np.random.uniform() < self.opt['gaussian_noise_prob2']:
                out = random_add_gaussian_noise_pt(
                    out, sigma_range=self.opt['noise_range2'], clip=True, rounds=False, gray_prob=gray_noise_prob)
            else:
                out = random_add_poisson_noise_pt(
                    out,
                    scale_range=self.opt['poisson_scale_range2'],
                    gray_prob=gray_noise_prob,
                    clip=True,
                    rounds=False)

            # JPEG compression + the final sinc filter
            # We also need to resize images to desired sizes. We group [resize back + sinc filter] together
            # as one operation.
            # We consider two orders:
            #   1. [resize back + sinc filter] + JPEG compression
            #   2. JPEG compression + [resize back + sinc filter]
            # Empirically, we find other combinations (sinc + JPEG + Resize) will introduce twisted lines.
            if np.random.uniform() < 0.5:
                # resize back + the final sinc filter
                mode = random.choice(['area', 'bilinear', 'bicubic'])
                out = F.interpolate(out, size=(ori_h // self.opt['scale'], ori_w // self.opt['scale']), mode=mode)
                out = filter2D(out, self.sinc_kernel)
                # JPEG compression
                jpeg_p = out.new_zeros(out.size(0)).uniform_(*self.opt['jpeg_range2'])
                out = torch.clamp(out, 0, 1)
                out = self.jpeger(out, quality=jpeg_p)
            else:
                # JPEG compression
                jpeg_p = out.new_zeros(out.size(0)).uniform_(*self.opt['jpeg_range2'])
                out = torch.clamp(out, 0, 1)
                out = self.jpeger(out, quality=jpeg_p)
                # resize back + the final sinc filter
                mode = random.choice(['area', 'bilinear', 'bicubic'])
                out = F.interpolate(out, size=(ori_h // self.opt['scale'], ori_w // self.opt['scale']), mode=mode)
                out = filter2D(out, self.sinc_kernel)

推理

推理就很简单了,直接运行inference即可:

总结

Real eargan就这样,大家后续联系我给百度网盘给数据代码啥的。比较大,还没上传完。

联系cv君,zxx15277368495z

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2109352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【苍穹外卖】Day 7 缓存、购物车相关接口

1 缓存 存在问题&#xff1a; 用户端小程序展示的菜品数据都是通过査询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 >解决&#xff1a; 通过 Redis 来缓存菜品数据&#xff0c;减少数据库查询操作 缓存逻辑分析&#xff1a; 每个分…

PyDracula:用 PySide6 和 PyQt6打造现代感 Python GUI 的利器

PyDracula 是一个基于 PySide6 或 PyQt6 的 Python GUI 库&#xff0c;它以其现代、美观、易于定制的特点而闻名。PyDracula 融合了流行的 Dracula 主题&#xff0c;并提供了丰富的功能&#xff0c;让开发者可以轻松构建出具有吸引力的图形界面。本文将详细介绍 PyDracula 的核…

【Godot4.3】CanvasShape资源化改造

概述 通过把之前自定义的CanvasShape类变成资源类型&#xff0c;将可以同时用于CanvasItem绘图和创建扩展的Node2D和Polygon2D节点等。 本篇就完成CanvasShape类的资源化改造&#xff0c;并记录改造过程和思路。 CanvasShape资源类型体系 CanvasShape仍然为图形基类&#xf…

Android Auto未来可能支持无线电广播

通过Android Auto&#xff0c;可以在车载收音机上使用 Google 地图、音乐、收听播客&#xff0c;还能获取天气等基本信息。最近&#xff0c;国外科技媒体9to5Google通过分析 Android Auto v12.3 和 v12.4的应用程序的代码发现了一些提示信息&#xff0c;特别提到了 AM、FM、HD …

【Protobuf】xml、json与protobuf有什么区别,protobuf详解(保姆篇)

文章目录 简介Protobuf 的原理安装 Protobuf 编译器在 Python 中使用 Protobuf安装语言特定的 Protobuf 库定义消息结构生成代码使用 Protobuf 进行序列化和反序列化 在 Java 中使用 Protobuf安装和配置编译 .proto 文件使用生成的 Java 类创建和序列化对象 代码注释 高级特性嵌…

LabVIEW灵活集成与调试的方法

在LabVIEW开发中&#xff0c;为了构建一个既便于调试又能灵活集成到主VI中的控制VI&#xff0c;开发者需要采用适当的编程方式和架构。常见的选择包括模块化设计、状态机架构以及事件驱动编程。这些方法有助于简化调试过程、提高系统的稳定性&#xff0c;并确保代码的重用性和可…

day43-测试平台搭建之前端vue学习-基础2

目录 一、数据代理 二、事件处理 三、计算属性 四、监控属性 五、绑定样式 六、今日学习思维导图 一、数据代理 1.1.数据代理&#xff1a;通过一个对象代理对另外一个对象中属性的操作 (读/写) 1.2.Vue中数据代理的好处&#xff1a;更加方便的操作data中的数据 1.3.基本原…

vue2结合element-ui使用tsx格式实现formily自定义组件

简洁 在公司实习&#xff0c;需要参与开发一个基于formily的低代码平台&#xff0c;实现自定义formily组件&#xff0c;在此记录一下。 示例源码 demo源码 实现思路 开始实现自定义组件之前最好先看一下formily官网的core、vue、element部分&#xff0c;如果有能力也可以阅…

2024数学建模国赛A题word版成品论文30页【附带完整解题代码+可视化图表】

0906 0:30 v1.0 问题一、问题二的完整可运行代码&#xff0c;模型建立与求解这一部分的论文。 0906 5:20 v1.1 增加了第三问的完整可运行代码和第二、三问的“模型建立与求解”的论文。&#xff08;即1-3问的代码、模型建立与求解、算法设计、结果分析&#xff09; 1-4问完整可…

TensorFlow创建回归神经网络及Optimizer优化器

一.TensorFlow创建神经层 如图所示&#xff0c;通过该神经网络识别动物猫或狗&#xff0c;共包括输入层&#xff08;Input Layer&#xff09;、隐藏层3层&#xff08;Hidden Layer&#xff09;和输出层&#xff08;Output Layer&#xff09;。其中每个隐藏层神经元都有一个激励…

Unity(2022.3.41LTS) - UI详细介绍- 原始图像

目录 零.简介 一、基本功能 二、属性和设置 三、与其他 UI 元素的配合 四、代码控制 六. 和 image的区别 零.简介 在 Unity 中&#xff0c;RawImage 是一种用于显示原始图像的 UI 组件。 一、基本功能 显示图像&#xff1a;RawImage 主要用于在 UI 中直接显示一张图像。…

Python数组遍历-从基础到高级的全面指南

你有没有想过,为什么有些程序员能够轻松地操纵大量数据,而其他人却在简单的数组操作上挣扎?答案往往藏在一个看似简单却至关重要的技能中:数组遍历。无论你是刚入门的新手,还是寻求提升的老手,掌握Python中的数组遍历技巧都将极大地提升你的编程效率和代码质量。 在这篇文章中…

使用 systemd-analyze 分析 Linux 系统启动慢的原因

使用 systemd-analyze 命令可以查看 Linux 系统在启动过程中每个服务的耗时情况, 方便我们排查是哪个环节导致系统启动缓慢, 以下是整理的常用命令参数和效果. 例子中一下子就可以定位到是 gssproxy.service 服务启动耗时过长. systemd-analyze blame Print list of running u…

LabVIEW如何自学成为专业开发者

自学成为LabVIEW专业开发者需要一个系统化的学习和实践过程&#xff0c;以下是一些关键步骤&#xff1a; 1. 扎实的基础学习 了解LabVIEW的基础概念&#xff1a;首先要熟悉LabVIEW的基本操作、数据流编程理念和图形化编程环境。可以通过LabVIEW的官方教程、Bilibili上的视频课程…

【舞动生命,不缺营养!】亨廷顿舞蹈症患者的维生素补给站

Hey小伙伴们~ &#x1f44b; 今天我们要聊的是一个温暖而重要的话题——关于亨廷顿舞蹈症&#xff08;HD&#xff09;患者如何通过合理补充维生素&#xff0c;来更好地支持他们的健康与生活品质&#xff01;&#x1f31f; &#x1f338; ‌首先&#xff0c;了解亨廷顿舞蹈症‌…

TCP的传输速度

如何确定TCP最大传输速度&#xff1f; TCP 的传输速度&#xff0c;受限于发送窗⼝&#xff0c;接收窗⼝以及⽹络设备传输能⼒。 其中&#xff0c;窗⼝⼤⼩由内核缓冲区⼤⼩决定。如果缓冲区与⽹络传输能⼒匹配&#xff0c;那么缓冲区的利⽤率就达到了最⼤化。 如何计算网络传…

JAVA:Spring Boot 整合 Swagger 的技术指南

请关注微信公众号&#xff1a;拾荒的小海螺 博客地址&#xff1a;http://lsk-ww.cn/ 1、简述 在现代Web开发中&#xff0c;API文档的生成和维护是非常重要的。Swagger是一款流行的API文档生成工具&#xff0c;它可以帮助开发者自动生成API文档&#xff0c;并提供可视化的接口…

Redis从简单使用到底层原理与分布式缓存

文章目录 [Redis参考手册](https://redis.io/docs/latest/commands/)1 基础认识1.1 安装配置1.2 通用命令1.3 数据类型1.3.1 数据结构与内部编码stringkey的结构hashlistsetsorted_set 1.4 单线程模型 2 redis客户端2.1 RESP协议&#xff08;Redis serialization protocol&…

SpringBoot2:请求处理原理分析-接口参数的常用注解

1、PathVariable 作用说明&#xff1a;获取路径参数 案例&#xff1a; 接口收参形式&#xff1a; GetMapping("/car/{id}/owner/{username}")public Map<String,Object> getCar(PathVariable("id") Integer id,PathVariable("username")…

echarts圆饼图定时器动画

(function () {const WdxjEcharts echarts.init(document.getElementById(wdxjEchart))let num 0;var imgURL "../imagesNew/wd-center.png";var trafficWay [{name: 火车,value: 20}, {name: 飞机,value: 10}, {name: 客车,value: 30}, {name: 轮渡,value: 40}]…