• 媒体生成
  • 计算机视觉
  • 深度学习
  • 人工智能
  • 大模型

【免费下载链接】mmagic

OpenMMLab Multimodal Advanced, Generative, and Intelligent Creation Toolbox. Unlock the magic 🪄: Generative-AI (AIGC), easy-to-use APIs, awsome model zoo, diffusion models, for text-to-image generation, image/video restoration/enhancement, etc.

项目地址: https://gitcode.com/gh_mirrors/mm/mmagic
点击查看 免费下载

本指南以 OpenMMLab MMagic 仓库中的 RealBasicVSR(CVPR'2022)实现为主线,系统讲解真实世界视频超分辨率(Real-World Video Super-Resolution)所面临的两大权衡(长期传播带来的伪影放大、训练代价带来的速度/性能权衡),并完整拆解仓库内两套官方配置:无 GAN 的第一阶段训练配置与带感知/对抗损失的第二阶段微调配置。读完本文,你将掌握 RealBasicVSR 的网络结构(图像清洗模块 + BasicVSR 传播主干)、随机退化(stochastic degradation)数据增强流水线的每个环节、tools/train.py / tools/test.py 的 CPU/单卡/多卡训练与测试方法,以及如何在 VideoLQ、REDS、UDM10 数据集上复现官方结果。

算法背景:为什么要为真实世界 VSR 引入"图像预清洗"

RealBasicVSR 论文《RealBasicVSR: Investigating Tradeoffs in Real-World Video Super-Resolution》发表于 CVPR'2022,其核心观察是:真实世界的视频退化(degradation)具有极大的多样性与复杂性,给训练和推理都带来了不小的挑战(见 configs/real_basicvsr/README.md 的 Abstract)。

从源码结构看,这个观察直接映射到了网络设计上:在 real_basicvsr_net.py 中,RealBasicVSRNet 由两个子模块串联组成——

  1. 图像清洗模块(image cleaning module):ResidualBlocksWithInputConv(3, mid_channels, num_cleaning_blocks) 再接一个 nn.Conv2d(mid_channels, 3, 3, 1, 1),作用是在传播之前先行降低噪声与伪影;
  2. BasicVSR 传播主干:直接复用 BasicVSRNet(mid_channels, num_propagation_blocks, spynet_pretrained),其中 SPyNet 光流网络权重被固定(requires_grad_(False)),仅作为运动估计的先验(见 basicvsr_net.py 中的 ResidualBlocksWithInputConv 与 SPyNet 定义)。

论文的核心论点在配置和源码中均有体现:

  • 长期传播的两面性:轻度退化下,长期传播能显著提升性能;但面对严重的真实世界退化,传播会放大伪影、损害输出质量。因此必须在传播之前加一个预清洗阶段来抑制噪声与伪影——这正是 image_cleaning 模块存在的原因。
  • 训练代价问题:为了提升泛化性,真实世界 VSR 模型常用多样化退化来训练,需要增大 batch size 以获得稳定梯度,从而带来 1) 速度-性能权衡、2) 序列长度-批量大小权衡。论文提出随机退化方案(stochastic degradation scheme),可减少最多 40% 的训练时间而不牺牲性能;并建议训练时使用更长的序列而非更大的 batch,以更有效地利用时序信息、获得更稳定的推理表现。
  • VideoLQ 数据集:为公平比较,论文提出包含大量真实世界低质量视频序列的 VideoLQ 数据集,本仓库的测试配置即默认在该数据集上评估(见下文数据准备小节)。

两阶段训练策略:先无 GAN 训练,再感知/对抗微调

仓库内 configs/real_basicvsr/ 目录下提供两套配置,对应官方推荐的两阶段训练流程(见 README_zh-CN.md):

  1. 第一阶段(无 GAN):使用 realbasicvsr_wogan-c64b20-2x30x8_8xb2-lr1e-4-300k_reds.py 训练一个不含感知损失和对抗性损失的模型(仅像素损失 + 清洗损失),共 300k iterations;
  2. 第二阶段(GAN 微调):以第一阶段权重为起点,使用 realbasicvsr_c64b20-1x30x8_8xb1-lr5e-5-150k_reds.py 加入感知损失与对抗性损失进行微调,共 150k iterations。

从配置继承关系可以清晰看到这一点:第二阶段的配置文件首行即为 _base_ = './realbasicvsr_wogan-c64b20-2x30x8_8xb2-lr1e-4-300k_reds.py',整体继承第一阶段的网络、数据流水线与数据加载器,仅在模型损失、优化器和训练轮数上做增量覆盖;文件内还保留了注释掉的 load_from 字段,指向第一阶段训练出的官方 checkpoint,用于作为微调起点(使用者取消注释并填入本地路径即可)。

此外,README_zh-CN.md 特别提示:可以先把图像裁剪成子图像以加快 IO,具体做法参见 preprocess_reds_dataset.py——这也是 train_dataloader 中 data_prefix=dict(img='train_sharp_sub', gt='train_sharp_sub') 使用 _sub 子图目录的原因。

配置文件深度解析(一):网络结构与损失设计

以第二阶段配置 realbasicvsr_c64b20-1x30x8_8xb1-lr5e-5-150k_reds.py 为例,model 字段完整定义了生成器、判别器与全部损失:

model = dict(
    type='RealBasicVSR',
    generator=dict(
        type='RealBasicVSRNet',
        mid_channels=64,
        num_propagation_blocks=20,
        num_cleaning_blocks=20,
        dynamic_refine_thres=255,  # change to 5 for test
        spynet_pretrained='https://download.openmmlab.com/mmediting/restorers/'
        'basicvsr/spynet_20210409-c6c1bd09.pth',
        is_fix_cleaning=False,
        is_sequential_cleaning=False),
    discriminator=dict(
        type='UNetDiscriminatorWithSpectralNorm',
        in_channels=3,
        mid_channels=64,
        skip_connection=True),
    pixel_loss=dict(type='L1Loss', loss_weight=1.0, reduction='mean'),
    cleaning_loss=dict(type='L1Loss', loss_weight=1.0, reduction='mean'),
    perceptual_loss=dict(
        type='PerceptualLoss',
        layer_weights={
            '2': 0.1,
            '7': 0.1,
            '16': 1.0,
            '25': 1.0,
            '34': 1.0,
        },
        vgg_type='vgg19',
        perceptual_weight=1.0,
        style_weight=0,
        norm_img=False),
    gan_loss=dict(
        type='GANLoss',
        gan_type='vanilla',
        loss_weight=5e-2,
        real_label_val=1.0,
        fake_label_val=0),
    is_use_sharpened_gt_in_pixel=True,
    is_use_sharpened_gt_in_percep=True,
    is_use_sharpened_gt_in_gan=False,
    is_use_ema=True,
    data_preprocessor=dict(
        type='DataPreprocessor',
        mean=[0., 0., 0.],
        std=[255., 255., 255.],
    ))

各关键字段的作用如下:

字段取值含义
typeRealBasicVSR顶层模型类型,注册于 mmagic/models/editors/real_basicvsr/real_basicvsr.py,继承自 RealESRGAN
mid_channels64中间特征通道数,清洗模块与传播模块共享
num_propagation_blocks20BasicVSR 每个传播分支的残差块数量
num_cleaning_blocks20图像清洗模块中残差块数量
dynamic_refine_thres255(训练)/ 5 或 1.5(测试)动态清洗停止阈值,源码中会除以 255 归一化;配置注释明确提示"测试时改为 5"(第一阶段配置注释为"改为 1.5"),见 real_basicvsr_net.py
is_fix_cleaningFalse是否固定清洗模块权重不参与训练
is_sequential_cleaningFalse是否逐帧顺序清洗(节省显存但稍慢)
pixel_lossL1Loss,权重 1.0像素级重建损失
cleaning_lossL1Loss,权重 1.0图像清洗模块的监督损失
perceptual_lossPerceptualLoss(vgg19)感知损失,指定 vgg19 的 2/7/16/25/34 层权重,style_weight=0 即关闭风格项
gan_lossGANLoss(vanilla)对抗损失,损失权重 5e-2,仅作用于生成器
is_use_sharpened_gt_in_*True/True/False是否用反锐化掩膜(unsharp masking)后的 GT 分别作为像素、感知、对抗损失的监督目标
is_use_emaTrue使用指数移动平均维护生成器 EMA 权重
data_preprocessormean=0,std=255输入归一化方式,等价于除以 255 缩放到 [0,1]

优化器与训练循环

第二阶段配置使用 MultiOptimWrapperConstructor 分别管理生成器与判别器的优化器,这也是 GAN 训练的标准做法:

optim_wrapper = dict(
    _delete_=True,
    constructor='MultiOptimWrapperConstructor',
    generator=dict(
        type='OptimWrapper',
        optimizer=dict(type='Adam', lr=5e-5, betas=(0.9, 0.99))),
    discriminator=dict(
        type='OptimWrapper',
        optimizer=dict(type='Adam', lr=1e-4, betas=(0.9, 0.99))),
)

train_cfg = dict(
    type='IterBasedTrainLoop', max_iters=150_000, val_interval=5000)

生成器学习率 5e-5、判别器学习率 1e-4,二者均使用 Adam(beta=(0.9, 0.99));训练按 iteration 计数,共 150k 步,每 5k 步验证一次。第一阶段配置则只优化生成器(Adam, lr=1e-4),且显式注释"NO learning policy",即全程不使用学习率调度。

EMA 与检查点

第一阶段配置(被第二阶段继承)在 default_hooks 中定义了检查点保存策略:每 5000 iteration 保存一次、save_best='PSNR' 且 rule='greater';同时通过 custom_hooks 注册 ExponentialMovingAverageHook(module_keys=('generator_ema'),momentum=0.001,每步更新),并在 model_wrapper_cfg 中使用 MMSeparateDistributedDataParallel 包装模型(broadcast_buffers=False、find_unused_parameters=False),适配生成器/判别器分离优化的分布式训练场景。

配置文件深度解析(二):随机退化数据增强流水线

真实世界 VSR 训练的关键在于模拟真实退化。第一阶段配置的 train_pipeline 完整实现了论文提出的随机退化方案,全过程如下:

  1. 序列采样与加载:GenerateSegmentIndices(interval_list=[1])生成连续帧索引;LoadImageFromFile 以 RGB 顺序加载 GT 帧。
  2. 空间增强:FixedCrop 裁剪到 256×256;水平/垂直 Flip(各 0.5 概率);RandomTransposeHW 转置 H/W(0.5 概率);MirrorSequence 镜像序列以增广时序。
  3. 反锐化掩膜生成 GT:UnsharpMasking(kernel_size=51,sigma=0,weight=0.5,threshold=10)生成 gt_unsharp,再由 CopyValues 将其复制为 img——即把锐化后的图像当作后续退化的输入,这与模型配置中 is_use_sharpened_gt_in_pixel=True 相呼应。
  4. 第一轮随机退化(核心退化强度大):
    • RandomBlur:核尺寸 7~21,核类型含 iso/aniso/generalized_iso/generalized_aniso/plateau_iso/plateau_aniso/sinc 共 7 种,核概率 [0.405, 0.225, 0.108, 0.027, 0.108, 0.027, 0.1],sigma_x/sigma_y 范围 [0.2, 3];
    • RandomResize:resize_mode_prob=[0.2, 0.7, 0.1](放大/缩小/保持),缩放因子 [0.15, 1.5],插值方式 bilinear/area/bicubic 等概率;
    • RandomNoise:高斯噪声 sigma [1, 30] 与泊松噪声 scale [0.05, 3] 各 0.5 概率,灰度噪声概率 0.4;
    • RandomJPEGCompression:质量因子 [30, 95],步长 3;
    • RandomVideoCompression:libx264/h264/mpeg4 三种编码器等概率,码率 [1e4, 1e5]。
  5. 第二轮随机退化(强度稍低):重复一轮模糊(prob=0.8、sigma [0.2, 1.5])、缩放([0.3, 1.2])、噪声(sigma [1, 25])、JPEG 压缩,模拟"二次退化"的真实场景。
  6. 退化打乱与极端组合:DegradationsWithShuffle 将视频压缩与另一组退化(缩放到 64×64 + sinc 核模糊)以随机顺序/随机选择的方式组合,增加退化多样性。
  7. 收尾:Clip 将像素裁剪到合法范围,PackInputs 打包成模型输入。

从源码角度看,这套流水线的设计意图与论文"用随机退化提升泛化性"的主张完全一致:每一轮退化都从宽泛的参数区间内随机采样,且两轮退化的强度分布刻意错开,使网络见到从轻微到极端的连续退化谱。

验证与测试流水线

  • val_pipeline:在 UDM10 上验证,filename_tmpl='{:04d}.png',直接加载 LQ(BIx4)与 GT;
  • test_pipeline:在 VideoLQ 上测试,filename_tmpl='{:08d}.png';
  • demo_pipeline:推理演示用,仅需 img 键。

验证与测试的评估器不同:val_evaluator 使用 PSNR/SSIM(监督指标),test_evaluator 使用 NIQE(无参考指标,input_order='CHW'、convert_to='Y'),对应 README 中"在 Y 通道上评估"的说明。

网络实现原理:清洗模块与动态清洗阈值

深入 real_basicvsr_net.py 可以看到 RealBasicVSRNet 的关键实现逻辑:

  • 构造时 self.dynamic_refine_thres = dynamic_refine_thres / 255.,把配置中的整数阈值归一化到 [0,1] 区间;
  • forward 中最多执行 3 轮清洗(for _ in range(0, 3),论文经验值),每轮把残差加回 LQ 图像(lqs = lqs + residues),并用 torch.mean(torch.abs(residues)) < self.dynamic_refine_thres 判断是否提前停止——当残差足够小时说明清洗已收敛;
  • 清洗支持两种模式:is_sequential_cleaning=True 时逐帧顺序清洗(省显存、略慢);默认 False 时先把 (n, t, c, h, w) 展平为 (n*t, c, h, w) 一次性批量清洗(更快);
  • 清洗完成后再送入 self.basicvsr(lqs) 做 4 倍超分(源码注释明确"Support only x4 upsampling")。

顶层模型 RealBasicVSR(见 real_basicvsr.py)继承自 RealESRGAN,并额外引入 cleaning_loss:训练时生成器以 return_lqs=True 前向,同时输出超分结果与清洗后的 LQ;g_step 中除常规像素/感知/对抗损失外,还计算 cleaning_loss(fake_g_lq, gt_clean)。其中 gt_clean 由 extract_gt_data 通过 F.interpolate(scale_factor=0.25, mode='area') 对 GT 做 4 倍面积下采样得到——即用 GT 的 1/4 分辨率版本监督清洗模块,语义上与"清洗到与退化前一致"的目标对齐。

仓库还配套了两个单元测试:test_real_basicvsr.py 与 test_real_basicvsr_net.py,分别验证顶层模型的训练/推理流程与网络前向/清洗逻辑,可作为理解实现细节与自行修改后的回归测试参考。

数据准备

训练与评估共涉及三个数据集(见 realbasicvsr_wogan-c64b20-2x30x8_8xb2-lr1e-4-300k_reds.py 中的 data_root = 'data'):

数据集路径用途配置要点
REDSdata/REDS训练train_sharp_sub 子图目录,num_input_frames=15,batch_size=2(第一阶段)/1(第二阶段),InfiniteSampler 无限采样
UDM10data/UDM10验证data_prefix=dict(img='BIx4', gt='GT'),评估 PSNR/SSIM
VideoLQdata/VideoLQ测试论文提出的真实低质量视频集,评估 NIQE

BasicFramesDataset 的 metainfo 分别标注 dataset_type='reds'/'udm10'/'video_lq' 与 task_name='vsr'。训练数据默认期望已经预处理成子图(REDS 的 _sub 目录),预处理脚本为 preprocess_reds_dataset.py;如需了解数据目录的通用准备步骤,可参考文档 docs/en/user_guides/train_test.md 或中文版 docs/zh_cn/user_guides/train_test.md。

结果与模型

官方模型在 Y 通道上评估;其中 NRQM、NIQE、PI 使用 PIRM2018 提供的代码计算,BRISQUE 使用 MATLAB 官方代码计算(详见 configs/real_basicvsr/README.md)。

模型数据集NRQM (Y)NIQE (Y)PI (Y)BRISQUE (Y)训练资源
realbasicvsr_c64b20_1x30x8_lr5e-5_150k_redsREDS6.04773.76623.859329.0308×Tesla V100-SXM2-32GB
realbasicvsr_wogan-c64b20-2x30x8_8xb2-lr1e-4-300k_redsREDS----8×Tesla V100-SXM2-32GB

完整模型与训练日志的下载链接见上述 README 文档中的表格(模型 checkpoint 文件名分别为 realbasicvsr_c64b20_1x30x8_lr5e-5_150k_reds_20211104-52f77c2c.pth 与 realbasicvsr_wogan_c64b20_2x30x8_lr1e-4_300k_reds_20211027-0e2ff207.pth,在测试命令中可直接作为权重参数传入)。注意:第二阶段模型正是第一阶段模型的微调产物,其指标(NRQM/NIQE/PI/BRISQUE)即为 README 表格中的完整结果。

快速开始:训练与测试

训练

以下命令训练第二阶段 GAN 模型(第一阶段训练把命令中的配置换成 realbasicvsr_wogan-c64b20-2x30x8_8xb2-lr1e-4-300k_reds.py 即可):

# CPU 训练
CUDA_VISIBLE_DEVICES=-1 python tools/train.py configs/real_basicvsr/realbasicvsr_c64b20-1x30x8_8xb1-lr5e-5-150k_reds.py

# 单 GPU 训练
python tools/train.py configs/real_basicvsr/realbasicvsr_c64b20-1x30x8_8xb1-lr5e-5-150k_reds.py

# 多 GPU 训练(8 卡)
./tools/dist_train.sh configs/real_basicvsr/realbasicvsr_c64b20-1x30x8_8xb1-lr5e-5-150k_reds.py 8

训练入口为 tools/train.py,多卡脚本为 tools/dist_train.sh。更详细的训练配置说明(如数据集准备、batch size 调整、断点续训等)可参考 docs/en/user_guides/train_test.md 或 docs/zh_cn/user_guides/train_test.md。

测试

测试命令需要传入配置与预训练权重(将 <模型权重路径> 替换为上文提到的官方 checkpoint 文件或本地训练权重):

# CPU 测试
CUDA_VISIBLE_DEVICES=-1 python tools/test.py configs/real_basicvsr/realbasicvsr_c64b20-1x30x8_8xb1-lr5e-5-150k_reds.py <模型权重路径>

# 单 GPU 测试
python tools/test.py configs/real_basicvsr/realbasicvsr_c64b20-1x30x8_8xb1-lr5e-5-150k_reds.py <模型权重路径>

# 多 GPU 测试(8 卡)
./tools/dist_test.sh configs/real_basicvsr/realbasicvsr_c64b20-1x30x8_8xb1-lr5e-5-150k_reds.py <模型权重路径> 8

测试入口为 tools/test.py,多卡脚本为 tools/dist_test.sh。测试前请务必按配置注释将 generator.dynamic_refine_thres 从训练值(255)调整为测试值(配置注释分别给出 5 与 1.5 两个参考值),否则动态清洗的停止条件在推理时会与训练语义不一致。

引用

若你的工作使用了 RealBasicVSR 或其 MMagic 实现,请按如下方式引用原论文:

@InProceedings{chan2022investigating,
  author = {Chan, Kelvin C.K. and Zhou, Shangchen and Xu, Xiangyu and Loy, Chen Change},
  title = {RealBasicVSR: Investigating Tradeoffs in Real-World Video Super-Resolution},
  booktitle = {Proceedings of the IEEE conference on computer vision and pattern recognition},
  year = {2022}
}

小结:RealBasicVSR 在 MMagic 中的落地可以概括为一条清晰的链路——先用随机退化流水线在 REDS 上训练"像素损失 + 清洗损失"的基础模型,再用感知/对抗损失微调出最终模型;推理时,图像清洗模块以动态阈值决定清洗轮数,随后由 BasicVSR 主干完成 4 倍超分。理解这一链路(两阶段配置的继承关系、退化流水线的参数区间、dynamic_refine_thres 的训练/测试差异),即可在真实世界的低质量视频上复现官方结果,并进一步改造网络或流水线以满足自定义场景。

  • 媒体生成
  • 计算机视觉
  • 深度学习
  • 人工智能
  • 大模型

【免费下载链接】mmagic

OpenMMLab Multimodal Advanced, Generative, and Intelligent Creation Toolbox. Unlock the magic 🪄: Generative-AI (AIGC), easy-to-use APIs, awsome model zoo, diffusion models, for text-to-image generation, image/video restoration/enhancement, etc.

项目地址: https://gitcode.com/gh_mirrors/mm/mmagic
点击查看 免费下载
Logo

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。

更多推荐