简介:这份资源是面向深度学习与图像处理方向学习者、课程大作业与毕业设计需求者的完整项目源码,围绕卷积神经网络图像去噪算法展开研究。项目以DnCNN为核心,同时实现均值滤波、中值滤波、非局部均值NLM与BM3D四种传统算法作为对照,并采用PSNR与SSIM两项指标量化评估去噪效果,五种算法分目录组织,进入对应目录即可运行,便于横向对比实验结论。压缩包共177个文件,以m脚本、mat数据、png图像及多平台mexw64、mexa64等编译文件为主,另含少量txt与md说明,整体约80.31MB,结构清晰、下载即用。目前已有691人学习关注,适合需要完整实验方案、对照算法实现与评价指标代码的读者参考,也可作为大作业与论文实验的可靠起点。
1. 从一份能跑通的图像去噪源码包说起:CNN 与四种传统算法同台对比
很多人做图像去噪大作业时,最头疼的不是写不出代码,而是找不到一份能直接跑、还能横向对比的完整工程。这份基于卷积神经网络的图像去噪项目源码,恰好解决了这个痛点——它把深度学习方法 DnCNN 和四种传统算法(均值滤波、中值滤波、非局部均值 NLM、三维块匹配 BM3D)放在同一个框架下,统一在 Set12 数据集上做对比实验,用 PSNR 和 SSIM 两个指标量化效果。你拿到手后不需要从零搭环境,进入对应目录运行脚本就能看到去噪前后的图像对比。适合正在做深度学习课程设计、需要快速复现 baseline 的本科生和研究生,也适合想理解传统方法与 CNN 方法差异的从业者。整个项目用 MATLAB 实现,目录结构清晰,每个算法独立存放,互不干扰。
2. 五种去噪算法的目录结构与运行入口:先搞清楚每个文件干什么
2.1 目录组织与文件职责划分
拿到压缩包解压后,你会看到五种算法分别放在五个不同的目录中。这种组织方式的好处是依赖隔离——BM3D 需要额外的变换域工具箱,DnCNN 需要深度学习工具箱,分开存放可以避免路径冲突。从项目正文给出的文件列表来看,核心文件包括:
| 文件名 | 所属算法 | 作用 |
|---|---|---|
BM3D.m | BM3D | 基础三维块匹配去噪主函数 |
BM3DDEB.m | BM3D | 去噪增强块(Deblocking)变体 |
BM3DDEB_init.m | BM3D | DEB 变体的初始化参数脚本 |
BM3DSHARP.m | BM3D | 锐化增强版本,适合纹理丰富图像 |
CBM3D.m | BM3D | 彩色图像三维块匹配去噪 |
VBM3D.m | BM3D | 视频序列三维块匹配去噪 |
CVBM3D.m | BM3D | 彩色视频三维块匹配去噪 |
BM3D_CFA.m | BM3D | CFA 格式(Bayer 阵列)图像去噪 |
Demo_test_DnCNN3.m | DnCNN | 深度卷积网络去噪演示脚本 |
Demo_IDDBM3D.m | BM3D | IDD-BM3D 迭代去噪演示 |
均值滤波、中值滤波和 NLM 直接调用 MATLAB 自带函数,没有额外文件。BM3D 和 DnCNN 的代码在原版基础上做了小幅修改,主要是适配 Set12 数据集的读取路径和输出格式。
2.2 运行入口与最小验证流程
先确认 MATLAB 版本不低于 R2018b,深度学习工具箱需要单独安装。验证流程按以下步骤走:
% 步骤1:设置工作目录到对应算法文件夹 cd('path_to/BM3D'); % 切换到 BM3D 目录 % 步骤2:加载 Set12 数据集中的一张测试图 img = imread('Set12/01.png'); % 01.png 是标准测试图 if size(img,3) == 3 img = rgb2gray(img); % 统一转灰度处理 end img = double(img); % 步骤3:添加高斯白噪声,sigma=25 是常用测试强度 sigma = 25; noisy_img = img + sigma * randn(size(img)); % 步骤4:调用 BM3D 去噪 denoised_img = BM3D(noisy_img, sigma); % 步骤5:计算 PSNR 和 SSIM psnr_val = psnr(denoised_img, img); ssim_val = ssim(denoised_img, img); fprintf('PSNR: %.2f dB, SSIM: %.4f\n', psnr_val, ssim_val);这段代码的逻辑很直接:读图、加噪、去噪、评估。sigma参数控制噪声强度,常见取值是 15、25、35、50。BM3D函数的第二个参数必须和加噪时的 sigma 一致,否则去噪效果会明显下降——这是新手最容易翻车的地方。DnCNN 的运行方式类似,但需要先加载预训练模型:
% DnCNN 去噪示例 cd('path_to/DnCNN'); load('model/DnCNN_sigma25.mat'); % 加载对应噪声水平的模型 denoised_img = DnCNN_denoise(noisy_img, net);注意 DnCNN 的模型是和噪声水平绑定的,sigma=25 的模型不能直接用于 sigma=50 的场景。如果要用不同噪声水平,需要重新训练或找对应模型。
3. PSNR 与 SSIM 评价指标:怎么算、怎么看、怎么不踩坑
3.1 PSNR 的计算原理与参数含义
峰值信噪比 PSNR 衡量的是去噪后图像与干净图像之间的像素级差异。计算公式是:
PSNR = 10 * log10(MAX^2 / MSE)其中 MAX 是像素最大值,8 位图像取 255;MSE 是均方误差。PSNR 越大,说明去噪后图像和原图越接近,去噪效果越好。但 PSNR 有个已知局限:它只看像素差异,不考虑人眼视觉特性。有时候 PSNR 很高的图像看起来反而模糊,这就是为什么还需要 SSIM。
在 MATLAB 中计算 PSNR 时要注意数据类型。如果图像是uint8格式,psnr函数会自动按 255 计算;如果转成了double且范围在 [0,1],则需要指定峰值:
% uint8 格式直接算 psnr_val = psnr(denoised_uint8, clean_uint8); % double 格式需要指定峰值 psnr_val = psnr(denoised_double, clean_double, 1.0);很多同学在这里踩坑:去噪函数返回的是 double,原图是 uint8,直接相减会得到错误结果。统一转成 double 再做计算,或者统一用 uint8,不要混用。
3.2 SSIM 的取值解读与边界情况
结构相似性 SSIM 从亮度、对比度、结构三个维度比较两幅图像,取值 0 到 1,越接近 1 表示结构越相似。SSIM 对模糊和结构失真更敏感,和主观视觉质量的相关性比 PSNR 更好。但 SSIM 也有边界情况:当图像本身纹理极少(比如纯色区域),SSIM 会异常偏高,这时候不能只看 SSIM 就下结论。
% SSIM 计算,注意指定窗口大小 ssim_val = ssim(denoised_img, clean_img, 'Window', fspecial('gaussian', 11, 1.5));默认的 SSIM 使用 11x11 高斯窗口,标准差 1.5。对于小尺寸图像(小于 11x11),需要调小窗口,否则会报错。Set12 数据集里的图像尺寸都是 256x256 或 512x512,用默认参数没问题。
3.3 五种算法的指标对比与选型参考
在 sigma=25 的高斯噪声下,五种算法在 Set12 上的典型表现大致如下:
| 算法 | 平均 PSNR (dB) | 平均 SSIM | 运行速度 | 适用场景 |
|---|---|---|---|---|
| 均值滤波 | 26.5 | 0.72 | 极快 | 快速预览,对细节要求低 |
| 中值滤波 | 27.8 | 0.78 | 快 | 椒盐噪声,边缘保持一般 |
| NLM | 29.3 | 0.84 | 中等 | 纹理图像,参数需调 |
| BM3D | 31.2 | 0.89 | 慢 | 高质量去噪,计算量大 |
| DnCNN | 31.8 | 0.91 | 快(GPU) | 有训练数据,泛化好 |
这张表是选型的核心依据。如果你只是做课程设计对比,BM3D 和 DnCNN 是必须保留的;如果追求极致速度,均值滤波可以作为下界参考。注意 DnCNN 的速度优势依赖 GPU,用 CPU 跑会慢很多。
4. 避坑与排查:五个让去噪结果翻车的常见问题
4.1 现象:PSNR 计算结果为负数或异常低
原因:图像数据类型不匹配。去噪函数返回 double 类型且范围在 [0,1],而原图是 uint8 范围 [0,255],直接调用psnr会按 255 计算,导致 MSE 巨大。
解决:统一数据类型。要么都转 uint8,要么都转 double 并指定峰值。
% 统一转 uint8 denoised_uint8 = im2uint8(denoised_double); psnr_val = psnr(denoised_uint8, clean_uint8);4.2 现象:BM3D 运行报错“未定义函数或变量”
原因:BM3D 依赖多个子函数和变换域工具箱,如果只复制了BM3D.m而没复制同目录下的辅助文件,就会报错。
解决:确保整个 BM3D 目录完整,不要单独移动某个文件。检查 MATLAB 路径是否包含所有子目录:
addpath(genpath('path_to/BM3D'));4.3 现象:DnCNN 去噪结果全黑或全白
原因:预训练模型的输入归一化方式与测试图像不匹配。DnCNN 训练时输入是 [0,1] 范围的 double,如果直接喂 uint8 图像,输出会饱和。
解决:在送入网络前做归一化:
input_img = double(noisy_img) / 255; output_img = predict(net, input_img); denoised_img = output_img * 255;4.4 现象:NLM 去噪后图像过度平滑,细节丢失
原因:NLM 的滤波参数DegreeOfSmoothing设置过大。默认值是按噪声方差自动估计的,但如果手动指定了过大的值,会过度平滑。
解决:让 MATLAB 自动估计,或根据噪声水平调整:
% 自动估计平滑参数 denoised = imnlmfilt(noisy_img); % 手动指定,sigma 越大值越大 denoised = imnlmfilt(noisy_img, 'DegreeOfSmoothing', 0.01);4.5 现象:Set12 数据集读取失败,提示文件不存在
原因:项目中的路径是相对路径,如果当前工作目录不是项目根目录,就会找不到文件。
解决:用绝对路径或先切换到项目根目录:
project_root = 'path_to_project'; cd(project_root); addpath(genpath(project_root));5. 进阶技巧:用批处理脚本一次性跑完五种算法并自动生成对比报告
单张图跑通之后,下一步是把 Set12 全部 12 张图跑一遍,自动记录 PSNR 和 SSIM,生成对比表格。手动一张张跑太慢,写个批处理脚本是常规做法。
% batch_denoise.m % 批量运行五种算法,输出对比结果 clear; clc; project_root = pwd; addpath(genpath(project_root)); sigma = 25; algorithms = {'Mean', 'Median', 'NLM', 'BM3D', 'DnCNN'}; num_imgs = 12; results = zeros(num_imgs, length(algorithms), 2); % PSNR 和 SSIM for idx = 1:num_imgs % 读取干净图像 img_path = fullfile(project_root, 'Set12', sprintf('%02d.png', idx)); clean = imread(img_path); if size(clean, 3) == 3 clean = rgb2gray(clean); end clean = double(clean); % 添加高斯噪声 rng(42); % 固定随机种子,保证可复现 noisy = clean + sigma * randn(size(clean)); % 均值滤波 denoised_mean = imfilter(noisy, fspecial('average', 3)); results(idx, 1, 1) = psnr(denoised_mean, clean, 255); results(idx, 1, 2) = ssim(denoised_mean, clean, 'DynamicRange', 255); % 中值滤波 denoised_median = medfilt2(noisy, [3 3]); results(idx, 2, 1) = psnr(denoised_median, clean, 255); results(idx, 2, 2) = ssim(denoised_median, clean, 'DynamicRange', 255); % NLM denoised_nlm = imnlmfilt(noisy); results(idx, 3, 1) = psnr(denoised_nlm, clean, 255); results(idx, 3, 2) = ssim(denoised_nlm, clean, 'DynamicRange', 255); % BM3D denoised_bm3d = BM3D(noisy, sigma); results(idx, 4, 1) = psnr(denoised_bm3d, clean, 255); results(idx, 4, 2) = ssim(denoised_bm3d, clean, 'DynamicRange', 255); % DnCNN load(fullfile(project_root, 'DnCNN', 'model', 'DnCNN_sigma25.mat')); denoised_dncnn = predict(net, single(noisy/255)) * 255; results(idx, 5, 1) = psnr(denoised_dncnn, clean, 255); results(idx, 5, 2) = ssim(denoised_dncnn, clean, 'DynamicRange', 255); fprintf('Image %02d done.\n', idx); end % 输出平均结果 fprintf('\n===== Average Results (sigma=%d) =====\n', sigma); fprintf('%-10s %-12s %-12s\n', 'Algorithm', 'PSNR(dB)', 'SSIM'); for a = 1:length(algorithms) avg_psnr = mean(results(:, a, 1)); avg_ssim = mean(results(:, a, 2)); fprintf('%-10s %-12.2f %-12.4f\n', algorithms{a}, avg_psnr, avg_ssim); end % 保存结果到 mat 文件 save('comparison_results.mat', 'results', 'algorithms', 'sigma');这段脚本的关键点有三个。第一,rng(42)固定随机种子,保证每次加噪结果一致,否则 PSNR 会有小幅波动,对比不公平。第二,psnr和ssim都显式指定了DynamicRange为 255,因为输入是 double 但范围是 [0,255],不指定会按 1.0 计算导致结果错误。第三,DnCNN 的predict输入需要single类型,MATLAB 的深度学习工具箱对数据类型比较敏感,double 会报错。
跑完这个脚本,你会得到一张完整的对比表,直接放进大作业报告里就是现成的实验数据。如果想进一步分析,可以把results矩阵导出成 CSV,用 Python 画柱状图对比:
import scipy.io as sio import matplotlib.pyplot as plt import numpy as np data = sio.loadmat('comparison_results.mat') results = data['results'] algorithms = ['Mean', 'Median', 'NLM', 'BM3D', 'DnCNN'] avg_psnr = np.mean(results[:, :, 0], axis=0) avg_ssim = np.mean(results[:, :, 1], axis=0) fig, axes = plt.subplots(1, 2, figsize=(12, 5)) axes[0].bar(algorithms, avg_psnr, color='steelblue') axes[0].set_ylabel('PSNR (dB)') axes[0].set_title('Average PSNR on Set12') axes[1].bar(algorithms, avg_ssim, color='coral') axes[1].set_ylabel('SSIM') axes[1].set_title('Average SSIM on Set12') plt.tight_layout() plt.savefig('comparison_chart.png', dpi=150) plt.show()从那以后我每次跑对比实验都强制走一遍固定随机种子、统一数据类型、显式指定 DynamicRange 这三步,再也没出现过指标异常的问题。希望帮到你。
本文还有配套的精品资源,点击获取