Ala*_*aor 75 language-agnostic algorithm pattern-recognition signal-processing machine-learning
我正在尝试从心电图中读取图像并检测其中的每一个主波(P波,QRS波群和T波).现在我可以读取图像并得到一个像(4.2; 4.4; 4.9; 4.7; ...)这样的矢量代表心电图中的值,这是问题的一半.我需要一种算法,可以遍历此向量并检测每个波的开始和结束时间.
以下是其中一个图表的示例:
如果它们总是具有相同的尺寸会很容易,但它不是很有效,或者如果我知道心电图会有多少波,但它也会有所不同.有没有人有想法?
谢谢!
更新
我想要实现的例子:
鉴于波
我可以提取矢量
[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;]
我想检测一下,例如
P波[19 - 37]
QRS复合体[51 - 64]
等等...
Ste*_*joa 53
我要做的第一件事就是看看那里已有的东西.实际上,这个具体问题已经得到了大量研究.以下是一些非常简单的方法的简要概述:链接.
我也必须回答另一个答案.我从事信号处理和音乐信息检索的研究.从表面上看,这个问题看起来确实类似于起始检测,但问题背景并不相同.这种类型的生物信号处理,即P,QRS和T相的检测,可以利用这些波形中的每一个的特定时域特性的知识.MIR中的起始检测实际上并非如此.(至少不可靠.)
一种适用于QRS检测(但不一定用于音符开始检测)的方法是动态时间扭曲.当时域特征保持不变时,DTW可以非常好地工作.这是一篇简短的IEEE论文,它使用DTW来解决这个问题:链接.
这是一篇很好的IEEE杂志文章,比较了许多方法:链接.您将看到许多常见的信号处理模型已经尝试过.浏览论文,尝试一下你在基层理解的论文.
编辑:浏览这些文章后,基于小波的方法对我来说似乎最直观.DTW也会运行良好,并且存在DTW模块,但小波方法对我来说似乎最好.其他人通过利用信号的衍生物来回答.我的第一个链接检查了1990年以前的方法,但我怀疑它们不像更现代的方法那样健壮.
编辑:我会尽力给出一个简单的解决方案,当我得到机会,但原因为什么我觉得小波在这里适用的是因为他们在无论参数化各种形状的有效时间或幅度缩放.换句话说,如果您的信号具有相同的重复时间形状但是在不同的时间尺度和幅度下,小波分析仍然可以将这些形状识别为相似(粗略地说).另请注意,我有点将过滤器库归入此类别.类似的事情.
roo*_*ook 15
这个难题的一部分是" 起始检测 ",并且已经编写了许多复杂的算法来解决这个问题.以下是有关开始的更多信息.
下一部分是汉明距离.此算法允许您进行模糊比较,输入是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))
Run Code Online (Sandbox Code Playgroud)
此脚本输出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序列的位置,那么您将知道在p波的所有位置处不重叠的50个最短距离. 答对了! 这简单到底是怎么回事?然而,由于距离计算的数量增加,折衷是效率损失.
您可以使用互相关.获取每个模式的模型样本并将其与信号相关联.您将获得相关性高的峰值.通过这种提取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];
}
}
Run Code Online (Sandbox Code Playgroud)
并查找r中的峰值(例如,超过阈值的值)
不要分析绝对数据,而是分析从一个数据点到下一个数据点的变化量.
这是一个快速的单行,将;
分离的数据作为输入,并输出该数据的增量.
perl -0x3b -ple'( $last, $_ ) = ( $_, $_-$last )' < test.in > test.out
Run Code Online (Sandbox Code Playgroud)
在您提供的数据上运行它,这是输出:
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
Run Code Online (Sandbox Code Playgroud)
;; 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 _________/
Run Code Online (Sandbox Code Playgroud)
虽然在第二个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 ________________/
Run Code Online (Sandbox Code Playgroud)
第三个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 __________/
Run Code Online (Sandbox Code Playgroud)
你会发现t波的方式与p波类似.主要区别在于它们何时发生.
这两个单线仅作为示例,不建议日常使用.
另外两个尖锐的峰谷也是qrs复合体吗?
在我的脑海中,我认为你需要做的是计算该图在每个点的斜率。然后您还需要查看斜率变化的速度(二阶导数???)。如果你发生了突然的变化,那么你就知道你已经达到了某种尖锐的顶峰。当然,您希望限制对变化的检测,因此您可能需要执行类似“如果斜率在时间间隔 T 内变化 X”之类的操作,这样您就不会在图表中发现微小的凸起。
我已经有一段时间没有做过任何数学了……这似乎是一个数学问题;)哦,我也没有做过任何类型的信号分析:)。
只是补充一点。我想你也可以尝试信号平均。例如,对最后 3 或 4 个数据点求平均值。我认为你也可以通过这种方式检测突然的变化。