私は心電図から画像を読み取って、その中の主な波(P波、QRS複素数、T波)のそれぞれを検出しようとしています。これで画像を読み取って、心電図の値を表す(4.2; 4.4; 4.9; 4.7; ...)のようなベクトルを取得できます。これは問題の半分です。このベクトルをウォークスルーして、この各波の開始と終了を検出できるアルゴリズムが必要です。
以下は、そのグラフの1つの例です。
それらが常に同じサイズであったとしても簡単ですが、それが機能するようではないか、または心電図が持つ波の数がわかっていれば、それも変化する可能性があります。誰かがいくつかのアイデアを持っていますか?
ありがとう!
更新中
私が達成しようとしていることの例:
波を考えると
ベクターを抽出できます
[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]
[51-64]のQRS複合システム
等...
[〜#〜] i [〜#〜]が最初に行うことは、すでにそこにあるものを見る。実際、この特定の問題はすでに徹底的に研究されています。これは、いくつかの本当にシンプルなメソッドの概要です: link 。
私も別の答えに答えなければなりません。私は信号処理と音楽情報検索の研究をしています。表面的には、この問題は発症検出と似ていますが、問題のコンテキストは同じではありません。このタイプの生体信号処理、つまりP、QRS、およびT相の検出は、これらの各波形の特定の時間領域特性の知識を活用できます。実際、MIRでの発症検出はそうではありません。 (少なくとも、確実ではありません。)
QRS検出に有効なアプローチの1つ(ただし、必ずしもノート開始検出に有効ではない)は、動的タイムワーピングです。時間領域特性が不変のままである場合、DTWは非常によく機能します。この問題にDTWを使用する短いIEEEペーパーを以下に示します: link 。
これは、多くの方法を比較する、ニースIEEEの雑誌記事です link 。多くの一般的な信号処理モデルが試されていることがわかります。紙をすくい、基本的なレベルで理解できるものを試してください。
編集:これらの記事を閲覧した後、ウェーブレットベースのアプローチは私にとって最も直感的に思えます。 DTWもうまく機能し、そこにはDTWモジュールが存在しますが、私にはウェーブレットアプローチが最適のようです。他の誰かが信号の派生物を利用して答えました。私の最初のリンクはそれを行う1990年以前の方法を調べていますが、それらはより現代的な方法ほど頑健ではないと思います。
編集:機会があれば簡単な解決策を提供しようとしますが、なぜここでウェーブレットが適していると思うのは、さまざまなパラメーターのパラメーター化に役立つためです時間または振幅スケーリングに関係なく形状。言い換えれば、同じ時間的形状が繰り返されるが、時間スケールと振幅が異なる信号がある場合でも、ウェーブレット分析はこれらの形状を(大まかに)類似していると認識できます。また、私はフィルタバンクをこのカテゴリにまとめていることに注意してください。同様のもの。
このパズルの一部は「 開始検出 」であり、この問題を解決するために多数の複雑なアルゴリズムが作成されています。 onsets の詳細については、こちらをご覧ください。
次のピースは ハミング距離 です。このアルゴリズムを使用すると、あいまいな比較を行うことができます。入力は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つの配列間の距離である2を出力します。
次に、これらの部品を組み立てます。開始検出を使用して、データセット内のすべての波の始まりを見つけることができます。次に、これらの場所をループして、各波をサンプルのP-Waveと比較します。 QRS Complexにぶつかった場合、距離は最大になります。別の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の最短距離がわかりますBingo!簡単にするためにそれはどうですか?ただし、トレードオフは、距離計算の数の増加による効率の損失です。
相互相関 を使用できます。各パターンのモデルサンプルを取得し、信号と相関させます。相関が高い場所でピークが発生します。この手法で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のピークを探します(たとえば、しきい値を超える値)
絶対データを分析する代わりに、あるデータポイントから次のデータポイントへの変化量を分析します。
以下は、;
で区切られたデータを入力として受け取り、そのデータのデルタを出力する簡単なワンライナーです。
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; -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; -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 _________/
ただし、2番目のp波のパターンを確認するのは簡単ではありません。これは、2つ目がさらに広がるためです。
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 ________________/
3番目のp波は、他の2つよりも少し不安定です。
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 __________/
あなたは、p波と同様の方法でt波を見つけるでしょう。主な違いは、いつ発生するかです。
2つのワンライナーは一例にすぎず、毎日の使用にはお勧めできません。
私はこの特定の問題の専門家ではありませんが、より一般的な知識から頭を離れています:QRS複合システム(または他の機能の1つを知っていますが、この例ではQRS複合システムを使用します)長さLのほぼ一定の時間内に発生します。これを次のように分類問題として扱うことができるかどうか疑問に思います。
それらの他の2つの鋭い山と谷もqrs複合体ですか?
私の頭の上で、私はあなたがする必要があるのは各点でこのグラフの傾きを計算することだと思います。次に、勾配の変化の速さも確認する必要があります(2次導関数???)。急激な変化がある場合は、何らかの鋭いピークに達したことがわかります。もちろん、変化の検出を制限したいので、「時間間隔Tで勾配がXだけ変化した場合」のようにして、グラフの小さな隆起を拾わないようにする必要があります。
私が計算をしてからしばらく経ちました...そしてこれは数学の質問のようです;)おお、そして私は信号分析のどんな種類も行っていません:).
別のポイントを追加するだけです。信号平均化も試してみてください。たとえば、最後の3つまたは4つのデータポイントを平均します。 I think突然の変化をそのように検出することもできます。
良い結果をもたらす可能性が非常に高いアプローチの1つは、曲線近似です。
心電図曲線のすべての可能な変動を概算するために使用できるモデル関数を定義します。これは最初に思われるほど難しくありません。モデル関数は、各波の原点(t_)、振幅(a_)、および幅(w_)のパラメーターを持つ3つの関数の合計として作成できます。
_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)
は、3つの波のそれぞれをモデル化するために使用できる単純な関数です。
フィッティングアルゴリズム(例: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。
パラメータt_p、t_qrsおよびt_pは、関心のあるパラメータです。
これはすばらしい質問です。私はいくつかの考えを持っています:
ダイナミックタイムワーピング は、ここで興味深いツールになる可能性があります。 3つのクラスの「テンプレート」を確立し、DTWを使用すると、テンプレートと信号の「チャンク」の間の相関関係を確認できます(たとえば、信号を.5秒のビットに分割します(つまり、0-.5)。 1-.6 .2-.7 ...)。私は、加速度計データを使った歩行分析に似たものを使用しましたが、それはかなりうまくいきました。
別のオプションは、信号処理/機械学習アルゴリズムの組み合わせです。信号を再び「チャンク」に分割します。もう一度「テンプレート」を作成します(クラスごとに1ダースほど必要になります)。次の [〜#〜] fft [〜#〜] を取ります各チャンク/テンプレートを使用して、 NaïveBayes Classifier (または別のML分類子を使用しますが、NBはそれをカットする必要があります) 3つのクラスのそれぞれを分類します。これを歩行データで試したところ、98%以上の精度を取得し、比較的複雑な信号で再現できました。これがどのように機能するかを教えてください。これは非常にエキサイティングな問題です。
ウェーブレットは、ピークが「異なるサイズ」であるこのタイプのデータでピークを特定するための最良のツールであることが示されています。ウェーブレットのスケーリングプロパティは、このタイプのマルチスケールピーク検出に理想的なツールです。これは非定常信号のように見えるため、DFTを使用することは、一部の人が示唆しているように適切なツールではありませんが、これが探索的プロジェクトである場合は、信号のスペクトルを使用して調べることができます(本質的に、自己相関のFFTを使用して推定されます)シグナル。)
ここ は、いくつかのピーク検出方法をレビューする優れた論文です。これは、出発点として最適です。
-ポール
bioSPPYの使用
現時点ではR波解析しか含まれていないため、T波解析を実装することは現時点では可能ではありません。例Tstart Tpeak Tend
自動的に補完されない
独自の分析を使用する必要があります。
私の提案は、以下の方法を試して実装することです
http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3201026/
これは私が最近発見したもので、非常に興味深いことがわかりました
注目に値するもう1つのt波解析方法は、ECGlibチームによるものです。
http://ieeexplore.ieee.org/document/6713536/
お役に立てれば
" Wavelet transform "は関連するキーワードかもしれません。ノイズのある心電図でさまざまな心拍フェーズを検出するためにこのテクニックを使用した人のプレゼンテーションに一度出席したことがあります。
私の限られた理解では、これはフーリエ変換に似ていますが、aの(スケーリングされた)コピーを使用します。
第1に、標準の心電図波のさまざまな成分が、特定のプロットから欠落している可能性があります。このようなプロットは通常異常であり、通常は何らかの問題を示していますが、そこにあるとは保証できません。
第二に、それらを認識することは、特に何かがうまくいかない場合に、科学と同じくらい芸術です。
私のアプローチは、コンポーネントを識別するためにニューラルネットワークをトレーニングすることです。過去30秒間のデータを正規化して、最低点が0、最高点が1.0になり、出力が11になるようにします。異常評価ではなかった出力は、最後の10秒間の重み付けになります。 0.0は現在から-10秒、1.0は現在を意味します。出力は次のようになります。
他の人が提案した他の種類の分析でこれを再確認するか、ニューラルネットワークの出力と一緒に他の種類の分析を使用して回答を提供する場合があります。
もちろん、このニューラルネットワークの詳細な説明は、規範的なものとして解釈されるべきではありません。たとえば、必ずしも最適な出力を選択したわけではなかったと思います。たとえば、それらが何であるかについてのアイデアを投げただけです。