
简介这份资源是面向图像处理与深度学习方向的开发者、学生及研究者的NAFNet图像去模糊实战项目基于Python实现适合具备一定深度学习基础、希望上手图像复原任务的中高级学习者。压缩包共20个文件约11.98MB以png、jpg图像样本和xml配置为主辅以2个Python脚本、md说明文档及IDE工程文件覆盖模型运行所需的代码、数据与配置。项目围绕NAFNet的卷积层、残差块与注意力机制展开提供4k_pic_restoration.py与normal_pic_restoration.py两套脚本分别对应高清与普通分辨率图像的去模糊处理并附带inputs、outputs目录便于直接观察输入输出效果。已有763人学习下载读者可借此理解模型定义、训练与测试流程掌握数据预处理、PSNR与SSIM指标评估及超参数调整思路快速搭建可复用的图像去模糊实验环境。1. 从一张糊掉的夜景照片说起NAFNet 图像去模糊到底解决什么问题夜里拍的路牌灯光边缘一圈毛刺车牌数字糊成一团这种图丢给传统锐化只会把噪点一起放大。NAFNetNonlinear Activation Free Network是图像复原领域一个很实用的基线它把注意力机制里常见的非线性激活GELU、ReLU、Sigmoid几乎全部拿掉用乘法和门控代替在去模糊、去噪、超分这几类任务上都能用较小的显存跑出接近 SOTA 的效果。这个标题对应的就是一套 Python 实现的 NAFNet 去模糊工程拿到手后你要做的事很明确配好 Python 环境、装依赖、准备成对的模糊/清晰图、跑推理或训练、把结果图导出来。适合两类人一类是手里有模糊照片想批量修复的工程同学一类是想拿 NAFNet 当 backbone 做二次开发的研究向开发者。下面按「环境怎么搭 → 数据怎么组织 → 模型怎么跑 → 坑在哪 → 怎么调优」的顺序讲透。2. 环境搭建与依赖安装把 Python 侧的坑先填平2.1 为什么 NAFNet 对 Python 环境比一般脚本敏感NAFNet 依赖 PyTorch、torchvision、以及可选的 basicsr / timm 等库这些库对 CUDA 版本、Python 版本、编译器版本都有耦合。很多人pip install一把梭之后报undefined symbol或者CUDA error: no kernel image is available本质是 PyTorch 的 CUDA 版本和本机驱动不匹配。我的习惯是先固定 Python 3.9 或 3.10再按显卡驱动去 PyTorch 官网选对应 CUDA 版本的安装命令而不是直接pip install torch。如果你只是推理CPU 也能跑只是单张 1080p 图可能要十几秒批量处理会很难受。2.2 用 conda 建一个干净环境并装依赖# 创建独立环境避免污染系统 Python conda create -n nafnet python3.10 -y conda activate nafnet # 按本机 CUDA 版本装 PyTorch这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 常用辅助库 pip install opencv-python pillow numpy tqdm scikit-image逻辑说明conda create保证环境隔离避免和系统里已有的 numpy、opencv 冲突PyTorch 用官方 index 安装能自动匹配 CUDA runtime比手动编译省事。参数上python3.10是兼容性最好的版本区间3.12 目前部分视觉库轮子还不全。装完用下面这段验证import torch print(torch:, torch.__version__) print(cuda available:, torch.cuda.is_available()) print(device:, torch.cuda.get_device_name(0) if torch.cuda.is_available() else CPU)如果cuda available是 False先别急着改代码去查驱动版本nvidia-smi和 PyTorch 要求的 CUDA 版本是否对得上。这一步是后面所有操作的前提翻车大多翻在这里。2.3 目录结构与权重放置拿到工程后常见目录是models/、options/、data/、results/。权重文件.pth一般放在experiments/或weights/下具体路径以工程里的配置为准。我一般会先跑一次python -c import models之类的导入测试确认没有缺模块再动数据。如果工程里带requirements.txt优先用它但要注意里面可能锁死了旧版本 torch和你的 CUDA 冲突时以能跑起来为准不要死磕版本号。3. 数据准备与推理跑通从单张图到批量去模糊3.1 输入数据的组织方式NAFNet 去模糊训练需要成对数据模糊图input和清晰图target文件名一一对应。推理阶段只需要模糊图。常见做法是建两个文件夹datasets/ train/ input/ # 模糊图 target/ # 清晰图 val/ input/ target/文件名保持一致比如0001.png对0001.png。格式上 PNG 无损适合做训练JPG 会有压缩伪影去模糊任务里会干扰模型。分辨率不要求统一但训练时会被裁剪成 patch常见是 256×256。如果你的图特别大4K 以上推理时显存吃紧需要分块处理这个后面讲。3.2 单张图推理的最小命令python inference_nafnet.py \ --input ./datasets/val/input/0001.png \ --output ./results/0001_out.png \ --weights ./weights/nafnet_deblur.pth \ --device cuda逻辑说明--input指向待处理图--output是结果路径--weights是训练好的权重--device选 cuda 或 cpu。参数上如果工程用的是配置文件驱动options/*.yml那命令会变成python inference.py -opt options/deblur.yml此时改路径要去 yml 里改不要硬改脚本。跑完先肉眼对比输入输出如果输出和输入几乎一样多半是权重没加载成功或者模型处于 eval 之外的状态。3.3 批量推理脚本import os, cv2, torch from models.NAFNet import NAFNet # 路径以实际工程为准 device torch.device(cuda if torch.cuda.is_available() else cpu) model NAFNet(width32, enc_blk_nums[2,2,4,8], middle_blk_num12, dec_blk_nums[2,2,2,2]).to(device) model.load_state_dict(torch.load(./weights/nafnet_deblur.pth, map_locationdevice)[params]) model.eval() in_dir, out_dir ./datasets/val/input, ./results os.makedirs(out_dir, exist_okTrue) with torch.no_grad(): for name in os.listdir(in_dir): img cv2.imread(os.path.join(in_dir, name)) # BGR, HWC img cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(float32) / 255.0 tensor torch.from_numpy(img).permute(2,0,1).unsqueeze(0).to(device) out model(tensor).clamp(0, 1) # 输出限制到 [0,1] out out.squeeze(0).permute(1,2,0).cpu().numpy() * 255 cv2.imwrite(os.path.join(out_dir, name), cv2.cvtColor(out.astype(uint8), cv2.COLOR_RGB2BGR))逻辑说明load_state_dict里取[params]是因为很多 NAFNet 权重保存成 dict 包了一层直接 load 会报 key 不匹配clamp(0,1)防止输出溢出导致保存出花屏颜色通道 BGR→RGB→BGR 的来回转换是最容易写错的地方写反了结果会偏色。参数上width32是通道基数越大越准也越吃显存enc_blk_nums等要和权重训练时的结构完全一致结构对不上会直接报 size mismatch。4. 训练自己的去模糊模型参数怎么设、显存怎么省4.1 训练配置的关键参数参数常见取值作用与调整建议batch_size4~16显存不够先降这个再考虑降 patchpatch_size256太小模型学不到全局模糊太大显存爆lr1e-4 ~ 2e-4配合 cosine 衰减太大直接发散iters20w~40w去模糊收敛慢几万步看不出效果lossL1 FFT纯 L1 偏平滑加频域损失锐度更好4.2 启动训练python train.py -opt options/train_deblur.yml逻辑说明配置文件里改dataroot、batch_size_per_gpu、total_iter。如果单卡显存 8Gbatch 设 4、patch 256 一般能跑12G 可以上 8。训练日志里重点看 L1 loss 是否稳定下降如果前几千步就震荡先降 lr。验证集 PSNR 涨得慢是正常的去模糊任务前期提升很缓别急着换模型。4.3 显存不够时的三个手段第一开混合精度torch.cuda.amp能省 30% 左右显存第二梯度累积把 batch 拆成多次前向再统一 backward第三patch 从 256 降到 192 或 128但要注意降太多会损失大范围模糊的建模能力。这三招按顺序试不要一上来就砍 patch。5. 避坑与排查NAFNet 去模糊最常见的 5 个翻车点5.1 输出全黑或全白现象推理结果是一张纯色图。原因权重没加载成功或者输入归一化方式不对有的工程用 [0,1]有的用 [-1,1]。解决打印模型第一层输出确认非零检查预处理是否和训练时一致/255.0还是/127.5 - 1要对齐。5.2 结果偏色、发绿或发紫现象去模糊后颜色明显不对。原因BGR/RGB 通道顺序在读写时搞反了cv2 读进来是 BGR送模型前要转 RGB保存前再转回 BGR。解决统一在送模型前转 RGB保存时转回中间不要重复转。5.3 CUDA out of memory现象跑到一半报显存不足。原因图太大或 batch 太大。解决推理时对大图做分块tile每块带 overlap 再拼接训练时降 batch 或开 amp。分块拼接要注意边缘融合否则会有明显接缝。5.4 PSNR 很高但肉眼很糊现象指标好看实际观感差。原因L1/L2 损失偏向平均值模型学会了「保守输出」。解决加感知损失或频域损失或者用 GAN 框架微调但要注意 GAN 容易引入伪影调参成本高。5.5 训练 loss 不降现象跑了几万步 loss 几乎不动。原因学习率太大导致发散或者数据对没对齐input 和 target 不是同一场景。解决先降 lr 到 1e-5 试几百步再检查数据配对随机抽几对图叠一起看是否对齐。6. 进阶技巧分块推理与结果验证怎么做才靠谱大图去模糊最实际的问题是显存。我的做法是把图切成带 overlap 的 tile比如 512×512、overlap 64逐块推理后按权重融合边缘。融合权重可以用简单的余弦窗中间权重高、边缘低这样接缝几乎看不出来。代码上就是在每个 tile 输出上乘一个窗函数累加到 canvas最后除以权重和。验证方面别只看 PSNR。去模糊任务里 PSNR 高不代表观感好我一般会同时看三样一是局部放大对比文字、边缘二是频域能量分布是否更接近清晰图三是找几张训练集里没有的场景做泛化测试。如果模型只在训练分布上好换个场景就崩说明过拟合了需要加数据增强或者正则。还有一个容易忽略的点推理时的 padding。NAFNet 里有下采样输入尺寸不是 2 的幂次时边缘会出现伪影。稳妥做法是把输入 pad 到 32 的倍数推理完再裁回去。这个细节不写进代码里跑小图看不出来跑大图边缘就会翻车。我自己踩过最深的一次坑是拿一个去噪权重直接去做去模糊结果输出全是涂抹感后来才明白任务不匹配的权重再像也不能混用。所以每次换权重先跑一张已知结果的图验证再上批量。希望帮到你。本文还有配套的精品资源点击获取