ARTICLE DETAIL

资讯详情

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

图像去噪实战:MATLAB中传统滤波与DnCNN残差学习对比

图像去噪实战:MATLAB中传统滤波与DnCNN残差学习对比 简介基于MATLAB的图像去噪项目整合传统算法与深度学习方法适合图像处理相关毕业设计、课程设计及入门研究者使用。项目完整实现了均值滤波、中值滤波、高斯滤波等经典去噪手段均值滤波通过imfilter实现中值滤波使用medfilt2高斯滤波调用imgaussfilt便于对照原理学习代码同时提供深度卷积神经网络DnCNN模型的构建、训练与预测代码并包含BM3D等进阶去噪算法方便横向对比不同方法的降噪效果与适用场景。资源包共177个文件以.m源码和.mat数据为主体辅以png图像示例、mex编译文件和说明文档整体大小约80.31MB目录结构清晰可在MATLAB中直接运行演示。目前已有854人学习下载对理解去噪原理、掌握深度学习工具箱应用以及完成实验报告都有实在帮助。1. 同一张噪图的两种解法传统滤波与DnCNN残差学习的边界在哪里图像去噪的问题在于噪声是高频随机信号而图像边缘也是高频信息简单滤波在压制噪声的同时必然损伤细节。传统均值、中值、高斯滤波在MATLAB里几行代码就能跑通适合快速验证但PSNR到了27dB左右就再也上不去而DnCNN通过17层卷积去学习“噪声残差”把去噪问题转化为残差估计效果能提升2到3个dB代价是需要构造训练数据并调网络结构。这个压缩包同时给出了两类方法的MATLAB实现还包括Demo_test_DnCNN3.m和BM3D系列扩展文件很适合毕业设计或课程设计中做“传统方法与深度学习方法对比”的实验主线。下面我会从滤波核参数讲起再展开DnCNN的网络搭建、训练流程和评估指标最后给出几个能让对比实验更可信的细节。2. 传统去噪算法均值、中值与高斯的边界取舍2.1 三类滤波器在MATLAB中的实现与适用场景传统滤波器的共同假设是噪声是局部统计上的离群值可以用邻域像素的中值或加权平均来抑制。均值滤波是线性卷积在MATLAB里用imfilter配合fspecial(average, N)生成N×N平均核也可以用imboxfilt直接实现。它的运算速度最快但每个像素都被邻域平均边缘会随核尺寸增大而变得模糊。中值滤波完全不同medfilt2会取邻域内像素排序后的中位数对椒盐噪声这种极值点有天然排斥作用因为它不需要计算均值所以边缘保持能力比均值滤波好但对高斯噪声这类连续分布噪声的抑制效果一般。高斯滤波在均值滤波基础上引入了空间距离权重imgaussfilt允许直接指定标准差sigma。在实际图像处理大作业里最常用的对比组合就是这三种。下面这段脚本会生成一张带高斯噪声的图像并分别用三种滤波去处理最后用montage拼在一起看视觉效果。这也是MATLAB图像处理课程设计里最基础的可视化路径。% demo_traditional_compare.m rng(0); I im2double(imread(cameraman.tif)); I_noisy I 0.05 * randn(size(I)); % 添加高斯噪声均方差0.05 I_avg imfilter(I_noisy, fspecial(average, 3)); % 3x3均值滤波 I_med medfilt2(I_noisy, [3 3]); % 3x3中值滤波 I_gauss imgaussfilt(I_noisy, 1.2); % 高斯滤波标准差1.2 figure; montage({I_noisy, I_avg, I_med, I_gauss}, Size, [1 4]);fspecial(average, 3)生成的是3×3、每个元素为1/9的卷积核imfilter默认在图像边界补零这会导致边缘出现一条暗边所以我建议在完整实验里加上replicate参数来复制边缘像素。medfilt2的第二个输入是窗口尺寸[3 3]对双精度图像同样有效。imgaussfilt的第二个参数1.2是高斯核标准差它决定了平滑半径这个值越大图像越模糊。提示randn每次生成的噪声序列不同为了让三种滤波器的对比不受到随机噪声差异的干扰代码开头先调用rng(0)固定随机种子。2.2 参数选择核尺寸和标准差如何影响结果这三个滤波器的核心参数都指向同一个问题——邻域范围。均值滤波核从3×3增大到5×5高频分量衰减更明显噪声虽然更少但文字边缘和纹理细节也会被抹掉。中值滤波窗口变大后相同的问题同样会出现尤其是宽度小于窗口的细线会被直接当成噪声消除。高斯滤波标准差增大时等效的卷积核变宽在频域上会压掉更多中低频成分整体平滑感会增强但原始图像的结构信息也会被同步削弱。实际调试时如果已知噪声标准差为sigma高频滤波的sigma建议取1到1.5倍中值滤波窗口大小应略大于噪声颗粒的尺寸均值滤波则尽量控制不超过5×5。下面的表格总结了不同参数下的变化趋势方便做报告时对照方法参数结果趋势均值滤波3×3噪声减少边缘模糊均值滤波5×5平滑更强细节丢失增多中值滤波3×3对椒盐噪声效果好边缘保留中等中值滤波5×5连续噪声抑制一般细线可能被滤除高斯滤波sigma1.0噪声抑制较好边缘略损失高斯滤波sigma1.5平滑更强边缘更模糊从趋势上能看出传统方法很难同时满足“去噪”和“保边”。均值滤波的线性平均决定了它必然牺牲边缘中值滤波的保护能力由窗口形状决定高斯滤波则在空间域上做加权平滑。所有策略都没有利用图像本身的语义信息所以到了更高噪声水平时效果就会明显下降。想要继续提升就需要让模型去“学习”噪声与干净图像之间的关系这正是下一章DnCNN要解决的问题。3. DnCNN网络结构与残差学习为什么能恢复细节3.1 DnCNN的17层卷积设计DnCNN由Zhang等在2017年提出结构上比VGG等分类网络简单核心是17层全卷积。第一层是3×3卷积加ReLU激活输出64个特征图第2到第16层是“卷积批量归一化ReLU”的组合所有卷积核都是3×3特征通道数固定为64最后一层是独立的3×3卷积将特征图映射为单通道输出。批量归一化层在这里不是为了加速收敛而是为了让中间特征分布保持稳定这对像素级回归任务非常关键。最后一层不加ReLU是因为网络输出的是噪声残差残差可能是正数也可能是负数。如果在最后加ReLU所有负残差都会变为0网络就无法正确估计负向噪声。层与层之间使用Padding, same保证输入输出尺寸一致这样网络输出的残差图与输入图像可以逐像素相减不需要额外做裁剪或重采样。3.2 残差学习让网络去学噪声而不是图像如果用网络直接学习从噪声图到干净图的映射网络本质上要重构完整的图像内容训练难度很高。DnCNN的巧妙之处在于它学习的是残差假设输入为y干净图像为x则网络学习的目标是y - x。训练阶段用噪声图减干净图得到残差标签测试阶段把预测残差从输入图中减掉得到去噪结果。从信号角度看干净图像的空间结构复杂想直接生成它需要模型记住大量模式而噪声通常接近零均值随机场统计特性相对简单。网络学习残差相当于只估计“图里哪些像素是被噪声污染的”而干净图像的低频结构完全由输入提供。这种残差学习方式让网络收敛更快也使得边缘和纹理得以原样保留因为网络没有被要求去“重新画”这些细节。3.3 在MATLAB深度学习工具箱中搭建网络在MATLAB里构建这个网络推荐用layerGraph逐层添加和连接。下面这段代码生成了一个输入64×64单通道图像的DnCNN网络结构层数和原文保持一致。代码里使用addLayers配合循环添加中间层再用connectLayers完成连接方便后续调整层数。% build_dncnn.m lgraph layerGraph(); lgraph addLayers(lgraph, imageInputLayer([64 64 1], Name, input, Normalization, none)); lgraph addLayers(lgraph, convolution2dLayer(3, 64, Padding, same, Name, conv1)); lgraph addLayers(lgraph, reluLayer(Name, relu1)); for k 2:16 lgraph addLayers(lgraph, convolution2dLayer(3, 64, Padding, same, Name, [conv num2str(k)])); lgraph addLayers(lgraph, batchNormalizationLayer(Name, [bn num2str(k)])); lgraph addLayers(lgraph, reluLayer(Name, [relu num2str(k)])); end lgraph addLayers(lgraph, convolution2dLayer(3, 1, Padding, same, Name, conv17)); lgraph addLayers(lgraph, regressionLayer(Name, mse)); lgraph connectLayers(lgraph, input, conv1); lgraph connectLayers(lgraph, conv1, relu1); for k 2:16 lgraph connectLayers(lgraph, [relu num2str(k-1)], [conv num2str(k)]); lgraph connectLayers(lgraph, [conv num2str(k)], [bn num2str(k)]); lgraph connectLayers(lgraph, [bn num2str(k)], [relu num2str(k)]); end lgraph connectLayers(lgraph, relu16, conv17); lgraph connectLayers(lgraph, conv17, mse);imageInputLayer里的Normalization, none很关键因为图像已经在训练前归一化过如果这里默认做z-score归一化会破坏残差标签的取值分布。convolution2dLayer第一个参数是核大小3×3第二个参数是卷积核数量64最后一层的输出通道数设为1对应残差图。connectLayers的连接顺序必须保证上一层的输出维度与下一层的输入维度匹配中间插入BN层后ReLU的输入就是经过规范化后的特征图。提示如果MATLAB版本低于R2019abatchNormalizationLayer可能不被支持建议升级到新版否则需要自己实现BN层会增加不必要的复杂度。DnCNN的每个中间层都保持64个通道这意味着网络可学习的参数总量很大。按照这些层参数可以整理成一张简表帮助理解层名类型核大小输出通道说明inputimageInputLayer-164×64单通道输入conv1卷积ReLU3×364第一层特征提取conv2..conv16卷积BNReLU3×364中间15层conv17卷积3×31输出噪声残差mseregressionLayer--均方误差损失4. 训练与评估从噪声图像对到PSNR/SSIM指标4.1 数据准备生成配对样本训练DnCNN需要“干净图像-噪声图像”的配对数据。公开数据集规模比较大课程设计阶段可以先用MATLAB自带的cameraman.tif、peppers.png等图像快速验证流程。下面这段代码生成了单张训练样本并把干净图和噪声图保存到.mat文件中% prepare_training_data.m clean im2double(imread(cameraman.tif)); noise_sigma 25/255; noisy clean noise_sigma * randn(size(clean)); save(train_pair.mat, clean, noisy);这里noise_sigma用的是相对值25/255含义是噪声标准差在0到1的动态范围内约为0.098。randn产生的随机数是标准正态分布乘上noise_sigma后噪声强度就落在预期范围内。实际训练时不会只靠一张图通常用imageDatastore读取整个文件夹的图像再用transform函数批量生成噪声。但要注意网络要学的残差是noisy - clean所以训练标签不能直接使用clean。4.2 训练参数设置有了数据后用trainNetwork训练之前需要设置优化器、学习率和最大轮数。下面这组训练选项适合在小数据集上做初步验证显存占用不大% train_dncnn.m options trainingOptions(adam, ... InitialLearnRate, 1e-3, ... MiniBatchSize, 32, ... MaxEpochs, 30, ... Plots, training-progress, ... Verbose, false, ... Shuffle, every-epoch); X reshape(noisy, [size(noisy,1), size(noisy,2), 1, 1]); Y reshape(noisy - clean, size(X)); net trainNetwork(X, Y, lgraph, options);reshape把单张图变成H×W×C×N的四维数组这是trainNetwork要求的输入格式。adam优化器在像素回归任务上通常比sgdm更稳更快学习率1e-3是正常起点。如果看到训练损失曲线震荡优先把学习率降到1e-4。MiniBatchSize是每次迭代输入的样本数它影响梯度估计的稳定性数值越大梯度越平滑但显存占用越高。MaxEpochs设为30可以先观察收敛趋势实际训练可能需要50到100轮才能充分收敛。训练选项参数含义如下表参数推荐值作用InitialLearnRate1e-3梯度更新步长过大可能发散MiniBatchSize32每次迭代样本数MaxEpochs30最大训练轮数Shuffleevery-epoch每轮训练前打乱数据顺序Plotstraining-progress实时显示损失曲线4.3 评估与可视化训练完成后用predict生成残差图再与原图相减得到去噪结果。评估指标使用psnr和ssim这两个函数在MATLAB图像处理工具箱里可以直接使用。下面这段代码展示了完整流程% test_dncnn.m X reshape(noisy, [size(noisy,1), size(noisy,2), 1, 1]); residual predict(net, X); I_denoised squeeze(noisy - residual); psnr_val psnr(I_denoised, clean); ssim_val ssim(I_denoised, clean); fprintf(PSNR%.2f dB, SSIM%.4f\n, psnr_val, ssim_val);squeeze用于去掉predict输出中长度为1的维度否则noisy - residual的维度会不匹配。psnr默认计算范围为0到1因为我们把图像都转成了double类型所以不需要额外指定峰值信号。如果输入的是uint8图像psnr也会自动处理动态范围。ssim的结构相似度能反映边缘和纹理保持情况通常去噪效果好的网络SSIM会比传统滤波明显更高。5. 对比实验中的实用技巧让传统与DnCNN的结果真的说明问题5.1 用同一噪声种子做公平对比很多课程项目里传统滤波和深度学习的对比图不一致原因是两次生成的噪声不同。固定随机种子是最基本的一步。下面这段脚本把传统高斯滤波、DnCNN预测放在同一噪声样本上进行评估% compare_all.m rng(0); I im2double(imread(cameraman.tif)); n 0.05 * randn(size(I)); I_noisy I n; I_traditional imgaussfilt(I_noisy, 1.5); X reshape(I_noisy, [size(I_noisy,1), size(I_noisy,2), 1, 1]); residual predict(net, X); I_dncnn I_noisy - squeeze(residual); fprintf(高斯滤波 PSNR%.2f dB\n, psnr(I_traditional, I)); fprintf(DnCNN PSNR%.2f dB\n, psnr(I_dncnn, I));rng(0)保证每次运行脚本生成的噪声序列一致这是量化对比的前提。imgaussfilt里标准差设成1.5如果噪声强度是0.05这个值接近噪声标准差的1倍算是一个合理的中间值。5.2 从压缩包里的BM3D系列看传统方法的边界压缩包里包含BM3D.m、CBM3D.m、VBM3D.m、BM3D_CFA.m和BM3DSHARP.m这是传统去噪领域公认效果最好的方法之一。BM3D把相似图像块分成组在变换域协同滤波后再聚合回原位置效果明显优于普通高斯滤波但计算量也高出两个数量级。做报告时可以形成“高斯滤波-BM3D-DnCNN”的三层对比展示从局部线性滤波到非局部协同滤波再到数据驱动残差学习的演进。使用BM3D时需要传入噪声标准差比如噪声水平25/255时一般传25而非归一化后的值否则内部阈值会不匹配导致去噪不足或过平滑。5.3 处理彩色图像与视频帧的小坑DnCNN原版针对单通道灰度图。如果要对彩色图去噪简单的做法是取RGB三个通道分别用同一个网络去噪后再合并也可以把网络输入改成3通道重新训练但训练成本和模型复杂度都会增加。压缩包里的VBM3D.m说明作者已经考虑了视频去噪场景视频相邻帧之间存在时域冗余逐帧独立去噪会导致闪烁DnCNN处理视频帧时也可以做类似处理在时间方向做滑动窗口平均或在训练时把多帧合成一个样本。这几个判断点基本决定了你的对比实验是否经得起问。本文还有配套的精品资源点击获取
返回列表