简介这份资源是面向图像处理与深度学习方向的开发者、学生及研究者的NAFNet图像去模糊Python实现包适合具备一定PyTorch或PaddleGAN基础、希望复现或二次开发去模糊模型的中高级学习者。压缩包共20个文件约11.98MB以png、jpg图像样本和xml配置为主辅以py脚本、md说明文档及工程配置文件可用于数据准备、模型训练与测试的完整流程。项目围绕PictureRestoration-master目录组织包含4k_pic_restoration.py与normal_pic_restoration.py两个核心脚本并配套inputs、outputs及4kpictures等图像目录便于直接运行与结果对比。已有763人学习下载读者可借此理解NAFNet的卷积层、残差块与注意力机制组合方式掌握从环境准备、代码研读到训练测试、PSNR与SSIM评估的完整链路并基于现有脚本调整超参数以优化去模糊效果。1. 拆开这个 NAFNet 去模糊包它到底能修什么样的糊图手机拍夜景手一抖或者抓拍小孩跑动回来一看整张照片像蒙了层雾——这种糊不是靠锐化滤镜能救的本质是卷积核未知的盲去模糊问题。这个使用NAFNet进行图像去模糊_Python_下载.zip里装的PictureRestoration-master就是拿 NAFNetNonlinear Activation Free Network做图像复原的一套 Python 工程。NAFNet 最早在图像去噪和去模糊基准上把 SOTA 刷了一轮核心卖点是去掉了传统残差块里的非线性激活ReLU/GELU用简化通道注意力加门控机制替代推理时显存和延迟都压得比较低。这个包不是论文复现仓库而是一个能直接跑推理的工程壳4k_pic_restoration.py和normal_pic_restoration.py两个入口脚本配pictures、inputs、outputs三个目录外加一份 README。适合两类人手里有一批糊图想批量过一遍的从业者以及想拿 NAFNet 当 baseline 改结构的学生。它不负责训练权重得自己按 README 指路去拿这点先有心理预期。2. 环境与目录把 Python 依赖和两个入口脚本对齐2.1 目录结构先摸清楚别急着 pip install解压后第一件事不是装库是tree一遍看结构。这个包的目录组织是有意图的pictures放的是示例或待处理原图inputs和outputs是脚本运行时的输入输出落点4kpictures单独给 4K 大图留了一份。.idea是 PyCharm 工程配置PictureRestoration.iml是模块文件这俩跟运行无关可以无视。真正要盯的是两个 py 脚本和 README。# 解压后先看结构确认脚本和目录都在 unzip 使用NAFNet进行图像去模糊_Python_下载.zip cd PictureRestoration-master find . -maxdepth 2 -type d | sort # 预期看到 pictures / inputs / outputs / 4kpictures / .idea ls *.py # 预期看到 4k_pic_restoration.py 和 normal_pic_restoration.py逻辑说明find只列两层目录避免.idea里的深层配置刷屏ls *.py确认两个入口脚本存在。参数上没什么可调的这一步纯粹是建立空间感——后面所有路径报错根源都是没搞清哪个目录是输入哪个是输出。2.2 依赖装什么PyTorch 是主线别装成 TensorFlow摘要里提到 TensorFlow 或 PyTorch 二选一但 NAFNet 官方实现和这类工程壳基本都走 PyTorch。装错框架的后果是 import 直接炸而且报错信息不会告诉你你装错框架了只会说找不到某个 module。常见做法是建独立虚拟环境Python 3.83.10 之间比较稳太新的 3.12 有时会卡在个别科学计算库的 wheel 上。# 建虚拟环境隔离依赖 python -m venv nafnet_env source nafnet_env/bin/activate # Windows 用 nafnet_env\Scripts\activate # 装核心依赖PyTorch 按自己 CUDA 版本去官网选对应命令 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install opencv-python pillow numpy tqdm逻辑说明venv隔离是为了不污染系统 Python这是血泪经验——一旦全局装乱后面排查依赖冲突能耗掉一晚上。PyTorch 的--index-url要按本机 CUDA 版本换cu118 只是示例没有 N 卡就装 CPU 版。opencv-python负责图像读写和 resizepillow兜底一些格式tqdm给批量处理加进度条。装完用python -c import torch; print(torch.cuda.is_available())验证 GPU 是否可见返回 False 就说明要么没卡要么驱动没配好CPU 也能跑只是慢。2.3 权重文件放哪README 是唯一可信来源这个包本身不含训练好的权重.pth文件README 里会写权重从哪拿、放哪个路径。常见约定是放在工程根目录或weights/下脚本里用相对路径加载。如果 README 没写清楚就去翻两个 py 脚本里torch.load或model.load_state_dict那几行看它拼的路径是什么照着放。# 典型加载逻辑实际以脚本内为准 import torch from model import NAFNet # 模块名以实际为准 device torch.device(cuda if torch.cuda.is_available() else cpu) model NAFNet().to(device) state torch.load(weights/nafnet.pth, map_locationdevice) model.load_state_dict(state) model.eval() # 推理前必须切 eval否则 BN/Dropout 行为不对逻辑说明map_location保证在没 GPU 的机器上也能加载 GPU 训出来的权重model.eval()这行最容易被漏漏了之后 BatchNorm 用 batch 统计量而不是滑动统计量输出会飘。参数上NAFNet()的构造参数宽度、编码器块数必须和权重匹配不匹配会报 size mismatch这时候要么换权重要么改构造参数别硬改 state_dict 的 key。3. 跑通推理normal 和 4k 两个脚本的用法与参数3.1 normal_pic_restoration.py普通分辨率批量处理普通脚本处理的是常规尺寸图一般 1080p 以内流程是遍历inputs目录、逐张推理、写到outputs。跑之前把待处理图丢进inputs别丢进pictures——pictures多半是示例图脚本不一定读它。# 把待处理图放进 inputs然后跑普通脚本 cp /path/to/your/blurry/*.jpg inputs/ python normal_pic_restoration.py # 跑完看 outputs ls -lh outputs/逻辑说明脚本内部一般用os.listdir或glob扫inputs所以文件名别带中文和空格否则某些老代码的路径拼接会翻车。输出默认写outputs同名覆盖。如果脚本支持命令行参数有些版本用 argparse可以python normal_pic_restoration.py --input inputs --output outputs显式指定具体看脚本头部有没有argparse。3.2 4k_pic_restoration.py大图为什么要单独一个脚本4K 图3840×2160 及以上直接塞进网络会爆显存因为 NAFNet 的中间特征图尺寸和输入分辨率成正比显存占用大致随像素数平方级增长。所以 4K 脚本通常做了分块tile或下采样再上采样的处理。分块推理的代价是块与块接缝处可能出现亮度或纹理不连续这是这类方案的固有 trade-off。# 4K 图放 4kpictures 或按脚本约定放 inputs cp /path/to/4k/*.jpg 4kpictures/ python 4k_pic_restoration.py逻辑说明如果脚本用分块块大小tile size和重叠overlap是关键参数。重叠太小接缝明显太大显存又吃紧。常见做法是 overlap 取 tile 的 1/8 到 1/4。跑完重点看接缝处有没有横竖条纹有的话调大 overlap 重跑。显存不够就先把 tile 调小别硬扛。3.3 参数怎么改学习率、批次这些训练参数在推理里没用摘要里列了学习率、批次大小、训练轮数但这是推理工程这些参数在normal_pic_restoration.py里根本不会出现——它们属于train.py而这个包里没有 train.py。别在推理脚本里找学习率找不到是正常的。推理阶段真正能调的是输入尺寸是否 resize、输出格式jpg/png、是否保留原图尺寸。这些通常在脚本里以常量或 argparse 参数形式存在。参数典型位置作用调整建议输入尺寸脚本内 resize 调用控制送入网络的分辨率太大爆显存太小丢细节输出格式cv2.imwrite 后缀决定输出编码png 无损但体积大jpg 有压缩tile/overlap4k 脚本内分块大小与重叠接缝明显就加大 overlapdevicetorch.deviceCPU/GPU 选择有卡用 cuda没卡自动回退提示改任何参数前先备份原脚本或者用 git 初始化一下改崩了能回滚。这类工程壳的代码注释往往很少改之前先读一遍相关函数。4. 避坑与排查跑不起来时先看这几条4.1 现象ModuleNotFoundError: No module named model原因脚本 import 的模块名和实际文件名对不上或者工作目录不对。这个包里模型定义可能内联在脚本里也可能单独一个文件但摘要提到的model.py不一定存在。解决grep -rn import *.py看脚本到底 import 了什么再ls确认对应文件在不在。如果 import 的是from models.nafnet import NAFNet这种带包的路径确认目录层级对得上。工作目录必须是工程根目录别在子目录里跑。4.2 现象CUDA out of memory原因输入图太大或者 4K 图误用了 normal 脚本。NAFNet 虽然比 Transformer 类模型省显存但 4K 全图仍然吃不消。解决普通图用 normal 脚本4K 用 4k 脚本仍然爆就手动把输入 resize 到 1080p 左右再跑或者调小 tile。临时救急可以torch.cuda.empty_cache()但治标不治本。4.3 现象输出图全黑或全灰原因权重没加载成功或者输入归一化方式不对。常见的是权重加载时 key 不匹配但被strictFalse吞掉了模型跑的是随机初始化。解决加载权重时先print(state.keys())和print(model.state_dict().keys())对比确认对得上。归一化方面NAFNet 一般输入除以 255 再减均值除方差输出再反归一化脚本里如果漏了反归一化就会全黑。4.4 现象处理速度慢到无法接受原因跑在 CPU 上或者没开torch.no_grad()。推理时不开 no_grad 会保留计算图显存和速度都受影响。解决确认torch.cuda.is_available()为 True在推理循环外套with torch.no_grad():。这两条是推理脚本的基本功漏一条速度差好几倍。4.5 现象中文路径或文件名导致读写失败原因OpenCV 的imread/imwrite对非 ASCII 路径支持不好这是老问题。解决要么把文件名改成英文数字要么用cv2.imdecode(np.fromfile(path, dtypenp.uint8), cv2.IMREAD_COLOR)绕过。批量处理前统一重命名最省事。5. 验证效果与进阶PSNR/SSIM 怎么算以及一个提细节的技巧跑完一轮怎么知道去模糊到底有没有用肉眼看是一方面但批量处理时得有个量化指标。PSNR 和 SSIM 是最常用的两个前提是你有清晰原图作为参考——如果没有配对数据就只能靠肉眼。有配对数据时用下面这段算指标import cv2 import numpy as np from skimage.metrics import peak_signal_noise_ratio as psnr from skimage.metrics import structural_similarity as ssim def evaluate(gt_path, pred_path): gt cv2.imread(gt_path) pred cv2.imread(pred_path) # 尺寸对齐不一致先 resize if gt.shape ! pred.shape: pred cv2.resize(pred, (gt.shape[1], gt.shape[0])) p psnr(gt, pred, data_range255) s ssim(gt, pred, channel_axis2, data_range255) return p, s p, s evaluate(gt/001.png, outputs/001.png) print(fPSNR{p:.2f} SSIM{s:.4f})逻辑说明data_range255是因为图像是 uint8channel_axis2告诉 SSIM 这是彩色图不指定会按灰度算导致数值偏高。PSNR 对亮度误差敏感SSIM 对结构敏感两个一起看。经验上 PSNR 提升 1dB 以上肉眼能感知SSIM 提升 0.02 以上算明显。注意如果你的清晰原图本身也是压缩过的指标会虚高参考价值打折。进阶技巧NAFNet 去模糊后有时会偏平细节不够锐。一个不改模型的做法是把输出和原图做一个加权融合保留一点原始高频# 输出与原图按比例融合alpha 控制锐度 alpha 0.85 restored cv2.imread(outputs/001.png).astype(np.float32) original cv2.imread(inputs/001.png).astype(np.float32) fused alpha * restored (1 - alpha) * original cv2.imwrite(outputs/001_fused.png, fused.clip(0, 255).astype(np.uint8))alpha取 0.80.9 之间比较稳太低等于没去模糊太高又回到偏平。这个融合对运动模糊效果一般但对轻微失焦和噪点混合的糊图观感提升明显。从那以后我每次跑完去模糊都会先抽三五张做融合对比确认 alpha 再批量——直接全量跑完再发现偏平返工成本太高。希望帮到你。本文还有配套的精品资源点击获取