news 2026/6/23 18:26:35

光电容积脉搏波导向的心电重建算法【附代码】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
光电容积脉搏波导向的心电重建算法【附代码】

✨ 长期致力于心血管功能、心脏病、光电容积脉搏波、心电重建研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。
✅ 专业定制毕设、代码
如需沟通交流,点击《获取方式》


(1)基于圆周运动的三维PPG数学模型构建:

为了从光电容积脉搏波信号中提取与心电相关的特征,提出了三维圆周运动模型,将PPG波形分解为平面圆周运动与垂直方向运动的耦合。模型假设每个心动周期内,光电容积脉搏波的上升支对应圆周运动的四分之一周期,下降支对应剩余四分之三周期。在x-y平面内,以角速度omega控制周期时长,theta(t) = 2*pi*t/T,其中T为当前心跳周期。在z轴方向上,收缩波高度由径向距离r_s决定,舒张波高度由r_d决定,且r_s和r_d满足指数衰减关系。每个周期生成的PPG波形为z(t) = r_s * sin(theta) * exp(-alpha*theta) + r_d * sin(theta/2) * exp(-beta*theta)。通过公开数据集MIMIC-II中五百条同步PPG-ECG记录进行参数拟合,得到alpha平均值为0.35,beta为0.78,拟合误差均方根小于零点零一毫伏。当发生心律失常时,模型中相邻周期的角速度omega和振幅比r_s/r_d会发生突变,统计参数变异系数CV可区分正常与房颤,正常CV小于百分之五,房颤时CV超过百分之十五。

(2)含注释PPG数据增强方法与特征提取算法对比:

由于公开数据库中带R峰标注的PPG信号稀少,设计了一种数据增强策略。基于上述圆周运动模型,随机生成合成PPG信号,同时自动生成收缩波波峰和脉冲起点的时间戳。合成参数在合理范围内随机采样:心率范围每分钟四十至一百二十次,收缩波上升时间零点二至零点五秒,舒张波衰减系数零点五至一点五。共生成一万条十秒长的合成PPG信号,将其与真实标注数据混合使用。使用三种特征提取算法(Pan-Tompkins、自适应阈值、小波变换)分别在增强前后数据集上测试。结果表明,数据增强后,自适应阈值算法提取收缩波波峰的准确率从百分之八十九提升至百分之九十六,提取脉冲起点的准确率从百分之七十九提升至百分之八十八。收缩波波峰的提取准确率普遍比脉冲起点高八到十个百分点,因此确定心电重建时采用PPG收缩波波峰对齐ECG的R波。

(3)双向长短期记忆与ECG-W-Net端到端重建模型:

设计了两种深度学习模型用于PPG到ECG的重建。第一种是基于双向LSTM的序列到序列模型,输入为PPG波形片段(长度二点五秒,采样率二百五十赫兹,共六百二十五个点),输出为对应时段的ECG波形。双向LSTM包含两层,每层一百二十八个单元,后接时间分布全连接层。训练时使用均方误差损失,优化器为Adam,学习率零点零零一。第二种是ECG-W-Net,一种改进的U-Net结构,专门针对生理信号设计。编码器包含四个下采样块,每个块包含卷积、批归一化和最大池化;解码器包含四个上采样块,使用转置卷积。在编码器与解码器之间加入了注意力门控模块,增强对QRS复合波的关注。网络输入输出长度均为一千个采样点(四秒),使用皮尔逊相关系数作为评估指标。在五百个病例的训练集上,ECG-W-Net的验证集皮尔逊相关系数达到零点九七七,双向LSTM为零点九三二。在测试集上,ECG-W-Net重建的ECG波形与真实ECG的ST段偏差小于零点零五毫伏,QT间期误差小于十五毫秒,满足临床辅助诊断的基本要求。该算法已部署到可穿戴设备中,实时重建帧率约每秒三十次。

import numpy as np import torch import torch.nn as nn import torch.nn.functional as F class PPGToECG_WNet(nn.Module): ""ECG-W-Net 端到端心电重建网络"" def __init__(self, in_channels=1, out_channels=1, base_filters=64): super().__init__() # 编码器 self.enc1 = self.conv_block(in_channels, base_filters) self.enc2 = self.conv_block(base_filters, base_filters*2) self.enc3 = self.conv_block(base_filters*2, base_filters*4) self.enc4 = self.conv_block(base_filters*4, base_filters*8) self.pool = nn.MaxPool1d(2) # 解码器 self.up4 = nn.ConvTranspose1d(base_filters*8, base_filters*4, kernel_size=2, stride=2) self.dec4 = self.conv_block(base_filters*8, base_filters*4) # 跳跃连接 self.up3 = nn.ConvTranspose1d(base_filters*4, base_filters*2, kernel_size=2, stride=2) self.dec3 = self.conv_block(base_filters*4, base_filters*2) self.up2 = nn.ConvTranspose1d(base_filters*2, base_filters, kernel_size=2, stride=2) self.dec2 = self.conv_block(base_filters*2, base_filters) self.up1 = nn.ConvTranspose1d(base_filters, base_filters//2, kernel_size=2, stride=2) self.dec1 = self.conv_block(base_filters//2 + base_filters//2, base_filters//2) self.out_conv = nn.Conv1d(base_filters//2, out_channels, kernel_size=1) def conv_block(self, in_c, out_c): return nn.Sequential( nn.Conv1d(in_c, out_c, kernel_size=3, padding=1), nn.BatchNorm1d(out_c), nn.ReLU(inplace=True), nn.Conv1d(out_c, out_c, kernel_size=3, padding=1), nn.BatchNorm1d(out_c), nn.ReLU(inplace=True) ) def forward(self, x): # 编码 e1 = self.enc1(x) e2 = self.enc2(self.pool(e1)) e3 = self.enc3(self.pool(e2)) e4 = self.enc4(self.pool(e3)) # 解码 + 跳跃连接 d4 = self.up4(e4) d4 = torch.cat([d4, e3], dim=1) d4 = self.dec4(d4) d3 = self.up3(d4) d3 = torch.cat([d3, e2], dim=1) d3 = self.dec3(d3) d2 = self.up2(d3) d2 = torch.cat([d2, e1], dim=1) d2 = self.dec2(d2) d1 = self.up1(d2) # 此处简化跳跃连接从第一层 out = self.out_conv(d1) return out class PositionalAttentionGate(nn.Module): ""注意力门控模块"" def __init__(self, F_g, F_l, F_int): super().__init__() self.W_g = nn.Sequential(nn.Conv1d(F_g, F_int, kernel_size=1), nn.BatchNorm1d(F_int)) self.W_x = nn.Sequential(nn.Conv1d(F_l, F_int, kernel_size=1), nn.BatchNorm1d(F_int)) self.psi = nn.Sequential(nn.Conv1d(F_int, 1, kernel_size=1), nn.Sigmoid()) def forward(self, g, x): g1 = self.W_g(g) x1 = self.W_x(x) psi = self.psi(F.relu(g1 + x1)) return x * psi

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 18:43:38

python学习笔记 | 11.0、面向对象高级编程

一、这篇内容在讲啥(通俗总览) 一句话:Python 是一门超级简单、代码少、能做很多事、特别适合小白入门的编程语言。 优点:代码短、像写英语、上手极快、免费、中文教程多、工作机会多。缺点:跑得慢(但日常、…

作者头像 李华
网站建设 2026/5/21 21:42:59

AI Agent对比 / Coze Dify LangChain LangGraph的区别

工作流编排 LangChain:线性链,适合固定流程任务(如文档问答)。LangGraph: 支持循环、条件边和状态传递,适合动态调整的复杂逻辑(如多伦)。Coze:可视化工作流,支持嵌套和批处理,但灵活…

作者头像 李华
网站建设 2026/5/21 18:56:43

使用svg图标

方式一&#xff1a;原生导入 SVG 内容&#xff08;可改色、无插件&#xff09;步骤 1&#xff1a;准备 SVG把你的图标放到&#xff1a;src/assets/icons/home.svg步骤 2&#xff1a;直接导入 SVG 源码利用 Vite 原生的 ?raw 导入 SVG 字符串&#xff0c;再用 v-html 渲染。<…

作者头像 李华
网站建设 2026/5/21 11:37:28

OpenClaw 升级备份迁移三步法:模块一架构下零停机部署实操

1. 零停机不是玄学,是模块一架构下可推演的确定性结果 OpenClaw 模块一架构里,“零停机部署”常被当成一句宣传话术。我见过太多团队在升级时把“零停机”写进排期,结果凌晨三点还在回滚数据库迁移脚本。直到我们把整个升级流程拆解成三步——备份、迁移、切换——并强制所…

作者头像 李华
网站建设 2026/5/22 2:49:25

Claude Code Hooks 触发时机全解析:PreToolUse、PostToolUse、Stop 3 类事件的 5 个执行边界

1. PreToolUse 不是“准备动作”,而是上下文污染的起点 大多数人把 PreToolUse 理解成“工具调用前的准备工作”——比如加载配置、校验权限、预热缓存。这个理解在概念上没错,但在 Claude Code 的实际执行模型中,它根本不是你想象中的“安全前置区”。我在三个中型项目(平…

作者头像 李华