简介这份小波实验资源包聚焦Morlet小波在二维图像分析与信号去噪中的应用适合信号处理、图像分析相关方向的初学者和研究人员。Morlet小波由高斯函数与正弦波复合而成具有较强的时频局部化能力非常适合提取混合信号中的谐波成分。压缩包共9个文件以MATLAB脚本.m为主另含实验数据.mat、处理结果图像.jpg/.png和可交互图形窗口.fig整体仅2.81MB便于快速下载与复现实验。内容围绕一维信号与二维图像的三级分解展开通过具体代码演示Morlet小波的构造、多尺度分解及阈值去噪过程同时提供去噪前后的图像对比和可视化结果帮助使用者直观理解小波系数分布与噪声剔除机制。已有557人学习下载对于想掌握小波去噪原理、熟悉MATLAB小波工具箱应用的读者来说这份资源既能作为实验参考也能作为算法验证的起点。1. 小波去噪实验为什么绕不开 Morlet一次“滤不干净”的现场复盘做传感器信号清洗时我第一次遇到“滤不干净”的难题信号里既有 50 Hz 工频干扰又有一段短促的机械冲击低通滤波器把冲击沿磨圆了高通滤波器又放过了工频。后来把数据拿到小波去噪流程里重跑先用 Morlet 小波画时频图才看清噪声和有效成分在频带上是怎么重叠的。Morlet 小波是一种复值连续小波它的价值不在“直接替代 db 小波做离散分解”而在帮你先看准噪声长什么样再决定用什么策略去噪。这篇文章就按一条可复现的路径走先弄懂 Morlet 的结构和参数再做一维信号去噪然后扩展到二维 Morlet 图像去噪最后把常见坑和自适应阈值技巧讲透。适合刚接触小波变换的算法工程师也适合在现场被噪声问题缠住的调试人员。2. 先弄懂 Morlet 小波再动手复值结构与中心频率的意义2.1 Morlet 小波的数学定义与可视化一个高斯包络下的复指数Morlet 小波可以理解成一个复指数载波乘上一个高斯包络。一维形式的典型写法是ψ(t) (1/π^(1/4)) * e^(iω₀t) * e^(-t²/2)其中 ω₀ 是中心频率e^(-t²/2) 是高斯包络。标题里提到的“morlet二维”“Morlet图像”本质上是把自变量从一维时间换成二维坐标高斯包络从一维变成二维各向同性形式载波变成一个沿某个方向的复指数。先看一维形式二维在第四章单独展开。为什么要用复值而不是实数余弦因为复值小波同时给出幅值和相位两路信息。实部是余弦调制虚部是正弦调制两者正交。把信号与复值小波做卷积得到的系数模长代表该频率成分在某个时刻的强度相位则代表振荡的起始位置。对去噪来说幅值足够用来做阈值判断相位能帮你确认波形有没有发生倒相或者跳变这在分析脉冲类干扰时很有用。下面这段代码用 numpy 手动生成一个 Morlet 小波并画实部、虚部import numpy as np import matplotlib.pyplot as plt fs 1000 # 采样率单位 Hz t np.linspace(-4, 4, 800) # 时间轴单位秒 omega0 6.0 # 中心频率单位 rad/s psi_real np.exp(-t**2 / 2) * np.cos(omega0 * t) psi_imag np.exp(-t**2 / 2) * np.sin(omega0 * t) plt.figure(figsize(10, 4)) plt.plot(t, psi_real, labelreal part) plt.plot(t, psi_imag, labelimag part) plt.legend() plt.grid(True) plt.show()逻辑说明psi_real 和 psi_imag 分别是复值小波的实部与虚部高斯包络 exp(-t²/2) 保证能量集中在零点附近满足小波“有限支撑”的直觉要求。omega0 决定包络内振荡次数。这里没有加归一化系数只用于观察形状后面做滤波时会补上能量归一化。参数说明omega0 越大时域振荡次数越多频率选择性越强但时间分辨率下降。建议把 omega0 分别设成 2、6、12 对比看三张图这是理解时频分辨率矛盾最快的方法。实际调试中我一般先用 6 跑通再根据信号的载波频率微调。2.2 中心频率与带宽怎么设omega06 的由来与容许条件小波必须满足容许条件也就是零频处的傅里叶变换要趋于零否则逆变换不成立。对 Morlet 小波来说这个条件表现为中心频率 omega0 要足够大。工程上默认取 5 到 6取 6 是一个保守且好记的经验值。在 PyWavelets 里复 Morlet 小波用字符串 cmorB-C 指定B 是带宽参数C 是中心频率。例如 cmor1.0-6.0 表示带宽 1.0、中心频率 6.0。带宽 B 越大高斯包络在频域里越宽频率分辨率越差时间分辨率越好中心频率 C 决定小波主瓣对准哪个频率。实验里我习惯先用 cmor1.0-6.0 跑通再按信号特征调 B。还有一个容易混淆的点用 cmor 画时频图时尺度与频率不是线性对应的。物理频率 f 与尺度 scale 的关系是f C / (scale * sp)其中 C 是中心频率sp 是采样周期。这个公式在做 CWT 时非常常用第 3 章会直接用。如果尺度取得太小算出来的频率会超过奈奎斯特频率那段频谱实际没有物理意义所以 scales 数组要从合适的值开始而不是习惯性地从 1 开始。2.3 连续小波与离散小波的分工先想清楚去噪路径再选小波族去噪实验里选小波本质上是选一套“基”。离散小波变换用 db 族、sym 族这类正交小波系数冗余少阈值去噪后重构的波形平滑且算法稳定。连续小波变换用 cmor 这类复小波系数冗余大但时频定位能力好适合先分析再去噪。小波族例子正交性适合场景常见注意点离散正交db4, sym8正交一维/二维阈值去噪、压缩阈值参数决定去噪质量离散双正交bior2.4双正交图像重建、边缘保持重构时正反向滤波器别设错连续复小波cmor1.0-6.0非正交时频分析、瞬时频率不能用于 wavedec连续实小波morl非正交脊提取、振荡分析只有幅值丢失相位信息我的习惯是拿到信号第一步先用 cmor 做一张 CWT 时频图看噪声在哪些频率、哪些时段占主导确定频带之后如果需要干净的时域波形再回过来用 db4 或 sym8 做离散小波阈值去噪。这套组合拳比单独用任何一种小波更可靠也是标题里“信号去噪_小波去噪”最稳的落地方式。下一章就按这个顺序演示完整的一维信号去噪流程。3. 一维信号去噪用复 Morlet 的 CWT 定位噪声频带再下阈值决策3.1 最小可跑通实验用 db4 做离散小波软阈值去噪先从最稳的路径开始。假设有一段 1 秒长的信号由 50 Hz 和 150 Hz 两个余弦叠加构成采样率 1000 Hz再叠加高斯白噪声。目标是恢复两个余弦成分。import numpy as np import pywt fs 1000 t np.arange(0, 1, 1/fs) sig np.cos(2*np.pi*50*t) 0.5*np.sin(2*np.pi*150*t) sig_noisy sig 0.3*np.random.randn(len(t)) coeffs pywt.wavedec(sig_noisy, waveletdb4, level4) sigma np.median(np.abs(coeffs[-1])) / 0.6745 thresh sigma * np.sqrt(2 * np.log(len(sig_noisy))) coeffs_th [coeffs[0]] [pywt.threshold(c, thresh, modesoft) for c in coeffs[1:]] sig_den pywt.waverec(coeffs_th, waveletdb4)逻辑说明wavedec 把信号分解成 level1 个系数列表第 0 项是低频近似系数后面各项是各层细节系数。噪声主要落在细节系数里所以只对细节系数做阈值处理。sigma 用最高频细节系数coeffs[-1]的中位绝对偏差估计噪声标准差除以 0.6745 是因为高斯噪声的中位绝对偏差约为标准差的 0.6745 倍。thresh 使用通用的 visuShrink 公式也就是 sigma 乘以 sqrt(2 ln N)N 是信号长度。参数说明level4 对 1 秒信号是合适的经验值大致是 log2(N) 再减 3。level 太大时低频近似系数里也会混入噪声太小则滤不干净。waveletdb4 是 8 阶滤波器时域支撑适中大多数工业信号先拿它跑基线是最好的选择。modesoft 表示软阈值系数绝对值小于阈值直接置零大于阈值的部分减去阈值软阈值重构的波形比硬阈值平滑但幅值会整体收缩一点。注意这里有一个很多新手会翻车的点wavedec 传 cmor1.0-6.0 会直接报错。原因在第 2.3 节已经说过cmor 是连续小波没有离散滤波器系数。如果你确实想用 Morlet 的思路做一维去噪最可靠的路径不是硬塞 wavedec而是先做 CWT 时频分析再回到 db4 上做阈值去噪。3.2 用 cmor 画 CWT 时频图噪声频带一眼定位上一节的去噪流程能跑通但有一个问题你并不知道噪声到底分布在哪个频带阈值只能靠公式盲算。很多现场信号是脉冲干扰叠加窄带噪声不是均匀白噪声盲算阈值经常把有效振荡当成噪声滤掉。我的做法是先做 CWT 时频图再回过来定阈值策略。scales np.arange(12, 129) coefs, freqs pywt.cwt(sig_noisy, scales, waveletcmor1.0-6.0, sampling_period1/fs) print(freqs[:5]) plt.figure(figsize(12, 4)) plt.imshow(np.abs(coefs), aspectauto, extent[0, 1, freqs[-1], freqs[0]]) plt.colorbar(labelamplitude) plt.ylabel(frequency (Hz)) plt.xlabel(time (s)) plt.title(CWT scalogram) plt.show()逻辑说明pywt.cwt 接收一维数组和尺度数组返回的 coefs 形状是 (len(scales), len(sig_noisy))。cmor1.0-6.0 的中心频率是 6采样周期是 0.001 秒。按第 2.2 节的公式 f C / (scale * sp)scale12 时对应 500 Hz刚好是采样率 1000 Hz 的奈奎斯特频率。所以 scales 从 12 开始避免计算没有物理意义的高频段最大 128 对应约 46 Hz能看到 50 Hz 成分的附近。参数说明如果信号有更低的频带把 scales 上限继续加大比如 256代价是计算量翻倍。imshow 的 extent 参数把纵轴映射到频率范围aspectauto 保证横纵轴比例不被图像分辨率扭曲。实际观察时白噪声在时频图上表现为全频带均匀分布的细碎亮点50 Hz 和 150 Hz 两个成分是两条稳定亮线。如果某条亮线在某个时间段突然断裂或变亮那大概率是脉冲干扰这时阈值策略要改成局部阈值而不是全局阈值。这就是“先分析后去噪”的价值。提示pywt.cwt 的 sampling_period 参数非常关键。漏传时返回的频率轴是归一化频率单位是 cycles/sample换成物理频率需要自己乘以 fs。传了之后 pywt 会帮你把 freqs 换算成 Hz少一步出错机会。3.3 阈值规则对比软阈值、硬阈值与分层自适应阈值工程里阈值规则远比阈值公式重要。下面这张表是我调试时常用的对比方式阈值规则实现方式优点缺点硬阈值绝对值小于阈值置零其余不变保留幅值峰值不收缩重构信号在阈值点附近跳跃可能出现伪吉布斯振荡软阈值绝对值小于阈值置零其余向零收缩波形平滑振荡少有效成分幅值被压缩能量偏低分层广义阈值每层各用 sigma_j 与 mad 估计高低频区别对待适应非白噪声参数多调起来费时间对应到代码上只用替换 3.1 里的阈值估计部分coeffs_th [] coeffs_th.append(coeffs[0]) for c in coeffs[1:]: sigma_j np.median(np.abs(c)) / 0.6745 thresh_j sigma_j * 3 coeffs_th.append(pywt.threshold(c, thresh_j, modesoft)) sig_den_adapt pywt.waverec(coeffs_th, waveletdb4)逻辑说明分层阈值最大的区别是每一层细节系数都用自己的 sigma_j 估计噪声水平而不是用最高频那层代替所有层。高频层包含噪声多sigma_j 往往大低频层包含有效信号多sigma_j 小阈值自然小不会误伤信号。参数说明这里乘的系数 3 是我常用的经验值意思是只保留超过噪声水平 3 个标准差的系数。信号干净时可以降到 2噪声非常重时可以升到 4。每层单独调是耗时活但对非白噪声场景效果提升明显。硬阈值与软阈值的选择一句话总结波形要拿去计算能量或幅值时用硬阈值波形要拿去观察趋势或做控制时用软阈值。我在电力设备振动分析里用软阈值多一些因为重构波形平滑不会因为阈值点的跳跃产生虚假的高频分量。4. 二维 Morlet 图像去噪构造复值滤波器核在频域做系数收缩4.1 二维 Morlet 小波核的构造方向、尺度与零均值修正把一维的 Morlet 公式推广到二维自变量变成 (x, y)高斯包络变成二维高斯载波变成沿某个角度方向的复指数。这样的核具有明确的方向选择性旋转 theta 角度核只对图像里该方向的纹理和边缘有强响应。这一特性对图像去噪很有价值因为自然图像的边缘方向性很强而高斯白噪声没有方向性。下面这段代码构造一个二维复 Morlet 核并做两件关键的事减去均值让核的直流分量为零再做 L2 归一化让不同尺度的核有可比性。import numpy as np def morlet2d_kernel(size31, sigma4.0, k0.35, theta0.0): half size // 2 y, x np.mgrid[-half:half1, -half:half1] # x 为列方向y 为行方向 g np.exp(-(x**2 y**2) / (2 * sigma**2)) kx k * np.cos(theta) ky k * np.sin(theta) carrier np.cos(kx*x ky*y) 1j * np.sin(kx*x ky*y) psi g * carrier psi psi - psi.mean() norm np.sqrt(np.sum(np.abs(psi)**2)) if norm 0: psi psi / norm return psi逻辑说明mgrid 生成以中心为原点的网格坐标g 是各向同性高斯包络carrier 是复指数载波。减去 mean 是为了保证对于常数图像卷积响应不为常数这一步对应小波的容许条件。除以 L2 范数是为了让不同尺度、不同方向的核总能量一致否则大尺度核的响应天然偏大多尺度融合时小尺度核会被淹没。参数说明size 是核的边长覆盖约 3 个 sigma 的范围就够sigma4 时取 size31。k 是空间频率也就是载波振荡的快慢单位是 rad/pixel0.35 对应约 18 像素的波长适合中等纹理。theta 是方向角0 表示水平纹理pi/2 表示垂直纹理。如果图像里纹理尺度较大把 sigma 拉到 8同时核 size 要相应增大。4.2 多方向带通滤波与系数收缩一整套可复现的去噪流水线有了方向核接下来做多方向带通滤波。基本思路是对含噪图像分别做四个方向的 Morlet 实部卷积得到该方向的带通分量白噪声在各方向都有响应但幅值分散纹理结构只在对应方向有强响应。对每个方向分量的系数做软阈值收缩抑制低幅值噪声再把清理后的结果叠加回原图。from scipy.signal import fftconvolve from skimage import data import numpy as np import pywt img data.camera() / 255.0 rng np.random.default_rng(42) img_noisy np.clip(img rng.normal(0, 0.14, img.shape), 0, 1) def morlet_denoise(img_noisy, thetasNone, sigma4.0, k0.35, thresh_factor2.5): if thetas is None: thetas [0, np.pi/4, np.pi/2, 3*np.pi/4] img_den img_noisy.copy() for theta in thetas: kernel morlet2d_kernel(size31, sigmasigma, kk, thetatheta) resp fftconvolve(img_noisy, kernel.real, modesame) noise_sigma np.median(np.abs(resp)) / 0.6745 thresh noise_sigma * thresh_factor resp_shrink pywt.threshold(resp, thresh, modesoft) img_den resp_shrink - resp return np.clip(img_den, 0, 1) img_den morlet_denoise(img_noisy)逻辑说明每个方向算一次卷积得到该方向带通分量的实部。pywt.threshold 可以直接处理二维数组逐元素操作不需要手写循环。noise_sigma 用该方向响应的中位绝对偏差估计白噪声在任意方向子带里近似高斯分布所以这个估计比较稳。关键一行是 img_den resp_shrink - respresp 是含噪图像在这个方向的分量resp_shrink 是收缩后的干净分量差值就是被识别出的噪声把差值减回去保留其他频段同时压制这个方向的噪声。参数说明thresh_factor 控制去噪强度2.5 是中等偏保守的取值改成 1.5 时细节保留多但噪声略多改成 4 时图像更平滑但边缘发虚。这里只用 kernel.real 做卷积有两个原因一是高斯白噪声在实部和虚部两个通道同时存在取模反而会把两路噪声能量叠加不利于阈值判断二是实部卷积输出是实数阈值处理后的残差更新更直观。4.3 与 wavedec2 标准图像去噪做对照算法边界与工程选型Morlet 方向滤波不是唯一解工程里更主流的二维小波去噪是 wavedec2。它把图像分解成低频近似和三个方向细节水平、垂直、对角再对细节系数做阈值。我们跑一个对照实验用小波去噪里经典的“图像 高斯噪声”来评估这样能直观看到两种方案的差异coeffs2 pywt.wavedec2(img_noisy, waveletdb4, level3) coeffs2_th [coeffs2[0]] sigma2 np.median(np.abs(coeffs2[-1][-1])) / 0.6745 thresh2 sigma2 * np.sqrt(2 * np.log(img_noisy.size)) for detail in coeffs2[1:]: coeffs2_th.append(tuple(pywt.threshold(c, thresh2, modesoft) for c in detail)) img_den_dwt pywt.waverec2(coeffs2_th, waveletdb4) from skimage.metrics import peak_signal_noise_ratio as psnr print(DWT PSNR:, psnr(img, img_den_dwt)) print(Morlet PSNR:, psnr(img, img_den))逻辑说明wavedec2 返回列表的第一项是近似系数后面每项是一个三元组对应水平、垂直、对角三个方向细节系数。阈值处理时三个方向分别做软阈值tuple() 只是为了保持 waverec2 重构时要求的系数格式。visuShrink 在 DWT 里适用性较好因为正交变换下噪声方差在各层一致。参数说明level3 是 512 分辨率图像的常用分解层数层数过多会引入振铃。psnr 的取值范围通常在 20 到 50 dB同类噪声下去噪结果比含噪图高 3 到 6 dB 就算有效。实际项目里我通常两个都跑一遍wavedec2 作为基线保证结果稳定Morlet 方向滤波作为增强手段查漏补缺。遇到纹理方向非常一致的图像比如钢材表面轧制纹路Morlet 方向滤波会明显更好如果是随机自然照片db4 基线的普适性更强。做完四方向滤波后可以把四个方向的响应分别存成图肉眼就能看到哪个方向保留了结构、哪个方向被清理干净。5. 小波去噪的 5 个常见坑现象、原因与解决办法5.1 wavedec 里传入 cmor 报错离散与连续小波别混用现象代码写 pywt.wavedec(signal, cmor1.0-6.0)运行时抛 ValueError提示小波名称不识别或小波类型不受支持。原因cmor 属于连续小波没有离散的尺度滤波器系数wavedec 的实现要求小波必须是正交或双正交的。pywt 内部的小波族划分非常明确morl、cmorB-C、gaus 这类只能用于 pywt.cwt用于 wavedec 就是类型错误。解决离散阈值去噪一律用 db4、sym8 这类正交小波cmor 只用于 CWT 时频分析。记住一条经验先分析用 cmor后重构用 db4。如果你执意用 Morlet 思路做去噪就走第 4 章的滤波器组方案不要再硬塞 wavedec。5.2 CWT 时频图两端出现异常亮斑边界系数失真现象用 cmor 画出的 CWT 时频图在时间轴最左和最右各出现一块高幅值亮斑把真实信号都盖住了。原因小波在信号边界处只有一半数据参与运算卷积不完整边界系数在数值上被放大。pywt.cwt 内部会做边界扩展但扩展方式与信号真实趋势不一致时边界伪影就非常明显。解决先对信号做对称扩展再计算 CWT算完裁剪掉扩展区。更简单的做法是把时频图两端各 2% 的区域标记为不可信区分析时跳过。注意不要用零填充做扩展零填充会在边界制造跳变伪影更严重。5.3 阈值一刀切把有效冲击滤成平滑曲线现象去噪后的信号非常干净但原本短促有力的冲击脉冲变成了一段平缓的鼓起峰值幅值掉了快一半。原因软阈值对系数是整体收缩的幅值低于阈值的系数被置零高于阈值的系数也减去了阈值。脉冲信号在高频细节系数里幅值大但软阈值把它收缩了。统一阈值更大的问题在于它假设噪声在所有层均匀而现场噪声往往不是均匀白噪声。解决改用分层阈值每层用各自的中位绝对偏差估计 sigma_j。对脉冲型信号我还会专门留一层细节系数不动那一层对应冲击脉冲的中心频带只做带通范围内的小阈值处理。也就是把“全局盲算”改成“按频带管理”。5.4 二维 Morlet 核没归一化多尺度融合被大尺度核主导现象把 sigma2、4、8 三个尺度的 Morlet 滤波结果叠加起来最终图像几乎只剩大尺度核的特征小尺度细节看不到。原因不同尺度的高斯包络能量差异很大sigma8 的核总能量远大于 sigma2 的核直接用原核卷积时大尺度响应天然占优。这不是噪声问题是核本身没做能量归一化。解决构造核之后除以 L2 范数就是 4.1 代码里的 norm 那一步。归一化之后再做多尺度融合各尺度贡献才平衡。顺手检查核的直流分量是否为零均值不为零会在滤波结果里引入常数偏移表现为图像整体亮度变化。5.5 图像边缘出现规则条纹边界填充方式与卷积模式不匹配现象去噪结果四周出现一圈规律性条纹像把图像边框描了一遍中间区域正常。原因fftconvolve 的 modesame 默认做零填充零填充让图像边缘产生跳变。Morlet 核是带通型的跳变在带通响应里会被放大成条纹。wavedec2 默认 mode 是 symmetric所以 DWT 流程不容易出这个问题但自定义滤波容易忽略。解决先做边界复制填充再卷积最后裁回原尺寸。参考做法pad_w 31 // 2 img_pad np.pad(img_noisy, pad_w, modeedge) resp_pad fftconvolve(img_pad, kernel.real, modevalid) resp resp_pad[:img_noisy.shape[0], :img_noisy.shape[1]]逻辑说明np.pad 用 modeedge 把图像四周扩展 pad_w 个像素再卷积时边界参与计算的数据是平滑的复制值不会制造跳变。fftconvolve 用 modevalid 只保留有效卷积区域最后裁回原始尺寸。参数说明pad_w 至少要等于核半径否则扩展的像素不够边缘还是会受影响。这一招对大多数方向滤波都适用成本只是多复制一圈像素。关于这一章的调试顺序我总结一下我的习惯先看是否报错再看时频图边界然后检查去噪后波形幅值有没有异常收缩最后确认图像边缘有没有条纹。按这个顺序排查大部分问题十分钟内能定位。6. 进阶把固定阈值换成 BayesShrink让去噪参数自动适应当前图像前面所有实验里阈值乘子都是手调的。手调在单个信号上没问题但换一张图、换一种噪声强度就得重新试非常费时间。我现在做二维图像去噪时优先用 BayesShrink 做自适应阈值。它把阈值计算和图像本身的统计特征绑定不需要反复猜乘子。BayesShrink 的核心思想是对每个子带分别估计噪声方差和信号方差阈值按下式给出T σ_noise² / σ_signalσ_noise 用中位绝对偏差估计σ_noise median(|c|) / 0.6745c 是当前子带系数。σ_signal 由观测系数的方差减去噪声方差得到如果差值小于等于零说明这个子带里基本没有有效信号阈值取子带系数绝对值的最大值。放在第 4 章的 Morlet 滤波器组里只需要把 4.2 节的收缩部分替换成下面这个函数def bayes_shrink(coeff): sigma_noise np.median(np.abs(coeff)) / 0.6745 var_obs np.var(coeff) var_signal np.maximum(var_obs - sigma_noise**2, 0) if var_signal 0: thresh sigma_noise**2 / np.sqrt(var_signal) else: thresh np.max(np.abs(coeff)) return pywt.threshold(coeff, thresh, modesoft)逻辑说明var_obs 是子带系数的总方差包含信号和噪声两部分减去噪声方差后得到信号方差的估计值也就是信号能量。阈值公式让信号能量大的子带阈值变小保留更多细节噪声主导的子带阈值变大清理得更干净。把这个函数替换 4.2 里的 resp_shrink 计算其他流程完全不变。验证时我会同时看 PSNR 和图像里细线的保留程度固定乘子调低时噪声多调高时细线断裂BayesShrink 通常能兼顾两者。我已经用这套组合替换了原来的固定乘子方案运行时间几乎没有增加效果却稳定不少。如果你更激进一点想把阈值乘子做成可学习参数再叠一层循环网络去逼近子带依赖关系那就是“小波 Elman 神经网络”方向要做的实验了。我还没在线上项目里落地过但建议先把 BayesShrink 基线的效果跑出来任何学习型阈值都需要一个可解释的非学习基线作对照。在实际项目里我对每一种新阈值策略的验收标准就是在保持边缘结构的前提下PSNR 不低于基线主观视觉不能出现振铃。希望这篇文章能帮你把 Morlet 小波的一维和二维实验路径理顺少踩几个我当年踩过的坑。本文还有配套的精品资源点击获取