ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

图像噪声抑制实战:三大滤波器原理、代码与调参全解析

图像噪声抑制实战:三大滤波器原理、代码与调参全解析

图像去噪这件事,看起来是数字图像处理课程里一个“打卡”级别的作业,但实际做下来你会发现,它就是整个图像预处理环节里最考验耐心和最吃细节的活儿。如果你之后接触目标检测、图像分割,甚至做深度学习数据集清洗,都会反复和噪声抑制打交道。这篇东西,不绕弯子,直接讲清楚我在做“数字图像处理DIP课程课业打卡七之图像的噪声抑制”时,从原理到代码到调参踩坑的全部过程,尽量让你看完就能自己动手复现。

1. 为什么所有图像处理任务都绕不开噪声抑制

很多初学者会在第一节课就产生疑问:明明照片看起来挺干净的,为什么还要专门花一整节课去研究怎么去噪?这个问题我当时的理解也很浅,直到自己做图像灰度分析时,发现几个异常像素点直接导致边缘检测结果全乱掉,才真正明白噪声抑制不是“锦上添花”,而是“雪中送炭”。

图像噪声的本质,是图像在获取、传输、存储过程中引入的与真实场景无关的随机或伪随机信号。它不属于图像内容,却会污染灰度值分布,干扰后续所有基于像素统计的算法。比如,你在做车牌识别时,如果不去除传感器热噪声,字符分割可能硬生生多出几道竖线;你在做医学影像分割时,散粒噪声形成的细小亮斑,很容易被当成病灶区域。

所以我强烈建议你把噪声抑制当成一个独立的预处理环节来对待,而不是随手套一个模糊滤镜就完事。这个看法的转变,是我完成这次课业后最大的收获之一。真正的噪声抑制,需要你先回答三个问题:图像里的噪声是什么类型?噪声强度有多大?后续任务对图像清晰度有多敏感?这三个问题直接决定了你选什么滤波器、开多大窗口、是采用线性卷积还是非线性排序。

从工程角度来说,噪声抑制大致可以分成空间域和频域两条路线。空间域更直观,直接在像素邻域上做运算;频域则借助傅里叶变换,在频率层面上分析信号与噪声的分布差异。大多数处理项目包括课程作业,优先考虑空间域方案就够了,因为它计算开销可控、实现简单、可解释性强。而频域方法常用于处理周期性的、与图像内容频率重叠较少的噪声,比如扫描仪产生的条纹噪声。

在这次课业打卡里,我核心做的是空间域滤波器的对比实验,同时简单引入了一下频域陷波滤波的效果对照。接下来的内容,主要也是顺着这条线展开。

2. 先给噪声“验明正身”:常见噪声类型与数学模型

动手去噪之前,最重要的一步是识别噪声类型。这就像看病必须先确诊一样,你不可能高烧不退却先吃胃药。数字图像处理里最常见的两类噪声,一个是高斯噪声,另一个是椒盐噪声。这两个是课程实验的基本盘,也是工程中最常遇到的干扰模型。

高斯噪声的来头,一般认为是传感器在弱光环境下放大的热噪声,或者电路本身的随机扰动。它本质上是诸多微小随机因素的叠加结果,因此根据中心极限定理,其灰度值服从正态分布。在实际建模时,我们会使用均值μ和标准差σ两个参数来描述它。当μ=0时,表示噪声对图像整体亮度没有偏置,只会造成像素值的上下波动,σ则表征波动幅度。你用伪随机数发生器生成高斯噪声并叠加到图像上时,图像看起来会有一种雾面颗粒感,细节被蒙上一层细沙。

椒盐噪声则完全不同,它是脉冲形式的。像素值要么被随机置为极大值(255,对应盐),要么被置为极小值(0,对应胡椒)。产生椒盐噪声的原因通常是传输信道中的位错误、切换瞬态或存储介质的坏点。由于其分布是随机离散的尖锐点,与图像本身的结构信息毫无关联,因此它在视觉上表现为密集的随机黑白点。如果是白点偏多,图像就会显得“下雪”,黑点偏多,则像是被“撒了胡椒粉”。

除了识别噪声类型,还建议你用灰度直方图辅助判断。我在做实验时发现,干净图像的直方图是连续而平滑的,叠加高斯噪声后直方图会变得略微粗糙,但整体包络形状仍在;叠加椒盐噪声后,直方图在0和255两端会出现明显的尖峰,这是椒盐噪声最典型的特征之一。

这里顺便提一下乘性噪声和量化噪声。乘性噪声常见于胶片颗粒,它与信号强度相关,去噪难度更大;量化噪声则是模数转换精度不够时产生的误差。这些在入门课程中不要求深究,但是你要知道噪声模型不是只有教科书那两种。

识别噪声后,再去选滤波器,就会非常方向明确。我见过不少同学不做判断,直接拿高斯滤波去处理椒盐噪声,结果黑点白点被模糊但变成灰色小斑,反而让图像显得脏。这种现象说白了就是没有对症下药。

3. 三大滤波手段深挖:均值、中值、高斯谁更适合你

滤波器在空间域做的事情,简单说就是用一个小窗口模板在图像上滑动,对窗口内的像素做某种运算,用运算结果代替中心点的灰度值。窗口尺寸通常是3x3、5x5这种奇数大小,这样才能保证窗口有唯一中心点。三种最常用的滤波器,都遵循这个框架,但“内部运算”完全不同。

均值滤波是最朴素的,窗口内所有像素的灰度值取平均,作为中心点的新值。它属于典型线性滤波,数学上就是一个卷积过程,卷积核所有元素相等且和为1。优点是计算极快,可以用积分图算法进一步加速,在实时视频流预处理中比较吃香。缺点是它会把边缘和细节也一起平均掉,造成图像模糊。尤其是窗口越大,模糊越剧烈。为什么?因为边缘两侧的灰度值差异很大,平均之后,边缘的突变强度就被强行拉平了。你可以想象成一幅漫画被人在上面抹了一层半透明油脂,线条边缘都化开了。

中值滤波则走的是完全不同的路子。它先把窗口内所有灰度值排序,然后取中间值替换中心点。正因为有这个排序操作,它是典型的非线性滤波。这个特性让它对椒盐噪声几乎是“天敌”级的存在。因为椒盐噪声是极端离群点,排序之后极端值会分布在序列两端,中间值大概率还是正常像素数据。举个例子,3x3窗口内有4个像素是50,4个像素是52,一个是255的盐点,排序后中位数是51,盐点被完美剔除。而如果用均值滤波,这个255会被强行拉低,但也会把其他8个像素抬高,造成整块区域发亮,效果不太理想。

高斯滤波从效果上介于两者之间,它也是线性卷积,但卷积核的权重不是平均分布,而是中心元素权重最高,越远离中心的元素权重按高斯函数递减。它模拟了人眼视觉的聚焦特性,中心信息最重要。高斯滤波的优势在于保留边缘轮廓方面优于均值滤波,因为中心点权重较高,对自身原值影响更大,不会像均值那样被邻域值“带跑”太远。但它对椒盐噪声的抑制也很一般,因为极端值依然有非零权重参与计算,会形成亮暗斑块的残留。

从应用角度选型,我的经验是:

  • 图像有椒盐噪声,优先中值滤波。如果想在去噪同时适当保留纹理,可以考虑自适应中值滤波或加权中值滤波。
  • 图像有高斯分布的传感器噪声,优先高斯滤波,sigma参数通常取1到2之间,配合相对较小的窗口。
  • 如果噪声类型不明确,但图像整体较平滑、对细节要求不高,均值滤波可以作为简单兜底方案。

需要注意的是,滤波过程本质上是在做某种信息取舍。你不可能既把噪声彻底去掉,又把所有细节全部保留,这两者在空间域是天然矛盾的。所以每次选用滤波器前,你要想清楚:这个任务里,我守住的是边缘还是平整区域。

4. 从代码层面拆解:MATLAB与Python双平台实现对比

我这次课业打卡用了两种环境实现,一个是MATLAB,另一个是Python的OpenCV。选双平台不是为了炫技,而是想验证同一套理论在不同工具链下的实现差异,顺便也给自己以后做工程选型留个底。坦率说,两者效果上几乎无差别,但在写代码体验和调试效率上各有优缺点。

MATLAB版本最核心的魅力在于,它把图像处理变成了“胶水式开发”。利用内置的imnoise函数可以直接生成噪声图像,然后用fspecial或者直接构造卷积核,配合imfilter一行调用实现均值和高斯滤波;中值滤波更是有一个专门的medfilt2函数。语法极简到令人发指,适合快速验证算法思想。

我写的一段核心MATLAB脚本逻辑是这样的:读入图像,转灰度,分别生成高斯噪声和椒盐噪声图像,接着对两类噪声分别应用三种滤波器,最后用psnr函数计算峰值信噪比来评估效果。这里有个细节必须先说清楚:MATLAB的imnoise,如果输入图像灰度范围是[0,1],那参数也要对应归一化理解;如果你输入uint8的图像,函数会自行处理,但生成结果的数据类型要留意,避免后续运算出现类型不匹配。

Python端我用的是OpenCV配合NumPy实现,代码量会多一些,但胜在可控性高,每个步骤你都清楚知道数据是什么样、经过什么操作变成什么样。NumPy的np.random.normal和np.random.randint可以很简单地生成噪声叠加图。均值滤波用cv2.blur,高斯用cv2.GaussianBlur,中值则是cv2.medianBlur。三者在参数上都支持指定核大小,但有一个非常关键的差异:cv2.medianBlur的核大小只接受大于1的奇数,如果你传一个偶数进去,等待你的就是运行时异常。

直接列出两边的核心代码框架,方便需要的人复制对照。

MATLAB版本:

img = imread('lena_gray.bmp'); if size(img, 3) == 3 img = rgb2gray(img); end img = im2double(img); % 转换到[0,1]范围便于处理 % 生成噪声 gauss_noise_img = imnoise(img, 'gaussian', 0, 0.02); saltpepper_img = imnoise(img, 'salt & pepper', 0.05); % 均值滤波 mean_filtered = imfilter(gauss_noise_img, ones(3)/9, 'replicate'); % 高斯滤波,fspecial构造卷积核 h = fspecial('gaussian', [5 5], 1.5); gauss_filtered = imfilter(gauss_noise_img, h, 'replicate'); % 中值滤波 median_filtered = medfilt2(saltpepper_img, [3 3]); % 评估 psnr_gauss = psnr(gauss_filtered, img); psnr_median = psnr(median_filtered, img);

Python + OpenCV版本:

import cv2 import numpy as np img = cv2.imread('lena_gray.bmp', cv2.IMREAD_GRAYSCALE) img = img.astype(np.float64) / 255.0 # 生成高斯噪声(均值为0,方差0.02) gauss_noise = np.random.normal(0, np.sqrt(0.02), img.shape) gauss_noise_img = np.clip(img + gauss_noise, 0, 1) # 生成椒盐噪声(密度5%) saltpepper = np.random.rand(*img.shape) sp_noise_img = img.copy() sp_noise_img[saltpepper < 0.025] = 0 sp_noise_img[saltpepper > 0.975] = 1 # 均值滤波 mean_filtered = cv2.blur(gauss_noise_img, (3, 3)) # 高斯滤波 gauss_filtered = cv2.GaussianBlur(gauss_noise_img, (5, 5), 1.5) # 中值滤波 median_filtered = cv2.medianBlur((sp_noise_img * 255).astype(np.uint8), 3) median_filtered = median_filtered.astype(np.float64) / 255.0 # 评估 PSNR(注意输入区间一致) psnr_gauss = cv2.PSNR((gauss_filtered * 255).astype(np.uint8), (img * 255).astype(np.uint8)) psnr_median = cv2.PSNR((median_filtered * 255).astype(np.uint8), (img * 255).astype(np.uint8))

需要特别提醒Python端一个容易埋坑的点:OpenCV很多函数支持浮点图像,但cv2.medianBlur不支持float64输入,你必须先把像素范围转到[0,255]并转为uint8,处理完再转回来做PSNR计算,否则会直接报类型错误。这个坑我一开始就踩过,查了半天文档才反应过来。

从工程选型角度说,如果你想快速复现理论结果、把注意力放在算法本身而不被语法细节干扰,MATLAB更舒坦;如果你之后要走上生产系统,Python生态的OpenCV几乎是无法绕开的选择,因为它能无缝衔接模型的推理和其他预处理步骤。两种工具我都推荐过给身边做项目的朋友,最终选择取决于你的后端环境和更习惯的生态。

5. 核心参数怎么定:窗口尺寸、边界处理与sigma选择的门道

滤波器选好之后,真正决定效果上限的是参数调节。窗口尺寸、边界填充方式、高斯分布的标准差sigma,这三个参数每一个单独拿出来都值得说道说道。

窗口尺寸决定了邻域范围。窗口越大,参与运算的像素越多,平滑力度越强,但代价是模糊和细节损失越明显。在实践验证中,3x3窗口是细节保留和噪声抑制之间的黄金平衡点,适用于大多数轻度噪声场景。5x5更平滑,比较适合中等密度的噪声,但边缘明显变钝。7x7或更大的窗口只有在噪声极重、并且图像内容本身纹理要求不高时才推荐,比如一些大的平面区域图像。我的经验是以噪声颗粒的大小为参考标准:窗口至少要能完全覆盖一个噪声颗粒的范围,否则滤波后噪声只是被削弱,还会以颗粒形态残留。

边界填充这个点很容易被忽略,但它是滤波结果好坏的重要分水岭。模板滑动到图像边缘时,窗口会超出图像范围,如果直接舍去边界像素,那么输出图像的尺寸会缩小;如果简单补零,边缘一圈会因为填充了不自然的0值而出现黑色突兀边界。比较推荐的做法是replicate复制填充,也就是把最边缘的像素值向外延伸。这个方式对大多数自然图像都适用,不会在边界产生突变。如果想更平滑地过渡,可以用reflect镜像填充;如果追求计算速度且对边界要求不高,默认的补零方式也能凑合,但要意识到边界区域滤波结果是不可靠的。

高斯滤波的sigma参数,这个变数确实比较多。sigma决定高斯核的“胖瘦”,sigma越小,核的中心权重越集中,滤波效果越接近“不动”;sigma越大,权重分布越平坦,平滑力度越大,越接近均值滤波。OpenCV的GaussianBlur里sigmaX可以直接指定,如果设为0,函数会根据窗口大小自动计算sigma,算法大致方向是sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8。我在实验中测试过,对于方差为0.02左右的高斯噪声,5x5窗口搭配sigma=1.5效果比较理想;如果sigma小于1,噪声残余较多;大于2,图像开始有油画的模糊感。

中值滤波虽然没有sigma,但窗口内如果有过多噪声点,可能导致中位数本身也是一个噪声点。当噪声密度超过30%时,普通3x3中值滤波已经不顶用了,你可以先加大窗口到5x5,再考虑对中心点与中位数做阈值判断的加权方案。这次我没有展开自适应中值,但你们自己实验时可以往这个方向试试,效果会有明显上升。

不同滤波器的窗口尺寸选择其实可以沉淀为一个简单的通用判断逻辑:先查看噪声颗粒在图像中的像素覆盖范围。如果噪声点占1个像素,3x3窗口就够;如果噪声颗粒成团、占2到3个像素,就要上5x5。窗口尺寸永远以匹配噪声尺度为首要原则,而不是越大越好。

6. 这次实验的完整流程与质量评估方法

做图像处理实验,没有客观评价指标的支撑,结果就是“公说公有理”。这次实验我采用的评估指标是PSNR(峰值信噪比)和SSIM(结构相似性),主观视觉评测作为辅助。

PSNR本质上是信号最大可能功率与噪声功率之比,单位为dB。公式推导过程不赘述,你只需要掌握,PSNR越高,代表处理结果越接近原图,失真越小。通常30dB以上表示质量良好,35dB以上表示非常好,低于25dB代表失真已经比较严重了。需要特别提醒的是,如果两张图一模一样,PSNR是无穷大,OpenCV实现里有时会出现一个接近0的极大值,那是除零保护的极限情况。实际上只要两张图完全相同,PSNR就失去了对比意义。

SSIM则是从亮度、对比度、结构三个维度去评价两张图的相似度,取值范围是-1到1,越接近1表示结构保持得越好。PSNR强调像素级误差,SSIM强调人眼感知结构的一致性,两者最好一起用。特别是当你对比不同滤波器的结果时,可能会出现某方法PSNR高但视觉上边缘太糊的情况,这就能体现SSIM的价值了。

我这次实验的具体流程可以按这六步走:

  1. 读取测试图像并转灰度。建议选一张带纹理细节的图像,比如楼房、毛发这类,不要用纯色块图,因为滤波效果在平整区域上体现不明显。
  2. 分别叠加高斯噪声和椒盐噪声。高斯噪声方差设为0.02左右,椒盐噪声密度设为0.05,这样不会把图像内容完全淹没,能清晰对比出滤波器的性能。
  3. 对含高斯噪声图像分别应用均值滤波、高斯滤波。记录处理结果的灰度直方图和主观视觉效果。
  4. 对含椒盐噪声图像应用中值滤波,并把结果与均值、高斯滤波的结果放在一起对比。这一步能直观展现出非线性滤波在处理脉冲噪声上的优势。
  5. 统计PSNR和SSIM,生成对比表。
  6. 扩展实验:对同一含噪图像分别使用3x3和5x5窗口,观察窗口尺寸对结果的影响。

我的实验结果基本符合预期,具体数值我大概复述一下,你们做出来的可以自行对比。以灰度Lena图为基准原图,叠加高斯噪声后PSNR约为27.1dB,均值滤波处理后PSNR提升到28.9dB左右,高斯滤波处理后可到30.4dB,说明高斯滤波在对高斯噪声的场景下确实比均值滤波更强。叠加椒盐噪声的原图PSNR大概在24.6dB,均值滤波处理后只能回到27.0dB,且图像表面残留大量灰斑;中值滤波处理后可达到34dB以上,视觉上几乎是干净无噪的,这就是非线性滤波器的实力。

表格整理如下:

噪声类型处理方法PSNR (dB)SSIM视觉评价
高斯噪声原始噪声图27.10.82可见颗粒感
高斯噪声均值滤波3x328.90.86颗粒减弱,边缘略糊
高斯噪声高斯滤波5x530.40.89颗粒感基本消除
椒盐噪声原始噪声图24.60.61黑白点密集
椒盐噪声中值滤波3x334.80.96几乎完全恢复
椒盐噪声均值滤波3x327.10.74黑白点变灰斑

质量评估过程中有一点很重要:指标只能部分反映结果,最后一定要配合人眼观察。有些情况下PSNR数值很高,但图像出现了难以接受的振铃效应或细节涂抹,照样不能用于实际工程。评估环节建议把各个结果图拼接起来统一显示,用相同的显示范围对比,这样细微的差异才不会被误判。

7. 实操避坑指南:这些细节不处理好,效果直接打折

从代码逻辑、数学推导到实验结果,看似都顺了,但实际操作中其实有很多细节是教科书不会写的。这些坑我这次课业基本踩了个遍,拿出来讲一讲,希望能帮各位省掉几个小时排查问题的时间。

第一个坑:uint8溢出问题。用Python做图像叠加时,如果图像数据类型是uint8,你直接加上一个float类型的噪声,NumPy会先报类型转换错误。即使转成整数做加法,灰度值也可能超过255。正确的做法是先把图像转成float64,归一化到[0,1]区间,做完所有处理再在保存或显示时重新转回uint8。如果像素值被截断到255,高光区域会出现一片白斑,导致信息损失,后续处理数据就不干净了。

第二个坑:RGB图像直接滤波。彩色图像有三个通道,如果你对三个通道分别滤波再合并回来,会破坏通道间的色彩关系,容易出现色边。更合理的做法是在转换到合适颜色空间后处理,或者保留原色彩空间、对每个通道采用完全一致的参数滤波。我在实验中发现,直接对RGB三通道各自做中值滤波后,在某些高饱和边缘区域出现了不自然的色彩过渡,这就是通道独立性带来的错觉结果。如果你的任务不强制需要彩色,转灰度处理往往能更专注于噪声抑制本身。

第三个坑:边界处理类型混用。同一批实验里,有的滤波用了补零,有的用了复制填充,这样出来的对比结果完全不可信,因为差异并不是单纯滤波器贡献的。我在做第一个版本实验时就是没注意这个,导致均值滤波的PSNR偏低,后来统一改成replicate模式,所有结果才对齐。

第四个坑:kernel为偶数导致异常。在OpenCV中,绝大多数滤波核尺寸都要求为奇数,3、5、7都可以,但2就不行。你写代码时可以顺手加一个断言,或者干脆用循环确保传入的核大小是奇数。遇到此类异常时,报错信息可能不太直观,尤其是批量跑参数时比较难定位,所以代码里主动定义一个参数检查函数比事后查错更高效。

第五个坑:PSNR计算前数值范围不一致。这是个非常隐蔽的坑。MATLAB的psnr函数会自动处理数据范围,但OpenCV里cv2.PSNR要求两张图是相同类型、且都在[0,255]范围。如果你一张是float型[0,1]的图、另一张是uint8的图,直接跑PSNR,结论会偏离很远。正确姿势是统一转成uint8再计算,或者统一float之后自己按公式算。我后面为了排除这个干扰,写了一个公用函数,专门负责把各种形态的图像统一成像同一种格式,然后再走指标计算。

第六个坑:过于依赖滤波器,忽略图像自身灰度范围。有些图像的动态范围很窄,比如整体偏暗,此时噪声在视觉上会被放大。先对图像做直方图均衡化或自适应对比度增强,再去噪,效果往往比直接滤波更好。你可以把预处理想象成先把“衣服”上的灰尘拍松,再用去噪“吸尘器”慢慢吸,直接吸硬土反而吸不干净。

擦完这些坑,整个实验的流畅度会提升很多,你也能把注意力真正放在核对算法设计和结果分析的逻辑上,而不是天天对着奇怪的图像发呆。

8. 从课程作业到工程应用:噪声抑制还能怎么延伸

课业打卡做到这个程度,其实已经算是画上了阶段性的句号。但如果你还想更进一步,把噪声抑制的研究带到实际应用中,有几个方向值得展开。第一个是非局部均值滤波NLM的引入,它不局限于当前窗口内的局部信息,而是从整张图搜索相似块做加权平均。它的去噪能力和细节保留比经典局部滤波强不少,但计算复杂度也格外高,通常需要使用积分图或结构相似性搜索来加速。第二个是双边滤波,它同时考虑像素间的灰度相似度和空间距离,能在去噪的同时较完整地保留边缘信息,这在实时美颜、AR领域用得比较多。第三个方向是频域的思路,比如傅里叶变换后做一个低通滤波或陷波滤波,对周期性纹理噪声、扫描条纹的消除有奇效。我这次实验里也顺手验证了一下陷波滤波的效果,对付特定频率点干扰非常果断,缺点是噪声不在固定频率时容易伤及真实信息。

另外一条实用的思路是多种滤波器级联。比如先中值去椒盐噪声,再高斯去高斯残留,再对整体做一个微量的非局部均值修正。级联方案的问题在于参数组合会让系统变得太复杂,如果调参不当反而更糟。我在处理一批航拍图像时,级联方案的稳定性确实比单一滤波器好,但耗时整整增加了三倍多。所以建议级联只在你明确知道噪声来源是复合型时才用,不然老老实实选一个主滤波方案。

如果你正在准备面试,噪声抑制这块大概率会以“如何对图像去噪且保持边缘”的形式出现。它考察的其实不是你会调哪个函数,而是你能不能理解空间域滤波的取舍逻辑,能不能说出不同噪声模型的适用场景。把这次课程的实验总结成“识别噪声类型,选型滤波器,用指标量化,做好边界与数据范围控制”这个方法流程,你在开放性的算法题里就有了一个扎实的支点。这个支点还可以继续向外延伸,比如迁移到图像超分辨率重建、视频降噪、医学影像低剂量处理等领域。那些场景的核心问题依然是噪声抑制,只不过约束条件更复杂了而已。

9. 写在打卡之外:我对噪声抑制的一点实操体会

这次课业打卡做完,我对“降噪“这个词的理解确实深入了一层。它并不只是按几下滤镜按钮,它要求你理解噪声从哪里来、是什么分布、对后续任务有多大伤害,然后才谈得上用什么手段去应对。你可能会发现,同样的图像,在不同滤波参数下,结果千差万别;而同样的滤波参数,在不同图像上,也可能表现截然不同的效果。所以那个唯一的参数组合是不存在的,每一组完整的实验数据背后,都要有明确的理由支撑。

我在实际复核结果时,还有个操作习惯,就是在每一组滤波结果旁边放上原图和噪声图,方便做像素级对比。这个小细节很大程度上提高了我的调参效率:哪里的噪声没压干净、哪里的边缘被模糊了,一比就知道问题出在哪个环节。如果你也想快速验证自己的滤波器表现,建议多用有重复纹理和边缘突变的测试图,而不要只用纯风景图来感受差异。

这次实验的完整思路和落地的代码细节就是我前面写到的这些。你现在拿着这些内容,足够独立完成一次标准图像噪声抑制实验了。不过如果你还有精力,我挺建议你去试试自适应中值滤波或者小波去噪的入门案例,这类进阶方案会在更大程度上打磨你对图像细节和频域特征的敏感度。围绕噪声抑制的探索空间还很大,保持用手实测的节奏,比单纯堆理论更容易看到效果。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进