小波变换作为一种时频分析工具,在信号处理领域已经发展了三十余年。我第一次接触小波分析是在研究生阶段分析振动信号时,当时就被它既能定位时间又能分析频率的特性所震撼。与傅里叶变换只能提供全局频率信息不同,小波变换通过可伸缩和平移的小波基函数,实现了对信号的多尺度分析。
在MATLAB环境中实现小波分析,最核心的就是理解小波分解与重构的数学原理。小波分解的本质是将信号投影到一系列由母小波经过伸缩和平移得到的子空间上。以离散小波变换(DWT)为例,其分解过程可以表示为:
matlab复制[cA, cD] = dwt(signal, 'db4');
这里'db4'指代Daubechies 4阶小波,cA是近似系数(低频部分),cD是细节系数(高频部分)。这个过程实际上是一系列滤波和下采样操作的组合:信号先后通过低通和高通滤波器,然后进行二抽取(下采样)。
小波基的选择直接影响分析效果。Daubechies系列(dbN)适合瞬态信号,Symlets(symN)更对称适合图像处理,Coiflets(coifN)则具有更好的近似对称性。选择时需要考虑信号的特性以及小波的支撑长度和消失矩。
完整的分解重构流程需要掌握几个关键函数。以分析一个包含50Hz和120Hz的合成信号为例:
matlab复制% 生成测试信号
fs = 1000; % 采样率
t = 0:1/fs:1-1/fs;
x = sin(2*pi*50*t) + sin(2*pi*120*t);
% 3层小波分解
[c, l] = wavedec(x, 3, 'db4');
% 提取各层细节
d1 = detcoef(c, l, 1); % 第一层高频细节
d2 = detcoef(c, l, 2); % 第二层
d3 = detcoef(c, l, 3); % 第三层
a3 = appcoef(c, l, 'db4', 3); % 第三层低频近似
% 信号重构
x_rec = waverec(c, l, 'db4');
这个过程中,wavedec函数完成了多层分解,返回的c是系数向量,l是各层系数长度记录。重构误差可以通过计算原始信号与重构信号的均方误差来评估:
matlab复制mse = sum((x - x_rec).^2)/length(x);
当需要更精细的频率划分时,小波包变换(WPT)是更好的选择。与DWT只分解低频部分不同,WPT会对高低频都进行分解。实现代码示例:
matlab复制% 小波包树构建
wpt = wpdec(x, 3, 'db4');
% 绘制小波包树
plot(wpt)
% 获取特定节点系数
node = [2 1]; % 第二层第一个节点
cfs = wpcoef(wpt, node);
% 最优基选择
[btree, q] = bestbas(wpt, 'shannon');
小波包变换特别适合分析频率成分复杂的信号,比如机械故障诊断中多个轴承故障频率的分离。通过最优基选择算法(如香农熵准则),可以自动找到最有效的分解方式。
提取特征频率的关键在于选择合适的尺度转换方法。对于小波分解得到的各层细节系数,可以通过尺度图(scalogram)来观察时频分布:
matlab复制% 计算连续小波变换尺度图
scales = 1:64;
cwt_coefs = cwt(x, scales, 'db4');
freq = scal2frq(scales, 'db4', 1/fs); % 尺度转频率
% 绘制尺度图
figure;
contour(t, freq, abs(cwt_coefs));
set(gca, 'YScale', 'log');
ylabel('Frequency (Hz)');
xlabel('Time (s)');
对于旋转机械的故障诊断,包络分析尤为重要。实现步骤包括:
matlab复制% 包络谱分析示例
d3 = detcoef(c, l, 3); % 选择第三层细节
env = abs(hilbert(d3)); % 希尔伯特变换
[Penv, f] = periodogram(env, [], [], fs); % 功率谱估计
figure;
plot(f, 10*log10(Penv));
xlabel('Frequency (Hz)');
ylabel('Power Spectrum (dB)');
不同分解层对应不同的频率范围,这由采样率和分解层数决定。频率范围计算公式为:
code复制第n层细节频率范围:fs/2^(n+1) ~ fs/2^n
第n层近似频率范围:0 ~ fs/2^(n+1)
基于此可以设计特征提取策略。以轴承故障诊断为例:
matlab复制% 计算各层能量特征
energy = zeros(1, 4);
energy(1) = sum(d1.^2); % 第一层细节能量
energy(2) = sum(d2.^2); % 第二层
energy(3) = sum(d3.^2); % 第三层
energy(4) = sum(a3.^2); % 第三层近似能量
% 计算能量熵
total_energy = sum(energy);
prob = energy / total_energy;
entropy = -sum(prob .* log(prob));
这些特征可以用于后续的模式识别和故障分类。在实际项目中,我通常会结合时域特征(如峰值、峭度)和频域特征(如重心频率)一起使用。
小波变换的边界效应是实际应用中常见的问题。MATLAB提供了多种扩展模式:
matlab复制% 设置边界处理模式
dwtmode('sym'); % 对称延拓
dwtmode('per'); % 周期延拓
dwtmode('zpd'); % 零填充(默认)
% 查看当前模式
current_mode = dwtmode('status');
对于长信号,我推荐使用分段处理策略:将信号分成有重叠的段,分别处理后再拼接。重叠长度一般取小波滤波器长度的两倍。
处理长信号时,计算效率至关重要。几个实用技巧:
matlab复制% 并行计算示例
parfor i = 1:num_signals
[c, l] = wavedec(signals{i}, 5, 'db4');
features(i, :) = extract_features(c, l);
end
对于实时处理系统,可以考虑使用提升方案(lifting scheme)实现小波变换,它比传统方法快约30%。
调试时可以从小数据量开始,使用'plot'函数可视化各层系数,确保分解结果符合预期后再处理完整数据集。我曾在一个项目中花费两天时间调试,最后发现只是因为采样率设置错误导致频率对应关系不对。
在风机轴承故障诊断项目中,我们采集了振动信号并观察到调制现象。通过以下步骤成功提取了故障特征:
matlab复制% 实际项目代码片段
[c, l] = wavedec(vibration, 5, 'db10');
d4 = detcoef(c, l, 4);
env = abs(hilbert(d4));
[Penv, f] = pwelch(env, [], [], [], fs);
% 查找峰值
[pks, locs] = findpeaks(Penv, f, 'MinPeakHeight', 0.1*max(Penv));
fault_freq = locs(pks == max(pks)); % 最大峰值对应的频率
分析电网电压信号中的谐波成分时,小波包变换展现出独特优势:
matlab复制% 谐波分析代码
wpt = wpdec(voltage, 6, 'db12');
[btree, q] = bestbas(wpt, 'shannon');
% 获取50Hz基波节点
base_node = [ones(1,6); zeros(1,6)]; % 路径全为1
base_cfs = wpcoef(wpt, base_node);
base_thd = thd(base_cfs); % 计算总谐波畸变率
这个案例中,我们发现小波包变换对间谐波的检测效果明显优于FFT方法,特别是在非稳态情况下。