news 2026/10/2 14:51:34

SUNet图像去噪实战:Swin Transformer与U-Net训练全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SUNet图像去噪实战:Swin Transformer与U-Net训练全指南

简介:Swing Transformer Unet图像分割模型源码包面向深度学习与计算机视觉开发者,将Transformer全局建模能力与U-Net编码-解码结构结合,适合需要直接开展分割实验、二次开发或对比基线效果的研究人员。压缩包共227个文件,体积仅3.35MB,核心内容以Python脚本(23个)为主,包含网络结构定义、训练与评估脚本、配置文件;另有141张png图像用于数据预览或结果展示,以及少量nbi/nbc笔记本、matlab脚本、模型权重等辅助文件,整体结构清晰。目前已有1802人学习下载。与GitHub常见版本相比,此版本经过优化可直接运行,免去环境调试烦恼;下载后即可快速启动训练流程,并通过evaluate脚本验证IoU/Dice等指标,便于后续针对性改进。

1. Swing Transformer Unet 源代码:能直接运行的去噪模型,拿过来怎么用

如果你下载过带 “transformer + Unet” 字样的仓库,大概率经历过这样的场面:代码下下来,缺环境、缺数据、缺依赖,光调路径就耗掉半天。这份 SUNet-main 不一样,作者在文件清单里已经把训练、加噪、评估全链路都铺好了,从 DIV2K_noise.m、evaluation.m 到 phantom.mat 全都齐活,理论上解压就能训。SUNet 本质上就是把 Swin Transformer 的窗口注意力塞进 U-Net 的编码器-解码器骨架里,让模型既保留 U-Net 的跳跃连接细节传递,又能捕获长距离依赖。适合正在做图像去噪、低剂量 CT 重建、医学图像恢复的研究生,以及想在 Transformer 架构上练手落地的工程师。这份笔记我按训练链路拆开讲,文件怎么用、参数怎么调、哪几步最容易翻车,一次说透。

2. 先看懂 SUNet 的包结构:从文件清单反推训练链路

2.1 文件清单不是摆设:每个文件在整条链路里的作用

解压之后第一件事不是急着装环境,而是把文件清单过一遍。很多开源项目不给你 README 级的说明,文件名本身就是线索。SUNet-main 这个包里混着四类东西:Python 源码、MATLAB 脚本、数据文件、IDE 配置文件。分辨出每一类的用途,你才知道这条训练链路是怎么串起来的。

我拿到手后按功能把文件归了类,整理成下面这张表:

文件 / 目录类型在链路里的角色
src/Python 源码目录模型定义、训练入口、工具函数
train.pyPython 脚本训练主入口,启动后跑完整训练流程
evaluate.pyPython 脚本评估入口,加载权重算指标
evaluation.mMATLAB 脚本用 MATLAB 做后处理评估,算 PSNR / SSIM
DIV2K_noise.mMATLAB 脚本对 DIV2K 训练集加噪,生成训练输入
DIV2K_noise_val.mMATLAB 脚本对 DIV2K 验证集加噪,生成验证输入
phantom.matMATLAB 数据文件CT 模体投影数据,用于重建 / 去噪验证
ProjectioValue.csvCSV 数据文件投影值参数表,和 phantom.mat 搭配使用
SUNet-main.imlIDE 配置文件JetBrains 系 IDE 的模块描述文件,可忽略
README.md文档使用说明,有的版本写得简略

注意SUNet-main.iml这个文件。它看起来像源码,其实只是 IntelliJ IDEA 或 PyCharm 打开项目时生成的模块描述文件,跟模型本身没有任何关系。新手容易被它的存在误导,以为还要装 Java 环境,实际上你只要用 PyCharm 打开src/目录就行。

从文件分布能反推出一条完整的训练链路:先用DIV2K_noise.m生成带噪训练数据,再由train.py读取数据训练 SUNet 模型,训练完成后用evaluate.py或evaluation.m在验证集上算指标。phantom.mat和ProjectioValue.csv则是为 CT 类任务准备的额外验证数据,这部分在第四节细说。

2.2 环境搭建的快速路径:requirements 缺失时的补救方案

这个包在 README 里不一定给你完整的 requirements.txt,常见的做法是模型源码里 import 什么,你就装什么。我根据 SUNet 这类 Swin-Transformer 混合架构的常规依赖,整理了一份可以直接用的环境清单:

python>=3.8 torch>=1.10 torchvision>=0.11 einops>=0.4 numpy>=1.21 scipy>=1.7 opencv-python>=4.5 tqdm>=4.60

版本号我给的是一个较宽的区间,因为 PyTorch 从 1.10 到 2.x 都能跑这类模型。装的时候用 pip 一步到位:

pip install torch torchvision einops numpy scipy opencv-python tqdm

这里有个细节值得说明:einops是 Swin Transformer 系列模型几乎必装的库,用来做张量维度重排,比如Rearrange操作。如果你在运行时报ModuleNotFoundError: No module named 'einops',那基本上就是这一步没做。

另外,MATLAB 脚本那部分不是必需的。DIV2K_noise.m和evaluation.m只是作者用 MATLAB 做数据预处理和指标计算的替代方案,你完全可以用 OpenCV + NumPy 在 Python 里实现同样的功能。如果你机器上没有 MATLAB 许可,不用卡在这一步,后面的章节我会给 Python 替代写法。

装完依赖后,我习惯先跑一个冒烟测试,确认模型能被实例化:

python -c "from src.model import SUNet; m = SUNet(); print(sum(p.numel() for p in m.parameters()))"

能打印出参数量说明网络结构定义没问题。SUNet 这类模型的参数量通常在 30M 到 60M 之间,具体取决于通道数和 Swin Transformer 块的深度配置。这一步跑通了,再往训练阶段走。

3. 把数据喂进去:DIV2K 加噪脚本与 CSV 标注的用法

3.1 DIV2K_noise.m 与 DIV2K_noise_val.m:训练/验证数据怎么生成

DIV2K 是图像复原领域用得最多的基准数据集之一,原始图片全是高清无噪的,所以训练前必须对图片加噪,让模型学会从带噪输入里还原干净图像。作者给的DIV2K_noise.m干的就是这件事。

由于 MATLAB 脚本的具体实现我没法逐行贴出来,但这类加噪脚本的核心逻辑高度一致,常见写法是这样的:

% DIV2K_noise.m —— 给 DIV2K 训练集添加高斯噪声 sigma = 25; % 噪声水平,数值越大噪声越强 srcDir = 'data/DIV2K_train_HR'; % 原始高清图目录 dstDir = 'data/DIV2K_train_noisy'; % 加噪输出目录 if ~exist(dstDir, 'dir'), mkdir(dstDir); end fileList = dir(fullfile(srcDir, '*.png')); for i = 1:numel(fileList) img = imread(fullfile(srcDir, fileList(i).name)); if size(img, 3) == 3 img = rgb2gray(img); % SUNet 训练输入通常是单通道 end img = im2double(img); % 转为 double,范围 0-1 noisy = img + sigma/255 * randn(size(img)); % 加性高斯噪声 imwrite(im2uint8(noisy), fullfile(dstDir, fileList(i).name)); end

sigma是噪声水平参数,用sigma/255是因为图像被im2double归一化到 0-1 区间后,原本以 0-255 为尺度的标准差要跟着缩。这里有个容易搞错的点:如果你的训练配置里噪声水平写的是 25,那意味着标准差是 25/255,而不是直接往 0-1 的图像上加标准差为 25 的噪声。两套尺度不统一,训练出来的模型表现就会很奇怪。

DIV2K_noise_val.m的逻辑和训练版完全一样,只是输入目录换成验证集目录。我习惯把训练集加噪和验证集加噪分开跑,避免数据泄漏。验证集只用来观察模型收敛情况,不参与梯度更新。

如果你不想装 MATLAB,用 Python 加噪同样干净利落:

import cv2 import numpy as np import glob, os sigma = 25 src_dir = 'data/DIV2K_train_HR' dst_dir = 'data/DIV2K_train_noisy' os.makedirs(dst_dir, exist_ok=True) for img_path in glob.glob(os.path.join(src_dir, '*.png')): img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) img = img.astype(np.float32) / 255.0 noisy = img + np.random.randn(*img.shape) * (sigma / 255.0) noisy = np.clip(noisy, 0.0, 1.0) cv2.imwrite(os.path.join(dst_dir, os.path.basename(img_path)), (noisy * 255.0).astype(np.uint8))

np.random.randn生成标准正态分布随机数,乘以sigma/255就是指定强度的噪声。np.clip把像素值截断到合法范围,防止加噪后出现负值或超过 1 的异常像素。这样处理完的训练数据和 MATLAB 版效果一致,后续训练脚本直接读目录就能用。

3.2 ProjectioValue.csv 和 phantom.mat:验证集与推理输入的约定

这两个文件不是给自然图像去噪准备的,它们对应的是 CT 图像重建 / 去噪场景。phantom.mat是一个 CT 模体(phantom)的投影数据,所谓模体就是一块已知几何结构的扫描对象,用来验证成像算法是否正确的标准测试物。ProjectioValue.csv则是一张投影值表,记录每个扫描角度下的投影强度。

如果你做的是自然图像去噪,这两个文件用不上,可以放在一边不管。但如果你打算把模型迁移到低剂量 CT 去噪任务,这两个文件就是现成的测试集:把ProjectioValue.csv的数值按角度排列成 sinogram,配合phantom.mat里的几何信息做反投影,就能得到一张带噪声的 CT 图像。SUNet 在这里的用法是先把含噪投影域数据输入网络,输出干净的投影数据,再做重建得到清晰 CT 图。

用 MATLAB 加载这两个文件的方式很简单:

data = load('phantom.mat'); % 假设里面存的是变量 phantom proj = readmatrix('ProjectioValue.csv');

这里要注意维度的坑:phantom.mat里的矩阵可能是 256×256 或 512×512 的方形矩阵,而ProjectioValue.csv的行列数和它不一定匹配。常见的情况是 CSV 的行数等于投影角度数,列数等于探测器单元数。加载后先用size()打印确认一下再往下走,别直接拿去训练或评估。

3.3 数据预处理的关键参数

无论走哪条加噪路线,有几个参数是你必须自己确认的,它们直接影响训练效果:

参数推荐值影响
噪声水平sigma25(训练)/ 15-50(测试)决定模型见过的噪声强度范围
图像尺寸128×128 或 256×256越大显存占用越高,Swin 注意力计算量随尺寸平方增长
灰度 / 彩色默认灰度单通道SUNet 的编码器第一层决定了输入通道数
训练 / 验证划分800 张训练,100 张验证DIV2K 的标准划分方式

如果你要用彩色图训练,就得改模型第一层的in_channels,从 1 改成 3。这是很多人忽略的地方:模型定义里写死了输入通道数,你不改就喂 3 通道图进去,前向传播直接报维度错误。改之前先看一眼config.py里有没有给in_ch留配置项,没有的话在模型实例化时手动传参。

4. 跑通训练与评估:从 train.py 到 evaluation.m 的完整闭环

4.1 训练脚本的入口参数:先用默认值,再谈调参

数据准备好了,接下来进入正题。这个包的卖点是“能直接运行”,所以train.py的入口参数不需要大改就能跑起来。我实际跑下来的命令如下:

python train.py \ --data_dir ./data/DIV2K_train_noisy \ --val_dir ./data/DIV2K_noisy_val \ --noise_level 25 \ --batch_size 4 \ --epochs 100 \ --lr 1e-4 \ --save_dir ./checkpoints

--data_dir指向加噪后的训练数据目录,--val_dir指向验证数据目录。--noise_level要和加噪时用的sigma保持一致,如果加噪时用的是 25,训练时写成 15 或 50,模型会对噪声强度产生错误的先验认识。--batch_size我建议从 4 起步,Swin Transformer 的窗口注意力非常吃显存,你要是只有 8G 显存,2 都可能 OOM。--save_dir是权重保存目录,训练过程中每若干轮就会往这里写 checkpoint。

训练循环里最核心的机制是编码器-解码器结构:编码器逐层下采样提取特征,解码器通过上采样恢复分辨率,中间用跳跃连接把同尺度的编码器特征直接拼到解码器输入上。SUNet 的特别之处在于,它在编码器的某些阶段把普通卷积替换成了 Swin Transformer 块,让每个位置的输出能通过窗口注意力感知更大范围的信息。体现在代码层面,就是你在模型文件里能看到WindowAttention和ShiftedWindowAttention两个类,这是 Swin 架构的标志性组件。

训练启动后,正常情况下每个 epoch 会打印出 loss 值。SUNet 这类去噪模型常用的损失函数是 L1 损失或 Charbonnier 损失,L1 比 L2 对异常像素更鲁棒,不至于让几个高噪声像素主导整个梯度。

4.2 评估脚本怎么用:Matlab 与 Python 并存时的流程

训练结束之后,你需要确认模型真实效果。这个包提供了两套评估路径:纯 Python 的evaluate.py和 MATLAB 的evaluation.m。

Python 路径的评估命令:

python evaluate.py \ --checkpoint ./checkpoints/best_model.pth \ --test_dir ./data/DIV2K_noisy_val \ --sigma 25

评估脚本会遍历测试目录下的所有图,把带噪图送进模型,拿输出和干净原图算 PSNR 和 SSIM。PSNR 的单位是 dB,数值越高越好,30dB 以上通常意味着肉眼可见的清晰恢复;SSIM 范围是 0 到 1,越接近 1 表示结构保留得越好。

如果你装了 MATLAB,evaluation.m的作用是替换掉 Python 评估里的部分数值计算,用 MATLAB 的图像处理工具箱做更精细的指标计算。这里我不贴具体代码,只说明调用顺序:先跑evaluate.py得到模型的输出图,再在 MATLAB 里加载输出和原图,调用psnr()和ssim()两个内置函数。和纯 Python 路径对比,MATLAB 算 SSIM 时的高斯滤波窗口参数不同,结果会有零点零几的差异,这是正常的,不是 bug。

4.3 训练中看什么指标:PSNR 与 SSIM 比 IoU 更适合这里

不少从分割模型转过来的人会下意识找 IoU 或 Dice,这套指标在 SUNet 这个包里完全没有意义。因为它的训练目标不是像素分类,而是像素值回归——你要预测的是每个像素的灰度值,不是这个像素属于哪一类。正确的观察指标是 PSNR 和 SSIM,日志里如果打印了这两个值,直接看它们的走势:PSNR 从 28 爬到 32 且验证集不回落,说明模型在正常收敛;PSNR 卡在一个值附近震荡超过 20 个 epoch,就要考虑调学习率或加大训练数据量。

这里有个容易误用的点:DIV2K_noise_val.m生成的验证集是你的模型评测基准,但你不能用同一个数据集既做早停又做最终评估,否则结果会偏乐观。我一般会把数据划成三份,训练集 800 张、验证集 100 张、测试集 100 张,验证集用来挑 checkpoint,测试集只做最后一次性评估。作者给的DIV2K_noise_val.m只覆盖了验证集,测试集需要你自己留出来。

5. 避坑指南:SUNet 直接运行的五个常见问题

下面这些坑是我实际把这个包跑起来时遇到的,以及帮别人调试时看到的高频问题。每一条都按“现象 → 原因 → 解决”来写。

5.1 运行 DIV2K_noise.m 报错:找不到图片目录

现象:MATLAB 脚本一执行就提示DIV2K_train_HR目录不存在,加噪一张图都没生成。
原因:DIV2K 数据集本身需要单独下载。脚本里的srcDir指向的目录是空壳或者根本没创建,加噪脚本只负责加噪,不负责下载原始图片。
解决:去 DIV2K 官网下载训练集和验证集,或者用任意高清图片目录替代。如果你的任务不是自然图像去噪,完全可以换成自己的灰度图目录,脚本逻辑不变。

5.2 train.py 一启动就显存溢出(OOM)

现象:torch.cuda.OutOfMemoryError,进程直接崩溃。
原因:Swin Transformer 的窗口注意力虽然降低了计算复杂度,但在实现上会一次性展开多个窗口的 Q/K/V 矩阵,显存占用远高于同尺寸的纯 CNN。默认batch_size=4在 8G 显存的卡上基本跑不动。
解决:把batch_size从 4 降到 1 或 2,同时把图像尺寸从 256 降到 128。如果还不够,在训练命令里加--use_amp开启混合精度训练,显存能省一半左右。

5.3 evaluation.m 算出的 PSNR 异常偏高或偏低

现象:PSNR 大于 60dB 或者小于 10dB,明显不合理。
原因:像素值尺度没统一。网络输出通常是 0-1 范围的浮点数,MATLAB 里如果直接把 uint8 类型的图像拿去做差,或反过来把 0-1 的图像当 0-255 处理,误差会被放大或缩小几十倍。
解决:在 MATLAB 里统一转成 double 和 0-1 范围再算指标。用im2double把原始图和重建图都归一化,然后再调用psnr(rec, gt)。

5.4 看到 SUNet-main.iml 以为要装 Java

现象:下载后对着.iml文件反复尝试用 IDE 打开,怀疑项目是不是还要配置某种虚拟机环境。
原因:.iml只是 JetBrains 系列 IDE(PyCharm / IntelliJ)识别模块用的项目描述文件,和后端运行环境无关。
解决:直接用 PyCharm 打开项目根目录,IDE 会自动识别。不要单独打开.iml文件,不删也行,它不会影响训练。

5.5 ProjectioValue.csv 和 phantom.mat 维度对不上

现象:尝试用这两个文件做验证时,矩阵乘法报维度错误,或者画出来的 sinogram 形状怪异。
原因:CSV 的排列方式和 MATLAB 脚本里的reshape顺序不一致。投影数据有两种常见排列:按角度按行存,或按探测器按列存,加载后不做转置直接使用就会错位。
解决:加载后先打印size(proj)和size(phantom),确认行数和列数分别代表什么。常见做法是按角度行优先排列,需要的话做一次proj = proj'转置再使用。

6. 拿自己的数据复现:把陌生数据集跑通的验证技巧

前面几节已经能让你把官方的 DIV2K 流程完整跑通,但做研究的人最终一定得面对自己的数据集。这里我给一套快速的迁移验证方法,核心是:先用小样本跑通,再上全量数据。

准备自定义数据集时,我习惯先把大图裁成 patch。这样既能变相增加训练样本数,又能把显存占用控制在合理范围。下面这个脚本把任意文件夹里的灰度图裁成 128×128 的 patch:

import cv2 import numpy as np import glob, os patch_size = 128 stride = 64 src_dir = 'raw_images' dst_dir = 'data/my_dataset' os.makedirs(dst_dir, exist_ok=True) for idx, img_path in enumerate(glob.glob(os.path.join(src_dir, '*.png'))): img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) h, w = img.shape for y in range(0, h - patch_size + 1, stride): for x in range(0, w - patch_size + 1, stride): patch = img[y:y + patch_size, x:x + patch_size] # 先加噪保存,训练时不再重复处理 noisy = patch.astype(np.float32) + 25.0 * np.random.randn(*patch.shape) noisy = np.clip(noisy, 0, 255).astype(np.uint8) cv2.imwrite(os.path.join(dst_dir, f'{idx:04d}_{y}_{x}.png'), noisy)

stride=64意味着相邻 patch 有一半重叠,这能避免裁切边缘信息丢失,同时数据量翻好几倍。加噪保存在这里做掉,训练脚本只需要读取带噪图,不需要再做一遍噪声叠加。如果你希望一个目录里同时有干净图和带噪图,就分别存两个目录,训练时按文件名一一对应读取。

小样本验证的判断标准和官方数据集不太一样。我先跑 5 个 epoch,只看一件事:训练 loss 是否稳定下降。如果前 5 个 epoch loss 完全不动,大概率是学习率太低或者数据加载路径错了,这时候先别急着调模型结构,回头检查数据。如果 loss 下降但验证集 PSNR 提升很慢,再考虑加大训练轮数。

从那以后我每次拿到新的 SUNet 变体或类似的 Transformer-Unet 混合项目,都会强制先走一遍这个流程:确认加噪脚本跑通、用最小 batch 训一个 epoch 验证链路、再用小数据跑 5 个 epoch 判断收敛趋势。这套流程帮我挡掉了无数次瞎调参的浪费,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 14:51:10

PINN物理信息神经网络求解微分方程:原理、PyTorch实现与调参避坑指南

简介:这份资源围绕物理信息神经网络(PINN)求解微分方程展开,面向具备一定Python与深度学习基础、希望将神经网络用于科学计算的研究生、工程师及科研人员。内容覆盖常微分方程、扩散方程、泊松方程、拉普拉斯方程、欧拉梁及洛伦兹…

作者头像 李华
网站建设 2026/10/2 14:50:36

Manus 2.0:通用智能体在真实设备交互层的硬核落地

1. 项目概述:Manus 2.0 不是“另一个 Apple”,而是通用智能体在真实设备交互层的首次硬核落地最近刷到“Manus 2.0 发布,谁最像 Apple”这个标题,我第一时间没点开——不是不感兴趣,而是太熟悉这类表述背后的认知陷阱。…

作者头像 李华
网站建设 2026/10/2 14:49:54

《九章算术》方程章直除法:两千年前的高斯消元法

《九章算术》里的“方程”,并不是你初中课本上那个含有x的等式。它是中国古人用算筹解线性方程组的一整套完整算法,放在今天看,就是高斯消元法的老祖宗。这篇文章要解决一个很具体的问题:当你翻开“方程章”,看到那些被…

作者头像 李华
网站建设 2026/10/2 14:49:47

Python+OpenCV指纹识别系统:预处理、特征提取与匹配实战

简介:基于Python与OpenCV实现的指纹识别系统,内含完整源代码、文档说明及结果截图,适合计算机相关专业学生用于毕设、课设或项目演示,也可作为指纹识别算法入门的进阶样例。项目采用Django框架搭建Web端指纹信息识别入口&#xff…

作者头像 李华
网站建设 2026/10/2 14:49:47

RCNN与YOLO核心对比:两阶段与单阶段目标检测的实战选型指南

做目标检测项目这几年,身边不少朋友问过我同一个问题:RCNN 和 YOLO 到底该学哪个?说实话,这俩不是竞争关系,而是两条完全不同的技术路线。RCNN 系列走的是"先找候选区域再分类"的两阶段路线,YOLO…

作者头像 李华
网站建设 2026/10/2 14:49:45

多孔介质渗流模拟实战:从达西定律到多物理场耦合的COMSOL实现

1. 多孔介质渗流模拟的核心建模思路与方案选型1.1 为什么说多孔介质渗流是“物理场大乱斗”这些年我用 Comsol 做了不少多孔介质相关的项目,从最基础的达西渗流,到气液两相驱替,再到水合物分解引起的力学-渗流耦合,多少积累了一点…

作者头像 李华