J'essaie de lire une image d'une électrocardiographie et de détecter chacune des principales ondes en elle (onde P, complexe QRS et onde T). Maintenant, je peux lire l'image et obtenir un vecteur comme (4.2; 4.4; 4.9; 4.7; ...) représentatif des valeurs de l'électrocardiographie, ce qui représente la moitié du problème. J'ai besoin d'un algorithme qui peut parcourir ce vecteur et détecter le début et la fin de chacune de ces vagues.
Voici un exemple de l'un de ses graphiques:
Ce serait facile s'ils avaient toujours la même taille, mais ce n'est pas comme si cela fonctionnait, ou si je savais combien de vagues l'ECG aurait, mais cela peut aussi varier. Quelqu'un a-t-il des idées?
Merci!
Mise à jour
Exemple de ce que j'essaie de réaliser:
Vu la vague
Je peux extraire le vecteur
[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; dix; 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;]
Je voudrais détecter, par exemple
Onde P dans [19 - 37]
Complexe QRS dans [51 - 64]
etc...
La première chose que [~ # ~] je [~ # ~] ferait est de voir ce qui existe déjà . En effet, ce problème spécifique a déjà fait l'objet de nombreuses recherches. Voici un bref aperçu de quelques méthodes vraiment simples: link .
Je dois également répondre à une autre réponse. Je fais des recherches sur le traitement du signal et la recherche d'informations musicales. En surface, ce problème semble similaire à la détection de début, mais le contexte du problème n'est pas le même. Ce type de traitement biologique du signal, c'est-à-dire la détection des phases P, QRS et T, peut exploiter la connaissance de caractéristiques spécifiques du domaine temporel de chacune de ces formes d'onde. La détection de début dans MIR ne le fait pas vraiment. (Pas fiable du moins.)
Une approche qui fonctionnerait bien pour la détection QRS (mais pas nécessairement pour la détection de début de note) est la déformation temporelle dynamique. Lorsque les caractéristiques du domaine temporel restent invariantes, DTW peut fonctionner remarquablement bien. Voici un court article IEEE qui utilise DTW pour ce problème: link .
Ceci est un article du magazine Nice IEEE qui compare de nombreuses méthodes: link . Vous verrez que de nombreux modèles courants de traitement du signal ont été essayés. Parcourez le document et essayez celui que vous comprenez au niveau de base.
EDIT: Après avoir parcouru ces articles, une approche basée sur les ondelettes me semble la plus intuitive. DTW fonctionnera bien aussi, et il existe des modules DTW, mais l'approche en ondelettes me semble la meilleure. Quelqu'un d'autre a répondu en exploitant les dérivés du signal. Mon premier lien examine les méthodes d'avant 1990 qui font cela, mais je soupçonne qu'elles ne sont pas aussi robustes que les méthodes plus modernes.
EDIT: J'essaierai de donner une solution simple quand j'en aurai l'occasion, mais la raison pourquoi Je pense que les ondelettes sont appropriées ici parce qu'elles sont utiles pour paramétrer une grande variété de formes indépendamment de mise à l'échelle du temps ou de l'amplitude. En d'autres termes, si vous avez un signal avec la même forme temporelle répétée mais à différentes échelles de temps et amplitudes, l'analyse en ondelettes peut toujours reconnaître ces formes comme étant similaires (grosso modo). Notez également que je suis en quelque sorte des banques de filtres dans cette catégorie. Choses similaires.
Une pièce de ce puzzle est " détection de début " et un certain nombre d'algorithmes complexes ont été écrits pour résoudre ce problème. Voici plus d'informations sur onsets .
La pièce suivante est une distance de Hamming . Ces algorithmes vous permettent de faire des comparaisons floues, l'entrée est 2 tableaux et la sortie est une "distance" entière ou une différence entre les 2 ensembles de données. Plus le nombre est petit, plus les 2 se ressemblent. C'est très proche de ce dont vous avez besoin, mais ce n'est pas exact. Je suis allé de l'avant et j'ai apporté quelques modifications à l'algorithme de distance de Hamming pour calculer une nouvelle distance, il a probablement un nom mais je ne sais pas ce que c'est. Fondamentalement, il additionne la distance absolue entre chaque élément du tableau et renvoie le total. Voici le code pour cela en 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))
Ce script génère 2, qui est la distance entre ces 2 tableaux.
Maintenant pour assembler ces pièces. Vous pouvez utiliser la détection Onset pour trouver le début de toutes les vagues dans l'ensemble de données. Vous pouvez ensuite parcourir ces emplacements en comparant chaque vague avec un échantillon de P-Wave. Si vous touchez un complexe QRS, la distance sera la plus grande. Si vous frappez un autre P-Wave, le nombre ne sera pas nul, mais ce sera beaucoup plus petit. La distance entre n'importe quelle onde P et toute onde T va être assez petite, CEPENDANT, ce n'est pas un problème si vous faites l'hypothèse suivante:
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.
La série ressemble à ceci: pQtpQtpQt ... L'onde p et l'onde t sont côte à côte, mais comme cette séquence est prévisible, elle sera plus facile à lire.
D'un côté non, il existe probablement une solution basée sur le calcul à ce problème. Cependant, dans mon esprit, l'ajustement des courbes et les intégrales rendent ce problème plus compliqué. La fonction de distance que j'ai écrite trouvera la différence de surface qui est très similaire en soustrayant l'intégrale des deux courbes.
Il est peut-être possible de sacrifier les calculs de début au profit d'une itération d'un point à la fois et d'effectuer ainsi des calculs de distance O(n), où n est le nombre de points dans le graphique. Si vous avait une liste de tous ces calculs de distance et savait où se trouvaient 50 séquences pQt, alors vous connaîtriez les 50 distances les plus courtes qui ne se chevauchent pas où tous les emplacements des ondes p. Bingo! comment est-ce pour la simplicité? Cependant, le compromis est une perte d'efficacité due à un nombre accru de calculs de distance.
Vous pouvez utiliser corrélation croisée . Prélevez un échantillon modèle de chaque modèle et corrélez-les avec le signal. Vous obtiendrez des pics où la corrélation est élevée. Je m'attendrais à de bons résultats avec cette technique d'extraction des ondes qrs et t. Après cela, vous pouvez extraire les ondes p en recherchant des pics sur le signal de corrélation qui sont avant qrs.
La corrélation croisée est un algorithme assez facile à implémenter. Fondamentalement:
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];
}
}
Et recherchez les pics de r (valeurs supérieures à un seuil, par exemple)
Au lieu d'analyser des données absolues, analysez la quantité de changement d'un point de données au suivant.
Voici une doublure rapide qui prendra ;
les données séparées en entrée et la sortie du delta de ces données.
Perl -0x3b -ple'( $last, $_ ) = ( $_, $_-$last )' < test.in > test.out
En l'exécutant sur les données que vous avez fournies, voici la sortie:
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;
Il y a des sauts de ligne insérés dans le texte ci-dessus qui ne sont pas initialement présents dans la sortie.
Après avoir fait cela, il est trivial de trouver le complexe 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 ;;;
Le 20
et -35
les points de données résultent des données d'origine commençant et se terminant par 0
.
Pour trouver les autres points de données, vous devrez vous fier à la correspondance de motifs.
Si vous regardez la première onde p, vous pouvez clairement voir un motif.
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 _________/
Cependant, il n'est pas aussi facile de voir le motif sur la deuxième onde p. En effet, le second est plus étendu
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 ________________/
La troisième onde p est un peu plus erratique que les deux autres.
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 __________/
Vous trouveriez les ondes t d'une manière similaire aux ondes p. La principale différence est quand ils se produisent.
Les deux one-liners sont par exemple uniquement, non recommandés pour une utilisation quotidienne.
Je ne suis pas un expert dans ce problème spécifique, mais juste au-dessus de ma tête de connaissances plus générales: Disons que vous connaissez le complexe QRS (ou l'une des autres fonctionnalités, mais j'utiliserai le complexe QRS pour cet exemple) se déroule à peu près dans une période de temps fixe de longueur L. Je me demande si vous pourriez traiter cela comme un problème de classification comme suit:
Ces deux autres pics et vallées nets sont-ils également des complexes qrs?
Du haut de ma tête, je pense que ce que vous devez faire est de calculer la pente de ce graphique à chaque point. Ensuite, vous devez également voir à quelle vitesse la pente change (dérivée 2e ???). Si vous avez un changement brusque, vous savez que vous avez atteint une sorte de pic aigu. Bien sûr, vous voulez limiter la détection du changement, vous pouvez donc vouloir faire quelque chose comme "si la pente change de X sur l'intervalle de temps T", afin de ne pas capter les petites bosses du graphique.
Cela fait un moment que je n'ai pas fait de maths ... et cela semble être une question de maths;) Oh, et je n'ai pas fait d'analyse de signal non plus :).
J'ajoute juste un autre point. Vous pouvez également essayer la moyenne du signal, je pense. Par exemple, faire la moyenne des 3 ou 4 derniers points de données. I pensez vous pouvez également détecter les changements brusques de cette façon.
Une approche qui donnera très probablement de bons résultats est l'ajustement de la courbe:
Définissez une fonction de modèle qui peut être utilisée pour approximer toutes les variations possibles des courbes électrocardiographiques. Ce n'est pas aussi difficile qu'il n'y paraît en premier. La fonction de modèle peut être construite comme une somme de trois fonctions avec des paramètres pour l'origine (t_), l'amplitude (a_) et la largeur (w_) de chaque onde.
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)
Les fonctions f_p(t)
, f_qrs(t)
, f_t(t)
sont des fonctions simples qui peuvent être utilisées pour modéliser chacune des trois vagues.
Utilisez un algorithme d'ajustement (par exemple, l'algorithme de Levenberg-Marquardt http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm ) pour déterminer les paramètres d'ajustement a_p, t_p, w_p, a_qrs, t_qrs, w_qrs, a_t, t_t, w_t pour l'ensemble de données de chaque intervalle.
Les paramètres t_p, t_qrs et t_p sont ceux qui vous intéressent.
C'est une merveilleuse question! J'ai quelques réflexions:
La déformation temporelle dynamique pourrait être un outil intéressant ici. Vous établiriez des "modèles" pour vos trois classes, puis l'utilisation de DTW pourrait voir la corrélation entre votre modèle et des "morceaux" du signal (décomposer le signal en, disons, 0,5 seconde bits, soit 0 à 0,5). 1-.6 .2-.7 ...). J'ai travaillé avec quelque chose de similaire pour l'analyse de la marche avec des données d'accéléromètre, cela a fonctionné assez bien.
Une autre option est un algorithme combiné de traitement du signal/d'apprentissage automatique. Brisez à nouveau votre signal en "morceaux". Faites à nouveau des "modèles" (vous en aurez besoin d'une douzaine pour chaque classe) prenez le [~ # ~] fft [~ # ~] de chaque bloc/modèle, puis utilisez un Naïve Bayes Classifier (ou un autre classificateur ML, mais NB devrait le couper) à classer pour chacune de vos trois classes. J'ai également essayé cela sur des données de marche, et j'ai pu atteindre une précision de 98% et me rappeler avec des signaux relativement compliqués. Faites-moi savoir comment cela fonctionne, c'est un problème très excitant.
Les ondelettes se sont révélées être le meilleur outil pour localiser les pics dans ce type de données où les pics sont de "tailles différentes" - les propriétés de mise à l'échelle des ondelettes en font un outil idéal pour ce type de détection de pics à plusieurs échelles. Cela ressemble à un signal non stationnaire, donc l'utilisation d'un DFT ne serait pas le bon outil comme certains l'ont suggéré, mais s'il s'agit d'un projet exploratoire, vous pouvez regarder en utilisant le spectre du signal (estimé en utilisant essentiellement la FFT de l'autocorrélation de le signal.)
Ici est un excellent article qui passe en revue plusieurs méthodes de détection des pics - ce serait un bon point de départ.
-Paul
en utilisant BioSPPY
il n'est actuellement pas possible de mettre en œuvre une analyse des ondes T, car à l'heure actuelle, elle ne contient qu'une analyse des ondes R. par exemple Tstart Tpeak Tend
ne sont pas implémentés automatiquement
il faudrait utiliser votre propre analyse.
ma suggestion serait d'essayer de mettre en œuvre la méthode ci-dessous
http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3201026/
qui est celui que j'ai récemment découvert et trouvé très intéressant
L'autre méthode d'analyse des ondes t qui mérite d'être étudiée est celle de l'équipe ECGlib
http://ieeexplore.ieee.org/document/6713536/
j'espère que cela t'aides
" transformée en ondelettes " peut être un mot clé pertinent. J'ai déjà assisté à une présentation de quelqu'un qui a utilisé cette technique pour détecter différentes phases du rythme cardiaque dans un ECG bruyant.
En ce qui concerne ma compréhension limitée, c'est un peu comme une transformée de Fourier, mais en utilisant des copies (à l'échelle) d'un Pulse en forme de battement de cœur dans votre cas.
Premièrement, les différents composants de l'onde d'électrocardiogramme standard peuvent être absents de tout tracé donné. Un tel complot est généralement anormal et indique généralement une sorte de problème, mais on ne peut pas vous promettre qu'il est là.
Deuxièmement, les reconnaître est autant de l'art que de la science, surtout dans les cas où quelque chose ne va pas.
Mon approche pourrait être d'essayer de former un réseau de neurones pour identifier les composants. Vous lui donneriez les 30 secondes de données précédentes, normalisées de sorte que le point le plus bas était à 0 et le point le plus haut à 1,0 et il aurait 11 sorties. Les sorties qui n'étaient pas des notes d'anomalie seraient une pondération pour les 10 dernières secondes. Un 0.0 correspondrait à -10 secondes et un 1.0 signifierait maintenant. Les résultats seraient:
Je pourrais vérifier ceci avec certains des autres types d'analyses suggérés par les gens, ou utiliser ces autres types d'analyses avec la sortie du réseau neuronal pour vous donner votre réponse.
Bien entendu, cette description détaillée du réseau neuronal ne doit pas être considérée comme normative. Je suis sûr que je n'ai pas nécessairement choisi les sorties les plus optimales par exemple, j'ai simplement jeté quelques idées sur ce qu'elles pourraient être.
Je ne me suis pas lu attentivement, mais je les ai scannées et j'ai remarqué que personne ne recommandait de regarder la transformée de Fourier pour segmenter ces ondes.
Pour moi, cela semble être une application claire de analyse harmonique en mathématiques. Il peut y avoir plusieurs points subtils qui me manquent.
Les coefficients Transformée de Fourier discrète vous donnent l'amplitude et la phase des différentes composantes sinusoïdales qui composent votre signal temporel discret, ce qui est essentiellement ce que votre problème indique que vous voulez trouver.
Il se peut que je manque quelque chose ici ...