matlab时频分析之连续小波变换cwt
作者:互联网
matlab时频分析之连续小波变换cwt
1 小波分析简介
和傅里叶变换比,小波变换和短时傅里叶变换都有着相同的优点,就是可以同时在时域和频域观察信号。所以小波变换非定常信号的分析中有很大的作用。
有关短时傅里叶变换的文章,可以参见我之前写的:
matlab时频分析之短时傅里叶变换 spectrogram
https://blog.csdn.net/weixin_42943114/article/details/88735799
和短时傅里叶变换相比,小波变换有着窗口自适应的特点,即高频信号分辨率高(但是频率分辨率差),低频信号频率分辨率高(但是时间分辨率差),而在工程中常常比较关心低频的频率,关心高频出现的时间,所以近些年用途比较广泛。
在数学上,小波还有正交化等优点,应用领域广泛。
但是,本文只讨论如何利用matlab实现cwt的时频分析
2 小波分析基本原理
小波的含义,即为时间上衰减快,和傅里叶的正弦波相比要短。
一个典型的morlet小波如下图:
matlab有很多自带的小波函数,利用wavemngr(‘read’,1)可以进行小波的查看,利用waveinfo可以查看小波的相关信息。
在时间域上,可以通过小波在时间上的移动,逐一比较不同位置的窗口信号,得到小波系数,小波系数越大,则证明小波与该段信号的拟合程度越好。计算中用小波函数与该窗口信号的卷积,作为该窗口下的小波系数。窗口的长度和小波的长度是相同的。
在频率域上,通过拉伸或压缩小波的长度,来改变小波的长短和频率,实现不同频率下的小波系数。相应的,窗口长度也会随着小波长度变化。由于高频处小波被压缩,时间窗变窄,使得时间分辨率更高。
将不同频率下的小波系数组合起来,便得到了时频变换的小波系数图。
从图上可以看到,低频处频率分辨率要好于高频处的。小波时频图的特点为整体呈现高频处高而瘦,低频处矮而宽。
小波中,一般用尺度scale来衡量小波的频率f,两者之间的转换关系为:
scale∗f=Fs∗wcf
公式中,Fs代表信号的采样频率,wcf为小波的中心频率(wave central freq),在matlab里可以用 centfrq(wavename) 来查询。
3 cwt的matlab实现
matlab自带的有两种实现方式,一种是2006年版本推出的函数cwt,一种是2016年版本推出的函数cwt。两个函数名称相同,用法不同。
(我也不知道为什么会这样。。。-_-||)
由于名称一样,在使用中,要想调用不同的版本,只能用输入输出格式来区分。
旧版本cwt用法为:
coefs = cwt(x,scales,'wname')
新版本cwt用法为:
[wt,f] = cwt(x,wname,fs)
最明显的区别在于,新版本取消了自定义尺度函数scales的功能。同时新版本还更新替换了一部分小波函数。旧版本支持 ‘haar’,‘db’,‘sym’,‘cmor’,‘mexh’,‘gaus’,‘bior’等小波,新版本支持’morse’, 'amor’和 'bump’小波。
新版本的小波函数用法如下:
% 定义信号信息
fs=2^6; %采样频率
dt=1/fs; %时间精度
timestart=-8;
timeend=8;
t=(0:(timeend-timestart)/dt-1)*dt+timestart;
L=length(t);
z=4*sin(2*pi*linspace(6,12,L).*t);
%matlab自带的小波变换
%新版本
figure(1)
[wt,f,coi] = cwt(z,'amor',fs);
pcolor(t,f,abs(wt));shading interp
旧版本的小波函数用法如下:
这里用到了cmor小波,以及频率转尺度的方法。
% 定义信号信息
fs=2^6; %采样频率
dt=1/fs; %时间精度
timestart=-8;
timeend=8;
t=(0:(timeend-timestart)/dt-1)*dt+timestart;
L=length(t);
z=4*sin(2*pi*linspace(6,12,L).*t);
%旧版本
wavename='cmor1-3'; %可变参数,分别为cmor的
%举一个频率转尺度的例子
fmin=2;
fmax=20;
df=0.1;
f=fmin:df:fmax-df;%预期的频率
wcf=centfrq(wavename); %小波的中心频率
scal=fs*wcf./f;%利用频率转换尺度
coefs = cwt(z,scal,wavename);
figure(2)
pcolor(t,f,abs(coefs));shading interp
对于cmor小波Fc和Fb的选取,可以认为最终结果只与Fc*√Fb的乘积大小有关就行。实际应用中具体值需要根据最终效果选择。
cmor小波最终得到的coefs小波系数,是一个复数矩阵,绝对值abs()代表信号的幅值,角度angle()代表信号的相位。一般用小波系数的实部real()来同时表示信号正负变化。
其实cwt的原理很简单,就是用不同尺度的小波逐个窗口去卷积,得到小波系数矩阵。所以根据原理,可以自己编程实现小波变换。
自己编程的cwt函数如下,这里主要算法参考了matlab官方的文档。这里我依然用的是cmor小波作为例子,morlet函数公式可以查询到,也可以用cmorwavf()函数调用:
fs=2^6; %采样频率
dt=1/fs; %时间精度
timestart=-8;
timeend=8;
t=(0:(timeend-timestart)/dt-1)*dt+timestart;
L=length(t);
z=4*sin(2*pi*linspace(6,12,L).*t);
%定义计算范围和精度
fmin=2;
fmax=20;
df=0.1;
totalscal=(fmax-fmin)/df;
f=fmin:df:fmax-df;%预期的频率
wcf=centfrq(wavename); %小波的中心频率
scal=fs*wcf./f;
%自己实现的小波函数
coefs2=cwt_cmor(z,1,3,f,fs);
figure(3)
pcolor(t,f,abs(coefs2));shading interp
%后面是函数
function coefs=cwt_cmor(z,Fb,Fc,f,fs)
%1 小波的归一信号准备
z=z(:)';%强行变成y向量,避免前面出错
L=length(z);
%2 计算尺度
scal=fs*Fc./f;
%3计算小波
shuaijian=0.001;%取小波衰减长度为1%
tlow2low=sqrt(Fb*log(1/shuaijian));%单边cmor衰减至1%时的时间长度,惨叫cmor的表达式
%3小波的积分函数
iter=10;%小波函数的区间划分精度
xWAV=linspace(-tlow2low,tlow2low,2^iter);
stepWAV = xWAV(2)-xWAV(1);
val_WAV=cumsum(cmorwavf(-tlow2low,tlow2low,2^iter,Fb,Fc))*stepWAV;
%卷积前准备
xWAV = xWAV-xWAV(1);
xMaxWAV = xWAV(end);
coefs = zeros(length(scal),L);%预初设coefs
%4小波与信号的卷积
for k = 1:length(scal) %一个scal一行
a_SIG = scal(k); %a是这一行的尺度函数
j = 1+floor((0:a_SIG*xMaxWAV)/(a_SIG*stepWAV));
%j的最大值为是确定的,尺度越大,划分的越密。相当于把一个小波拉伸的越长。
if length(j)==1 , j = [1 1]; end
waveinscal = fliplr(val_WAV(j));%把积分值扩展到j区间,然后左右颠倒。f为当下尺度的积分小波函数
%5 最重要的一步 wkeep1取diff(wconv1(ySIG,f))里长度为lenSIG的中间一段
%conv(ySIG,f)卷积。
coefs(k,:) = -sqrt(a_SIG)*wkeep1(diff(conv2(z,waveinscal, 'full')),L);
%
end
end
输出的结果如下,可以看到和matlab自带的函数得到的结果基本相同。
4 cwt的边缘效应与影响锥
利用自带的cwt函数,可以很方便的绘制出影响锥。
cwt(z)
由于小波计算中,小波系数是利用窗口函数和小波卷积而来的,当窗口在信号的边缘时,窗口内会存在一部分没有信号。这时,matlab就把窗口内这部分不完整的信号补零处理,凑够长度。
此时由于信号在边缘被强制补零,导致信号会失真,具体在时频图中表示为频率变宽,信号强度降低。严重的时候,甚至整个低频部分都会出现失真。这就是cwt的边缘效应。
为了确定边缘效应的影响,绘制出了一条影响曲线,曲线内部的信号影响小或者不受影响,曲线外部影响较大。曲线像一个锥形,高频处靠近两侧,低频处靠近中间,所以也被叫做影响锥。
所以根据边缘效应的原理,可以知道,之所以高频处影响范围小,是因为高频处小波被压缩,所以窗口更窄。低频处小波被拉伸,所以对应着窗口更宽。窗口的长度和小波的长度是相同的。
关于影响范围的评价,有很多种,这里为了方便说明,我直接用小波的半长度作为影响范围,来绘制影响锥。具体的思路如下,我认为超过小波长度一半的范围都是失真的,然后通过频率求出每一点的小波长度,再在图上连线绘制出来。
代码如下,依然以cmor小波为例,为了反应相位的影响,这里用的是real():
%小波变换展示
clear
fs=2^6; %采样频率
dt=1/fs; %时间精度
timestart=-8;
timeend=8;
t=(0:(timeend-timestart)/dt-1)*dt+timestart;
L=length(t);
z=sin(2*pi*5.*t)+sin(2*pi*9.*t)+sin(2*pi*15.*t);
%定义范围
wavename='cmor1-3'; %可变参数
fmin=2;
fmax=20;
df=0.1;
totalscal=(fmax-fmin)/df;
f=fmin:df:fmax-df;%预期的频率
wcf=centfrq(wavename); %小波的中心频率
scal=fs*wcf./f;
%旧版本
coefs = cwt(z,scal,wavename);
figure(2)
pcolor(t,f,real(coefs));shading interp
tlow2low=sqrt(1*log(1/0.001));%单边cmor衰减至1%时的时间长度
tcoi41=tlow2low*scal;%小波一半长度
bur=(tcoi41<L/2);
fcoi4=f(bur);
tcoi41=tcoi41(bur);
tcoi42=-tcoi41+L;
hold on
plot(tcoi41/fs+timestart,fcoi4,'r','LineWidth',2)
plot(tcoi42/fs+timestart,fcoi4,'r','LineWidth',2)
hold off
5 cwt的重构——icwt
如果用的是matlab新版的默认小波,那么可以直接把cwt之后小波系数icwt即可。
load mtlb;
wt = cwt(mtlb);
xrec = icwt(wt);
对于morlet小波,可以直接 sum(real(coefs),1) 来实现重构。但是,这里尺度最好用默认尺度,否则会出现重复叠加导致幅值出现问题。
具体用法可以参见帮助文档。
6 增加cwt的分辨率的wsst
利用wsst可以显著的提高cwt的频率分辨率。具体用法如下:
clear
fs=2^6; %采样频率
dt=1/fs; %时间精度
timestart=-8;
timeend=8;
t=(0:(timeend-timestart)/dt-1)*dt+timestart;
L=length(t);
z=4*sin(2*pi*linspace(6,12,L).*t);
[sst,f] = wsst(z,fs);
figure(4)
pcolor(t,f,abs(sst));shading interp
与普通cwt的对比图如下:
左图是cwt的时频图,右图是wsst的时频图。
wsst同样可以利用iwsst进行重构,具体方法可以参见iwsst的帮助文档。
如果想要提高wsst的精度,可以在matlab里选中wsst,然后Ctrl+D进入wsst的代码界面,把里面的na参数,强行改的大一点。
具体方法为在下面代码后,加上一个na=512(这里不一定是512,具体根据na实际值进行适当放大,在我这里的例子中,na=288。如果怕出错,建议备份)。
na = noct*params.nv;
na=512
这样做的优点是,在不影响iwsst的运行结果的基础上,显著的提高分解的精度。
标签:fs,小波,cwt,时频,matlab,频率,dt 来源: https://blog.csdn.net/weixin_42943114/article/details/89603208