ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于TensorFlow和GAN的图像超分辨率重建工程实战与避坑指南

基于TensorFlow和GAN的图像超分辨率重建工程实战与避坑指南 简介基于深度学习的图像超分辨率重建项目包面向深度学习入门及毕业设计学生聚焦利用卷积神经网络、生成对抗网络和残差网络实现低分辨率图像的高清化复原。压缩包共43个文件、大小1.65MB以Python脚本、Visual Studio工程文件及png/jpg效果图为主其中py文件涵盖训练、模型及工具模块图片用于展示各阶段重建结果同时包含工程配置与README说明便于快速上手。项目以CelebA人脸数据集为示例涉及TensorFlow、CUDA、cuDNN等环境配置并结合scipy.misc与PIL.image完成图像预处理适合作为图像重建方向的实验参考。已有411人学习下载。内含完整的VS解决方案与训练入口可帮助读者快速复现超分辨率模型理解网络结构设计、损失计算和训练流程并借助附带的中间结果图对比不同阶段的重建效果可用于课程设计、毕业设计或算法效果验证。1. 图像超分辨率重建这份 VS TensorFlow 工程能让你少走三周弯路图像超分辨率重建这个方向网上资料一搜一大把但十个下载过资源的人里八个卡在环境搭建还有两个卡在不知道代码从哪看起。这份基于深度学习的图像超分辨率重建工程把模型、训练、工具、入口脚本拆成四个独立文件还带一套 Visual Studio 解决方案属于能让你在 Windows 上少折腾三周、直接把项目跑起来的资源。它用 CelebA 人脸数据集做实验覆盖卷积神经网络、生成对抗网络、残差网络三条技术线正好是深度学习毕设和实验项目里最常见的选题范围。想从理论落到代码的、想看 GAN 怎么参与图像重建的、被环境配置劝退过的都适合打开这份资源。别急着先读模型先把工程拆开。2. 先拆工程四个 py 文件和一个 VS 解决方案各自在干谁的活拿到压缩包的第一步不是急着装环境跑 train而是把目录结构摊开看。这个工程的文件名是有讲究的isr 是 image super-resolution 的缩写train、model、util、main 四个词把整个实验拆成了模型定义、训练、工具、入口四条线。这种拆分方式在深度学习工程里非常标准意味着你可以把四个文件抽出来直接挪到自己的项目里改不用动整体架构。Image-Super-Resolution-VS-master/ ├── isr_model.py # 模型定义生成器、判别器、残差块 ├── isr_train.py # 训练主循环数据加载、loss、交替更新 ├── isr_util.py # 工具函数图像读写、预处理、PSNR ├── isr_main.py # 入口脚本加载 checkpoint 做推理 ├── dataset/ # 数据目录CelebA 解压后放这里 ├── imgs/ # 实验过程生成的可视化结果图 ├── image-super-resolution.pyproj # VS Python 工程文件 ├── image-super-resolution.sln # VS 解决方案文件 ├── .gitattributes / .gitignore # git 配置文件 └── README.mdimgs 目录里那批 5-x-x.png 命名的小图是训练过程中保存下来的重建结果对照。从命名习惯看是分了几组样本、每组在不同 epoch 或不同配置下的输出。对新手来说这些图就是「训练到底跑没跑对」的最直观参考比你盯着一串 loss 数字靠谱得多。2.1 isr_model.pyCNN、残差和 GAN 各自在模型里承担什么超分辨率重建的任务一句话就能说清输入一张低分辨率图输出一张更清晰的大图。听起来像传统插值放大但深度学习做这件事的本质是学习一个从低分到高分的映射函数。isr_model.py 里通常一次定义了两套网络一套生成器负责把低分辨率图变成高分辨率图一套判别器负责判断输入图片是原始高分辨率图真还是生成器产出的假图。这两套网络合在一起就是生成对抗网络 GAN 在超分任务上的标准用法。生成器内部有两个关键设计。卷积神经网络负责特征提取——低分辨率图经过几层卷积把边缘、纹理这些信息逐步编码到特征图里残差网络负责把网络加深而不退化——几十个残差块叠起来每一块都保留一条从输入直通输出的跳线让梯度在反向传播时少绕路。以最常见的实现为例残差块的核心逻辑是这样写的# isr_model.py 中生成器残差块的核心逻辑工程里常见的写法 import tensorflow as tf def residual_block(inputs, filters64, kernel_size3, stride1): # 跳线 shortcut 让梯度能直接回流深层网络也能稳定训练 shortcut inputs x tf.layers.conv2d(inputs, filters, kernel_size, stride, paddingsame, activationNone) x tf.nn.relu(tf.layers.batch_normalization(x)) x tf.layers.conv2d(x, filters, kernel_size, stride, paddingsame, activationNone) x tf.layers.batch_normalization(x) return tf.add(shortcut, x) # 输入加输出残差学习filters64是特征通道数可以理解为网络用 64 个不同角度的滤波器去扫描图像kernel_size3是卷积核尺寸3x3 是超分网络里的主流选择感受野和参数量的平衡最好。这里有一个初学者容易忽略的点batch_normalization在生成器里一般放在激活函数前面它对稳定 GAN 训练帮助很大。但如果你后续要把模型导出部署需要先把 BN 层的统计量冻结否则推理时结果会偏暗或偏色。生成器整条链路是「特征提取 → 残差堆叠 → 亚像素上采样」def generator(images, num_res_blocks16): # 第一层卷积把输入 RGB 图抬到 64 通道特征空间 x tf.layers.conv2d(images, 64, 3, paddingsame, activationtf.nn.relu) shortcut x for _ in range(num_res_blocks): x residual_block(x) x tf.layers.conv2d(x, 64, 3, paddingsame) x tf.add(x, shortcut) # 全局残差训练更稳定 # 亚像素上采样depth_to_space 把通道数转成空间尺寸2 倍放大 x tf.layers.conv2d(x, 64 * 4, 3, paddingsame) x tf.depth_to_space(x, 2) x tf.nn.relu(x) x tf.layers.conv2d(x, 3, 3, paddingsame) # 输出 RGB 三通道 return xnum_res_blocks16是残差块数量数量越多网络表达力越强显存占用和训练时间也线性上涨。最后那步depth_to_space是超分工程里最关键的细节它把 64*4256 个通道重排成 64 通道的 2 倍分辨率图等效于亚像素卷积PixelShuffle比直接反卷积上采样干净得多不容易产生棋盘格伪影。判别器部分相对简单通常是一串带步长的卷积堆叠最后接一个全连接输出真/假分数这里就不单独贴代码了。2.2 isr_train.py 和 isr_util.py训练循环与图像处理工具的分工isr_train.py 是这个工程的发动机。它做的事按顺序是扫描 dataset 目录下的图片 → 用 isr_util 里的函数生成低分辨率/高分辨率配对 → 定义生成器和判别器的 loss → 交替更新两套网络的参数 → 每隔几个 epoch 保存 checkpoint并把当前结果可视化到 imgs。判别器和生成器不是一起反向传播的而是各算各的 loss、各更新各的参数这是 GAN 训练的常识但头一次看训练代码的人很容易被两个 optimizer 绕晕。# isr_train.py 训练循环里的两个核心 loss 计算 # 判别器要让真实 HR 输出 1、生成 SR 输出 0 d_loss_real tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logitsd_logits_real, labelstf.ones_like(d_logits_real))) d_loss_fake tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logitsd_logits_fake, labelstf.zeros_like(d_logits_fake))) d_loss d_loss_real d_loss_fake # 生成器要骗过判别器同时加 L1 内容损失保证像素贴近原图 g_loss_adv tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logitsd_logits_fake, labelstf.ones_like(d_logits_fake))) g_loss g_loss_adv 0.1 * tf.reduce_mean(tf.abs(hr_image - sr_image))g_loss里 0.1 是内容损失的权重这个系数直接决定了生成图是「细节丰富但可能变形」还是「平滑但清晰度不足」。权重调大图像更贴近原始 HR 但整体偏软权重调小判别器影响力更强细节锐利但训练不稳。工程里常用 0.1 作为起步值我一般会在这里做一轮小范围网格搜索0.05 到 0.2 之间通常能找到更好的点。isr_util.py 是纯工具模块负责图像读写、归一化、PSNR 计算这类杂活。超分项目里所有图像都要先归一化再进网络常见做法是把 0-255 的像素压到 [-1, 1]。这个区间对 GAN 训练比 [0, 1] 友好因为判别器输出能对称地收敛到 0 和 1 两个端点。PSNR 是量化重建质量的指标单位 dB数值越高越好20dB 以下基本没法看30dB 以上说明重建得比较接近原图。你在 imgs 里看到的那批 5-x-x.png就是用 PSNR 和视觉效果两套标准挑出来的对照结果。2.3 isr_main.py 与 dataset入口逻辑和数据目录约定isr_main.py 是验证用的入口。它不像 isr_train.py 那样跑几十个 epoch而是加载一个训练好的 checkpoint对单张图片做前向推理把超分结果写到指定路径。逻辑很短但它是你确认模型有没有训练对的最快路径# isr_main.py 推理流程恢复 checkpoint前向一次保存结果 saver tf.train.Saver() with tf.Session() as sess: saver.restore(sess, tf.train.latest_checkpoint(ckpt_dir)) lr_img isr_util.load_image(sys.argv[1]) # 读图并归一化 sr_img sess.run(generator_out, feed_dict{lr_placeholder: lr_img}) isr_util.save_image(sys.argv[2], sr_img)参数上sys.argv[1]是输入图片路径sys.argv[2]是输出路径。这个脚本默认只跑一张图如果你拿到的工程里没做 argc 校验自己补一个判断就能避免越界报错。dataset 目录在这个工程里就是数据集的挂载点把 img_align_celeba.zip 解压出来的图片放进去isr_train.py 默认从这里扫描文件。我拿到这类工程时第一步会先看训练脚本里数据集路径是怎么拼的——有些工程写死绝对路径换机器必炸相对路径的话就好办dataset 目录结构保持原样就行。2.4 VS 工程不是摆设.sln 和 .pyproj 这样用很多下载这套资源的人会忽略最上层的 .sln 和 .pyproj觉得 Visual Studio 是写 C# 用的。但这是在 Windows 上组织 Python 深度学习项目的正经方式.sln 是解决方案文件.pyproj 是 Python 工程文件配套的 VS Tools for AI 扩展能让 TensorFlow 脚本在 VS 里直接按 F5 调试、断点走完整个训练循环。比起命令行黑匣子式跑训练这种方式对新手友好得多——至少能看到当前变量值知道数据读进来到底是什么形状。实际打开顺序是先装好 VS Tools for AI 扩展再双击 .slnVS 会自动识别 .pyproj选择你配好的 Python 环境把 isr_main.py 或 isr_train.py 设为启动文件然后就能像调试普通程序一样跑深度学习了。如果不想用 VS四个 py 文件也完全独立用 PyCharm 或命令行没有任何障碍。我拆过不少毕设工程很多是 Jupyter Notebook 或纯脚本带完整 VS 解决方案的相对少见它属于课题组教学型工程结构上更规整也更容易让新手从头到尾跟下来。3. 环境搭建CUDA、cuDNN 与 TensorFlow 的版本匹配错一个就白装超分工程劝退人最多的地方不是网络结构是环境。这个工程涉及 TensorFlow、NumPy、scipy.misc、PIL.image 四类库scipy.misc 和 PIL.image 负责图像处理TensorFlow 负责跑图如果你的显卡是 NVIDIA还要往上叠驱动、CUDA、cuDNN 三层。深度学习环境配置这块版本匹配就是命门——TensorFlow 1.x 时代尤其苛刻差一个小版本都可能让你连 import 都过不去更别提跑训练。3.1 版本匹配表先装对再谈跑通TensorFlow 1.x 老项目最常见的稳定组合是 TensorFlow 1.14 配 CUDA 10.0 和 cuDNN 7.6Python 用 3.6 或 3.7。这不是官方文档里唯一的组合但这是我在多台 Windows 机器上实测过最省事的搭配TensorFlowCUDAcuDNNPython说明1.13 ~ 1.1510.07.43.6 / 3.7本资源 tf.layers / scipy.misc 风格最稳1.8 ~ 1.129.07.23.5 / 3.6老显卡兼容更好性能稍弱装之前先执行一次nvidia-smi你要看的是驱动版本最上方写的 CUDA Version。那个数字是驱动支持的 CUDA 上限比如它写着 11.2你装 CUDA 10.0 的 runtime 完全没问题二者是兼容关系而不是强制相等。很多人的误区是以为nvidia-smi显示的 CUDA 版本就是当前装的工具包版本其实驱动和工具包是两回事。在 Windows 上驱动更像是一个容器TensorFlow 需要的是对应版本的 CUDA runtime 动态库和 cuDNN 动态库这两样不装齐GPU 就是摆设。3.2 一步步装从 NVIDIA 驱动到 VS Tools for AI环境搭建的完整顺序是装显卡驱动 → 装 CUDA Toolkit → 放 cuDNN → 建 Python 环境装库 → 装 VS 扩展。每一步都有固定动作我按平时上手的顺序走一遍# 1. 装 CUDA 10.0自定义安装时只勾选 CUDA 组件别装全家桶 # 默认安装路径 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0 # 2. cuDNN 解压后把 cuda\bin、cuda\include、cuda\lib\x64 里的文件 # 分别复制到 CUDA 安装目录对应的同名文件夹下 # 3. 确认 bin 目录在系统 PATH 里 echo %PATH% # 4. 建 Python 环境 conda create -n isr python3.7 -y conda activate isr # 5. 安装 TensorFlow 和图像处理库scipy 版本要锁死 1.2.1 pip install tensorflow-gpu1.14.0 numpy scipy1.2.1 pillow第 3 步的 PATH 是环境搭建里最容易漏的一环。cuDNN 是动态库TensorFlow 在 import 时要到系统 PATH 里找 cudart64_100.dll 和 cudnn64_7.dll找不到就直接报Could not find cudart64_100.dll。把 CUDA 的 bin 目录加到 PATH 第一顺位能省掉后面一大半的玄学报错。安装 CUDA 时我一般只勾选 CUDA 组件不装全家桶因为全家桶里带的 OpenCL、PhysX 之类组件会往 PATH 里塞一堆东西有时候反而会把版本搞乱。VS Tools for AI 的安装简单打开 Visual Studio在扩展管理器里搜索 AI找到 VS Tools for AI 安装即可。装完之后 VS 才能识别 .pyproj 工程并提供 Python 解释器选择和 GPU 环境检测。如果 VS 版本比较新这个扩展可能已经整合进 Python 开发负载里你只需要在安装 VS 时勾选 Python 开发即可不需要额外折腾。3.3 装完别急着训练先确认 GPU 真的被 TensorFlow 看到了这一步非常关键也经常被跳过。很多人 pip 装完 tensorflow-gpu 就开始跑训练跑到一半发现速度不对一查才发现 TensorFlow 根本没在调用 GPU一直在 CPU 上硬算。验证方法极其简单import tensorflow as tf # 检查 GPU 是否可见 print(GPU available:, tf.test.is_gpu_available()) # 更稳妥的方式显存按需增长避免一次占满 gpu_options tf.GPUOptions(allow_growthTrue) sess tf.Session(configtf.ConfigProto(gpu_optionsgpu_options)) print(sess.run(tf.test.is_gpu_available()))allow_growthTrue表示显存按需分配用多少占多少而不是程序一启动就把整张卡占满。如果你在跑训练的同时还要开浏览器或者做别的这个选项能救你。如果is_gpu_available()返回 False先回头查 3.1 的版本表对齐组合再不行就确认 cuDNN 是不是复制漏了文件。还有一招排查技巧把环境变量CUDA_VISIBLE_DEVICES设成 0 再跑一次排除多卡序号混乱的问题。这条习惯我一直保留着每次换机器都是先花五分钟做完 GPU 验证再决定要不要开工。4. CelebA 数据准备到训练闭环从 img_align_celeba.zip 到 219x178 配对样本环境通了下一步是数据。这个实验用 CelebA 数据集做演示从摘要就能看出数据链路很完整下载 img_align_celeba.zip取前 10661 张统一对齐到 219x178。建议你也照着这条链路走因为它把数据准备的问题从「怎么处理乱七八糟的原始图」简化成了「怎么把一张已经对齐好的图变成训练样本」——你可以把全部精力放到超分算法本身而不是花一半时间做人脸检测和对齐。4.1 为什么选 CelebA对齐好的图省掉一半预处理功夫CelebA 是香港中文大学开放的人脸识别数据集包含 10177 个名人的 202599 张人脸图片每张图带 5 个关键点位置标记和 40 个属性标记。它既可以用在人脸检测、人脸属性识别、人脸位置定位也可以像这个实验一样把人脸图像当作超分重建的对象。资源里用的 img_align_celeba.zip 是做过人脸对齐的版本——每张脸都按双眼位置做了旋转和裁剪图片内容基本居中脸的角度一致性很高。取前 10661 张是有道理的CelebA 全量 20 万张图训练要跑太长时间对验证网络结构和调参来说一万张左右的子集已经足够看到效果。219x178 这个尺寸是对齐后统一裁剪的结果。需要说明的是这个尺寸的长宽都不是 4 的整数倍做 4 倍超分时会浪费几个像素但作为教学工程完全够用。后面我会讲到怎么把这个尺寸改得更顺手。如果你刚接触深度学习实战项目案例用这种已对齐的数据集起步能把「数据工程」和「模型训练」两个变量拆开出了效果你知道该感谢模型还是感谢数据。4.2 预处理生成低分辨率和高分辨率的配对样本超分训练需要成对的数据一张高分辨率原图和一张对应的低分辨率退化图。常见做法是先对原图做高斯模糊和降采样再把降采样后的小图放大回原尺寸配成一组训练对。这样网络学习的映射就是「从模糊放大图复原出清晰原图」。核心逻辑如下# isr_util.py 中读 CelebA 并生成高低分辨率配对的核心逻辑 from PIL import Image import numpy as np TARGET_SIZE (219, 178) # 数据集对齐后的统一尺寸 SCALE 4 # 超分倍率输入缩小 4 倍输出放大 4 倍 LOW_SIZE (219 // SCALE, 178 // SCALE) # 降采样后的尺寸 def load_pair(path): hr Image.open(path).convert(RGB).resize(TARGET_SIZE) # BICUBIC 降采样模拟真实世界的图像退化过程 lr hr.resize(LOW_SIZE, Image.BICUBIC) # 再放大回原尺寸保证网络输入输出分辨率一致 lr lr.resize(TARGET_SIZE, Image.BICUBIC) # 归一化到 [-1, 1]GAN 训练比 [0, 1] 更稳 hr (np.asarray(hr, dtypenp.float32) / 127.5) - 1.0 lr (np.asarray(lr, dtypenp.float32) / 127.5) - 1.0 return lr, hr这里有两个细节值得注意。第一lr先降采样再放大回来而不是直接用低分辨率小图当输入是因为网络的输出尺寸必须和真实 HR 一致loss 才能逐像素计算。第二219 和 178 除以 4 除不尽LOW_SIZE实际取到 (54, 44)放大回来会损失 3 个像素的边缘信息。我在实操中会把训练图随机裁剪到 192x160 这类能被 4 整除的尺寸既解决对齐问题又顺带做了数据增强。PIL.image 和 scipy.misc 的分工是PIL 负责读图、缩放、保存scipy.misc 在老版本工程里负责一些矩阵类的图像处理操作。如果你升级到新版本环境scipy.misc 的画图接口基本都要换成 PIL 或 OpenCV。4.3 训练启动与参数设计从命令到每个参数的含义数据准备好之后训练就一句话的事。这个工程的命令行入口是 isr_train.py我在实际复现时用的参数组合是这样的python isr_train.py \ --data_dir dataset/celeba \ --scale 4 \ --batch_size 16 \ --lr 1e-4 \ --epochs 30 \ --num_res_blocks 16参数推荐值说明--data_dirdataset/celeba解压后的 CelebA 图片目录--scale4超分倍率想快速看效果可先设 2--batch_size16显存 8G 以下先调成 8 或 4--lr1e-4Adam 优化器初始学习率GAN 训练常用起点--epochs3010661 张图跑 30 个 epoch半天内能看出趋势--num_res_blocks16残差块数量跟生成器深度挂钩我习惯在正式训练前先跑 2 个 epoch 验证链路如果 loss 能正常波动、不直接变 NaN再启动完整训练。因为超分项目最怕的不是效果差而是跑了一整晚发现数据加载就是错的白白浪费一个晚上。注意如果几个 epoch 后保存出来的图一直是一团灰先检查数据归一化是不是混用了 [0,1] 和 [-1,1]再检查数据加载顺序不要急着改网络结构。5. 避坑指南超分辨率重建项目里五个真实翻车现场这个工程能跑通但不代表你不会踩坑。下面五条是我复现这类 TensorFlow 1.x 超分项目时真实遇到过的翻车现场每一条都按现象、原因、解决的顺序写你可以直接对号入座。环境类坑占了三席这跟超分项目本身的特点有关——它比一般的图像分类工程多了 CUDA 层面的依赖任何一个环节版本漂移后面全是连锁反应。5.1 scipy.misc.imresize 失踪一启动就 AttributeError现象运行 isr_train.py 或 isr_util.py 时直接报AttributeError: module scipy.misc has no attribute imresizestack trace 指向图像缩放那一行。原因scipy 从 1.3.0 开始移除了imresize、imread等旧图像接口。老工程里调用了这些接口就会崩。我见过很多人装环境时随手pip install scipy装到了最新版然后在这条报错上卡一整天。解决锁版本是最快的后悔药执行pip install scipy1.2.1。如果不想降版本就把scipy.misc.imresize的调用改成PIL.Image.resize或 OpenCV 的cv2.resize。这需要你在 isr_util.py 里把所有相关行改一遍工程量不大但要注意别漏掉读取图片那几处。5.2 cudart64_100.dll 找不到TensorFlow 在 import 阶段就崩现象import tensorflow时抛ImportError: Could not find cudart64_100.dll或者提示 CUDA driver version is insufficient整个环境像没装 GPU 版一样。原因TensorFlow 1.14 默认去找 CUDA 10.0 的 runtime 动态库。机器上如果只有 CUDA 9 或 CUDA 11或者装了 10.0 但 bin 目录没进 PATH就会在加载阶段直接失败。多版本 CUDA 并存时系统 PATH 的先后顺序也会导致 TF 找错版本。解决按第 3.1 节的匹配表对齐版本执行nvcc -V确认当前生效的 CUDA 版本检查echo %PATH%里 CUDA bin 目录是否排在前列。最省事的办法是只保留一个版本删干净再重装。这条解决路径我在五台机器上验证过每次都有效。5.3 显存溢出OOM 不用急着换显卡先调 batch现象训练过程跑了几十步报Resource exhausted: OOM when allocating tensor with shape [16, 64, 110, 90]进程直接退出。原因生成器和判别器是两套网络显存是同时占的。219x178 的输入不算大但如果--batch_size设成 32、还在后台开着浏览器和 IDE8G 显存很容易被填满。很多人第一反应是换显卡其实大多数情况是 batch 设大了。解决先把--batch_size降到 8 或 4能立刻缓解同时开第 3.3 节的allow_growthTrue。如果你用的是 6G 以下的显卡建议把输入图改成随机裁剪 128x128 的训练策略整体显存占用能降一半以上。我自己的经验是超分 GAN 在小显存卡上宁可 batch 小一点、裁剪小一点也要保证能跑完一个完整 epoch这样调参才有意义。5.4 训练 loss 震荡、出图模糊判别器太强压住了生成器现象训练时判别器的 loss 一路走低生成器的 loss 反复横跳保存出来的 sample 图是一团模糊的色块完全看不出人脸轮廓。原因GAN 的本质是两套网络互相对抗判别器学得太快太强生成器怎么骗都骗不过它梯度信号失去意义生成器索性摆烂输出平滑的均值图。这不是超分项目独有所有 GAN 训练里都常见。解决把学习率从 1e-4 降到 5e-5让判别器学慢一点或者先用只含 L1 内容损失的 loss 单独预训练生成器 10 个 epoch等生成器有了基本重建能力再让判别器参与对抗。我碰到这种情况还会检查数据归一化是否一致HR 和 LR 如果一边是 [-1,1] 一边是 [0,1]网络一样会学崩。从调试顺序上看这个坑排在环境坑之后、网络结构坑之前属于训练阶段的头号嫌疑犯。5.5 棋盘格伪影上采样方式没选对现象超分结果的纹理区域有明显方块状周期性纹路皮肤上像盖了一层纱网远处看以为是 JPEG 压缩噪声放大看是规则的格子。原因上采样用了转置卷积反卷积它在特征图上做带重叠的插值对图像边缘的权重不一致就容易形成棋盘格。老工程里这种写法很常见不是 bug但效果有瑕疵。解决改用亚像素卷积也就是第 2.1 节里tf.depth_to_space那套方案把通道重排成空间尺寸而不是用卷积核插值。如果你的 isr_model.py 里已经是 depth_to_space这条可以跳过如果是tf.layers.conv2d_transpose替换掉通常能立刻改善。替换完记得对比一下 imgs 里的重建图棋盘格一般会肉眼可见地消失。6. 进阶换自己的数据集复现把训练好的模型做成批量超分工具环境配好、流程跑通之后这个工程的真正价值才开始显出来——它足够小小到你能放心大胆地改成自己的东西。我从这个工程里移植出来的两个能力一个是换数据集一个是批量推理都是在它基础上二十分钟内就能完成的改动。换数据集的核心是替换 isr_util.py 里的配对生成逻辑。CelebA 是已经对齐好的脸你自己的图片通常不具备这个条件所以预处理要换成「中心裁剪到可整除尺寸 缩放到高分辨率 降采样生成低分辨率」的通用流程from PIL import Image import os def make_dataset(src_dir, out_hr, out_lr): # 通用数据准备中心裁剪 生成 LR/HR 对 os.makedirs(out_hr, exist_okTrue) os.makedirs(out_lr, exist_okTrue) for i, f in enumerate(sorted(os.listdir(src_dir))): img Image.open(os.path.join(src_dir, f)).convert(RGB) w, h img.size cw, ch 192, 160 # 保证能被 4 整除 left, top (w - cw) // 2, (h - ch) // 2 img img.crop((left, top, left cw, top ch)) img.save(os.path.join(out_hr, f{i:05d}.png)) img.resize((cw // 4, ch // 4), Image.BICUBIC).save( os.path.join(out_lr, f{i:05d}.png))中心裁剪尺寸定成 192x160 是我的习惯4 倍超分下低分辨率图是 48x40这个尺寸对显存和训练速度都友好。如果你的原始图是竖构图或者特别大先统一缩放到合适尺寸再裁效果比直接裁好。批量推理则是把 isr_main.py 包一层循环用 shell 逐个调用简单直接# 对 test_imgs 目录下的所有图片执行超分重建 for f in test_imgs/*.png; do python isr_main.py --input $f --output output_sr/$(basename $f) --scale 4 done跑完记得看一眼输出目录里有没有漏图、有没有异常尺寸的文件。如果输出全是纯黑或者纯灰先检查单张推理是否正常再进批量循环别让一个坏文件浪费整轮处理时间。从那以后我每次换机器跑超分项目都会先写一个版本检查脚本把 TensorFlow、CUDA、cuDNN、scipy 的版本一次性打印出来再决定要不要开工。这招帮我避掉了太多装完环境才发现不匹配的尴尬。希望帮到你。本文还有配套的精品资源点击获取
返回列表