ECG信号心率检测:能量信号自相关/阈值法实现及Matlab代码求助
ECG心率检测实现思路及代码补全
核心实现逻辑
你已经完成了ECG信号的预处理流程,后续心率计算可通过以下两种方案实现:
能量阈值法
- 基于滤波后的ECG信号计算能量序列,放大R峰与噪声的差异
- 设定合理阈值过滤伪峰值,提取有效R峰的位置
- 计算相邻R峰的时间差(RR间期),取平均值后用60除以平均RR间期得到心率值(单位:次/分钟)
自相关法
- 利用ECG信号的周期性,对能量序列做自相关运算,自相关结果的峰值间隔对应信号的周期长度
- 提取0延迟之外的第一个主峰位置,对应平均RR间期的采样点数,直接换算得到心率值,抗噪性优于阈值法
代码修正与补全
你现有代码存在两处明显问题:一是15Hz低通+20Hz高通的滤波逻辑会滤除所有有效信号,建议替换为15~20Hz带通滤波;二是findpeaks(j)中的j为未定义变量,应为能量序列et。补全后代码如下:
% -------------- 修正滤波逻辑 -------------- % 替换原代码中15Hz低通、20Hz高通的两行代码,改为带通滤波 fcutlow=15; % 低截止频率 fcuthigh=20; % 高截止频率 [c,d]=butter(4,[fcutlow,fcuthigh]/(fs/2),'bandpass'); % 直接一次带通滤波即可 ecg_vhd_bandpass = filter(c,d,ecg_vhd_btr); ecg_hc_bandpass = filter(c,d,ecg_hc_btr); % -------------- 心率检测代码 -------------- % ========== 能量阈值法实现 ========== % 计算健康组能量序列 et_hc = abs(ecg_hc_bandpass).^2; th_hc = 2 * mean(et_hc); % 阈值可根据实际效果在1.5~3倍均值区间调整 % 找峰值,加入最小间隔限制避免误检(按最高心率180次/分设置最小间隔300个采样点@1000Hz) [pks_hc, locs_hc] = findpeaks(et_hc, 'MinPeakHeight', th_hc, 'MinPeakDistance', 300); % 计算RR间期与平均心率 rr_intervals_hc = diff(locs_hc) / fs; mean_hr_hc = 60 / mean(rr_intervals_hc); fprintf('健康组平均心率:%.2f 次/分\n', mean_hr_hc); % 疾病组计算逻辑一致 et_vhd = abs(ecg_vhd_bandpass).^2; th_vhd = 2 * mean(et_vhd); [pks_vhd, locs_vhd] = findpeaks(et_vhd, 'MinPeakHeight', th_vhd, 'MinPeakDistance', 300); rr_intervals_vhd = diff(locs_vhd) / fs; mean_hr_vhd = 60 / mean(rr_intervals_vhd); fprintf('疾病组平均心率:%.2f 次/分\n', mean_hr_vhd); % ========== 自相关法实现 ========== ac_hc = xcorr(et_hc, 'coeff'); % 归一化自相关,结果更直观 mid_idx = length(ac_hc) / 2 + 1; % 自相关序列中间位置对应0延迟 ac_pos = ac_hc(mid_idx:end); % 仅保留正延迟部分的结果 % 找正延迟部分的峰值,跳过前0.2s避免误检 [pks_ac, locs_ac] = findpeaks(ac_pos, 'MinPeakDistance', 300); rr_ac = locs_ac(1) / fs; % 第一个峰值位置对应平均RR间期 mean_hr_ac = 60 / rr_ac; fprintf('自相关法计算健康组平均心率:%.2f 次/分\n', mean_hr_ac);
优化建议
- 若信号噪声较大,可将阈值调整为自适应阈值,比如取前几秒信号的峰值均值的0.7倍作为阈值,鲁棒性更好
- 可以对得到的RR间期做异常值过滤,去掉偏离均值±30%的区间,避免偶发误检影响结果
- 若需要更高的R峰检测精度,可以替换为Pan-Tompkins算法,是目前工业界最常用的ECG R峰检测方案
内容的提问来源于stack exchange,提问作者NoProg
相关产品推荐
相关产品推荐

