资讯动态

ESRGAN实战指南:从解压、训练到调参的完整超分落地

发布时间:2026/9/26 5:12:30 来源:尧图企业网站定制
简介这是一份基于增强超分辨率生成对抗网络ESRGAN的图像超分项目压缩包面向计算机视觉学习者和深度学习实践者重点解决低分辨率图像细节不足、画质模糊等问题也可支撑退化图像修复和水印相关处理的扩展研究。压缩包共28个文件大小约9.16MB包含源码脚本、预训练模型目录、多组超分对比样张、动态演示图以及说明文档和质量问答文档目录按代码、模型、结果三块组织结构简明。目前已有205人学习/下载通过源码和示例图能直观观察超分前后画质变化理解残差密集块、感知损失与生成对抗训练等关键设计并参照文档完成环境配置、模型加载和自定义图片推理。包内测试图涵盖真实照片、卡通漫画与动物样张等类型适合快速复现经典超分算法也适合对比不同退化程度下的增强效果对准备入门图像复原或希望基于现有代码做二次实验的读者是一份上手门槛较低的实用资源。1. ESRGAN 的 master.zip 包先分清你手里的是「能跑」还是「能训」从网上下到的 ESRGAN-master 这个 zip 包不是解压完就能出好看图的。我见过太多人卡在同一处压缩包打开了目录也齐了跑 test.py 却报错或者出来的图糊成一片。这个包要真正发挥价值得先分清两件事你只是想把老照片放大四倍还是要拿自己的数据重新训练一个超分模型。前者半小时能跑通后者要从数据配队开始重来。这篇就顺着 ESRGAN 标题背后最常见的落地路径往下走解压、推理、造数据、训练、调参、查坑每一步给你能直接抄的写法。2. 从 zip 包到第一次推理目录确认、权重补齐与最小测试2.1 解压后先确认这四样东西目录结构、权重、测试脚本、依赖文件拿到 ESRGAN-master.zip 第一件事不是双击解压而是先看压缩包里有没有被人二次打包过。GitHub 上直接 Download ZIP 下来的包通常根目录就是一个ESRGAN-master文件夹里面是代码、模型定义、README。但网上下载的「整合包」「waterpck 包」经常套了两层目录解压出来一个 zip 套一个 zip或者带中文文件名导致解压工具罢工。我一般先用 7-Zip 打开压缩包看一遍顶层结构确认不是伪加密或嵌套包再解压。# 在 Linux/macOS 下解压并查看目录树 unzip ESRGAN-master.zip -d ./ESRGAN cd ESRGAN tree -L 2解压后你要在目录里找四样东西模型定义文件常见为RRDBNet相关的 .py、训练/测试入口脚本常见名train.py、test.py、预训练权重.pth文件通常在 release 页面单独下载或放在experiments/pretrained_models/下、requirements 或 README 里的依赖清单。tree -L 2只显示两层目的是快速判断代码和权重放在哪不用一头扎进细节。如果解压时报「数据错误」或提示需要密码先别急着删包后面避坑部分会讲怎么救回这种包。2.2 跑通 test.py 的最小推理命令与四个入参ESRGAN 这类项目的最小推理入口通常叫test.py或inference.py参数风格因打包者而异。你先把目录里所有顶层.py文件列出来找到名字里带test、infer、demo的那个然后执行python test.py \ --input_dir ./demo/LR \ --output_dir ./results \ --model_name RRDB_ESRGAN_x4.pth \ --scale 4这个命令的意思是把demo/LR文件夹里的低分辨率图用RRDB_ESRGAN_x4.pth这个权重放大 4 倍结果写到results目录。--input_dir是输入目录而非单张图片大多数实现会递归读取目录下所有图片--output_dir不存在时脚本会自动创建--model_name要写权重文件的名字而不是绝对路径因为脚本会去固定目录常见是experiments/pretrained_models里找--scale 4是放大倍数ESRGAN 官方权重大多训在 4 倍上填 2 或 1 时个别模型会因网络结构不支持而报错。跑之前先确认 PyTorch 装好了版本在 1.x 范围内基本都能跑太新的 2.x 遇到旧代码偶尔要改一行torch.load的map_location。我的习惯是先建一个干净的虚拟环境再装依赖不要直接往系统 Python 里灌包超分项目依赖的 OpenCV、numpy、torch 版本纠缠起来非常头疼。2.3 权重文件缺失时别慌PSNR 模型兜底GAN 模型出效果ESRGAN 的核心不是代码是那两个.pth权重。很多人解压代码包发现里面没有权重以为包坏了其实权重通常单独放在 release 资产里。常见权重有两类一类是 PSNR 取向的预训练模型输出干净平滑几乎没有伪影适合做人像、文字、印刷品放大另一类是 GAN 取向的最终模型纹理细节更丰富但放大低质量图片时容易产生油画感假纹理。如果你的包里只找到了带PSNR字样的权重不要觉得低人一等。第一次跑通流程、验证输入输出格式用 PSNR 模型更稳GAN 权重在 CPU 上跑一张 512 的图可能要几分钟。等整条链路没问题了再换成 GAN 权重看效果差异。判断权重是否匹配网络结构看num_block和num_feat两个参数ESRGAN 常用的 RRDB 结构是 23 个残差块、64 个特征通道导入时报 shape 不匹配就说明权重和网络对不上。# 用 torch 快速检查权重文件能否加载避免推理到一半才报错 import torch ckpt torch.load(RRDB_ESRGAN_x4.pth, map_locationcpu) # 这一步成功说明文件不是损坏的再打印 key 数量核对结构 print(len(ckpt.keys()) if isinstance(ckpt, dict) else loaded)map_locationcpu是关键很多机器没配 CUDA 或驱动版本不对不写这句直接默认加载到 GPU会报AssertionError: Torch not compiled with CUDA enabled。这一步是黑匣子检查不通过就别往下跑了。3. 造数据HR/LR 配对与 patch 切图训练上限在这一步决定3.1 为什么 ESRGAN 训练必须吃 HR/LR 配对而不是一张原图ESRGAN 是一个有监督的超分模型训练时每次给网络看一对图一张高分辨率原图HR和一张由它降采样得到的低分辨率图LR。网络的任务是学会从 LR 复原出接近 HR 的细节。所以只丢一堆 JPG 进去是训不出来的你得先把数据切成对。降采样方式直接决定模型能力。官方训练用的退化模型是 bicubic 4 倍下采样模型学会的也是「把模糊的图变清晰」如果你要处理的是老照片、扫描件、压缩视频帧它们的退化不是纯 bicubic 那么简单常见的做法是加一点高斯模糊、JPEG 压缩噪声再降采样让 LR 更接近真实劣化。这就是网上说的「真实退化」也是很多人训完自己数据觉得效果不如官方模型的原因——不是网络问题是数据配队没对齐。一个可复现的做法是把数据集分成两路干净图库走 bicubic 降采样真实老照片走「模糊 降采样 JPEG 压缩」管线。两条路径合在一起训练模型既保清晰度又抗噪。注意 HR 和 LR 的命名要一一对应训练脚本读目录时就是靠文件名匹配的对不上会直接报错或静默跳过。3.2 从任意大图切 patch尺寸、步长、边界怎么设ESRGAN 训练时不吃整张大图显存放不下也不利于学习局部纹理。标准做法是把每张图切成 128x128 的 patchHR对应 32x32 的 LR4 倍降采样。切图是数据准备里最容易翻车的一步切太小丢纹理切重叠太多数据冗余边界切到一半留黑边又污染训练。我一般用下面这个脚本切图稳一点# 从 HR 大图滑窗切 patch同时生成配对 LR import os import cv2 from glob import glob HR_DIR hr_images # 原始高清大图目录 OUT_HR dataset/HR # 输出的 HR patch 目录 OUT_LR dataset/LR # 输出的 LR patch 目录 GT_SIZE 128 # HR patch 边长 STRIDE 64 # 滑窗步长小于 GT_SIZE 使 patch 之间重叠 SCALE 4 # 降采样倍数LR 边长为 GT_SIZE // SCALE os.makedirs(OUT_HR, exist_okTrue) os.makedirs(OUT_LR, exist_okTrue) idx 0 for img_path in glob(f{HR_DIR}/*.png): img cv2.imread(img_path) h, w img.shape[:2] for y in range(0, h - GT_SIZE 1, STRIDE): for x in range(0, w - GT_SIZE 1, STRIDE): hr_patch img[y:y GT_SIZE, x:x GT_SIZE] # 边缘不足时用反射补边不产生黑边数据 if hr_patch.shape[0] GT_SIZE or hr_patch.shape[1] GT_SIZE: hr_patch cv2.copyMakeBorder( hr_patch, 0, GT_SIZE - hr_patch.shape[0], 0, GT_SIZE - hr_patch.shape[1], cv2.BORDER_REFLECT ) # bicubic 4 倍降采样得到真正的 LR 小图 lr_patch cv2.resize(hr_patch, (GT_SIZE // SCALE, GT_SIZE // SCALE), interpolationcv2.INTER_CUBIC) cv2.imwrite(f{OUT_HR}/{idx:06d}.png, hr_patch) cv2.imwrite(f{OUT_LR}/{idx:06d}.png, lr_patch) idx 1 print(f生成 {idx} 对 patch)步长STRIDE设成GT_SIZE的一半相邻 patch 有 50% 重叠好处是同一张图的纹理被多次采样相当于数据增强代价是训练集体积变大显存紧张时可以把STRIDE调成 128 取消重叠。GT_SIZE不建议小于 96太小会让模型只盯着局部纹理学不到结构关系。生成完毕后抽查几对 HR/LR确认 LR 确实是 32x32、HR 是 128x128很多训练 loss 不降的问题就出在这一步的名字错位或尺寸不对。3.3 视频类训练集用 FFmpeg essentials 抽帧把视频变成图片如果手里没有大量高清照片视频是比想象中更丰富的训练数据来源。一段 4K 视频抽出来的帧比从网上爬图干净得多也没有版权和重复图问题。抽帧工具我一般用 FFmpeg 的 essentials 静态编译版Windows 下解压 zip 就能跑不用装环境。抽帧命令如下ffmpeg -i input.mkv \ -vf fps10,scale-2:1080 \ -compression_level 1 \ frames/%06d.pngfps10表示每秒取 10 帧视频动作快就取多些静态场景多就降到 5scale-2:1080把所有帧统一缩放到高 1080、宽度按比例自动计算-2 保证宽高是 2 的倍数避免后续切 patch 时出现奇数尺寸-compression_level 1是 PNG 的快速压缩级别写 0 最快但文件更大1 是速度和体积的折中。抽完帧不能直接拿去切 patch。视频相邻帧高度相似直接滑窗会产生大量重复 patch模型会在重复数据上严重过拟合。我一般会用 ffprobe 或脚本做粗去重算相邻两帧的像素差低于阈值的直接丢掉保留差异明显的关键帧。这一步不需要太精确粗筛掉完全相同的帧就够了重复的相似纹理反而有助于稳定训练。4. 训练命令与五个必调参数从能跑到能出图4.1 train.py 的入口与最小训练命令代码包里训练入口通常叫train.py有的包把它拆成train_esrgan.py或带options配置目录。不管叫什么第一次训练不推荐直接改源码先跑一遍默认配置验证数据管线和 GPU 是否正常。很多打包者把配置写死在配置文件里命令行参数不一定完整你先执行python train.py --help看支持哪些参数再决定是改命令行还是改 yaml。python train.py \ --batch_size 8 \ --lr 1e-4 \ --perceptual 1.0 \ --gan 0.1 \ --gt_size 128这段命令假设你的包支持这些参数名如果不支持打开options目录里的配置文件把对应字段改成同样数值即可。训练首次启动会先打印数据集的图片数量、模型参数量、输出路径还会跑几分钟的预热。看到类似Training started的日志才算真正跑起来。第一次训练只建议设很少的迭代步数比如 1000 步做 smoke test确认 loss 能打印、模型能保存再考虑全量训练别一上来就烧十几个小时。4.2 五个必调参数GT_size、batch、perceptual、GAN 权重、学习率这五个参数是 ESRGAN 训练里最影响最终效果的旋钮我把常见区间和踩坑心得汇总一下参数常见取值作用与翻车点gt_size96 / 128 / 160输入 HR patch 边长。越大越吃显存、纹理越丰富低于 96 输出容易发虚batch_size4 / 8 / 16受显存限制。低于 4 时 GAN 训练极易不稳定loss 曲线乱跳perceptual0.1 ~ 1.0感知损失权重。太大纹理平滑像磨皮太小结构崩坏gan0.005 ~ 0.2对抗损失权重。0.1 是常用起点调太大出油画纹理调太小没细节增益lr5e-5 ~ 1e-4学习率。ESRGAN 用 Adam超过 2e-4 大概率训崩低于 5e-5 收敛慢到怀疑人生perceptual和gan是 ESRGAN 区别于普通 SRCNN 的核心。感知损失用预训练 VGG 网络的特征图比较让输出在「语义上有细节」对抗损失让输出看起来「像真图」。我踩过的坑是gan权重直接照抄别人配置填 0.5结果纹理全是伪影后来改成 0.1 先跑 2 万步再慢慢加上去才稳定下来。学习率上ESRGAN 常见做法是前一段用固定 lr后面按步数衰减你可以先把lr固定为 1e-4等 loss 平台期再手动降一半。数据集规模对参数选择影响也大。几百张图的小数据集perceptual权重高一点1.0、gan低一点0.05防止模型把有限的训练图背下来上万张的大数据集gan可以大胆上 0.2。训出来的模型到底什么水平单看 loss 数字没有意义一定要拿没训练过的图做推理对比这也是我在最后一章要展开的验证习惯。4.3 显存不够怎么办尺寸收缩、梯度累积与单卡改法ESRGAN 比较吃显存12G 显存跑 128 patch、batch 8 刚好卡在边缘8G 显卡不开混合精度基本跑不动。我见过最省钱的做法是把gt_size从 128 降到 96显存占用直接降一半。如果降到 96 还不行就要动训练逻辑了。最常见的是梯度累积用小 batch 多次前向、凑够步数再更新一次权重效果等效于大 batch# 梯度累积batch_size2 累积 4 步等效 batch_size8 optimizer.zero_grad() accum_steps 4 for step, (lr_img, hr_img) in enumerate(train_loader): loss model(lr_img, hr_img) # 二次前向时梯度会叠加 loss.backward() if (step 1) % accum_steps 0: optimizer.step() optimizer.zero_grad()注意optimizer.zero_grad()只在一个累积周期开始时清一次中途清了梯度就白攒了。这个写法对 ESRGAN 的 GAN loss 部分也适用但要保证判别器和生成器各自保持累积逻辑别把两个网络的梯度混在一起。改完显存还不够就把输入图在 dataloader 里先缩到 64x64 跑通流程确认代码没问题再回到 96。5. 避坑排查从解压到训练的五个高频翻车点5.1 解压报「数据错误」或提示要密码伪加密与二次打包现象用 Windows 自带解压工具解压 ESRGAN-master.zip 到一半报错或者压缩包打开时提示输入密码但你从没设过密码。原因这类 zip 很多是伪加密——文件的通用标志位被置为加密位但实际数据根本没加密。还有一种是发布者在打包时用了特殊字符集中文文件名解压出来乱码工具认为文件结构损坏。解决先用 7-Zip 打开压缩包如果能看到文件名但双击文件要密码七成是伪加密。用下面这个 Python 脚本把加密位清掉生成一个 fixed.zip再正常解压# 处理 zip 伪加密把局部文件头的加密标志位清零 def repair_zip(src, dstfixed.zip): with open(src, rb) as f: data bytearray(f.read()) patched 0 for i in range(len(data) - 4): if data[i:i4] ! bPK\x03\x04: continue # 通用位标志偏移 6位 0 为加密位 flags int.from_bytes(data[i6:i8], little) if flags 0x0001: data[i6:i8] (flags 0xFFFE).to_bytes(2, little) patched 1 with open(dst, wb) as f: f.write(data) print(f修复 {patched} 个文件头输出 {dst}) repair_zip(ESRGAN-master.zip)脚本只处理了局部文件头如果中央目录也有加密位解压到后半段可能还是报错这时就换 Bandizip 的智能解压或直接用python zipfile读。修复完先看文件列表是否符合预期再释放别再白白解压一遍。5.2 推理输出全黑图或全绿图现象test.py 正常执行结束输出的图片打开是全黑、全绿或者颜色明显偏色。原因这是 ESRGAN 推理最常见的翻车点根源在颜色通道顺序。OpenCV 读图是 BGRPyTorch 训练时用的是 RGB如果预处理代码忘了cv2.cvtColor(img, cv2.COLOR_BGR2RGB)网络输入的就是颠倒通道的图输出自然鬼畜。另一个常见原因是数据范围网络训练时输入通常归一化到 [0,1] 或 [-1,1]推理时却把 0~255 的数组直接喂进去。解决先确认预处理代码找到推理脚本里read_img或transform的位置加上通道转换和归一化再在输出端做一次逆归一化和 RGB 转 BGR。一个小技巧是先拿一张纯红色图片测试推理如果输出变成蓝色或绿色就是通道顺序问题。5.3 训练 loss 不降或断崖式崩坏现象loss 前几千步还在缓慢下降突然变成 NaN 或断崖飙升或者 loss 一直在 0.1 附近纹丝不动。原因NaN 多数是学习率太大导致梯度爆炸。ESRGAN 的对抗损失对学习率极其敏感1e-3 的学习率对分类网络没问题对超分 GAN 直接炸。loss 纹丝不动则常见于数据没配对HR 和 LR 文件名对不上训练时喂进去的是两张不相关图片模型学不到映射关系只能停在某个平庸值。解决NaN 就把 lr 降到 5e-5同时检查数据里有没有损坏图片一张纯黑或全白的图会让 BN 层统计量崩掉。loss 不动先停训练抽样打印一个 batch 的 HR 和 LR 文件名确认它们是一对。再不行就关掉 GAN loss 只留 L1 和感知 loss 跑 1 万步如果 L1 能正常下降说明问题出在对抗训练设置不关模型结构的事。5.4 视频逐帧放大的闪烁问题现象用同一个模型逐帧超分视频单帧看效果很好连起来播放时画面在细节区域明显闪烁、抖动。原因模型对每一帧独立处理相邻帧之间微小的输入差异会被放大成不同的细节输出。人脸皮肤纹理、远处树叶这些高频区域最容易闪这是逐帧超分的固有局限不是模型坏了。解决最省事的是不直接超分原视频而是先用ffmpeg把视频抽帧超分后再处理。加大输入帧的连续性用低倍数2x超分两次比直接 4x 闪烁小。如果闪烁仍不可接受就在后期用视频平滑滤波。不要指望换个模型能根治闪烁时间一致性训练是另一套技术方向。5.5 训练中段显存溢出 OOM现象训练跑了几个小时突然报CUDA out of memory之前明明能跑。原因PyTorch 的显存分配是动态的训练初期显存占用低GAN 训练到后半段一些缓存变量变大或者验证阶段把大图加载进显存挤爆了。解决给 PyTorch 设置torch.backends.cudnn.benchmark False减少缓存波动同时把torch.cuda.empty_cache()插到每个 epoch 之间。显存允许时把pin_memoryTrue关掉这个选项省了 CPU 拷贝却额外吃显存。终极方案是回到 4.3 的梯度累积把 batch 拆小。注意 OOM 之后重新训练要清掉进程PyTorch 退出不彻底时显存不会立刻释放用nvidia-smi看看是不是残留了僵尸进程。6. 从单张到批量把模型接进正经工作流6.1 一个可复用的批处理推理脚本训练终于告一段落你会面对几百张图需要批量放大。每次手动敲test.py不现实我习惯把推理封装成一个小脚本支持递归读取目录、自动跳过已处理的文件、输出对比图import os import torch import cv2 from glob import glob def infer_dir(model, input_dir, output_dir, scale4): os.makedirs(output_dir, exist_okTrue) for img_path in glob(f{input_dir}/**/*.png, recursiveTrue): rel os.path.relpath(img_path, input_dir) out_path os.path.join(output_dir, rel) os.makedirs(os.path.dirname(out_path), exist_okTrue) if os.path.exists(out_path): continue # 断点续跑跳过已生成的图 img cv2.imread(img_path) lr torch.from_numpy(img).permute(2, 0, 1).float().unsqueeze(0) / 255.0 with torch.no_grad(): sr model(lr) sr sr.squeeze(0).permute(1, 2, 0).numpy() * 255.0 cv2.imwrite(out_path, sr, [cv2.IMWRITE_PNG_COMPRESSION, 2])第一次跑完检查输出尺寸是否真的一边放大 4 倍。很多入门者会漏掉这一步结果放大后的图和原图一样大还以为是模型不行其实是推理代码里少了插值动作。6.2 一个验证习惯降质回放测 PSNR/SSIM我建议你建立这样的验证习惯准备 50 张没进过训练集的干净图先看放大效果的边缘锐度再用降质回放做量化评估。把原图 bicubic 缩成低分辨率再送入模型放大回原尺寸跑 PSNR 和 SSIM。这一套只是参考但至少帮你判断模型有没有把训练集背下来。我个人的教训是早期训练只看 demo 图换了一批测试图后发现细节全面崩坏从此固定保留 50 张验证图。这次经验之后每个模型我都先跑量化、再看图、再谈上线希望你也能留好这批不掺水分的验证集让超分水准有可追溯的对照。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑