尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

基于深度学习的图像去噪:CNN与残差学习全解析

基于深度学习的图像去噪:CNN与残差学习全解析 简介图像去噪是计算机视觉长期关注的基础问题旨在从含噪观测中恢复干净图像。传统滤波算法在强噪声下易导致纹理模糊而卷积神经网络CNN凭借数据驱动的特征学习能力结合残差学习策略让网络预测噪声残差而非直接生成图像显著提升去噪性能。在图像采集、传输与压缩等应用场景中该类方法已成为预处理核心模块。围绕一套完整的DnCNN工程实现从网络分层结构、感受野设计、数据增强到训练评估流程均给出可复现代码并以PSNR、SSIM等量化指标客观衡量模型效果为深度学习和计算机视觉开发者提供从理论到落地的参考。1. 项目概述与核心思路拆解1.1 这个项目到底解决了什么问题图像去噪Image Denoising是计算机视觉里一个非常古老又极具生命力的研究方向。什么意思呢就是你的照片在拍摄、传输、压缩的过程中会因为传感器热噪、光线不足、信号干扰等原因混入一堆随机的亮度异常点直观表现就是画面发花、有颗粒感、边缘发糊。过去我们常用高斯滤波、中值滤波、双边滤波这类传统方法去处理效果怎么说呢——在噪声比较轻的时候勉强能用一旦噪声强度上去图像纹理细节就被抹得跟油画一样整个画面“塑料感”十足。深度学习起来之后这个局面被彻底打破了。这个项目就是一个典型的“深度学习去噪”实现而且用的是最经典、最扎实的基础架构——CNN卷积神经网络。它做的事情说白了就是用海量的人工加噪-干净图像对去训练一个神经网络让网络学会从含噪图像中“猜出”干净图像。和传统方法的本质区别在于传统滤波是数学家设计出来的固定模板而CNN是数据驱动的那套逻辑网络自动从训练数据里学出上百个甚至上千个滤波器。我最初拿到这个项目的时候第一反应是“又一个DnCNN套壳”毕竟CNN去噪领域的里程碑DnCNNDeep Convolutional Neural Network for Image Denoising框架太经典了。但实际看下来这个项目把从数据准备、网络搭建、训练流程到评估指标全链路打通了尤其适合做三件事第一深度学习入门者理解卷积网络是怎么做低层视觉任务的第二图像预处理工程中需要一个可靠去噪模块的开发者第三想复现经典论文但又被各种环境配置劝退的研究者。因为它不是那种只给一段核心代码的论文附属品而是一个能直接跑出结果、能替换数据集、能调整网络结构的完整工程。1.2 为什么是“预测噪声”而不是“直接输出干净图”这个项目最核心的一个设计思想是我觉得初学者最容易忽略的网络要学的目标不是干净图像本身而是“噪声图”即含噪图减去干净图的残差。这两个思路有什么区别我来用一个非常生活化的类比解释。假设你是一个文物修复师拿到一件被灰尘覆盖的古画。一种办法是直接凭空想象原画长什么样然后一笔一笔补回去这就是“直接映射到干净图”对网络来说非常难因为它要凭空生成大量高频纹理信息本质上是在做一个几乎病态的问题。另一种办法是只把“灰尘”识别出来、剥掉让原有的画面自然露出来即可这就是残差学习。灰尘模式噪声相对简单、可学而原画干净图的信息复杂度远高于噪声让网络去学简单的那部分收敛速度和最终效果都会好得多。数学上这个逻辑也很漂亮。如果用( y )表示含噪图像( x )表示干净图像( v )表示噪声那么( y x v )。传统CNN的做法是学一个函数( f(y) \approx x )而残差学习的做法是学( R(y) \approx v )然后输出( \hat{x} y - R(y) )。这里的巧妙之处在于网络把“生成图像”这个难题转换成了“拟合残差”这个相对简单的问题同时网络结构天然适合做这件事——输入和输出之间有一条类似恒等映射的路径深层信息不会被轻易抹掉。从实验效果看这个项目用17层卷积网络残差学习在BSD68数据集上σ25的高斯噪声条件下PSNR能达到29dB以上这个数字比我用双边滤波处理同样图像时的24dB左右高出一大截。而这种差距会随着噪声越强拉得越大。如果你把这个思想和“为什么传统方法干不过深度学习”结合起来理解对CNN能力边界会有更直观的认知。1.3 从项目结构看工程化设计的用心我拿到项目后先花了几分钟扫了一遍目录结构发现作者是个懂工程的人。它的组织方式非常清晰基本上是一个完整的深度学习项目模板数据加载模块单独抽出来了读图、加噪、切块、归一化都封装成类网络模型定义独立一个文件网络深度、卷积核数量都暴露成参数训练脚本和测试脚本分离训练好模型之后再单独跑测试不用重复加载训练集附带一个简单的预处理工具脚本可以批量生成训练用的噪声图像对。这种工程结构对学习者的价值很大。很多人学深度学习的痛点是论文里的代码和工程落地完全脱节——论文代码一堆实验细节藏在犄角旮旯而工程项目又往往层层封装让人摸不着头脑。这个项目属于那种“看得懂、跑得通、改得动”的中间态。你如果想快速改一个参数看看效果不需要理解全部代码逻辑如果你想深挖某个模块的运作原理每一块都能单独拎出来研究。2. 网络结构一层层拆解CNN去噪的核心设计2.1 三层划分特征提取、非线性映射、重构输出这个项目的网络结构整体走的是DnCNN的经典路线按功能可以拆成三个段落第一段是“特征提取层”。输入是一张含噪的灰度图形状是( H \times W \times 1 )第一层卷积用64个大小为( 3 \times 3 \times 1 )的卷积核做卷积后面接ReLU激活函数。这一步可以把图像从像素空间映射到64维的特征空间相当于把“图像”翻译成“特征的组合”在这个空间里噪声的模式比在原始像素空间更容易被区分出来。第二段是“非线性映射层”。中间连续堆叠多层卷积批归一化ReLU的结构本项目中设置为15层每层都是64个( 3 \times 3 \times 64 )的卷积核。每一层都在不断提炼特征让网络逐步分辨哪些特征是真正的图像结构哪些是噪声伪影。批归一化层的引入特别关键它把每一层的激活值重新拉回到均值为0、方差为1的分布大大缓解了深层网络梯度消失问题让17层深的网络也能稳定训练。这也是传统浅层方法做不到的——传统WWF去噪比如BM3D完全靠人工设计先验而这里的深层网络能自动学出从简单到复杂的特征层次。第三段是“重构输出层”。最后一层用一个单通道的( 3 \times 3 )卷积把64维特征映射回1维输出残差噪声图。如前所述最终去噪结果就是输入减去这个残差。这里有一个细节值得提一下整个网络没有池化层。池化层在分类任务里是标配能扩大感受野、降低计算量但代价是丢失空间细节。去噪任务恰恰要求输出和输入尺寸完全一致每一个像素位置都要对应上所以网络全程使用same padding保持特征图尺寸不变。这种“全程不降采样”的设计思路也是图像到图像翻译类网络比如超分辨率、去模糊、风格迁移的共同选择。2.2 感受野为什么深度是17层而不是3层“为什么网络要这么深”这是我看这个项目时思考最多的问题之一。答案藏在“感受野”这个概念里。感受野指的是输出特征图上每一个像素在原始输入图像上对应了一个多大的区域。一个( 3 \times 3 )卷积的感受野是3×3叠两层每个输出像素就能看到5×5的输入区域叠三层看到7×7。计算公式很简单第( n )层的感受野大小是( 2n1 )。叠了17层之后感受野是( 35 \times 35 )像素。这意味着什么网络在判断一个像素是不是噪声、该被怎么处理时依据的不仅仅是这个像素本身还包括了周围35×35范围内的上下文信息。这对去噪至关重要。想象一下画面里有一段平滑的墙面中间恰好有一个亮斑你只看这个亮斑可能会把它当成一个信号细节保留下来但如果能看到周围一大片平滑区域你就有足够把握判断这只是一个孤立的噪声点。感受野越大网络对“上下文”的判断能力越强误判率和保留细节的能力都越好。但这个深度也不是越深越好。我在实践中有个比较直观的感受到了20层以上训练时间大幅增加但PSNR的提升开始变得非常缓慢基本到了边际效应递减的阶段。17层这个数字不是拍脑袋定的它是DnCNN论文里反复实验后得到的“性能-成本平衡点”。这个项目沿用17层等于直接站到了巨人肩膀上。2.3 代码级实现一个可运行的CNN去噪网络真正想跑通这个项目核心网络结构的代码是理解一切的关键。这个项目用的是TensorFlow实现我根据自己的习惯用PyTorch复现了一版结构完全等价但代码更直观import torch import torch.nn as nn class DnCNN(nn.Module): def __init__(self, depth17, n_channels64, image_channels1): super(DnCNN, self).__init__() layers [] # 第一层卷积 ReLU不加BatchNorm layers.append(nn.Conv2d(image_channels, n_channels, kernel_size3, padding1)) layers.append(nn.ReLU(inplaceTrue)) # 中间层卷积 BatchNorm ReLU for _ in range(depth - 2): layers.append(nn.Conv2d(n_channels, n_channels, kernel_size3, padding1)) layers.append(nn.BatchNorm2d(n_channels)) layers.append(nn.ReLU(inplaceTrue)) # 最后一层卷积输出单通道残差图 layers.append(nn.Conv2d(n_channels, image_channels, kernel_size3, padding1)) self.model nn.Sequential(*layers) def forward(self, x): residual self.model(x) return x - residual代码是简单的但有几个关键细节我提一下这些都是实操中容易被坑到的地方第一第一层不加BatchNorm。这是DnCNN论文里的一个经验设计。输入图像像素值范围是[0,1]或[0,255]直接过BatchNorm会把数据分布强行拉向标准化分布反而丢失了原始图像的动态范围信息。而从第二层开始前一层经过ReLU之后特征分布已经比较混乱这时候加BatchNorm正则化效果就很好。这个细节看着不起眼但真的是论文作者做了大量对比实验得到的结论。第二中间层全是padding1。如果你把padding设成0那么每经过一层卷积特征图尺寸就会缩水2个像素17层下来输出尺寸会比输入小34个像素完全无法与输入相减。所以必须通过padding保持尺寸一致。这也是所有图像到图像任务的通用处理方式。第三输出层的激活函数是线性的即不加任何激活。因为噪声的取值可能是正的也可能是负的如果图像归一化到[0,1]噪声在[-0.5,0.5]范围内波动如果最后一层加一个ReLU强制输出非负值网络就永远学不会“负噪声”的模式。3. 数据准备与处理决定模型上限的隐形因素3.1 训练数据的选择BSD400与ImageNet裁剪策略很多初学者容易忽视一个事实模型效果的上限不是网络结构决定的而是数据决定的。DnCNN论文里用的训练集是BSD400Berkeley Segmentation Dataset中400张训练图加上ImageNet中随机裁剪的图片以增加数据多样性。这个项目在数据选择上沿用了这套思路。BSD400都是灰度图内容以自然场景为主树木、建筑、动物、纹理各异对于去噪任务来说是一个很均衡的训练集。实际使用中我也试过只用imagenet的灰度子集训练效果并没有比BSD400好多少反而因为数据量太大训练时间翻了好几倍。所以我比较建议先用BSD400把整个流程跑通、验证模型没问题再根据需求决定是否扩充数据。这算是我踩过坑之后的一个教训不要一开始就上大数据集否则你连是网络结构的问题还是代码的bug都无法快速定位。3.2 图像切块让有限的训练图像发挥最大价值训练图像尺寸差异很大有的1024×1024有的256×256不可能直接塞进网络训练。所以项目里的标准做法是“随机裁剪切块”——从每张训练图上随机裁剪出固定大小的图像块patch本项目中设置为( 40 \times 40 )像素。为什么是40×40这里其实有个很有讲究的设计逻辑网络感受野是35×35如果patch尺寸小于或等于感受野大小那么网络实际上就是在用整张patch的全部信息做判断边界效应会非常严重。40×40刚好比35×35大一圈意味着每个中心像素在做决策时都能看到完整的上下文窗口又不会因为patch太大导致单张图能切出的patch数量太少、训练样本不足。从效率角度看一张400×400的图像如果patch是40×40且不重叠只能切出100块但如果你用随机裁剪步长滑动的方式一张图轻松切出几千块。这也解释了为什么很多深度学习项目的训练集看起来只有几百张图却依然能训练出接近SOTA的效果——切块相当于把数据量放大了两个数量级。切块代码的逻辑非常简单def random_crop(image, patch_size40): h, w image.shape[:2] i np.random.randint(0, h - patch_size 1) j np.random.randint(0, w - patch_size 1) return image[i:ipatch_size, j:jpatch_size]3.3 加噪方式与数据增强的几种策略训练数据中的“含噪图”不是网上随便找来的真实噪图而是通过人为添加高斯噪声模拟出来的。这个项目默认使用均值为0、标准差为σ的高斯噪声σ的取值通常设为15、25、50之一对应低、中、高强度噪声。很多新手困惑的一个问题是训练时到底该用一个固定σ还是多个σ混合我的经验是如果你想得到一个在某一噪声水平下效果最好的模型就用固定σ训练如果你想得到一个通用去噪模型无论噪声强度都能处理就用噪声水平范围[0, 55]均匀采样随机生成每个patch的σ值。这个项目的做法比较灵活支持两种模式但默认配置文件里用的是固定σ25。我建议初次跑通的阶段先按默认来等模型能正常收敛、指标正常了再改成随机σ试试。这种逐步实验的方式能让你更清晰地理解每个因素对结果的影响。数据增强方面项目采用了常规的“随机翻转随机旋转90度”策略。这样做的意义在于卷积神经网络本身不具备旋转不变性——你把一个斜着的边缘输入网络和把这个边缘旋转90度再输入卷积核激活的模式是完全不同的。通过对训练样本做几何变换相当于让网络见过更多种姿态的边缘、纹理泛化能力会有非常明显的提升。实践中我观察到加了这组增强之后在BSD68测试集上PSNR大概能有0.3~0.5dB的提升这个提升幅度在去噪领域已经非常可观了。数据预处理最后一步是归一化。建议把像素值从[0,255]缩放到[0,1]再输入网络。好处有两个一是梯度更新更平稳避免数值溢出导致梯度爆炸二是不同训练集之间的分布差异被压缩模型迁移到新数据上时更稳定。这也是几乎所有深度学习视觉任务的标准做法。4. 训练、调参与评估从损失函数到PSNR/SSIM4.1 损失函数的选择MSE为何能同时服务训练和评估这个项目的训练目标是最小化“预测噪声图”和“真实噪声图”之间的均方误差Mean Squared ErrorMSE[ L(\theta) \frac{1}{N} \sum_{i1}^N || R(y_i; \theta) - (y_i - x_i) ||^2 ]其中( R(y_i; \theta) )是网络对第i个样本预测的噪声图( y_i - x_i )是真实噪声图。这个损失函数有两个值得说的地方。第一从数学角度看MSE对应的是高斯噪声模型下的最大似然估计。换句话说如果你假设观测到的图像是“干净图高斯噪声”那么让MSE最小化在统计学上就是在求解最可能的干净图。这一点和噪声类型是对齐的——你用什么假设去设计损失函数模型就会在相应噪声类型下有最好的表现。第二MSE直接对应PSNR指标峰值信噪比。PSNR的定义是[ PSNR 10 \cdot \log_{10} \left( \frac{MAX^2}{MSE} \right) ]其中MAX是像素最大值归一化后是1。所以训练时让MSE降低就等于直接优化PSNR指标。这也是为什么这个项目在评估阶段报告PSNR时能拿到很好看的值——因为训练目标和评估目标是一致的。这一点看似理所当然但在很多深度学习的任务里其实非常少见。你想象一下一个系统考试题目就是平时训练的作业题改了改数字分数能不高吗MSE和PSNR的关系就是这个逻辑。4.2 训练配置与调参实战经验训练阶段的参数选择直接影响收敛速度和最终效果。这个项目的默认配置参考了DnCNN论文我在此基础上做了一次完整的调参实验把我的实测记录分享给你。优化器用的是Adam初始学习率1e-3。为什么选Adam而不是SGDAdam自适应调整每个参数的学习率在训练初期收敛速度极快对学习率的敏感度也低很适合快速验证模型是否正确。但Adam也有缺点训练后期容易在最优解附近震荡收敛不够精细。因此项目采用了一个经典策略前30个epoch用1e-3的学习率之后每10个epoch衰减为之前的0.1倍。我在实践中验证过这个学习率调度策略比恒定学习率最终PSNR高出约0.4dB。batch size我建议设为128如果显存不够64也可以但效果略差一分。patch大小40×40、batch size为128意味着每次迭代要处理128张40×40的小图这让模型参数更新得非常频繁。我实测在单张NVIDIA RTX 3060上训练50个epoch大约需要2小时这个时间成本对初学者来说完全可以接受。还有一个容易被忽略但很重要的参数clipping。由于网络的输出是残差如果预测值过大用输入减去残差后可能出现负像素值或大于1的值。训练时应该对网络输出做幅值裁剪限制在[-1, 1]范围内。这个操作能显著提升训练的稳定性。4.3 推理与评估指标如何客观评价一个去噪模型训练完之后评估阶段是这个项目最让我觉得舒服的部分——它没有用花里胡哨的可视化自嗨而是给出了一套量化指标。评估在BSD68测试集上进行包含68张不同场景的自然图像。对每张图首先加噪加噪的σ和训练时的σ保持一致然后输入网络得到去噪结果最后计算两个指标第一个是PSNR峰值信噪比单位dB。一般来说PSNR在28dB以下说明去噪效果较差图像仍有明显噪声残留28~32dB说明效果不错肉眼基本看不到明显噪声32dB以上说明效果很好细节保留和去噪达到了较好的平衡。无噪声的原始图PSNR趋近于无穷大因为MSE趋近于0通常图像压缩算法达到40dB以上时肉眼就无法分辨差异了。第二个是SSIM结构相似性指数取值范围0~1越接近1说明去噪后的图像与原始图像的结构包括亮度、对比度、纹理越接近。相比PSNR纯粹算像素误差SSIM引入了人类视觉系统对结构信息的敏感度更能反映肉眼感知的图像质量。举个例子A去噪结果的PSNR是29dB但SSIM只有0.85B去噪结果的PSNR是28.5dB但SSIM是0.92在实际观感中B反而更好因为它的结构保留更完整、纹理更自然。这个项目在σ25的测试条件下我跑出来的结果是PSNR 29.3dB、SSIM 0.89这个数字在固定噪声水平下属于同类模型的正常水平。如果读者注意到DnCNN论文里报告的PSNR是29.23dB说明这个项目的复现是忠实的。评估代码也很简单我用PyTorch实现如下import numpy as np from skimage.metrics import peak_signal_noise_ratio, structural_similarity def evaluate(model, noisy_img, clean_img): model.eval() with torch.no_grad(): output model(torch.from_numpy(noisy_img).float().unsqueeze(0).unsqueeze(0)) denoised output.squeeze().numpy() psnr peak_signal_noise_ratio(clean_img, denoised, data_range1.0) ssim structural_similarity(clean_img, denoised, data_range1.0) return psnr, ssim5. 常见问题排查与训练提速技巧5.1 损失不下降或者直接NaN的排查清单我在跑这个项目的过程中以及帮朋友调试代码的时候遇到过几类高频问题这里直接整理成速查表现象可能原因解决方案Loss在前几个epoch就变成NaN学习率太大导致梯度爆炸调低学习率到1e-4确认数据归一化到[0,1]Loss下降缓慢几十个epoch仍不见起色数据没有归一化或者是网络最后一层没有线性激活导致输出范围受限检查数据预处理像素除以255确保最后一层无激活训练正常但测试时输出全黑/全白反归一化步骤缺失或者输入输出之间加了错误的反向操作推理时要对模型输出加回原始像素偏置检查减法和加法方向训练在固定epoch时Loss突然升高学习率衰减后模型在最优区域震荡这是正常的继续训练即可观察后续是否回落测试PSNR很低低于25dB训练和测试用的σ不一致或者模型没有收敛就提前停止确认训练/测试配置统一延长训练epoch其中最典型的坑是“训练和测试噪声水平不一致”。如果你用σ25训练的模型去测试σ50的含噪图PSNR会掉到25dB以下这并不代表模型不行而是任务本身超出了它的能力范围。所以在项目配置文件中一定要确保训练和评估的噪声参数是同一个值。5.2 训练时间太长怎么办几个立竿见影的技巧训练一个CNN去噪模型的时间成本是初学者最大的痛点之一。这里分享几个我验证有效的加速方案按推荐优先级排序先用小规模数据验证模型正确性。不要上来就跑完整的BSD400数据集。可以先从训练集中随机抽20张图切出2000个patch跑10个epoch。如果Loss能稳定下降、测试PSNR能到28dB以上说明网络结构和代码逻辑没有问题再上全量数据。这能把调试周期从2小时缩短到10分钟。使用混合精度训练。如果你的GPU支持AMPAutomatic Mixed Precision在PyTorch中只需要加几行代码就能实现半精度训练。我实测在RTX 3060上加速比大约1.5倍显存占用减少40%而PSNR几乎不变。训练脚本可以这样改from torch.cuda.amp import autocast, GradScaler scaler GradScaler() for inputs, targets in dataloader: optimizer.zero_grad() with autocast(): outputs model(inputs) loss criterion(outputs, targets) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()提前停止训练。我观察到这个项目在σ25的固定噪声训练中40个epoch之后PSNR的提升就已经很小了50个epoch之后基本进入平台期。与其把时间花在收益甚微的训练上不如提前停止把时间用来做数据增强或调整网络结构。具体判断标准是验证集PSNR连续5个epoch提升不超过0.05dB就果断早停。5.3 推理阶段的性能优化让模型跑得更快训练完成后模型最终是要被部署到实际场景中使用的。这里有几个推理阶段的优化技巧项目代码里没有直接提供但属于工程落地的必选项第一批处理batching。如果需要对大批量图像去噪不要一张一张地喂给模型而是把多张图拼成一个batch同时输入。GPU的并行计算特性决定了batch size为10时的耗时只比单张略高一点点但吞吐量提升了近10倍。而且模型内部没有RNN这样依赖序列的结构batch内部是天然独立的不存在任何串行依赖。第二模型简化/剪枝。如果你不需要17层的精度可以考虑把网络深度减到9层甚至7层。实测结果表明9层网络在σ25时的PSNR大约比17层低0.5dB但推理速度提升近一倍。对于实时视频去噪场景比如每帧16ms的处理时限这个精度-速度的权衡非常值得做。第三ONNX导出TensorRT加速。我在一个项目里把训练好的模型导出为ONNX格式再通过TensorRT做FP16量化推理在Jetson Nano嵌入式设备上实现了从每帧200ms到每帧30ms的飞跃。不过这个方案搭建起来需要额外配置环境适合有一定部署经验的开发者去尝试。对于新手我的建议是先把训练和评估流程完全跑通确保模型指标达标再来优化推理速度。优化是无止境的但前提是有一个运转正常、指标可信的基线模型。没有基线之前的所有优化都是空中楼阁。5.4 一个实用小工具测试单张图的完整脚本最后分享一个我写的小脚本可以在训练完模型后快速测试任意一张图片的去噪效果并生成对比图非常方便import cv2 import torch import numpy as np import matplotlib.pyplot as plt from model import DnCNN # 加载模型 device torch.device(cuda if torch.cuda.is_available() else cpu) model DnCNN(depth17).to(device) model.load_state_dict(torch.load(checkpoints/model_epoch50.pth)) model.eval() # 读取并预处理图像 img cv2.imread(test_noisy.png, cv2.IMREAD_GRAYSCALE).astype(np.float32) / 255.0 img_tensor torch.from_numpy(img).unsqueeze(0).unsqueeze(0).to(device) with torch.no_grad(): output model(img_tensor) denoised output.squeeze().cpu().numpy() # 保存并展示对比 plt.figure(figsize(12, 4)) plt.subplot(1, 3, 1); plt.imshow(img, cmapgray); plt.title(Noisy) plt.subplot(1, 3, 2); plt.imshow(denoised, cmapgray); plt.title(Denoised) plt.subplot(1, 3, 3); plt.imshow(cv2.imread(test_clean.png, cv2.IMREAD_GRAYSCALE), cmapgray); plt.title(Clean) plt.savefig(comparison.png, dpi150)这个脚本最大的好处是直观。你把一张被噪声污染的图片丢进去模型输出的对比图会清楚地告诉你去噪效果到底如何哪里留下了伪影、哪里细节被抹掉了一目了然。看指标和看实际图像是两码事很多模型在PSNR上表现不错但肉眼观感却一般这时候唯一的判断标准就是直接看图。我在实际使用这个项目时最深的一个体会是CNN去噪模型的性能上限很大程度上取决于你喂给它的数据质量和对噪声类型的理解。不同类型的噪声高斯噪声、泊松噪声、椒盐噪声需要不同的损失函数和数据生成策略如果只是机械地套用别人训练好的模型遇到真实场景中的复杂噪声时效果往往会打折扣。这也是为什么我强烈建议无论任务多简单都要从数据生成、网络设计到训练评估完整地自己跑一遍——只有亲手调过这些参数、亲眼看一遍Loss曲线和测试输出才能把“会用模型”变成“理解模型”。本文还有配套的精品资源点击获取
返回列表