检测波浪中的模式

时间:2010-02-03 22:51:59

标签: algorithm language-agnostic machine-learning signal-processing pattern-recognition

我正在尝试从心电图中读取图像并检测其中的每一个主波(P波,QRS波群和T波)。现在我可以读取图像并得到像(4.2; 4.4; 4.9; 4.7; ...)这样的矢量代表心电图中的值,这是问题的一半。我需要一种算法,可以遍历此向量并检测每个波的开始和结束时间。

以下是其中一个图表的示例:

alt text

如果它们总是具有相同的尺寸会很容易,但是它不会起作用,或者如果我知道心电图会有多少波,但它也会有所不同。有没有人有想法?

谢谢!

更新

我正在努力实现的例子:

鉴于波浪

alt text

我可以提取载体

[0; 0; 20; 20; 20; 19; 18; 17; 17; 17; 17; 17; 16; 16; 16; 16; 16; 16; 16; 17; 17; 18; 19; 20; 21; 22; 23; 23; 23; 25; 25; 23; 22; 20; 19; 17; 16; 16; 14; 13; 14; 13; 13; 12; 12; 12; 12; 12; 11; 11; 10; 12; 16; 22; 31; 38; 45; 51; 47; 41; 33; 26; 21; 17; 17; 16; 16; 15; 16; 17; 17; 18; 18; 17; 18; 18; 18; 18; 18; 18; 18; 17; 17; 18; 19; 18; 18; 19; 19; 19; 19; 20; 20; 19; 20; 22; 24; 24; 25; 26; 27; 28; 29; 30; 31; 31; 31; 32; 32; 32; 31; 29; 28; 26; 24; 22; 20; 20; 19; 18; 18; 17; 17; 16; 16; 15; 15; 16; 15; 15; 15; 15; 15; 15; 15; 15; 15; 14; 15; 16; 16; 16; 16; 16; 16; 16; 16; 16; 15; 16; 15; 15; 15; 16; 16; 16; 16; 16; 16; 16; 16; 15; 16; 16; 16; 16; 16; 15; 15; 15; 15; 15; 16; 16; 17; 18; 18; 19; 19; 19; 20; 21; 22; 22; 22; 22; 21; 20; 18; 17; 17; 15; 15; 14; 14; 13; 13; 14; 13; 13; 13; 12; 12; 12; 12; 13; 18; 23; 30; 38; 47; 51; 44; 39; 31; 24; 18; 16; 15; 15; 15; 15; 15; 15; 16; 16; 16; 17; 16; 16; 17; 17; 16; 17; 17; 17; 17; 18; 18; 18; 18; 19; 19; 20; 20; 20; 20; 21; 22; 22; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 32; 33; 33; 33; 32; 30; 28; 26; 24; 23; 23; 22; 20; 19; 19; 18; 17; 17; 18; 17; 18; 18; 17; 18; 17; 18; 18; 17; 17; 17; 17; 16; 17; 17; 17; 18; 18; 17; 17; 18; 18; 18; 19; 18; 18; 17; 18; 18; 17; 17; 17; 17; 17; 18; 17; 17; 18; 17; 17; 17; 17; 17; 17; 17; 18; 17; 17; 18; 18; 18; 20; 20; 21; 21; 22; 23; 24; 23; 23; 21; 21; 20; 18; 18; 17; 16; 14; 13; 13; 13; 13; 13; 13; 13; 13; 13; 12; 12; 12; 16; 19; 28; 36; 47; 51; 46; 40; 32; 24; 20; 18; 16; 16; 16; 16; 15; 16; 16; 16; 17; 17; 17; 18; 17; 17; 18; 18; 18; 18; 19; 18; 18; 19; 20; 20; 20; 20; 20; 21; 21; 22; 22; 23; 25; 26; 27; 29; 29; 30; 31; 32; 33; 33; 33; 34; 35; 35; 35; 0; 0; 0; 0;]

我想检测一下,例如

[19 - 37]中的P波

[51 - 64]中的QRS复合体

等...

13 个答案:

答案 0 :(得分:52)

要做的第一件事就是看看那里已有的东西。实际上,这个具体问题已经得到了大量研究。以下是一些非常简单的方法的简要概述:link

我也必须回答另一个答案。我从事信号处理和音乐信息检索的研究。从表面上看,这个问题看起来确实类似于起始检测,但问题背景并不相同。这种类型的生物信号处理,即P,QRS和T相的检测,可以利用这些波形中的每一个的特定时域特性的知识。 MIR中的起始检测实际上并非如此。 (至少不可靠。)

一种适用于QRS检测(但不一定用于音符开始检测)的方法是动态时间扭曲。当时域特征保持不变时,DTW可以非常好地工作。以下是使用DTW解决此问题的简短IEEE论文:link

这是一篇很好的IEEE杂志文章,比较了许多方法:link。您将看到许多常见的信号处理模型已经尝试过。浏览论文,尝试一下你在基层理解的论文。

编辑:浏览这些文章后,基于小波的方法对我来说似乎最直观。 DTW也会运行良好,并且存在DTW模块,但小波方法对我来说似乎最好。其他人通过利用信号的衍生物来回答。我的第一个链接检查了1990年以前的方法,但我怀疑它们不像更现代的方法那样健壮。

编辑:当我有机会时,我会尝试给出一个简单的解决方案,但为什么我认为小波适合的原因是因为它们可用于参数化各种形状,无论如何时间或幅度缩放换句话说,如果您的信号具有相同的重复时间形状但是在不同的时间尺度和幅度下,小波分析仍然可以将这些形状识别为相似(粗略地说)。另请注意,我有点将过滤器库归入此类别。类似的事情。

答案 1 :(得分:15)

这个难题的一部分是“onset detection”,并且已经编写了许多复杂的算法来解决这个问题。以下是有关onsets的更多信息。

下一部分是Hamming Distance。此算法允许您进行模糊比较,输入是2个数组,输出是整数“距离”或2个数据集之间的差异。数字越小,2越相似。这非常接近你所需要的,但不完全一样。我继续对汉明距离算法做了一些修改来计算一个新的距离,它可能有一个名字,但我不知道它是什么。基本上它将数组中每个元素之间的绝对距离相加并返回总数。这是python中的代码。

import math

def absolute_distance(a1, a2, length):
       total_distance=0
       for x in range(0,length):
               total_distance+=math.fabs(a1[x]-a2[x])
       return total_distance

print(absolute_distance([1,3,9,10],[1,3,8,11],4))

此脚本输出2,这是这两个数组之间的距离。

现在整理这些作品。您可以使用Onset检测来查找数据集中所有波的开头。然后,您可以循环这些位置,将每个波形与样本P-Wave进行比较。如果你击中QRS综合体,距离将是最大的。如果你击中另一个P-Wave,这个数字不会为零,但它会小得多。任何P-Wave和任何T-Wave之间的距离都会非常小,但如果您做出以下假设,这不是问题:

The distance between any p-wave and any other p-wave will be smaller than the distance between any p-wave and any t-wave.

该系列看起来像这样:pQtpQtpQt ... p波和t波彼此相邻,但由于这个序列是可预测的,因此更容易阅读。

另一方面,可能存在基于微积分的解决方案。然而在我看来,曲线拟合和积分使这个问题更加混乱。我写的距离函数将找到区域差异,它非常相似,减去两条曲线的积分。

可能牺牲起始计算有利于一次迭代1个点,从而执行O(n)距离计算,其中n是图中点的数量。如果您有所有这些距离计算的列表,并且知道50 pQt序列的位置,那么您将知道不重叠的50个最短距离其中p波的所有位置。 Bingo!为简单起见,这是怎么回事?然而,由于距离计算的数量增加,折衷是效率损失。

答案 2 :(得分:8)

您可以使用cross-correlation。获取每个模式的模型样本并将其与信号相关联。您将获得相关性高的峰值。通过这种提取qrs和t波的技术,我期望得到很好的结果。之后,您可以通过在qrs之前查找相关信号上的峰值来提取p波。

互相关是一种非常容易实现的算法。基本上是:

x is array with your signal of length Lx
y is an array containing a sample of the signal you want to recognize of length Ly
r is the resulting correlation

for (i=0; i<Lx - Ly; i++){
  r[i] = 0;
  for (j=0; j<Ly ; j++){
    r[i] += x[i+j]*y[j];
  }
}

查找r中的峰值(例如,超过阈值的值)

答案 3 :(得分:7)

我要做的第一件事是简化数据。

不是分析绝对数据,而是分析从一个数据点到下一个数据点的变化量。

这是一个快速的一个班轮,它将;个分开的数据作为输入,并输出该数据的增量。

perl -0x3b -ple'( $last, $_ ) = ( $_, $_-$last )' < test.in > test.out

在您提供的数据上运行它,这是输出:

  

0; 0; 20; 0; 0; 1; -1; -1; 0; 0; 0; 0; 1; 0; 0; 0; 0; 0; 0; 1; 0; 1 ; 1; 1; 1; 1; 1; 0; 0; 2; 0; -2; -1 -2 -1 -2 -1 0 -2 -1; 1; -1; 0; -1; 0; 0; 0;   0; -1; 0; 1; 2; 4; 6; 9; 7; 7; 6; -4; -6 -8; -7; -5; -4; 0; 1; 0; - 1; 1; 1; 0; 1; 0; 1; 1; 0; 0; 0; 0; 0; 0; 1; 0; 1; 1; -1; 0; 1; 0; 0; 0 ; 1; 0; 1; 1;   2; 2; 0; 1; 1; 1; 1; 1; 1; 1; 0; 0; 1; 0; 0; -1 -2 -1 -2 -2 -2 -2 ; 0; 1; 1; 0; 1; 0; 1; 0; 1; 0; 1; 1; 0; 0; 0; 0; 0; 0; 0; 0; 1; 1; 1; 0; 0; 0;   0; 0; 0; 0; 0; 1; 1; 1; 0; 0; 1; 0; 0; 0; 0; 0; 0; 0; 1; 1; 0; 0; 0; 0 -1; 0; 0; 0; 0; 1; 0; 1; 1; 0; 1; 0; 0; 1; 1; 1; 0; 0; 0; 1; -1; -2; - 1; 0; -2; 0;   -1; 0; 1; 0; 1; 1; 0; 0; 1; 0; 0; 0; 1; 5; 5; 7; 8; 9; 4; -7 -5 -8 ; -7 -6; -2; -1; 0; 0; 0; 0; 0; 1; 0; 0; 1; -1; 0; 1; 0; 1; 1; 0; 0; 0 ; 1; 0; 0; 0;   1; 0; 1; 0; 0; 0; 1; 1; 0; 2; 1; 1; 1; 1; 1; 1; 1; 1; 1; -1; 1; 0; 0; 1; -2 -2 -2 -2 -1 0 -1 -2 -1 0 -1 -1; 0; 1; -1; 1; 0; 1; 1; -1; 1; 0; 1;   0; 0; 0; 1; 1; 0; 0; 1; 0; 1; 0; 1; 0; 0; 1; 1; 0; 1; 1; 0; 1; 0; 0 ; 0; 0; 1; -1; 0; 1; 1; 0; 0; 0; 0; 0; 0; 1; -1; 0; 1; 0; 0; 2; 0; 1; 0; 1; 1; 1; -1;   0 -2 0 -1 -2 0 -1 -1 -2 -1; 0; 0; 0; 0; 0; 0; 0; 0; 1; 0; 0; 4; 3; 9; 8; 11; 4; 1-5; -6 -8 -8 -4 -2 -2; 0; 0; 0; 1; 1; 0; 0; 1; 0; 0; 1; -1;   0; 1; 0; 0; 0; 1; -1; 0; 1; 1; 0; 0; 0; 0; 1; 0; 1; 0; 1; 2; 1; 1; 2; 0; 1 ; 1; 1; 1; 0; 0; 1; 1; 0; 0; -35; 0; 0; 0;

上面的文字中插入的新行最初并未出现在输出中。


完成后,找到qrs复合体是微不足道的。

perl -F';' -ane'@F = map { abs($_) > 2 and $_ } @F; print join ";", @F'< test.out
  

;; 20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;; 4; 6; 9; 7; 7; 6; -4; -6 -8; -7; -5; -4;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;; 5; 5; 7; 8; 9; 4; -7 -5 -8; -7 -6
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;; 4; 3; 9; 8; 11; 4; 1-5; -6 -8 -8 -4;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - 35 ;;;

20-35数据点来自以0开头和结尾的原始数据。

要查找其他数据点,您必须依赖模式匹配。


如果你看第一个p波,你可以清楚地看到一个模式。

0;0;0;0;0;0;1;0;1;1;1;1;1;1;0;0;2;0;-2;-1;-2;-1;-2;-1;0;-2;-1;1;-1;0;-1;0;0;0;0;
#           \________ up _______/   \________ down _________/

虽然在第二个p波上看模式并不容易。这是因为第二个是进一步展开

0;0;0;1;0;1;1;0;1;0;0;1;1;1;0;0;0;-1;-1;-2;-1;0;-2;0;-1;0;-1;0;1;-1;0;0;-1;0;0;0;
#     \________ up _______/       \________________ down ________________/

第三波p波比其他两波稍微不稳定。

0;0;0;0;0;1;-1;0;1;0;0;2;0;1;0;1;1;1;-1;0;-2;0;-1;-2;0;-1;-1;-2;-1;0;0;0;0;0;
#                \_______ up ______/  \__________ down __________/

你会发现t波与p波的方式类似。主要区别在于它们何时发生。


这应该是足以帮助您入门的信息。

这两个单行仅作为示例,不建议日常使用。

答案 4 :(得分:4)

其他两个尖峰和山谷是否也是复合物?

在我的脑海中,我认为你需要做的是计算每个点的图形斜率。然后你还需要看看斜率变化的速度(二阶导数???)。如果你有一个突然的变化,那么你知道你已经达到某种尖锐的高峰。当然,您希望限制对变化的检测,因此您可能希望执行类似“如果斜率在时间间隔T内按X变化”的操作,这样您就不会在图中拾取微小的凹凸。 / p>

自从我做了数学学习已经有一段时间......这看起来像是一个数学问题;)哦,我还没有进行任何类型的信号分析:)。

添加另一个点。您也可以尝试使用信号平均值。例如,平均最后3或4个数据点。我认为你也可以通过这种方式发现突然的变化。

答案 5 :(得分:4)

我不是这个特定问题的专家,但是从一般知识中脱颖而出:假设您知道QRS复合体(或其他功能之一,但我会使用QRS复合体这个例子)大致在一段长度为L的固定时间内发生。我想知道你是否可以将其视为一个分类问题如下:

  1. 将您的信号分成长度为L的重叠窗口。每个窗口中都有或没有完整的QRS波群。
  2. 傅里叶变换每个窗口。您的功能是每个频率的信号强度。
  3. 在一些手工注释的数据上训练决策树,支持向量机等。

答案 6 :(得分:3)

一种非常可能产生良好结果的方法是曲线拟合:

  • 将连续波划分为间隔(可能最好将间隔边界设置在qrs复合体的尖峰之间的中间位置)。一次只考虑一个区间。
  • 定义一个模型函数,可用于逼近心电图曲线的所有可能变化。这并不像最初看起来那么困难。 模型函数可以构造为三个函数的总和,其中包含每个波的原点(t_),幅度(a_)和宽度(w_)的参数。

       f_model(t) = a_p   *  f_p  ((t-t_p  )/w_p) + 
                    a_qrs *  f_qrs((t-t_qrs)/w_qrs) +
                    a_t   *  f_t  ((t-t_t  )/w_t)
    

    函数f_p(t)f_qrs(t)f_t(t)是一些简单的函数,可用于模拟三个波中的每一个。

  • 使用拟合算法(例如Levenberg-Marquardt-Algorithm http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm)来确定数据集的拟合参数a_p,t_p,w_p,a_qrs,t_qrs,w_qrs,a_t,t_t,w_t每个intervall。

    参数t_p,t_qrs和t_p是您感兴趣的参数。

答案 7 :(得分:3)

这是一个很棒的问题!我有几点想法:

Dynamic Time Warping可能是一个有趣的工具。您将为您的三个类建立“模板”,然后使用DTW可以看到模板与信号“块”之间的相关性(将信号分解为,例如,.5秒位,即0-0.5。 1-.6 .2-.7 ......)。我使用加速度计数据进行步态分析的类似工作,效果相当不错。

另一种选择是组合信号处理/机器学习算法。再次将你的信号分成“块”。再次创建“模板”(每个类需要十几个)获取每个块/模板的FFT然后使用Naïve Bayes Classifier(或另一个ML分类器,但NB应该删除它)为你的三个班级分类。我也尝试过步态数据,并且能够获得高达98%的精度,并且可以通过相对复杂的信号进行调用。让我知道这是如何工作的,这是一个非常激动人心的问题。

答案 8 :(得分:1)

Wavelet transform”可能是相关的关键字。我曾经参加过使用这种技术在嘈杂的心电图中检测不同心跳阶段的人的演示。

就我有限的理解而言,它有点像傅里叶变换,但使用(缩放)a的副本,在你的情况下是心跳形的脉冲。

答案 9 :(得分:1)

小波已被证明是在此类数据中定位峰值的最佳工具,其中峰值为“不同大小” - 小波的缩放属性使其成为此类多尺度峰值检测的理想工具。这看起来像一个非平稳的信号,因此使用DFT不像某些人所建议的那样是正确的工具,但如果这是一个探索性的项目,你可以看看使用信号的频谱(估计主要是使用自相关的FFT)信号。)

Here是一篇很好的论文,回顾了几种峰值检测方法 - 这将是一个很好的起点。

-Paul

答案 10 :(得分:1)

使用BioSPPY

目前不可能实施T波分析,因为目前它只包含R波分析。例如Tstart Tpeak Tend

不会自动发挥作用

人们必须使用自己的分析。

我的建议是尝试实施以下方法

http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3201026/

这是我最近发现并发现非常有趣的一个

值得关注的另一种t波分析方法是ECGlib团队

http://ieeexplore.ieee.org/document/6713536/

希望这会有所帮助

答案 11 :(得分:0)

我没有彻底阅读对方的答案,但我已经扫描了它们,我注意到没有人建议查看傅里叶变换来分割这些波。

对我来说,这似乎是Harmonic analysis在数学中的明确应用。我可能会遗漏几个微妙的观点。

Discrete Fourier Transform系数为您提供构成离散时间信号的不同正弦分量的幅度和相位,这基本上就是您想要找到的问题。

我可能在这里遗漏了一些东西......

答案 12 :(得分:0)

首先,标准心电图波的各种成分可能会从任何给定的图中丢失。这样的情节通常是不正常的,通常表示某种问题,但你不能承诺他们在那里。

其次,认识到它们与科学一样艺术,特别是在出现问题的情况下。

我的方法可能是尝试训练神经网络来识别组件。你可以给它前30秒的数据,归一化,使最低点为0,最高点为1.0,它将有11个输出。非异常评级的输出将是过去10秒的加权。从现在开始,0.0为-10秒,现在为1.0。产出将是:

  1. 最近的P波开始的地方
  2. 最近的P波结束的地方
  3. 最近P波的异常评级,其中一个极端“缺席”。
  4. 最近的QRS综合体开始的地方
  5. 最近的QRS复合体的Q部分变成R部分。
  6. 最近的QRS复合体的R部分变为S部分。
  7. 最近的QRS综合体已经结束。
  8. 最近QRS波群的异常等级,其中一个极端“缺席”。
  9. 最近的T波开始的地方。
  10. 最近的T波结束的地方。
  11. 最近T波的异常等级,其中一个极端“缺席”。
  12. 我可以用人们建议的其他一些分析来仔细检查,或者使用其他类型的分析以及神经网络的输出来给你答案。

    当然,不应将此神经网络的详细描述视为规定性的。我确信我并不一定会选择最优的输出,例如,我只是想一些关于它们可能是什么的想法。