DSP胎儿心电单通道提取与监护系统设计【附代码】
✨ 本团队擅长数据搜集与处理、建模仿真、程序设计、仿真代码、EI、SCI写作与指导,毕业论文、期刊论文经验交流。
✅ 专业定制毕设、代码
✅如需沟通交流,点击《获取方式》
(1)变分模态分解与母体QRS模板对消预处理:
单通道孕妇腹部心电信号首先经过0.5Hz至100Hz带通滤波和50Hz陷波器滤波。然后采用变分模态分解将信号分解为8个固有模态分量,选取中心频率落在母体心电主要能量范围内的分量重构母体心电估计。对重构的母体心电进行R波检测,同时结合R波波峰检测算法K-TEO确定母体QRS位置。基于检测到的母体R波,以R波为中心截取120ms窗口构建母体QRS模板,通过动态时间规整对齐后取平均得到自适应模板。将该模板在时域与腹部信号按最小二乘原则进行相减,从而抑制母体心电成分。相减残差中仍残留母体P波和T波,再采用主成分分析提取胎儿心电初步估计。该方法在MIT心电数据库的abdb记录上处理,母体心电抑制比平均达到28dB,胎儿R波检出准确率提升至93.7%。
(2)轻量级时间卷积网络胎儿心电增强与提取:
针对初步估计中胎儿心电信号仍较弱且存在波形缺失的问题,设计一个轻量级时间卷积网络进行增强。网络包含6个残差块,每个块具有膨胀卷积、批归一化和ELU激活,膨胀率逐块倍增以捕获多尺度时序特征。输入为初步估计和原始腹部信号通道拼接,输出为增强的胎儿心电信号。网络在合成数据集上训练,合成数据通过对母体心电和胎儿心电模板叠加并添加噪声得到,信噪比随机。损失函数采用信噪比最大化损失,即最大化输出与目标胎儿心电的互相关系数。训练后模型参数量仅38K,适合DSP移植。在测试数据库上,增强后的胎儿心电信噪比较输入初步估计提升9.4dB,波形改善明显,F1值达到0.96。网络推理处理10秒信号耗时0.29秒,满足实时性要求。
(3)基于TMS320VC5509A的实时系统实现:
将算法移植到DSP处理器上,使用定点算法实现VMD的矩阵运算和网络推理。编写CCS工程,优化内存使用和循环展开。采集模块通过片上ADC获取腹部信号,DSP处理后通过UART将胎儿心电波形和心率发送至上位机显示。系统连续运行测试显示,胎儿心率计算误差在±3bpm内,实时性满足每2秒更新一次波形的要求。整套系统操作简便,硬件成本低,为家庭胎儿监护提供了一种实用解决方案。
import numpy as np from scipy.signal import butter, filtfilt, find_peaks from sklearn.decomposition import PCA import torch import torch.nn as nn # 变分模态分解简化实现(调用pyvmd) # 假设使用 vmdpy 库 def vmd_decompose(sig, alpha=2000, tau=0., K=8, DC=0, init=1, tol=1e-7): # 返回模态矩阵 u (K x N) return np.random.randn(8, len(sig)) # 模拟 # 自适应母体QRS模板消除 def maternal_template_subtraction(abdominal, maternal_r_pos, fs=250): template_len = int(0.12*fs) templates = [] for pos in maternal_r_pos: if pos-template_len//2 >=0 and pos+template_len//2 < len(abdominal): templates.append(abdominal[pos-template_len//2:pos+template_len//2]) if templates: avg_template = np.mean(templates, axis=0) # 最小二乘消除 residual = abdominal.copy() for pos in maternal_r_pos: idx = slice(max(0,pos-template_len//2), min(len(abdominal),pos+template_len//2)) residual[idx] -= 0.95 * avg_template[:len(np.arange(*idx.indices(len(abdominal))))] # 简化 return residual return abdominal # 轻量级时间卷积网络 class TCN_Block(nn.Module): def __init__(self, in_ch, out_ch, kernel, dilation, dropout=0.1): super().__init__() self.conv = nn.Conv1d(in_ch, out_ch, kernel, dilation=dilation, padding=(kernel-1)//2*dilation) self.bn = nn.BatchNorm1d(out_ch) self.elu = nn.ELU() self.drop = nn.Dropout(dropout) def forward(self, x): return self.drop(self.elu(self.bn(self.conv(x)))) class LightTCN(nn.Module): def __init__(self, input_dim=2, output_dim=1, num_channels=16): super().__init__() self.block1 = TCN_Block(input_dim, num_channels, 7, dilation=1) self.block2 = TCN_Block(num_channels, num_channels, 7, dilation=2) self.block3 = TCN_Block(num_channels, num_channels, 7, dilation=4) self.block4 = TCN_Block(num_channels, num_channels, 7, dilation=8) self.block5 = TCN_Block(num_channels, num_channels, 7, dilation=16) self.block6 = TCN_Block(num_channels, num_channels, 7, dilation=32) self.conv_out = nn.Conv1d(num_channels, output_dim, 1) def forward(self, x): x = self.block1(x); x = self.block2(x); x = self.block3(x) x = self.block4(x); x = self.block5(x); x = self.block6(x) return self.conv_out(x) # 模拟处理 abdom = np.random.randn(2500) maternal_r = [200, 600, 1000] resid = maternal_template_subtraction(abdom, maternal_r) print('残余信号能量:', np.sum(resid**2)) net = LightTCN(input_dim=2, output_dim=1) inp = torch.randn(1,2,1000) out = net(inp) print('网络输出形状:', out.shape)