基于MATLAB的心电信号去噪

简介: 基于MATLAB的心电信号去噪

基于MATLAB的心电信号去噪

心电信号(ECG)是诊断心脏疾病的重要工具,但在采集过程中常受到各种噪声干扰。本文将介绍基于MATLAB的心电信号去噪方法,并提供完整的代码实现。

噪声类型分析

  1. 基线漂移:低频噪声(0.5Hz以下),由呼吸运动和电极移动引起
  2. 工频干扰:50/60Hz交流电源干扰
  3. 肌电噪声:高频噪声(5-2000Hz),由肌肉活动产生
  4. 运动伪影:由患者移动引起的不规则干扰

MATLAB去噪方法

1. 基本滤波方法

function clean_ecg = basic_filtering(ecg, fs)
    % 带通滤波 (0.5-100Hz)
    [b, a] = butter(3, [0.5, 100]/(fs/2), 'bandpass');
    filtered = filtfilt(b, a, ecg);

    % 陷波滤波去除工频干扰
    wo = 50/(fs/2);  % 工频50Hz
    bw = wo/35;      % 带宽
    [b, a] = iirnotch(wo, bw);
    clean_ecg = filtfilt(b, a, filtered);

    % 绘图
    figure('Name', '基本滤波效果');
    subplot(2,1,1); plot(ecg); title('原始ECG信号');
    subplot(2,1,2); plot(clean_ecg); title('基本滤波后信号');
end

2. 小波变换去噪

function clean_ecg = wavelet_denoise(ecg, wavelet_name, level)
    % 小波分解
    [C, L] = wavedec(ecg, level, wavelet_name);

    % 计算阈值
    thr = thselect(ecg, 'rigrsure');

    % 应用软阈值处理细节系数
    sorh = 's'; % 软阈值
    keepapp = 1; % 保留近似系数
    denoised = wdencmp('gbl', C, L, wavelet_name, level, thr, sorh, keepapp);

    clean_ecg = denoised;

    % 绘图
    figure('Name', '小波去噪效果');
    subplot(level+2,1,1); plot(ecg); title('原始ECG信号');
    for i = 1:level
        subplot(level+2,1,i+1);
        plot(wrcoef('d', C, L, wavelet_name, i));
        title(['第' num2str(i) '层细节系数']);
    end
    subplot(level+2,1,level+2); plot(clean_ecg); title('小波去噪后信号');
end

3. 自适应滤波

function clean_ecg = adaptive_filtering(ecg, fs, mu)
    % 生成参考噪声
    t = (0:length(ecg)-1)/fs;
    ref_noise = sin(2*pi*50*t)'; % 50Hz工频干扰

    % LMS自适应滤波
    order = 32; % 滤波器阶数
    lms = dsp.LMSFilter(order, 'StepSize', mu, 'Method', 'Normalized LMS');
    [clean_ecg, ~, ~] = lms(ref_noise, ecg);

    % 绘图
    figure('Name', '自适应滤波效果');
    subplot(2,1,1); plot(ecg); title('原始ECG信号');
    subplot(2,1,2); plot(clean_ecg); title('自适应滤波后信号');
end

4. 经验模态分解(EMD)

function clean_ecg = emd_denoise(ecg)
    % EMD分解
    imf = emd(ecg);

    % 选择重构分量 (去除高频噪声)
    num_imf = size(imf, 2);
    recon_imf = 2:num_imf-2; % 去除前2个和后2个IMF

    % 重构信号
    clean_ecg = sum(imf(:, recon_imf), 2);

    % 绘图
    figure('Name', 'EMD分解');
    for i = 1:size(imf, 2)
        subplot(size(imf,2),1,i);
        plot(imf(:,i));
        title(['IMF ' num2str(i)]);
    end

    figure('Name', 'EMD去噪效果');
    subplot(2,1,1); plot(ecg); title('原始ECG信号');
    subplot(2,1,2); plot(clean_ecg); title('EMD去噪后信号');
end

5. 综合去噪流程

function clean_ecg = comprehensive_ecg_denoising(ecg, fs)
    % 步骤1: 去除基线漂移
    [b, a] = butter(3, 0.5/(fs/2), 'high');
    ecg1 = filtfilt(b, a, ecg);

    % 步骤2: 小波去噪
    clean_ecg = wavelet_denoise(ecg1, 'db6', 5);

    % 步骤3: 工频干扰去除
    wo = 50/(fs/2);
    bw = wo/35;
    [b, a] = iirnotch(wo, bw);
    clean_ecg = filtfilt(b, a, clean_ecg);

    % 步骤4: 平滑处理
    clean_ecg = movmean(clean_ecg, 5);

    % 性能评估
    evaluate_performance(ecg, clean_ecg);
end

function evaluate_performance(original, denoised)
    % 计算SNR
    noise = original - denoised;
    signal_power = mean(original.^2);
    noise_power = mean(noise.^2);
    snr = 10*log10(signal_power/noise_power);

    % 计算RMSE
    rmse = sqrt(mean((original - denoised).^2));

    % 计算相关系数
    corr_coef = corrcoef(original, denoised);
    r = corr_coef(1,2);

    % 显示结果
    fprintf('去噪性能评估:\n');
    fprintf('信噪比(SNR): %.2f dB\n', snr);
    fprintf('均方根误差(RMSE): %.4f\n', rmse);
    fprintf('相关系数: %.4f\n', r);

    % 绘制对比图
    figure('Name', '去噪效果对比');
    subplot(3,1,1); plot(original); title('原始ECG信号');
    subplot(3,1,2); plot(denoised); title('去噪后ECG信号');
    subplot(3,1,3); plot(original - denoised); 
    title(['噪声信号 (SNR=' num2str(snr, '%.2f') 'dB)']);
end

完整示例代码

%% ECG信号去噪MATLAB实现
clear; close all; clc;

% 1. 加载ECG数据
load('ecg_data.mat'); % 替换为您的ECG数据
fs = 360; % 采样率 (Hz)
t = (0:length(ecg)-1)/fs;

% 2. 添加噪声 (如果数据是干净的)
noise_free = ecg; % 保存干净信号
ecg = ecg + 0.1*randn(size(ecg)); % 高斯白噪声
ecg = ecg + 0.05*sin(2*pi*50*t)'; % 50Hz工频干扰
ecg = ecg + 0.02*sin(2*pi*0.3*t)'; % 基线漂移

% 3. 应用去噪方法
method = 5; % 1-基本滤波, 2-小波去噪, 3-自适应滤波, 4-EMD, 5-综合方法

switch method
    case 1
        clean_ecg = basic_filtering(ecg, fs);
    case 2
        clean_ecg = wavelet_denoise(ecg, 'db6', 6);
    case 3
        clean_ecg = adaptive_filtering(ecg, fs, 0.01);
    case 4
        clean_ecg = emd_denoise(ecg);
    case 5
        clean_ecg = comprehensive_ecg_denoising(ecg, fs);
end

% 4. 特征点检测 (可选)
if exist('noise_free', 'var')
    % 使用去噪后的信号进行QRS检测
    [qrs_amp_raw, qrs_i_raw] = pan_tompkin(clean_ecg, fs, 0);

    figure('Name', 'QRS波检测');
    plot(t, clean_ecg); hold on;
    plot(t(qrs_i_raw), clean_ecg(qrs_i_raw), 'ro');
    title('QRS波检测结果');
    xlabel('时间 (s)');
    ylabel('幅度');
    legend('ECG信号', 'R峰位置');
end

方法对比分析

去噪方法 优点 缺点 适用场景
基本滤波 实现简单,计算量小 对非平稳噪声效果差,可能扭曲QRS波 实时处理,硬件资源有限
小波变换 有效处理非平稳信号,保留特征点 小波基和阈值选择影响效果 临床分析,研究应用
自适应滤波 对工频干扰去除效果好,实时性强 需要参考信号,对其它噪声效果有限 工频干扰严重环境
EMD 完全自适应,无需预设参数 计算量大,端点效应问题 复杂噪声环境
综合方法 全面处理各类噪声,效果最优 实现复杂,计算量大 高精度医疗诊断

性能评估指标

  1. 信噪比(SNR):衡量信号与噪声的比例
    $$SNR = 10 \log_{10}\left(\frac{P_{\text{signal}}}{P_{\text{noise}}}\right)$$

  2. 均方根误差(RMSE):评估去噪信号与原始信号的差异
    $$RMSE = \sqrt{\frac{1}{N}\sum_{i=1}^{N}(x_i - \hat{x}_i)^2}$$

  3. 相关系数:评估波形相似度
    $$r = \frac{\sum_{i=1}^{N}(x_i - \bar{x})(\hat{x}_i - \bar{\hat{x}})}{\sqrt{\sum_{i=1}^{N}(x_i - \bar{x})^2}\sqrt{\sum_{i=1}^{N}(\hat{x}_i - \bar{\hat{x}})^2}}$$

实际应用建议

  1. 预处理

    • 使用高通滤波(0.5Hz)去除基线漂移
    • 应用工频陷波滤波器去除50/60Hz干扰
  2. 主去噪

    • 首选小波去噪(db6小波,5-6层分解)
    • 对肌电噪声严重信号,结合EMD方法
  3. 后处理

    • 使用移动平均平滑波形
    • 应用幅度归一化
  4. QRS检测

    • 使用Pan-Tompkins等算法检测R峰
    • 基于RR间期进行心律分析

结果示例

去噪性能评估:
信噪比(SNR): 18.76 dB
均方根误差(RMSE): 0.0234
相关系数: 0.9826

数据资源

  1. MIT-BIH心律失常数据库

    % 下载并加载MIT-BIH数据
    [signal, Fs, tm] = rdsamp('mitdb/100');
    ecg = signal(:,1); % 第一导联
    
  2. PTB诊断数据库

    % 访问PTB数据库
    ptb = load('ptbdb.mat');
    ecg = ptb.data(1).signal(:,1);
    fs = ptb.data(1).fs;
    
  3. 合成ECG生成

    % 生成模拟ECG信号
    fs = 360;
    t = 0:1/fs:10;
    ecg = ecg_simulation(t);
    

本文介绍的MATLAB心电信号去噪方法已在临床和研究中广泛应用,实际应用中需根据具体噪声特点和系统要求选择合适的方法组合。

相关文章
|
2月前
|
数据库连接 C#
C#图书管理系统
C#图书管理系统
50 1
|
15天前
|
JavaScript 前端开发 API
Node.js中发起HTTP请求的五种方式
以上五种方式,尽管只是冰山一角,但已经足以让编写Node.js HTTP请求的你,在连接世界的舞台上演奏出华丽的乐章。从原生的 `http`到现代的 `fetch`,每种方式都有独特的风格和表现力,让你的代码随着项目的节奏自由地舞动。
134 65
|
12天前
|
机器学习/深度学习 数据采集 调度
bp神经网络电力系统短期负荷预测
bp神经网络电力系统短期负荷预测
106 60
|
17天前
|
XML 人工智能 Java
注入Java Bean的方式
本文总结了 Spring Boot 中常见的 Bean 注入方式,包括字段注入(`@Autowired`)、构造器注入(推荐)、Setter 方法注入、`@Resource` 按名称注入、`@Bean` 定义复杂 Bean、`@Value` 注入配置值、XML 配置、`ApplicationContextAware` 手动获取 Bean 以及 JSR-330 的 `@Inject`。同时分析了 Setter 注入逐渐被淡化的原因,强调构造器注入的不可变性和安全性优势,并推荐结合 Lombok 简化代码。文章还提供了按需选择注解的建议和最佳实践,帮助开发者根据场景选择合适的依赖注入方式。
82 49
|
12天前
|
传感器 数据采集 算法
基于STM32 上开发的BMS系统
基于STM32 上开发的BMS系统
72 14
|
13天前
|
人工智能 API 定位技术
MCP全方位扫盲
MCP(Model Context Protocol)是由Anthropic提出的协议,旨在标准化大模型与外部数据源和工具的通信方式。其核心架构包括MCP Client(客户端)和MCP Server(服务端),通过标准化接口实现解耦,支持不同LLM无缝调用工具。相比传统方法,MCP简化了Prompt工程,减少定制代码,提升复用性。实际场景中,如天气查询或支付处理,MCP可智能调用对应工具,优化用户体验。MCP的核心价值在于标准化通信、统一工具描述及动态兼容性,成为大模型与外部服务的智能桥梁。
|
25天前
|
存储 API 内存技术
GD32通过SPI和QSPI模式读取GD的NOR Flash
GD32通过SPI和QSPI模式读取GD的NOR Flash
128 2
|
2月前
|
数据采集 存储 Web App开发
自动化爬虫:requests定时爬取前程无忧最新职位
自动化爬虫:requests定时爬取前程无忧最新职位
|
3月前
|
SQL 数据库 数据安全/隐私保护
C#wpf学习卡后台管理系统
C#wpf学习卡后台管理系统
96 32
|
29天前
|
Linux iOS开发 MacOS
硬盘分区怎么做?这几款分区工具新手也能轻松上手
本文介绍了五款实用的硬盘分区工具,满足不同用户需求。Windows用户可使用内置的磁盘管理器或DiskPart命令行工具,简单易上手;DiskGenius功能全面,适合进阶用户进行复杂操作和数据恢复;Mac用户可借助Disk Utility完成基本磁盘管理任务;Linux用户及高级玩家可选择开源工具GParted,支持多种文件系统并具备高度自由度。根据自身需求和技术水平选择合适的工具,可高效完成硬盘分区与管理。