小波变换是一种信号的时间——尺度(时间——频率)分析方法,它具有多分辨分析的特点,而且在时频两域都具有表征信号局部特征的能力,是一种窗口大小固定不变但其形状可改变,时间窗和频率窗都可以改变的时频局部化分析方法。即在低频部分具有较低的时间分辨率和较高的频率分辨率,在高频部分具有较高的时间分辨率和较低的频率分辨率,很适合于分析非平稳的信号和提取信号的局部特征,所以小波变换被誉为分析处理信号的显微镜。
傅里叶是将信号分解成一系列不同频率的正余弦函数的叠加,同样小波变换是将信号分解为一系列的小波函数的叠加(或者说不同尺度、时间的小波函数拟合),而这些小波函数都是一个母小波经过平移和尺度伸缩得来的。
小波变换常见的形式有连续小波变换(CWT
)、离散小波变换(DWT
)等。连续小波变换是在尺度基础上连续变换的,做信号的小波分析得到的是幅值,a 时间的三维图,对应的 a 值所截得的曲线即为该尺度的小波图形。而离散小波变换常用的是二进小波变换,对尺度和时间进行离散化处理。
CWT
步骤:
连续小波变换是在尺度基础上连续变换的,做信号的小波分析得到的是幅值,a 时间的三维图,对应的 a 值所截得的曲线即为该尺度的小波图形。而集散小波变换常用的是二进小波变换。
但是,CWT
的结果都相当于 DWT
中的细节信息(即所谓 DWT
中的高频信息。虽然越向后频率越低,有时已不能用 “高频” 来形容了,但这时的高频是相对概念,是相对于同阶逼近信息还是高的),只是其尺度是连续的尺度越大频率越低,一直低下去。
morlet
等小波只能做 CWT
,有些是因为没法儿构造尺度函数,有些是根本就没有逆变换(只有满足某些条件,CWT
才存在逆变换,这与小波基有关),有些是如何离散化也不能构成正交或双正交基,甚至按照二进制的离散化不能构成紧支的框架,所以它们通常不能做 DWT
,也就没有逆变换、重构一说了。
DWT
离散小波变换
离散小波变换 DWT
对尺度参数按幂级数进行离散化处理,对时间进行均匀离散化取值如二进制离散化尺度时间为 2, 4, 6, 8…2n(要求采样率满足尼奎斯特采样定理),常用于信号的多分辨分析、信号分解重构。
多分辨分析也称为多尺度分析,是建立在函数空间概念上的理论。在不同的尺度和时间下,分别构造了尺度函数向量组合小波函数向量组,也即是尺度函数向量空间V与小波函数向量空间 W,在一定层次下,信号在尺度空间做卷积所得到的是信号的近似、低频信息,信号在小波空间 W 做卷积所得到的是信号的细节、高频信息。(注意:尺度与分解层数不是一个概念,尺度与频率成反比的,分解层数是对频率的范围进行一定的划分)。
在多分辨分析中,如正交小波变换可以等效为一组镜像滤波的过程,即信号通过一个分解高通滤波器和分解低通滤波器,自然的高通滤波器输出对应的信号的高频分量部分,称为细节分量,低通滤波器输出对应了信号的相对较低的频率分量部分,称为近似分量。对应的快速算法称为 Mallat
算法。
从水平和竖直两个方向进行低通和高通滤波(水平和竖直先后不影响),用图像表述如下图所示:图 a 表示原图,图 b 表示经过一级小波变换的结果,h1 表示水平方向的细节,v1 表示竖直方向的细节,c1表示对角线方向的细节,b 表示下2采样的图像。图 c 中表示继续进行 Haar
小波变换。
A 是低频信息,H 是水平高频信息,V 是垂直高频信息、D 是对角高频信息。
例:[c,s]=wavedec2(X,2,'haar');
这个函数就是将一幅图像 X 分解成小波系数存入 c 中,其中 N 代表分解的级数,wname 代表所用的小波基函数。s 记录了每一级分解时各个小波系数的 size
,如下图,size
记录的其实就是最开始那个图上,HH1,HH2,HH3…的边长,也就是像素大小。s最后一行是原始图像的大小。
例:[H1, V1, D1] = detcoef2('all', c, s, 1);
将 c 里面的高频系数重组成矩阵形式,参数 N 代表对第 N 级的分解系数进行操作。此函数只能重组高频系数,H1 为水平方向,V1 为垂直方向,D1 为对角线方向。
例:A2 = appcoef2(c, s, 'haar', 2);
将 c 里面的低频系数重组成矩阵形式,N 代表第几级分解。
例:X_A2 = wrcoef2('a', c, s, 'sym5', 1)
通过第 N 级分解的低频系数或高频系数重构图像。其中 type 是代表选择的是系数 A,V,H,D 中的哪一个进行重构。
例:waverec2(c_Recon1, s, 'haar')
直接通过 c 里面的所有系数来重构图像,但这里一般会将 c 里面部分系数置 0,然后再重构图像。如果不置 0 的话,不就相当于重构回来的就是原来一模一样的图像了吗。
%% 小波分解与重构
clear;clc;close all;
X = imread('standard_lena.bmp');
% figure,imshow(X);
[c,s] = wavedec2(X, 2, 'haar'); %对图像X进行2级小波分解,分解得到的系数存到c,s是记录各个级系数的size
[H1, V1, D1] = detcoef2('all', c, s, 1); %将c里面的系数重组成矩阵形式,参数1代表对第一级的分解系数进行操作。都是高频系数,代表边缘
% A1 = appcoef2(c,s,'haar',1); %一级分解低频系数
[H2, V2, D2] = detcoef2('all', c, s, 2); %将c里面的系数重组成矩阵形式,参数1代表对第一级的分解系数进行操作。都是高频系数,代表边缘
A2 = appcoef2(c, s, 'haar', 2); %二级分解低频系数
X_A2 = wrcoef2('a', c, s, 'sym5', 2); %通过二级分解后的低频系数重构图
X_H1 = wrcoef2('h', c, s, 'sym5', 1);
X_V1 = wrcoef2('v', c, s, 'sym5', 1);
X_D1 = wrcoef2('d', c, s, 'sym5', 1);
X_H2 = wrcoef2('h', c, s, 'sym5', 2);
X_V2 = wrcoef2('v', c, s, 'sym5', 2);
X_D2 = wrcoef2('d', c, s ,'sym5', 2);
%% 保存各级分解重构图片
figure(1);imshow(X_A2,[]);saveas(1, 'picture/lena_A2.bmp');
figure(2);imshow(X_H1,[]);saveas(2, 'picture/lena_H1.bmp');
figure(3);imshow(X_V1,[]);saveas(3, 'picture/lena_V1.bmp');
figure(4);imshow(X_D1,[]);saveas(4, 'picture/lena_D1.bmp');
figure(5);imshow(X_H2,[]);saveas(5, 'picture/lena_H2.bmp');
figure(6);imshow(X_V2,[]);saveas(6, 'picture/lena_V2.bmp');
figure(7);imshow(X_D2,[]);saveas(7, 'picture/lena_D2.bmp');
%% 图像重构
c_RemainPortion = 0.05; %保留字带的系数所占百分比
c_end = s(1,1)^2+round((length(c)- s(1,1)^2)*c_RemainPortion); %在将系数c的后面部分设为0时,要考虑c的最前面是低频分量,是不可以去掉的;
c_Recon1 =zeros(1,length(c));
c_Recon1(1:c_end) = c(1:c_end);
X_Recon1 = uint8(waverec2(c_Recon1, s, 'haar'));
figure(8);imshow(X_Recon1,[]);title('保留系数5%');saveas(8,'picture/lena_Recon1.bmp');
c_RemainPortion = 0.1; %保留字带的系数所占百分比
c_end = s(1,1)^2+round((length(c)- s(1,1)^2)*c_RemainPortion); %在将系数c的后面部分设为0时,要考虑c的最前面是低频分量,是不可以去掉的;
c_Recon2 =zeros(1,length(c));
c_Recon2(1:c_end) = c(1:c_end);
X_Recon2 = uint8(waverec2(c_Recon2, s, 'haar'));
figure(9);imshow(X_Recon2,[]);title('保留系数10%');saveas(9,'picture/lena_Recon2.bmp');
c_RemainPortion = 0.2; %保留字带的系数所占百分比
c_end = s(1,1)^2+round((length(c)- s(1,1)^2)*c_RemainPortion); %在将系数c的后面部分设为0时,要考虑c的最前面是低频分量,是不可以去掉的;
c_Recon3 =zeros(1,length(c));
c_Recon3(1:c_end) = c(1:c_end);
figure(10);X_Recon3 = uint8(waverec2(c_Recon3, s, 'haar'));
figure(10);imshow(X_Recon3,[]);title('保留系数20%');saveas(10,'picture/lena_Recon3.bmp');
c_RemainPortion = 1; %保留字带的系数所占百分比
c_end = s(1,1)^2+round((length(c)- s(1,1)^2)*c_RemainPortion); %在将系数c的后面部分设为0时,要考虑c的最前面是低频分量,是不可以去掉的;
% c_Recon4 =zeros(1,length(c));
c_Recon4(1:c_end) = c(1:c_end);
figure(11);X_Recon4 = uint8(waverec2(c_Recon4, s, 'haar'));
figure(11);imshow(X_Recon4,[]);title('保留系数100%');saveas(11,'picture/lena_Recon4.bmp');
% 全部C系数
Z = waverec2(c, s, 'haar');
figure(12);imshow(Z,[]);title('全部的C系数');saveas(12,'picture/lena_X.bmp');
%% 计算熵和信噪比
entropy(X);
entropy(X_Recon1)
MSE1 = mean(mean(X-X_Recon1).^2);
PSNR1 = 20*log10(double(255/MSE1));
entropy(X_Recon2)
MSE2 = mean(mean(X-X_Recon2).^2);
PSNR2 = 20*log10(double(255/MSE2));
entropy(X_Recon3)
MSE3 = mean(mean(X-X_Recon3).^2);
PSNR3 = 20*log10(double(255/MSE3));
通常情况下, 我们在从设备上采集到的信号都是具有一定的噪声的,大多数情况下,可认为这种噪声为高斯白噪声。被噪声污染的信号=干净的信号+噪声。
为什么要使用阈值:由于信号在空间上(或者时间域)是有一定连续性的,因此在小波域,有效信号所产生的小波系数其模值往往较大;而高斯白噪声在空间上(或者时间域)是没有连续性的,因此噪声经过小波变换,在小波阈仍然表现为很强的随机性,通常仍认为是高斯白噪的。那么就得到这样一个结论:在小波域,有效信号对应的系数很大,而噪声对应的系数很小。 刚刚已经说了,噪声在小波域对应的系数仍满足高斯白噪分布。如果在小波域,噪声的小波系数对应的方差为 sigma
,那么根据高斯分布的特性,绝大部分(99.99%)噪声系数都位于[-3sigma,3sigma]区间内(切比雪夫不等式, 3sigma准则)。因此,只要将区间[-3sigma,3sigma]内的系数置零(这就是常用的硬阈值函数的作用),就能最大程度抑制噪声的,同时只是稍微损伤有效信号。将经过阈值处理后的小波系数重构,就可以得到去噪后的信号。 常用的软阈值函数,是为了解决硬阈值函数 “一刀切” 导致的影响(模小于3sigma的小波系数全部切除,大于3sigma全部保留,势必会在小波域产生突变,导致去噪后结果产生局部的抖动,类似于傅立叶变换中频域的阶跃会在时域产生拖尾)。软阈值函数将模小于 3sigma 的小波系数全部置零,而将模大于 3sigma 的做一个比较特殊的处理,大于 3sigma 的小波系数统一减去 3sigma,小于 -3sigma 的小波系数统一加 3sigma。经过软阈值函数的作用,小波系数在小波域就比较光滑了,因此用软阈值去噪得到的图象看起来很平滑,类似于冬天通过窗户看外面一样,像有层雾罩在图像上似的。
比较硬阈值函数去噪和软阈值函数去噪:硬阈值函数去噪所得到的峰值信噪比(PSNR
)较高,但是有局部抖动的现象;软阈值函数去噪所得到的 PSNR
不如硬阈值函数去噪,但是结果看起来很平滑,原因就是软阈值函数对小波系数进行了较大的 “社会主义改造”,小波系数改变很大。因此各种各样的阈值函数就出现了,其目的我认为就是要使大的系数保留,小的系数被剔出,而且在小波域系数过渡要平滑。
如何估计小波域噪声方差 sigma
的估计,这个很简单:把信号做小波变换,在每一个子带利用 robust estimator
估计就可以(可能高频带和低频带的方差不同)。 robust estimator
就是将子带内的小波系数模按大小排列,然后取最中间那个,然后把最中间这个除以0.6745 就得到噪声在某个子带内的方差 sigma
。利用这个 sigma
,然后选种阈值函数,就可以去去噪了,在 matlab
有实现 api
可使用。
在小波分析中经常用到近似和细节,近似表示信号的高尺度,即低频信息;细节表示信号的低尺度,即高频信息。对含有噪声的信号,噪声分量的主要能量集中在小波解的细节分量中。
在以上过程中,小波基和分解层数的选择,阈值的选取规则,和阈值函数的设计,都是影响最终去噪效果的关键因素。
可参考 http://blog.csdn.net/jbb0523/article/details/42586749 博文,一般选取小波基函数要从支撑长度、消失矩、对称性、正则性以及相似性等进行综合考虑。由于小波基函数在处理信号时各有特点,且没有任何一种小波基函数可以对所有类型信号都取得最优的去噪效果。一般来讲,db 小波系和 sym 小波系在语音去噪中是经常会被用到的两族小波基。
对于一个要采集的信号,根据奈奎斯采样定理,其采样频率 >= 2*信号的最大频率。而其他噪声频率如高斯白噪声的信号是幅度分布服从高斯分布,功率谱密度服从均匀分布的,并且与有效信号进行混合叠加的。
在小波分解中,分解层数的选择也是非常重要的一步。取得越大,则噪声和信号表现的不同特性越明显,越有利于二者的分离。但另一方面,分解层数越大,重构到的信号失真也会越大,在一定程度上又会影响最终去噪的效果。因此在应用时要格外注意处理好两者之间的矛盾,选择一个合适的分解尺度。
通常小波分解的频段范围与采样频率有关。若 N 层分解,则各个频段大小为 Fs/2/2^N 。例如:一个原始信号,经历的时间长度为 2 秒,采样了 2000 个点,那么做除法,可得出采样频率为 1000hz,由采样定理(做除法)得该信号的最大频率为 500hz,那么对该信号做 3层的 DWT
,一阶细节的频段为 250-500hz,一阶逼近的频段为小于 250hz,二阶细节的频段为 125-250hz,逼近的频段为小于125hz,三阶细节的频段约为 62.5-125hz,逼近的频段为小于 62.5hz。对于更多阶的分解也是以此类推的。
在小波域,有效信号对应的系数很大,而噪声对应的系数很小。噪声在小波域对应的系数仍满足高斯白噪分布。
阈值选择规则基于模型 y = f(t) + e,e 是高斯白噪声 N(0,1)。因此可以通过小波系数、或者原始信号来进行评估能够消除噪声在小波域的阈值。
目前常见的阈值选择方法有:固定阈值估计、极值阈值估计、无偏似然估计以及启发式估计等(N为信号长度)。
一般来讲,极值阈值估计和无偏似然估计方法比较保守,当噪声在信号的高频段分布较少时,这两种阈值估计方法效果较好可以将微弱的信号提取出来。而固定阈值估计和启发式阈值估计去噪比较彻底,在去噪时显得更为有效,但是也容易把有用的信号误认为噪声去掉。
确定了高斯白噪声在小波系数(域)的阈值门限之后,就需要有个阈值函数对这个含有噪声系数的小波系数进行过滤,去除高斯噪声系数,常用的阈值函数有软阈值和硬阈值方法,很多文献论文中也有在阈值函数进行一些大量的改进和优化。
硬阈值函数在均方误差意义上优于软阈值法,但是信号会产生附加震荡,产生跳跃点,不具有原始信号的平滑性。
软阈值估计得到的小波系数整体连续性较好,从而使估计信号不会产生附加震荡,但是优于会压缩信号,会产生一定的偏差, 直接影响到重构的信号与真实信号的逼近程度。
ddencmp
ddencmp()函数自动生成小波消噪或压缩的阈值选取方案。
调用方式:
自动生成信号 X 的小波或小波包消噪或数据压缩的阈值选取方案。
输入参数 X 为一维或二维的信号向量或矩阵;
输入参数 IN1 指定处理的目的是消噪还是压缩,可选值为:
输入参数 IN2 指定处理的方式,可选值:
输出参数 THR 为函数选择的阈值,SORH为函数选择阈值使用方式。Sorh=s,为软阈值;Sorh=h,为硬阈值。输出参数 KEEPAPP 决定了是否对近似分量进行阈值处理。可选为0或1。CRIT 为使用小波包进行分解时所选取的熵函数类型。
wdencmp
函数 wdencmp 用于一维或二维信号的消噪或压缩。
调用方式:
函数 wdencmp 用于一维或二维信号的消噪或压缩。
wname 是所用的小波函数,
gbl(global的缩写)表示每层都采用同一个阈值进行处理,lvd 表示每层用不同的阈值进行处理,N表示小波分解的层数,THR 为阈值向量,对于格式 (2) (3) 每层都要求有一个阈值,因此阈值向量 THR 的长度为 N,SORH 表示选择软阈值还是硬阈值(分别取为 ’s’ 和 ’h’),参数 KEEPAPP 取值为 1 时,则低频系数不进行阈值量化处理,反之,则低频系数进行阈值量化。
XC 是消噪或压缩后的信号,[CXC,LXC] 是 XC 的小波分解结构,PERF0 和 PERFL2 是恢复和压缩 L^2 的范数百分比,是用百分制表明降噪或压缩所保留的能量成分。如果 [C,L] 是X的小波分解结构,则 PERFL2=100*(CXC向量的范数/C向量的范数)^2; 如果X是一维信号,小波wname是一个正交小波,则PERFL2=100||XC||^2 / ||X||^2
% 软硬阈值去噪
clc,close all;
image = rgb2gray(imread('standard_lena.bmp')); % 读取灰度图像
noiseI = imnoise(image, 'gaussian', 0, 0.02); % 添加高斯白噪声
subplot(2, 3, 1),imshow(image),title('原图像');
subplot(2, 3, 2),imshow(noiseI),title('高斯白噪声图像');
% 对图像noiseI用sym5小波基函数实现N层分解
[c, z] = wavedec2(noiseI, 2, 'sym5');
% (1)[THR,SORH,KEEPAPP,CRIT]=ddencmp(IN1,IN2,X)
% (2)[THR,SORH,KEEPAPP,CRIT]=ddencmp(IN1,'wp',X)
% (3)[THR,SORH,KEEPAPP,CRIT]=ddencmp(IN1,'wv',X)
% 函数ddencmp用于获取信号在消噪或压缩过程中的默认阈值。
% 输入参数X为一维或二维信号;IN1取值为'den'或'cmp','den'表示进行去噪,'cmp'表示进行压缩;IN2取值为'wv'或'wp',wv表示选择小波,wp表示选择小波包。返回值THR是返回的阈值;SORH是软阈值或硬阈值选择参数;KEEPAPP表示保存低频信号;CRIT是熵名(只在选择小波包时使用)。
% 查找默认值
[thr, sorh, keepapp] = ddencmp('den', 'wv', noiseI);
% 全局阈值设置去噪.
% [XC,CXC,LXC,PERF0,PERFL2] = wdencmp('gbl',X,'wname',N,THR,SORH,KEEPAPP)
% 函数wdencmp用于一维或二维信号的消噪或压缩。wname是所用的小波函数,gbl(global的缩写)表示每层都采用同一个阈值进行处理,lvd表示每层用不同的阈值进行处理,N表示小波分解的层数,THR为阈值向量,对于格式(2)(3)每层都要求有一个阈值,因此阈值向量THR的长度为N,SORH表示选择软阈值还是硬阈值(分别取为’s’和’h’),参数KEEPAPP取值为1时,则低频系数不进行阈值量化处理,反之,则低频系数进行阈值量化。XC是消噪或压缩后的信号,[CXC,LXC]是XC的小波分解结构,PERF0和PERFL2是恢复和压缩L^2的范数百分比, 是用百分制表明降噪或压缩所保留的能量成分。如果[C,L]是X的小波分解结构,则PERFL2=100*(CXC向量的范数/C向量的范数)^2;如果X是一维信号,小波wname是一个正交小波,则PERFL2=100||XC||^2 / ||X||^2
[denoiseI, cxc, lxc, perf0, perf12] = wdencmp('gbl', c, z, 'sym5',2, thr, sorh, keepapp);
denoiseI = uint8(denoiseI);
subplot(2, 3, 3),imshow(denoiseI),title('降噪后的图像');
imwrite(denoiseI, 'denoiseI.jpg');
sigma = std(c);
% 采用硬阈值,软阈值小波变换对图像进行去噪,阈值取标准偏差的3倍
% 硬阈值是指将小于3倍标准偏差的小波系数全部置零,其他系数保持不变
% 软阈值是指键大于阈值的小波系数修改为减去阈值后的值,将小于阈值相反的小波系数
thresh = 3*sigma;
csize = size(c);
c(find(abs(c) thresh);
c(pos1) = c(pos1) - thresh;
pos2 = find(c <- thresh);
c(pos2) = c(pos2) + thresh;
denoiseI2 = uint8(waverec2(c, z, 'sym5'));
subplot(2, 3, 5),imshow(denoiseI2),title('软阈值降噪');
imwrite(denoiseI2, 'denoise3.jpg');