首页 > 其他分享 >单参总结——心电信号

单参总结——心电信号

时间:2024-08-31 22:21:23浏览次数:6  
标签:总结 Index Feak 电信号 filter 50Hz date data 单参

心电波形的滤波及心率计算

心电测量原理

心脏通过一系列电活动驱动其收缩和放松,这些电活动可以通过电极在身体表面检测到。心脏的电活动主要包括:

  1. 去极化:心脏的电信号从心房开始,经过心室,导致心脏的肌肉收缩。
  2. 复极化:心脏肌肉放松,准备下一次收缩。

心电波形

心电图(ECG)波形中的各种波代表了心脏电活动的不同阶段。标准的心电图波形包括P波、QRS波群和T波。每种波形反映了心脏电活动的特定部分。
在这里插入图片描述

P波
  1. 定义:P波是心电图中的第一个波,代表心房的去极化过程。
  2. 特点:
    形状:通常为圆润而且小的正向波(在大多数导联中)。
    持续时间:一般小于0.12秒(120毫秒)。
    振幅:通常在0.1到0.3毫伏(mV)之间。
  3. 意义:P波的出现表示心房正在去极化,即心房肌肉准备收缩。如果P波缺失或形状异常,可能指示心房电活动的异常,如心房颤动或心房扑动。
QRS波群
  1. 定义:QRS波群代表心室的去极化过程,是心电图中最显著的波形。

  2. 组成:
    Q波:QRS波群的第一个向下的波(负波),并不是所有心电图中都有Q波。 R波:QRS波群的第一个向上的波(正波),通常最为显著。
    S波:R波后的向下波(负波),跟在R波后面。

  3. 特点:
    形状:QRS波群通常为尖锐而且幅度较高。
    持续时间:正常情况下,QRS波群的持续时间小于0.12秒(120毫秒)。
    振幅:通常较大,尤其是R波。

  4. 意义:QRS波群的出现表示心室肌肉的去极化,即心室收缩。如果QRS波群的形状、持续时间或幅度异常,可能指示心室的电活动异常,如心室肥厚、心室早搏或心室传导阻滞。

T波
  1. 定义:T波代表心室的复极化过程,即心室电活动恢复到静息状态。
  2. 特点:
    形状:通常为圆润的正向波(在大多数导联中),但在某些导联中也可能是负向的。
    持续时间:比P波和QRS波群更长,但通常不具体测量。
    振幅:通常在0.1到0.5毫伏(mV)之间。
  3. 意义:T波的出现表示心室正在复极化。如果T波的形状、方向或幅度异常,可能指示心室复极化过程的异常,如心肌缺血、心肌梗死或电解质失衡。
U波
  1. 定义:U波是心电图中有时出现的波,紧接在T波之后。
  2. 特点:
    形状:通常较小且不总是清晰可见。
    振幅:较小,通常不超过0.1毫伏(mV)。
  3. 意义:U波的意义尚不完全清楚,但可能与心室复极化过程中的一些细微变化有关。异常的U波可能与电解质失衡或药物效应有关。

综上所述,心电图的各个波形反映了心脏不同部位的电活动情况:

  1. P波:心房去极化。
  2. QRS波群:心室去极化。
  3. T波:心室复极化。
  4. U波(如果存在):心室复极化的细微变化。

标准双极导联

标准双极导联是心电图(ECG)中常用的配置之一。它使用两个电极来记录心脏的电活动,并且每个导联都是双极的,即通过两个电极之间的电位差来测量心脏信号。以下是常见的标准双极导联配置:

  1. I导联
    电极位置:左手腕(LA)和右手腕(RA)。
    信号来源:测量从右手腕到左手腕的电位差。
    视角:主要监测心脏在水平面上的电活动。
  2. II导联
    电极位置:左脚踝(LL)和右手腕(RA)。
    信号来源:测量从右手腕到左脚踝的电位差。
    视角:提供心脏电活动的另一水平面视角,常用于观察心脏的整体电活动。
  3. III导联
    电极位置:左脚踝(LL)和左手腕(LA)。
    信号来源:测量从左手腕到左脚踝的电位差。
    视角:补充第二导联的电活动视角。

标准双极导联的特点是能够广泛地反映心脏的大致情况,如后壁心肌梗死、心律失常等,在导联Ⅱ或导联Ⅲ中可记录到清晰的波形改变。但标准导联只能说明两个肢体间的电位差,不能记录到单个电极处的电位变化。

心电波形处理

在心电图(ECG)信号的测量和分析中,硬件和软件滤波器用于提高信号的质量,去除噪声,增强信号的可读性。

心电测量电路设计

在这里插入图片描述
将原理图绘制好后进行PCB打板和贴片,通过板子实测模拟器发出的心电信号,打印出来得到原始心电波形:
在这里插入图片描述

这是心电信号进行归一化处理后得到的图形,能够清晰地看到不同频率在心电信号中的占比情况。图中可见一些干扰需要对其进行算法处理。

软件滤波

软件滤波是指在信号采集之后,通过计算机算法对信号进行处理。这种处理可以在信号记录后的后期分析中进行,本次实践中,只完成了50Hz陷波器、IIR低通滤波器、IIR高通滤波器、滑动窗口平滑器。

50Hz陷波器

50Hz陷波器的本质在于其能够精准地滤除特定频率(50Hz)的干扰信号,而对其他频率的信号影响最小。它是一种带阻滤波器,设计用来降低或消除中心频率为50Hz的干扰,同时尽可能保留其余信号。
关于50Hz陷波器的理论原理详见陷波器及其算法(基于C语言)
以下为具体的设计步骤:
在找到这里插入图片描述找到滤波器设计器进行滤波器设计
在这里插入图片描述
设计好滤波器后,找到相应的系数
在这里插入图片描述
在这里插入图片描述
Fs是采样频率,这里是500Hz。上述步骤是作为设计一个50Hz陷波器的步骤参考,最终得到的系数非下面代码所使用的系数,下面代码所使用的Fstop1和Fstop2的频率与上图不一致因此系数不一样。

//50Hz陷波器
static IIR_2OR_DATA_DEF notching_data = {
    Notching_filter_50Hz_GAIN,
    Notching_filter_50Hz_B0,       
    Notching_filter_50Hz_B1,       
    Notching_filter_50Hz_B2,       
    Notching_filter_50Hz_A1,        
    Notching_filter_50Hz_A2,  
    0, 0, 0, 0 
};
//陷波滤波器
#define Notching_filter_50Hz_GAIN  0.888856976280745336715938265115255489945 
#define Notching_filter_50Hz_B0      1
#define Notching_filter_50Hz_B1  -1.61816175199937850592846189101692289114 
#define Notching_filter_50Hz_B2      1
#define Notching_filter_50Hz_A1  -1.438314362015320924115258094388991594315
#define Notching_filter_50Hz_A2     0.777713952561490673431876530230510979891
double iir_50Hz_2or_func(IIR_2OR_DATA_DEF *filter_date, double target)
{
     //
     // w0 = x(0) - A1 * W1 - A2 * W2
     //
    filter_date->filter_W0 = (target) - filter_date->coeff_A1 * filter_date->filter_W1 \
                           - filter_date->coeff_A2 * filter_date->filter_W2;

    //
    // Y(0) = Gain * (B0 * W0 + B1 * W1 + B2 * W2)
    //
    filter_date->filter_out = filter_date->coeff_GAIN * ( filter_date->coeff_B0 * filter_date->filter_W0 \
                            + filter_date->coeff_B1 * filter_date->filter_W1 \
                            + filter_date->coeff_B2 * filter_date->filter_W2 );

    //
    // Update last data
    //
    filter_date->filter_W2 = filter_date->filter_W1;
    filter_date->filter_W1 = filter_date->filter_W0;

    //
    // Return Value
    //
    return(filter_date->filter_out);
}

效果展示

在这里插入图片描述在这里插入图片描述
从归一化图中可以看出,50Hz工频干扰滤除的效果不错,但高于50Hz的频率干扰没有滤除,需要进行IIR低通滤波。

IIR低通滤波器

IIR低通滤波器的作用是允许低频信号通过,同时抑制高频信号。关于原理详细可见嵌入式常用的算法 - 二阶IIR低通滤波器

static u16 lowFilters_IIR(u16 data)
{
  static double x1=0,x2=0,y,y1=0,y2=0;

  y=0.064591*(data +2.0*x1+1.0*x2)+1.401314*y1-0.659679*y2;
  x2=x1;
  x1=data;
  y2=y1;
  y1=y;
  return y;
}

对于滤波器的系数同50Hz陷波器步骤可得,只不过需要改变滤波器类型和截止频率,根据具体要求设计相应功能的滤波器。

效果展示

在这里插入图片描述
在这里插入图片描述
由图可见,50Hz后的干扰基本滤除了。

IIR高通滤波器

基线漂移通常表现为信号中的低频偏移或漂移。IIR高通滤波器可以去除基线漂移,因为它能够抑制低频信号成分。高通滤波器允许高频成分通过,同时对低频成分进行衰减,从而去除这些低频漂移,使信号的基线更稳定。
关于IIR高通滤波器这部分具体参考了一篇文献
在这里插入图片描述
这篇文献中具体展示了IIR高通滤波器对基线漂移的抑制效果
在这里插入图片描述

static u16 highFilters_IIR(u16 data)
{
  static double x1=0,x2=0,y,y1=0,y2=0;
     
  y=0.992173*(data -1.999993*x1+ 1.0*x2)+1.984303*y1-0.984382*y2;   //IIR4阶二型切比雪夫 0.55   30dB
  x2=x1;
  x1=data;
  y2=y1;
  y1=y;
  return y+2000;  
}

由于处理后打印出来的数据比较小所以加2000可以放大波形,当然不加也没有太大关系。

效果展示

在这里插入图片描述
在这里插入图片描述

滑动窗口平滑器

滑动窗口平滑器(也称为滑动平均滤波器)是一种常用的信号处理技术,主要用于减少数据中的噪声和波动,平滑波形。

 u16 sliding_average_filter(u16 value)
{
  static int data_num = 0;
  static u16 output = 0;
	int i;
  float sum = 0;

  if (data_num < 10) //不满窗口,先填充
  {
    buffer[data_num++] = value;
    output = value; //返回相同的值
  }
  else
  {
    memcpy(&buffer[0], &buffer[1], (int)(10 - 1) * 4); //将1之后的数据移到0之后,即移除头部
    buffer[10 - 1] = value;                       //即添加尾部

    for (i = 0; i < 10; i++) //每一次都计算,可以避免累计浮点计算误差
    {    
      sum += buffer[i];
    }
    output = sum / 10;
  }

  return output;
}
效果展示

在这里插入图片描述

心率计算

u16 ECG_Calculate(u16 data[Len] ,u16 len)
{
  u16 heart_rate = 0;   //计算得出的心率
  u16 i,j,k,t;
  u16 Max_data = 0;  //数组中的最大值
  u16 Min_data = 0; //数组中的最小值
  u16 T = 0;    //阈值
  u8 Feak_Flag = 0;  //波峰找到时标志位置1
  u16 Feak_Num = 0;   //波峰个数
  u16 Feak_Index[30];   //Feak是储存波峰的索引数组
  u16 Index_num[30];    //相邻两个峰值之间的数据个数
  u16 n;
  u8 swapped = 0;
  
  //第1步找出求出阈值T
  Max_data=data[0];
  Min_data=data[0];
  for(i = 0;i < len;i++)
  {
    if(data[i] > Max_data)
      Max_data = data[i];
    if(Min_data > data[i])
      Min_data = data[i];
  }
  T = (Max_data - Min_data) * 0.9 + Min_data;  //求出阈值T

  //第2步找出数组中所有大于阈值T的索引,并存入新的数组中
  for(i = 0 , k = 0 ;i < len;i++)
  {
    if(data[i] > T)
    {
      Feak_Flag = 0;
      if((data[i] > data[i-1]) || (data[i] == data[i + 1]))
      {
       
        Feak_Flag = 1;   //初步判定该数据为峰值
        if((i + j) > len)   //超出数组长度退出循环
          break;           
        for(j = 1; j < 6; j++)
        {
          if(data[i] < data[i + j])  //判断前一个数据是否大于后一个数据
          {
            Feak_Flag = 0;          //该数据并非峰值,将标志位置零并跳出循环
            break;
          }
        }
        if(Feak_Flag == 1)  //最终判定该数据是波峰
        {
          Feak_Index[k] = i;
          k += 1;
          Feak_Num += 1;
          i = i + n_min;  //提高代码运行速度,找到一个波峰索引后跳到下一个波峰索引的大概位置
        }
      }
    }
  }
 
  //第3步计算Feak数组两相邻元素之间的差值,即两波峰之间的数据个数
  if(Feak_Num > 1)
    for(i = 1 ,j = 0; i < Feak_Num; i++ ,j++)
    {
      Index_num[j] = Feak_Index[i] - Feak_Index[i - 1]; 
    }
  else
    Index_num[0] = Feak_Index[0];
  
  //第4步将Index_num中的数据按从小到大的顺序进行排序
  if(Feak_Num > 1)
    for (i = 0; i < Feak_Num - 1; i++)
    {
      swapped = 0; // 标记是否发生了交换
      for (j = 0; j < Feak_Num - i - 1; j++)
      {
        if (Index_num[j] > Index_num[j + 1])
        {
          // 交换 Index_num[j] 和 Index_num[j + 1]
          t = Index_num[j];
          Index_num[j] = Index_num[j + 1];
          Index_num[j + 1] = t;
          swapped = 1; // 记录发生了交换
        }
      }
      // 如果在这一轮遍历中没有发生交换,说明数组已经有序
      if (!swapped)
        break;
    }
      
  //第5步取中值作为R-R波之间的数据个数,计算心率
    if(Feak_Num >= 2)
    {
      if((Feak_Num % 2) == 0)  //波峰数量为偶数
        n = Index_num[(Feak_Num/2)-1];
      else                     //波峰数量为奇数
        n = Index_num[((Feak_Num+1)/2)-1];
    }
    else   //波峰数量小于2,为1或0
        n = Index_num[0];

  heart_rate = 30000 / n;

  return heart_rate;
}

标签:总结,Index,Feak,电信号,filter,50Hz,date,data,单参
From: https://blog.csdn.net/2301_76901677/article/details/141216816

相关文章

  • SQL注入总结
    一、万能密码:什么是万能密码?用户进行用户名和密码验证时,网站需要查询数据库。查询数据库就是执行SQL语句。用户登录时,后台执行的数据库查询操作(SQL语句)是:【Selectuser_id,user_type,emailFromusersWhereuser_id=’用户名’Andpassword=’密码’】这里我们......
  • 每周总结
    YARN(YetAnotherResourceNegotiator):YARN是Hadoop的资源管理和作业调度系统。本周你可能深入了解了YARN的架构及其组件,包括ResourceManager和NodeManager。ResourceManager负责全局资源调度和作业调度,而NodeManager负责单个节点的资源管理和监控。通过YARN,Hadoop能够高效地分配集......
  • 9 张图总结 MySQL 架构
    原文:9张图总结一下MySQL架构前言目前大部分的后端开发人员对MySQL的理解可能停留在一个黑盒子阶段。对MySQL基本使用没什么问题,比如建库、建表、建索引,执行各种增删改查。所有很多后端开发人员眼中的MySQL如下图所示:导致在实际工作中碰到MySQL中死锁异常、SQL性能太差......
  • 数据库的多表联合查询 后面有命令和格式的总结
    多表联合查询实践创建表:MySQL[company]>createtableemployee6(  emp_idintauto_incrementprimarykeynotnull,  emp_namevarchar(50),  ageint,  dept_idint);QueryOK,0rowsaffected(0.65sec)查看表结构:MySQL[company]>d......
  • Nginx 中的反向代理和负载均衡不是完全相同的概念,但它们经常一起使用,并且在某些场景下
    反向代理(ReverseProxy)反向代理指的是代理服务器接收来自客户端的请求,并将这些请求转发给实际提供服务的服务器。客户端并不直接与实际的服务器通信,而是通过反向代理服务器来完成请求和响应的传递。反向代理的主要用途包括:缓存静态内容以减少后端服务器的负载。提供额外的安全层,隐......
  • Python自动化测试面试题总结_pytest框架面试题
    ???16、请用python脚本实现从1到100的求和。???17、编写一个匿名函数,使其能够进行加法运算,例如说输入1,2能计算结果为3???18、list_1=[1,2,1,2,15,4,3,2,1,2],去除list_1的重复值,并且从大到小排序。???19、统计字符串中的单词个数,这里的单词指的是连续的不是空格的......
  • 经典跟踪算法总结
    https://github.com/mikel-brostrom/boxmotSORT SORT是一种多目标跟踪算法,可以有效地关联目标,并提升跟踪的实时性。SORT的核心主要是卡尔曼滤波和匈牙利算法的结合,可以达到较好的跟踪效果。在当时,跟踪速度达到了260HZ,相比其他方法速度提升了20倍。SORT关注的重点是实时跟踪......
  • python学习总结--面向对象
    1.面向对象(上)1.1定义面向对象编程:oop[objectorientedprogramming]是一种python的编程思路;面向过程:就是我们一开始学习的,按照解决问题的步骤去写代码【根据业务逻辑去写代码】,在思考问题的时候,首先分析'怎么按照步骤去实现'然后将问题解决拆解成若干个步骤,并将这些步骤对......
  • 关于pdf转markdown的一些总结
    实现一个陌生的功能,一般会经过这几个阶段如,调研,技术选型,确定最佳技术方案与备选方案,开发,测试,上线;调研大致了解不同的产品最好能上外网,首选用谷歌搜,其次用百度搜;关键词可以是pdf转markdown,或pdfmarkdownapi等等;例如我在百度搜索pdf转markdown,最后得到了方案有Nought:htt......
  • 2024.8.30 总结(集训 考 DP)
    上午三个多小时考四道题的DP。赛时会的分:[100](?)+100+[30](?)+100。估分:100+100+0+100。实际分:10+100+0+100。挂巨量的分,挂了120分。下面是一些值得注意的点:T1就是分组背包。DP数组下标要考虑负数可以直接全体加一个值变成非负的,[或者用map之类的](?)(&不......