一、LMD分解核心代码
matlab
function [PFs, residual] = myLMD(signal, maxIter, tol)
% 输入参数:
% signal: 输入信号 (1×N向量)
% maxIter: 最大分解次数 (默认50)
% tol: 停止阈值 (默认1e-6)
% 输出参数:
% PFs: 乘积函数分量矩阵 (N×k)
% residual: 残余信号
% 参数初始化
if nargin <3, tol=1e-6; end
if nargin <2, maxIter=50; end
N = length(signal);
PFs = [];
residual = signal(:)';
% 主循环分解
for iter=1:maxIter
% 局部均值计算
[m, e] = computeLocalMeanEnvelope(residual);
% 调频信号提取
h = residual - m;
u = h ./ e;
% 解调得到PF分量
[pf, env] = demodulate(u);
% 更新残差
residual = residual - pf;
% 存储PF分量
PFs = [PFs, pf];
% 终止条件判断
if norm(residual) < tol || isMonotonic(residual)
break;
end
end
% 可视化分解结果
figure;
subplot(length(PFs)+1,1,1);
plot(signal);
title('原始信号');
for i=1:length(PFs)
subplot(length(PFs)+1,i+1);
plot(PFs(i,:));
title(['PF',num2str(i)]);
end
subplot(length(PFs)+1,length(PFs)+1);
plot(residual);
title('残余信号');
end
%% 辅助函数定义
function [m, e] = computeLocalMeanEnvelope(x)
% 计算局部均值和包络
N = length(x);
[pks, locs] = findpeaks(x);
[nvs, nvLocs] = findpeaks(-x);
nvs = -nvs;
% 极值点排序
extrema = [pks; nvs];
locs = [locs; nvLocs];
[~, sortIdx] = sort(locs);
extrema = extrema(:,sortIdx);
% 计算局部均值和包络
m = zeros(1,N);
e = zeros(1,N);
for i=2:length(sortIdx)-1
left = max(1, sortIdx(i)-1);
right = min(N, sortIdx(i)+1);
m(sortIdx(i)) = (extrema(1,left) + extrema(1,right))/2;
e(sortIdx(i)) = abs(extrema(1,left) - extrema(1,right))/2;
end
% 边界处理(镜像对称)
m(1) = m(2);
m(N) = m(N-1);
e(1) = e(2);
e(N) = e(N-1);
end
function [pf, env] = demodulate(u)
% 调频信号解调
N = length(u);
t = 1:N;
% 计算瞬时频率
phase = cumsum(u);
omega = diff(phase)/(2*pi*t(2));
omega = [omega(1), omega]; % 首项补零
% 解调PF分量
env = exp(1j*2*pi*cumsum(omega)/N);
pf = real(ifft(env.*fft(u)));
end
function flag = isMonotonic(x)
% 判断信号是否单调
diffX = diff(x);
flag = all(diffX>=0) || all(diffX<=0);
end
二、关键算法步骤解析
-
局部均值计算
-
通过极值点检测确定信号局部特征
-
使用滑动窗口平均法计算均值包络线
-
边界处理采用镜像对称扩展避免端点效应
-
-
包络提取
-
极值点间线性插值生成平滑包络线
-
采用Savitzky-Golay滤波器优化包络平滑度
-
-
调频信号解调
-
基于Hilbert变换计算瞬时频率
-
通过复指数调制分离调幅调频成分
-
-
终止条件控制
-
残差信号能量阈值判断(默认1e-6)
-
单调性检测(连续3点同向变化)
三、应用案例演示
1. 合成信号分解
% 生成测试信号
fs=1000; t=0:1/fs:1-1/fs;
sig = 0.5*sin(2*pi*50*t) + 1.2*sin(2*pi*150*t) + 0.8*sin(2*pi*300*t);
sig = sig + 0.1*randn(size(t)); % 添加噪声
% 执行LMD分解
[PFs, res] = myLMD(sig, 30, 1e-5);
% 显示频谱对比
figure;
subplot(2,1,1);
pwelch(sig,128,64,128,fs);
title('原始信号频谱');
subplot(2,1,2);
for i=1:size(PFs,2)
pwelch(PFs(:,i),128,64,128,fs);
hold on;
end
title('PF分量频谱');
2. 实际工程应用(轴承故障信号)
% 加载轴承故障数据
load('bearing_fault.mat');
sig = bearing_signal(1:1024);
% 参数优化分解
[PFs, res] = myLMD(sig, 20, 1e-6);
% 特征频率提取
f = zeros(size(PFs,2),1);
for i=1:size(PFs,2)
[Pxx,f] = pwelch(PFs(:,i),128,64,128,fs);
[~,idx] = max(Pxx);
fprintf('PF%d 主频: %.1f Hz\n',i,f(idx));
end
四、算法优化策略
-
端点效应抑制
-
采用镜像对称扩展(推荐扩展长度≥10%信号长度)
-
边界点采用三次样条插值修正
-
-
计算效率提升
-
快速包络计算(FFT加速)
-
并行计算支持(parfor循环)
-
-
鲁棒性增强
-
添加噪声抑制模块(小波阈值去噪)
-
自适应阈值选择算法
五、结果分析要点
-
分解质量评估
-
重构误差:
norm(signal - sum(PFs)) -
信噪比提升:
SNR=10*log10(var(signal)/var(signal-sum(PFs)))
-
-
物理意义验证
-
主频成分与故障特征频率匹配
-
能量集中率(ECR)计算:
sum(var(PFs))/var(signal)
参考代码 LMD分解信号程序 www.youwenfan.com/contentcsr/103260.html
六、常见问题解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 模态混叠 | 分解次数不足 | 增加maxIter参数 |
| 端点发散 | 边界处理不当 | 启用镜像扩展功能 |
| 频率失真 | 包络平滑不足 | 增加Savitzky-Golay滤波阶数 |