【心电信号】基于小波变换实现心电信号ECG QRS波检测附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。

🍎 往期回顾关注个人主页:Matlab科研工作室

🍊个人信条:格物致知,完整Matlab代码及仿真咨询内容私信。

🔥 内容介绍

心电图 (ECG) 是反映心脏电活动的重要工具,QRS 波是 ECG 中最显著的特征,代表着心室除极过程。准确识别 QRS 波是心律失常诊断和心血管疾病研究的关键。近年来,基于小波变换的心电信号 QRS 波检测方法取得了显著进展。本文将详细介绍基于小波变换的心电信号 QRS 波检测方法,包括小波理论、QRS 波检测算法以及算法的评估指标。

1. 引言

心电图 (ECG) 是反映心脏电活动的重要工具,广泛应用于临床诊断和心血管疾病研究。ECG 信号包含丰富的生理信息,其中 QRS 波是 ECG 中最显著的特征,代表着心室除极过程。准确识别 QRS 波是心律失常诊断和心血管疾病研究的关键。

传统的心电信号 QRS 波检测方法主要包括基于阈值的方法、基于形态学的方法和基于滤波的方法。这些方法虽然能够在一定程度上识别 QRS 波,但存在着误检率高、抗噪声能力差等缺点。

近年来,基于小波变换的心电信号 QRS 波检测方法取得了显著进展。小波变换是一种时频分析方法,能够有效地提取信号的局部特征,并具有良好的抗噪声能力。基于小波变换的心电信号 QRS 波检测方法能够有效地克服传统方法的缺点,提高 QRS 波检测的准确率。

2. 小波理论

小波变换是一种时频分析方法,它将信号分解成一系列小波函数的线性组合。小波函数是一种具有良好局部化特性的函数,能够有效地提取信号的局部特征。

小波变换的基本原理如下:

  1. 选择一个母小波函数 ψ(t),它是一个具有良好局部化特性的函数。

  2. 将信号 f(t) 与母小波函数 ψ(t) 进行卷积运算,得到小波系数:

c(a, b) = ∫f(t)ψ(a, b)dt

其中,a 是尺度因子,b 是平移因子。

  1. 通过改变尺度因子 a 和平移因子 b,可以得到不同尺度和位置的小波系数。

小波系数包含了信号的时频信息,可以通过分析小波系数来提取信号的局部特征。

3. QRS 波检测算法

基于小波变换的心电信号 QRS 波检测算法主要包括以下步骤:

  1. 对心电信号进行小波分解,得到不同尺度的小波系数。

  2. 选择合适的尺度,提取 QRS 波的小波系数。

  3. 对 QRS 波的小波系数进行阈值处理,去除噪声和干扰。

  4. 根据 QRS 波的小波系数的特征,确定 QRS 波的起始点和终止点。

4. 结论

基于小波变换的心电信号 QRS 波检测方法是一种有效的方法,能够有效地克服传统方法的缺点,提高 QRS 波检测的准确率。该方法具有良好的抗噪声能力和鲁棒性,在心律失常诊断和心血管疾病研究中具有重要的应用价值。

📣 部分代码

file_ind = 0;last_it_num = 0;for n = 3:num_files   %%%%still need to deal with iteration #1    keep n file_ind z virmen_channe l_number acquisitions    if contains(z(n).name,string)==1     file_ind = file_ind +1;    [sync_data,sync_sampling_interval,~]= abfload(z(n).name);    sync_sampling_rate = 1/sync_sampling_interval*1e6;    temp = sync_data(:,virmen_channel_number);    time = 1:length(temp).*1/sync_sampling_rate;    temp = double(temp);    temp = temp-median(temp);        [pks,locs] = findpeaks(abs(temp),'MINPEAKHEIGHT',0.09,'MinPeakDistance',5);    temp = temp./abs(mean(temp(locs)));    %temp = temp./abs(mean(temp(locs)))*1e3; %do I need to do this???    %%%if it's the first file, ignore Virmen initializing? Very negative    %%%initial pulse    it_values = temp(locs); %%%wavesurfer values at pulse times    it_times = locs;  %%%in wavesurfer units        marked_its = find(it_values>0);    if isempty(marked_its)        disp('Error! Current file does not have positive values. File is probably too short')        n=n+1;        file_ind = file_ind +1;    else        %findpeaks could find peaks right next to each other this code will    %find the min of a group and use that as the marked_its    %it will get rid of extra neighbouring detected peaks and account for    %this by subtracting it from the marked_its    group = {}; count = 1;     temp2=[];    temp3=[];    if length(marked_its)>1        for m = 1:length(marked_its)-1            if marked_its(m)+2>marked_its(m+1) %if current value +2 is greater than current value+1                temp2 = [temp2,marked_its(m)];                temp3 = min(temp2);                group(count).group = temp3;                group(count).temp2 = temp2;            else                temp2 = [temp2,marked_its(m)];                group(count).temp2 = temp2;                group(count).group = min(group(count).temp2);                temp2=[];                count= count+1;            end        end    %dealing with if you have a last value with no group    if marked_its(length(marked_its)) - marked_its(length(marked_its)-1) >10 %10 value could change        group(length(group)+1).group = marked_its(length(marked_its));        group(length(group)).temp2 = marked_its(length(marked_its));    end    marked_its_old = marked_its;     extra_num = {};    marked_its=[];    marked_its_shifted = [];        for i =1:length(group)            extra_num(i).group = length(group(i).temp2)-1;            if i == 1 %no value in front of first one so this is the true value               marked_its(i) = group(i).group;               marked_its_shifted(i)=group(i).group;            else            temp5= [];            temp3 = group(i).group;                for j = i-1:-1:1                temp4 = sum(extra_num(j).group);                temp5 = [temp5, temp4];                end            marked_its(i) = temp3 - sum(temp5);            marked_its_shifted(i)= temp3;            end        end    extra_its = ~ismember(marked_its_old,marked_its_shifted);    it_times(marked_its_old(extra_its)) = [];    it_values = temp(it_times);    end    actual_it_values = zeros(1,length(it_values));        %if first 10000?    if round(it_values(marked_its(1)),0)==10 %round(it_values(marked_its(1)),1)==10 was set to 1 instead of 0        actual_it_values(marked_its(1)) = 1;             else        actual_it_values(marked_its(1)) = round(((it_values(marked_its(1))*1e5)/1e4))*1e4;               next_value = actual_it_values((marked_its(1))); %%%changed cb 2/18/22                next_its = marked_its(1)-1:-1:1;        %%%count back from first known landmark,        for it = 1:length(next_its)            actual_it_values(next_its(it)) = next_value-1;            next_value =  actual_it_values(next_its(it));        end    end      %%%and forward from first....    previous_value = actual_it_values((marked_its(1)))-1    if length(marked_its)>1        for m = 2:length(marked_its)            if m ==2                 for it = marked_its(m-1):marked_its(m)-1 %% changed from it = marked_its(m-1):marked_its(m)-1                    actual_it_values(it) = previous_value+1;                    previous_value = actual_it_values(it);                end           end%            if round(it_values(marked_its(1)),1)==0.1%                 if round(previous_value+1,-4)==round(((it_values(marked_its(m-1))*1e5)/1e4))*1e4%                    if m <length(marked_its) %                        for it = marked_its(m):marked_its(m+1)%length(it_values)%marked_its(m+1)-1%marked_its(m):marked_its(m+1) %have to figure out numbers%                             actual_it_values(it) = previous_value+1;%                             previous_value = actual_it_values(it);%                        end%                    else%                         for it = marked_its(m):length(it_values)%%have to figure out numbers%                             actual_it_values(it) = previous_value+1;%                             previous_value = actual_it_values(it);%                         end%                    end%                 else%                     disp('Error! Iteration numbers do not match')%                     keyboard%                 end%            else           if round(previous_value+1,-4)==round(((it_values(marked_its(m))*1e5)/1e4))*1e4               if m <length(marked_its)                    for it = marked_its(m):marked_its(m+1)%length(it_values)%marked_its(m+1)-1%marked_its(m):marked_its(m+1) %have to figure out numbers                        actual_it_values(it) = previous_value+1;                        previous_value = actual_it_values(it);                   end               else                    for it = marked_its(m):length(it_values)%%have to figure out numbers                        actual_it_values(it) = round(((it_values(marked_its(m))*1e5)/1e4))*1e4+1;                        previous_value = actual_it_values(it);                    end               end            else                if m <length(marked_its)                    for it = marked_its(m):marked_its(m+1)%length(it_values)%marked_its(m+1)-1%marked_its(m):marked_its(m+1) %have to figure out numbers                        actual_it_values(it) = round(((it_values(marked_its(m))*1e5)/1e4))*1e4+1;                        previous_value = actual_it_values(it);                   end               else                    for it = marked_its(m):length(it_values)%%have to figure out numbers                        actual_it_values(it) = round(((it_values(marked_its(m))*1e5)/1e4))*1e4+1;                        previous_value = actual_it_values(it);                    end               end           end        end    else        for it = marked_its(1):length(actual_it_values) % marked_its(1)+1:length(actual_it_values)            actual_it_values(it) = previous_value+1;            previous_value = actual_it_values(it);        end        actual_it_values(length(actual_it_values))    end        %for dealing with weird zeros before acqusition counter for first file    if file_ind ==1        if length(find(actual_it_values==0)) >0        no_zeros = find(actual_it_values>0);        no_zeros = [no_zeros(1)-1,no_zeros];        acquisitions(file_ind).actual_it_values = actual_it_values(no_zeros);        acquisitions(file_ind).it_times = it_times(no_zeros);        else        acquisitions(file_ind).actual_it_values = actual_it_values;        acquisitions(file_ind).it_times = it_times;        end    else    acquisitions(file_ind).actual_it_values = actual_it_values;    acquisitions(file_ind).it_times = it_times;    endfigure(2);clf; hold on;plot(temp); plot(it_times(marked_its),0,'*c'); hold off    end    endend%figure(3);clf;hold on; for i= 1:length(acquisitions) ; plot(acquisitions(i).it_times,acquisitions(i).actual_it_values);end;hold off%figure (3); clf;for i = 1:8; subplot(8,1,i); hold on; plot(ex_file_long(:,i)'); hold off; end

⛳️ 运行结果

🔗 参考文献

[1] 李卓妮.成人及胎儿心电信号R波检测算法的研究[D].华南理工大学[2024-04-26].DOI:CNKI:CDMD:2.1013.319172.

[2] 刘近贞,孙利飞,熊慧,等.基于能量分段与平稳小波变换的运动心电图特征波检测算法研究[J].生物医学工程学杂志, 2021, 38(6):1181-1192.

🎈 部分理论引用网络文献,若有侵权联系博主删除
🎁  关注我领取海量matlab电子书和数学建模资料

👇  私信完整代码和数据获取及论文数模仿真定制

1 各类智能优化算法改进及应用
生产调度、经济调度、装配线调度、充电优化、车间调度、发车优化、水库调度、三维装箱、物流选址、货位优化、公交排班优化、充电桩布局优化、车间布局优化、集装箱船配载优化、水泵组合优化、解医疗资源分配优化、设施布局优化、可视域基站和无人机选址优化、背包问题、 风电场布局、时隙分配优化、 最佳分布式发电单元分配、多阶段管道维修、 工厂-中心-需求点三级选址问题、 应急生活物质配送中心选址、 基站选址、 道路灯柱布置、 枢纽节点部署、 输电线路台风监测装置、 集装箱船配载优化、 机组优化、 投资优化组合、云服务器组合优化、 天线线性阵列分布优化、CVRP问题、VRPPD问题、多中心VRP问题、多层网络的VRP问题、多中心多车型的VRP问题、 动态VRP问题、双层车辆路径规划(2E-VRP)、充电车辆路径规划(EVRP)、油电混合车辆路径规划、混合流水车间问题、 订单拆分调度问题、 公交车的调度排班优化问题、航班摆渡车辆调度问题、选址路径规划问题
2 机器学习和深度学习方面

2.1 bp时序、回归预测和分类

2.2 ENS声神经网络时序、回归预测和分类

2.3 SVM/CNN-SVM/LSSVM/RVM支持向量机系列时序、回归预测和分类

2.4 CNN/TCN卷积神经网络系列时序、回归预测和分类

2.5 ELM/KELM/RELM/DELM极限学习机系列时序、回归预测和分类
2.6 GRU/Bi-GRU/CNN-GRU/CNN-BiGRU门控神经网络时序、回归预测和分类

2.7 ELMAN递归神经网络时序、回归\预测和分类

2.8 LSTM/BiLSTM/CNN-LSTM/CNN-BiLSTM/长短记忆神经网络系列时序、回归预测和分类

2.9 RBF径向基神经网络时序、回归预测和分类

2.10 DBN深度置信网络时序、回归预测和分类
2.11 FNN模糊神经网络时序、回归预测
2.12 RF随机森林时序、回归预测和分类
2.13 BLS宽度学习时序、回归预测和分类
2.14 PNN脉冲神经网络分类
2.15 模糊小波神经网络预测和分类
2.16 时序、回归预测和分类
2.17 时序、回归预测预测和分类
2.18 XGBOOST集成学习时序、回归预测预测和分类
方向涵盖风电预测、光伏预测、电池寿命预测、辐射源识别、交通流预测、负荷预测、股价预测、PM2.5浓度预测、电池健康状态预测、用电量预测、水体光学参数反演、NLOS信号识别、地铁停车精准预测、变压器故障诊断
2.图像处理方面
图像识别、图像分割、图像检测、图像隐藏、图像配准、图像拼接、图像融合、图像增强、图像压缩感知
3 路径规划方面
旅行商问题(TSP)、车辆路径问题(VRP、MVRP、CVRP、VRPTW等)、无人机三维路径规划、无人机协同、无人机编队、机器人路径规划、栅格地图路径规划、多式联运运输问题、 充电车辆路径规划(EVRP)、 双层车辆路径规划(2E-VRP)、 油电混合车辆路径规划、 船舶航迹规划、 全路径规划规划、 仓储巡逻
4 无人机应用方面
无人机路径规划、无人机控制、无人机编队、无人机协同、无人机任务分配、无人机安全通信轨迹在线优化、车辆协同无人机路径规划
5 无线传感器定位及布局方面
传感器部署优化、通信协议优化、路由优化、目标定位优化、Dv-Hop定位优化、Leach协议优化、WSN覆盖优化、组播优化、RSSI定位优化
6 信号处理方面
信号识别、信号加密、信号去噪、信号增强、雷达信号处理、信号水印嵌入提取、肌电信号、脑电信号、信号配时优化
7 电力系统方面
微电网优化、无功优化、配电网重构、储能配置、有序充电
8 元胞自动机方面
交通流 人群疏散 病毒扩散 晶体生长 金属腐蚀
9 雷达方面
卡尔曼滤波跟踪、航迹关联、航迹融合
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值