汉克矩阵和差分谱法的SVD信号去噪

简介: 使用汉克矩阵构造信号,并通过差分谱法进行奇异值分解(SVD)去噪。该算法特别适用于处理含噪的周期信号或准周期信号。

使用汉克矩阵构造信号,并通过差分谱法进行奇异值分解(SVD)去噪。该算法特别适用于处理含噪的周期信号或准周期信号。

function svd_denoising_hankel()
    % 清空工作区
    clc;
    close all;
    clear;

    %% 1. 生成模拟信号
    fs = 1000;              % 采样频率 (Hz)
    t = 0:1/fs:1-1/fs;      % 时间向量 (1)
    N = length(t);           % 信号长度

    % 原始信号: 多个正弦波叠加
    f1 = 50;                % 基频 (Hz)
    f2 = 120;               % 二次谐波
    f3 = 80;                % 另一个频率成分
    signal = 1.5*sin(2*pi*f1*t) + 0.8*cos(2*pi*f2*t) + 1.2*sin(2*pi*f3*t);

    % 添加高斯白噪声
    SNR = 5;                % 信噪比 (dB)
    noisy_signal = awgn(signal, SNR, 'measured');

    %% 2. 构造汉克矩阵
    L = floor(N/2);         % 汉克矩阵行数 (经验值)
    K = N - L + 1;          % 汉克矩阵列数

    % 构建汉克矩阵
    H = zeros(L, K);
    for i = 1:L
        H(i, :) = noisy_signal(i:i+K-1);
    end

    %% 3. 奇异值分解(SVD)
    [U, S, V] = svd(H, 'econ');
    singular_values = diag(S);  % 提取奇异值

    %% 4. 差分谱分析确定有效秩
    % 计算差分谱
    diff_spectrum = abs(diff(singular_values));

    % 找到差分谱的峰值点
    [pks, locs] = findpeaks(diff_spectrum, 'MinPeakHeight', 0.1*max(diff_spectrum));

    % 确定有效秩 (保留前r个奇异值)
    if isempty(locs)
        r = 1;  % 如果没有找到峰值,至少保留一个奇异值
    else
        [~, idx] = max(pks);  % 找到最大峰值
        r = locs(idx);        % 有效秩
    end

    % 确保有效秩合理
    r = min(r, length(singular_values)-1);
    r = max(r, 1);

    %% 5. 信号重构
    % 保留前r个奇异值
    S_denoised = S;
    S_denoised(r+1:end, r+1:end) = 0;

    % 重构汉克矩阵
    H_denoised = U * S_denoised * V';

    % 从汉克矩阵重构信号 (反对角线平均)
    denoised_signal = zeros(1, N);
    count = zeros(1, N);

    for i = 1:L
        for j = 1:K
            idx = i + j - 1;  % 反对角线索引
            denoised_signal(idx) = denoised_signal(idx) + H_denoised(i, j);
            count(idx) = count(idx) + 1;
        end
    end

    % 计算平均值
    denoised_signal = denoised_signal ./ count;

    %% 6. 性能评估
    % 计算信噪比改进
    noise_before = noisy_signal - signal;
    noise_after = denoised_signal - signal;

    SNR_before = 10*log10(var(signal)/var(noise_before));
    SNR_after = 10*log10(var(signal)/var(noise_after));

    improvement = SNR_after - SNR_before;

    % 计算均方根误差
    RMSE_before = sqrt(mean(noise_before.^2));
    RMSE_after = sqrt(mean(noise_after.^2));

    %% 7. 结果可视化
    % 创建主图窗
    fig = figure('Name', '基于汉克矩阵和差分谱法的SVD信号去噪', ...
                 'Position', [100, 100, 1200, 800], ...
                 'Color', [0.95, 0.95, 0.95]);

    % 信号对比图
    subplot(3, 2, [1, 2]);
    plot(t, signal, 'b', 'LineWidth', 1.8, 'DisplayName', '原始信号');
    hold on;
    plot(t, noisy_signal, 'Color', [0.7, 0.7, 0.7], 'LineWidth', 1, 'DisplayName', '含噪信号');
    plot(t, denoised_signal, 'r', 'LineWidth', 1.5, 'DisplayName', '去噪信号');
    hold off;
    title(sprintf('信号对比 (SNR提升: %.2f dB)', improvement), 'FontSize', 12);
    xlabel('时间 (s)');
    ylabel('幅值');
    legend('Location', 'best');
    grid on;
    xlim([0, 0.2]);  % 显示前200ms

    % 频谱分析
    subplot(3, 2, 3);
    [freq, P1] = calc_spectrum(signal, fs);
    [~, P2] = calc_spectrum(noisy_signal, fs);
    [~, P3] = calc_spectrum(denoised_signal, fs);

    plot(freq, P1, 'b', 'LineWidth', 1.5);
    hold on;
    plot(freq, P2, 'Color', [0.7, 0.7, 0.7], 'LineWidth', 1);
    plot(freq, P3, 'r', 'LineWidth', 1.2);
    hold off;
    title('频谱分析');
    xlabel('频率 (Hz)');
    ylabel('功率谱密度');
    grid on;
    xlim([0, 200]);

    % 奇异值分布
    subplot(3, 2, 4);
    semilogy(singular_values, 'bo-', 'LineWidth', 1.5, 'MarkerSize', 4);
    hold on;
    semilogy(1:r, singular_values(1:r), 'ro', 'MarkerSize', 6, 'LineWidth', 1.5);
    line([r+0.5, r+0.5], ylim, 'Color', 'k', 'LineStyle', '--', 'LineWidth', 1.2);
    hold off;
    title(sprintf('奇异值分布 (有效秩: r = %d)', r));
    xlabel('奇异值索引');
    ylabel('奇异值 (对数尺度)');
    grid on;

    % 差分谱分析
    subplot(3, 2, 5);
    plot(diff_spectrum, 'go-', 'LineWidth', 1.5, 'MarkerSize', 4);
    hold on;
    plot(locs, pks, 'r*', 'MarkerSize', 10, 'LineWidth', 1.8);
    plot([r, r], [0, max(diff_spectrum)], 'k--', 'LineWidth', 1.2);
    hold off;
    title('奇异值差分谱');
    xlabel('索引');
    ylabel('差分值');
    grid on;
    xlim([1, length(diff_spectrum)]);

    % 残差分析
    subplot(3, 2, 6);
    plot(t, noise_before, 'Color', [0.7, 0.7, 0.7], 'LineWidth', 1);
    hold on;
    plot(t, noise_after, 'r', 'LineWidth', 1.2);
    hold off;
    title(sprintf('噪声残差 (RMSE: %.4f -> %.4f)', RMSE_before, RMSE_after));
    xlabel('时间 (s)');
    ylabel('残差');
    legend('去噪前残差', '去噪后残差');
    grid on;
    xlim([0, 0.2]);  % 显示前200ms

    % 添加信息面板
    info_str = sprintf(['算法参数:\n' ...
                        '  信号长度: %d\n' ...
                        '  汉克矩阵: %d×%d\n' ...
                        '  信噪比(输入): %.2f dB\n' ...
                        '  信噪比(输出): %.2f dB\n' ...
                        '  信噪比提升: %.2f dB\n' ...
                        '  RMSE减少: %.2f%%'], ...
                        N, L, K, SNR_before, SNR_after, improvement, ...
                        100*(RMSE_before-RMSE_after)/RMSE_before);

    annotation('textbox', [0.1, 0.01, 0.8, 0.08], ...
               'String', info_str, ...
               'FitBoxToText', 'on', ...
               'BackgroundColor', [0.98, 0.98, 0.98], ...
               'EdgeColor', [0.8, 0.8, 0.8], ...
               'FontSize', 10);

    %% 辅助函数:计算频谱
    function [f, P] = calc_spectrum(x, fs)
        n = length(x);
        y = fft(x);
        P2 = abs(y/n);
        P1 = P2(1:floor(n/2)+1);
        P1(2:end-1) = 2*P1(2:end-1);
        f = fs*(0:(n/2))/n;
        f = f(:);
        P = P1(:);
    end
end

算法原理与实现步骤

1. 汉克矩阵构造

汉克矩阵是一种特殊矩阵,其反对角线上的元素相同:

H = zeros(L, K);
for i = 1:L
    H(i, :) = noisy_signal(i:i+K-1);
end

其中:

  • L 是矩阵行数(通常取信号长度的一半)
  • K = N - L + 1 是矩阵列数
  • N 是信号长度

汉克矩阵的构造将一维信号转换为二维矩阵,为后续的SVD分解做准备。

2. 奇异值分解(SVD)

对汉克矩阵进行SVD分解:

[U, S, V] = svd(H, 'econ');
singular_values = diag(S);

SVD将矩阵分解为:

H = U * S * V'

其中:

  • U 是左奇异向量矩阵
  • S 是对角奇异值矩阵
  • V 是右奇异向量矩阵

3. 差分谱分析

差分谱是确定有效秩的关键:

diff_spectrum = abs(diff(singular_values));
[pks, locs] = findpeaks(diff_spectrum, 'MinPeakHeight', 0.1*max(diff_spectrum));

奇异值差分谱定义为:

Δσ(i) = |σ(i) - σ(i+1)|

其中σ(i)是第i个奇异值。

有效秩r由差分谱的最大峰值位置确定:

[~, idx] = max(pks);
r = locs(idx);

4. 信号重构

基于有效秩重构信号:

S_denoised = S;
S_denoised(r+1:end, r+1:end) = 0;
H_denoised = U * S_denoised * V';

从重构的汉克矩阵恢复一维信号(反对角线平均法):

denoised_signal = zeros(1, N);
count = zeros(1, N);

for i = 1:L
    for j = 1:K
        idx = i + j - 1;
        denoised_signal(idx) = denoised_signal(idx) + H_denoised(i, j);
        count(idx) = count(idx) + 1;
    end
end

denoised_signal = denoised_signal ./ count;

参考代码 采用汉克矩阵构造信号,使用差分谱法进行SVD去噪 www.youwenfan.com/contentalf/96370.html

扩展与改进

  1. 自适应汉克矩阵大小

    % 基于信号自相关确定L
    [acf, ~] = xcorr(noisy_signal, 'coeff');
    acf = acf(length(noisy_signal):end);
    [~, lags] = findpeaks(acf, 'MinPeakHeight', 0.5);
    if ~isempty(lags)
        L = min(lags(1), floor(N/2));
    else
        L = floor(N/2);
    end
    
  2. 多通道信号处理

    % 对于多通道信号,构建块汉克矩阵
    H_multi = [];
    for ch = 1:nChannels
        H_ch = hankel_matrix(signal_ch(:, ch), L);
        H_multi = [H_multi; H_ch];
    end
    
  3. 实时处理实现

    % 滑动窗口处理
    window_size = 1000;
    step_size = 100;
    for start_idx = 1:step_size:(N-window_size)
        segment = noisy_signal(start_idx:start_idx+window_size-1);
        denoised_segment = svd_denoise(segment);
        % 拼接处理结果
    end
    
  4. 结合小波阈值

    % SVD去噪后的小波阈值处理
    denoised_signal_wavelet = wden(denoised_signal, 'modwtsqtwolog', 's', 'mln', 5, 'db4');
    

这个实现提供了基于汉克矩阵和差分谱法的完整SVD去噪流程,通过可视化展示各步骤结果,便于理解和分析算法性能。

相关文章
|
并行计算 算法 计算机视觉
【MATLAB 】 ICEEMDAN 信号分解+模糊熵(近似熵)算法
【MATLAB 】 ICEEMDAN 信号分解+模糊熵(近似熵)算法
1358 0
|
容器
关于在容器通过apt安装程序碰到的问题
记录容器安装程序的问题
2676 0
|
4月前
|
API 开发者
选Claude API中转站别被排名忽悠了:业内人揭露三大陷阱
# 选Claude API中转站别被排名忽悠了:业内人揭露三大陷阱 选择Claude API中转站时,市场上各种排名榜单让人眼花缭乱。但对个人开发者和中小企业来说,这些榜单的参考价值可能有限。 #
|
9月前
|
Web App开发 监控 JavaScript
Vue 3 内存泄漏排查与性能优化:从入门到精通的工具指南
本文深入剖析 Vue 3 应用内存泄漏的根源,从响应式系统机制讲起,结合定时器泄漏等实战案例,揭示闭包与全局引用导致的 GC 回收失败问题。通过对比 vue-performance-monitor、memory-monitor-sdk、Chrome DevTools 与 Memlab 四大工具,构建覆盖开发、测试到 CI/CD 的全链路检测体系,并提出三层防御架构与五大黄金法则,助力开发者打造高性能、零泄漏的 Vue 应用,实现从调试者到性能架构师的跃迁。(239字)
672 8
Vue 3 内存泄漏排查与性能优化:从入门到精通的工具指南
|
10月前
|
存储 并行计算 算法
基于变密度法的多相拓扑优化MATLAB实现
基于变密度法的多相拓扑优化MATLAB实现
1070 10
|
11月前
|
人工智能 监控 算法
迈向“可解释性GEO”:AI搜索时代的深度思考与实践探索
资深从业者王耀恒融合15年经验,首创可解释性GEO方法论,破解AI搜索黑箱。通过分层战略框架与闭环技术体系,助力企业构建可持续的数字信任资产,推动AI内容生态健康发展。(239字)
|
11月前
|
计算机视觉
MATLAB实现图像分割:Otsu阈值法
Otsu方法(大津法)是一种广泛使用的自动图像阈值分割技术,它通过最大化类间方差来确定最佳阈值。
|
资源调度 算法 计算机视觉
基于总变差(TV)的图像去模糊,使用总变差正则化进行图像去模糊研究(Matlab代码实现)
基于总变差(TV)的图像去模糊,使用总变差正则化进行图像去模糊研究(Matlab代码实现)
417 2

热门文章

最新文章