小波阈值去噪的算法是近些年比较流行的一种滤波方法,由于其阈值函数有着众多的改进方式和改进空间,改进阈值函数也往往可以作为创新点和亮点写到论文中,所以对于正在搞相关研究的同学们写论文是比较友好的(轻松水论文方式+1)。本篇将用尽量易懂的方式对小波阈值的原理进行讲解,帮大家梳理几个效果还可以的改进阈值函数,并提供一种非常便捷的MATLAB实现方法,供同学们使用。

小波阈值去噪的基础思想还是比较简单的,也就是通过分解+有选择的重构,实现去除噪声成分,留下关键信息的作用。我们从两个角度去理解就可以,谜底就在谜面上,这两个理解角度的关键词就是“小波”和“阈值”。

一、先说“小波”

需要注意的是,这里提到的小波指的是“小波分解”,而不是小波变换、离散小波变换或者小波包分解等等,涉及小波的概念比较多,这里要做好区分。

小波分解在我们之前的文章里也提到过,通过小波分解我们可以得到一串小波分解系数。而小波阈值去噪的理论基础就是[1]

小波变换具有很强的去数据相关性,他能使信号的能量在小波域集中在一些大的小波系数当中,而噪声的能量却分布于整个小波域内。因此,经小波分解后,信号的小波系数幅值要大于噪声的系数幅值,可以认为,幅值比较大的小波系数一般以信号为主,而幅值比较小的系数在很大程度上是噪声。于是,采用阈值的办法,使大部分噪声系数减小至0,即将小于阈值部分的系数作为干扰噪声去除,然后再进行小波重构,从而实现降噪。

二、然后是“阈值”

在小波阈值去噪中,阈值函数体现了对超过和低于阈值的小波系数的不同处理策略,是阈值去噪中关键的一步。

对于“策略”,主要也包括两部分内容,分别是“阈值”的选择和“阈值函数”的选择。

(一)阈值的选择

所谓阈值,就是设定一个数值,当小波系数的绝对值小于这个阈值的时候,通通赋值为0(注:有些改进方法不是)。

阈值的选择方法常用的有这几种:

  • 'rigsure' — Use the principle of Stein's Unbiased Risk.
  • 'heursure' — Use a heuristic variant of Stein's Unbiased Risk.
  • 'sqtwolog — Use the universal threshold √2ln(length(x)).
  • 'minimaxi' — Use minimax thresholding.
  • 'VisuShrink'— 通用阈值方法

上述前四种是MATLAB内置的阈值选择方法,还有一种比较常用的VisuShrink方法没有收录到MATLAB官方库中,笔者在编程过程中一起把它集成进去了。(代码见下边的文章介绍)

阈值选择的的几种方法这里就不展开说了,其计算公式在论文中都不难找到。

(二)阈值函数的选择

阈值函数的设计通常是使用小波阈值降噪方法的核心关键所在,在写论文时这里可以加以改进,实现更好的滤波效果,妥妥的创新点。

传统的阈值函数有两种,分别是硬阈值软阈值

1.硬阈值

所谓硬阈值函数,其实就是“不做处理”。。。换句话说,我们不是已经将小于阈值的小波系数的置0了嘛,大于阈值的小波系数就保持原值(这操作真够硬的)。所以阈值函数画出来就是下图这样的,这样处理就导致了函数的不连续,“不连续”这种事情在信号处理中显然是不够优雅的。

小波去噪python实现 小波分析去噪matlab_小波去噪python实现

从图上可以看出,转折处就是阈值,在这个例子里也就是2

2.软阈值

而所谓的软阈值函数,其实也没“软”到哪去(核心理念依旧有些生硬),只是将上图中W=2的幅值跳变的位置做了一个平移,他的图像如下图:

小波去噪python实现 小波分析去噪matlab_小波阈值_02

阈值依然是2

这样处理带来一个显而易见的问题:小波分解系数值变啦!相当于每个大于阈值的系数都减掉了2(也就是阈值),这毫无疑问会在信号重构的时候引入误差。

3.第一种改进的阈值函数

既然软阈值和硬阈值有缺点就好说了,此时我们就可以有针对性地进行改进,而改进的方法无非就是围绕一个核心目的:在消除阈值函数的不连续性的同时,使函数迅速靠近硬阈值函数。

就比如下图这样(蓝线):

这是一种比较简单且相对有效的阈值函数,表达式是这样的[2]

小波去噪python实现 小波分析去噪matlab_小波阈值_03

式中 λ 就是阈值。

这个改进方法表达式简单明了,阈值函数曲线也比较漂亮。

4.第二种改进的阈值函数

这里再举一个例子,其阈值函数的表达式是这样的[3]

小波去噪python实现 小波分析去噪matlab_小波去噪python实现_04

按照论文里的说法,配合这个阈值函数使用的是VisuShrink阈值计算方法。

这个阈值函数图像是这样的:

小波去噪python实现 小波分析去噪matlab_小波阈值降噪_05

这个方法相对于第一种改进方法靠近硬阈值的速度更快一些,不过在阈值位置还是有一个小一些的跳变,这个方法介于硬阈值与软阈值之间,也算是改进方法的一种。

5.其他更多改进方法

还有更多的阈值函数改进方法,不过很多种都要引入一个或多个调节因子,也就是引入了新的变量,这种情况下阈值函数的种类就比较多了,这里不再一一介绍。这里挑几个,贴一下他们的阈值函数图像,并附上参考论文,有需要的同学们可以更进一步查阅。

(1)改进方法3:《基于改进小波阈值-CEEMDAN算法的ECG信号去噪研究》

小波去噪python实现 小波分析去噪matlab_小波阈值_06

为了体现效果,这个图像范围画到了10

(2)改进方法4:《基于改进小波阈值函数的语音增强算法研究》,这个方法在小于阈值的位置也做了平滑处理。这个方法引入了两个调节因子alpha和gamma,可以调节阈值函数形状。

小波去噪python实现 小波分析去噪matlab_小波阈值_07

(3)改进方法5:《基于VMD与改进小波阈值的地震信号去噪方法研究》,这个方法也引入了两个调节因子,分别是alpha和beta,可以更加灵活地调整图线形状。

小波去噪python实现 小波分析去噪matlab_matlab_08

这个是alpha和beta都等于2的结果

三、MATLAB案例实现

我把上边讲到的7种阈值方法都进行了MATLAB代码实现。下面采用一个案例来进行演示。

首先我们仿真生成一段信号,并向其中加入白噪声。x为未加入白噪声的纯净信号,sig为加入白噪声后的信号,代码如下:

%% 1.生成仿真信号,x为无噪声信号,sig为添加噪声后的信号
rng(123); %设置随机种子,保证每次生成噪声的一致性
N = 200;
t = linspace(0,1,N);
x = 4*sin(4*pi*t);
x = x - sign(t-0.3) - sign(0.72-t);
sig = x + 0.2*randn(size(t));
figure('Color','w');subplot(2,1,1);plot(t,x);title('未加入白噪声信号')
subplot(2,1,2);plot(t,sig);title('加入白噪声信号')

小波去噪python实现 小波分析去噪matlab_小波阈值降噪_09

下边我们尝试做一下软阈值、硬阈值、以及5种不同改进阈值方法的滤波效果对比吧。

(一)MATLAB编程实现方法

在MATLAB中,软、硬阈值的小波阈值滤波方法通过调用wden函数可以实现,但是想要实现改进阈值方法,对于没有MATLAB代码基础的同学们可能就得花费一些周章了,而且MATLAB官方函数里还没有visushrink这个很常用的阈值选择方法,所以笔者改造了wden、thselect和wthresh三个函数文件,并进一步封装成filterWaveletTh函数,延续本专栏中以往代码的风格,实现“一行代码”完成小波阈值去噪的效果。当然啦,这里所说的“一行代码”还需要配合一些参数的设置。

举个例子,如果对上述的sig信号进行软阈值滤波,选取'db3'类型的小波,分解水平为3,阈值选择原则为visushrink,那代码可以这样写:

s = filterWaveletTh(sig,'db3','s',3,'visushrink',[]);  %调用函数进行滤波,filterWaveletTh函数获取方法见文末

这样就可以得到滤波后的数据s。

我们来画图看一下滤波效果:

%% 画滤波前后对比图
figure('color','w')
subplot(311);plot(x,'k');title('原始信号(未加入噪声)')
subplot(312);plot(sig,'k');title('原始信号(加入噪声)')
subplot(313);plot(s,'k');title('滤波后信号')

小波去噪python实现 小波分析去噪matlab_小波阈值_10

软阈值滤波效果

结合我们之前讲过的计算一下滤波效果评价指标。计算SNR、MSE和NCC这三个指标值,计算方法也同样进行了封装,就像这样调用就行:

ori = x;  %无噪声信号
fil = s;  %滤波后信号
[SNR,MSE,NCC] = FilterEffectEvaluation(ori,fil);
% 对滤波效果进行评估
% 目前包含的评估指标有:信噪比SNR,均方差MSE,波形相似系数NCC
% 输入:
% ori:无噪声的原始数据,一维序列
% fil:滤波后的数据,一维序列

软阈值滤波后的SNR、MSE和NCC值分别为:26.4164、0.021658、0.99887。

这个效果还是可以的,下面我们再计算一下另外几种滤波方法的结果。

(二)硬阈值及五种改进方法的滤波结果

下面我们直接贴上来滤波效果对比图以及评价指标计算结果,具体代码实现都与上边的例子类似,直接给定参数调用就可以。

小波去噪python实现 小波分析去噪matlab_matlab_11

硬阈值滤波结果:滤波后的SNR、MSE和NCC值分别为:27.1828、0.018154、0.99905

小波去噪python实现 小波分析去噪matlab_matlab_12

改进方法1:滤波后的SNR、MSE和NCC值分别为:28.4053、0.0137、0.99928

小波去噪python实现 小波分析去噪matlab_matlab_13

改进方法2:滤波后的SNR、MSE和NCC值分别为:25.1265、0.029149、0.99847

小波去噪python实现 小波分析去噪matlab_小波阈值滤波_14

改进方法3:滤波后的SNR、MSE和NCC值分别为:27.6984、0.016122、0.99916

小波去噪python实现 小波分析去噪matlab_小波阈值降噪_15

改进方法4:滤波后的SNR、MSE和NCC值分别为:28.4599、0.013529、0.99929

小波去噪python实现 小波分析去噪matlab_matlab_16

改进方法5:滤波后的SNR、MSE和NCC值分别为:28.3339、0.013927、0.99927

做个表格列一下评价指标,做一个直观的对比:

小波阈值方法

SNR

MSE

NCC

软阈值

26.4164

0.021658

0.99887

硬阈值

27.1828

0.018154

0.99905

改进方法1

28.4053

0.0137

0.99928

改进方法2

25.1265

0.029149

0.99847

改进方法3

27.6984

0.016122

0.99916

改进方法4

28.4599

0.013529

0.99929

改进方法5

28.3339

0.013927

0.99927

这三个指标里,SNR和NCC都是越大越好,MSE是越小越好,所以总体来看改进方法4对于这个信号来说是比较好的小波阈值方法。

这里有三点注意事项需要提醒大家:

第一。改进方法4和改进方法5都引入了调整因子,通过调参有可能得到更好的效果,不过这里仅做演示,就不详细地做参数调试啦。

第二。虽然改进的阈值方法在理论上对阈值函数进行了完善,但是并不意味着改进方法的滤波结果一定优于软/硬阈值方法,就像这个例子里的改进方法2。又或者换了一个分析对象,改进方法4的效果也比不上软/硬阈值也是有可能的,所以在实际应用过程中要灵活分析处理。

第三。SNR、NCC和MSE指标,都是需要知道“纯净信号”才能计算的,对于只知道真实含噪信号,不知道纯净信号的情况,是没办法计算这三个指标的。我在之前的文章里进行过详细的说明:Mr.看海:【滤波专题-第4篇】滤波器滤波效果的评价指标(信噪比SNR、均方误差MSE、波形相似参数NCC)

(三)获取小波阈值的封装函数

上边提到了两个笔者封装的函数,一个是实现小波阈值滤波的filterWaveletTh,还有一个是进行滤波效果评估指标计算的FilterEffectEvaluation,函数的详细说明如下,大家在调用的时候建议详细读一下:

function s = filterWaveletTh(data,wname,SORH,lev,tptr,options)
% 使用小波阈值法实现滤波,本文件是为了形式统一方便调用的一层封装,具体实现在kwden.m、kwdencmp.m、kwthresh.m、kthselect.m文件中
% 这4个文件均为经本人调整过后的函数文件,原函数分别为wden,wdencmp,wthresh,thselect,所以关于这几个函数更多介绍可以查看对应的官方帮助文档
% 输入:
% data:待滤波数据
% wname:小波名称,可选范围参考这里:https://ww2.mathworks.cn/help/wavelet/ref/wfilters.html?searchHighlight=wname&s_tid=srchtitle_wname_2#d123e130597
% SORH:阈值函数类型
%       sorh ='a1'时,采用改进方法1,改进后的软阈值:
%                     参考论文:孙万麟, 王超. 基于改进的软阈值小波包网络的电力信号消噪[J]. 海军工程大学学报, 2019(4).
%       sorh = 'a2'时,采用改进方法2:
%                     参考论文:刘冲, 马立修, 潘金凤,等. 联合VMD与改进小波阈值的局放信号去噪[J]. 现代电子技术, 2021, 44(21):6.
%       sorh = 'a3'时,采用改进方法4:
%                     参考论文:基于改进小波阈值-CEEMDAN算法的ECG信号去噪研究
%       sorh = 'a4'时,采用改进方法3:
%                     参考论文:基于改进小波阈值函数的语音增强算法研究
%                     采用该方法需要输入两个调节因子,分别是alpha和gamma,取alpha>0,0<gamma<1
%       sorh = 'a5'时,采用改进方法3:
%                     参考论文:基于VMD与改进小波阈值的地震信号去噪方法研究
%                     采用该方法需要输入两个调节因子,分别是alpha和beta% lev:  小波分解水平
% tptr: 阈值选择规则,有可选类型:
%       '' — Adaptive threshold selection using the principle of Stein's Unbiased Risk Estimate (SURE).
%       'sqtwolog' — Fixed-form threshold is sqrt(2*log(length(X))).
%       'heursure' — Heuristic variant of 'rigrsure' and 'sqtwolog'.
%       'minimaxi' — Minimax thresholding.
%       'visushrink' - 通用阈值去噪方法
% options:部分阈值函数需要补充的参数设置,即某些调节因子,需要用结构体方式调用幅值,如options.a4_alpha=2。如果不需要设置,可以赋值为options=[]。具体如下:
%          -a4_alpha:改进方法4的alpha值设置
%          -a4_gamma:改进方法4的gamma值设置
%          -a5_alpha:改进方法5的alpha值设置
%          -a5_beta:改进方法5的beta值设置
% 输出:
% s:经过滤波后得到的数据
% 理论讲解见:https://zhuanlan.zhihu.com/p/579187348/
function [SNR,MSE,NCC] = FilterEffectEvaluation(ori,fil)
% 对滤波效果进行评估
% 目前包含的评估指标有:信噪比SNR,均方差MSE,波形相似系数NCC
% 输入:
% ori:无噪声的原始数据,一维序列
% fil:滤波后的数据,一维序列
% 输出:
% SNR:信噪比
% MSE:均方误差
% NCC:波形相似系数
% 理论讲解见:https://zhuanlan.zhihu.com/p/558808890

这两个封装函数的方便之处在于,同学们差不多只需要导入自己要分析的数据,然后直接调用函数就可以了,更多的时间精力可以放在写论文和改进算法上。