83 votes

Détection de motifs dans les ondes

J'essaie de lire l'image d'un électrocardiogramme et de détecter chacune des principales ondes qu'elle contient (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 dans l'électrocardiographie, ce qui est la moitié du problème. J'ai besoin d'un algorithme qui peut parcourir ce vecteur et détecter quand chacune de ces ondes commence et se termine.

Voici un exemple d'un de ses graphiques :

alt text

Ce serait facile s'ils avaient toujours la même taille, mais ce n'est pas comme si ça marchait, ou si je savais combien de vagues l'ecg aurait, mais ça peut varier aussi. Est-ce que quelqu'un a des idées ?

Merci !

Mise à jour de

Exemple de ce que j'essaie d'obtenir :

Compte tenu de la vague

alt text

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 ; 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 ; 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 ; 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 en [19 - 37]

Complexe QRS en [51 - 64]

etc...

55voto

Steve Tjoa Points 15116

La première chose que I ferait est 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 : lien .

Je dois également répondre à une autre réponse. Je fais des recherches sur le traitement du signal et la recherche d'informations musicales. À première vue, ce problème semble similaire à la détection du début de la musique, mais le contexte du problème n'est pas le même. Ce type de traitement du signal biologique, c'est-à-dire la détection des phases P, QRS et T, peut exploiter la connaissance de l'information suivante caractéristiques spécifiques dans le domaine temporel de chacune de ces formes d'onde. La détection de l'onset dans MIR ne le fait pas, vraiment. (Pas de manière fiable, du moins.)

Une approche qui fonctionnerait bien pour la détection des QRS (mais pas nécessairement pour la détection du début des notes) est la déformation dynamique du temps. Lorsque les caractéristiques du domaine temporel restent invariables, la DTW peut fonctionner remarquablement bien. Voici un court article de l'IEEE qui utilise le DTW pour ce problème : lien .

Il s'agit d'un bel article du magazine IEEE qui compare plusieurs méthodes : lien . Vous verrez que de nombreux modèles courants de traitement du signal ont été essayés. Parcourez le document et essayez-en un que vous comprenez à un 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 par ondelettes me semble la meilleure. Quelqu'un d'autre a répondu en exploitant les dérivés du signal. Mon premier lien examine des 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 pour laquelle je suis ici est la suivante pourquoi Je pense que les ondelettes conviennent ici parce qu'elles sont utiles pour paramétrer une grande variété de formes, indépendamment de la nature de la forme. 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 à des échelles de temps et des amplitudes différentes, l'analyse par ondelettes peut toujours reconnaître ces formes comme étant similaires (en gros). Notez également que je mets en quelque sorte les bancs de filtres dans cette catégorie. Des choses similaires.

17voto

Rook Points 34698

Une pièce de ce puzzle est " détection de l'apparition "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 un Distance de Hamming . Cet algorithme vous permet de faire des comparaisons floues, l'entrée est constituée de deux tableaux et la sortie est une "distance" entière ou une différence entre les deux ensembles de données. Plus le nombre est petit, plus les deux sont semblables. C'est très proche de ce dont vous avez besoin, mais ce n'est pas exact. J'ai fait quelques modifications à l'algorithme de la distance de Hamming pour calculer une nouvelle distance, qui a probablement un nom mais que je ne connais pas. En gros, il additionne la distance absolue entre chaque élément du tableau et renvoie le total. Voici le code 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 sort 2, qui est la distance entre ces 2 tableaux.

Maintenant, il faut assembler ces pièces. Vous pouvez utiliser la détection de l'apparition pour trouver le début de toutes les ondes dans l'ensemble des données. Vous pouvez ensuite passer en boucle ces emplacements en comparant chaque onde avec un échantillon d'onde P. Si vous rencontrez un complexe QRS, la distance sera la plus grande. Si vous rencontrez une autre onde P, le nombre n'est pas nul, mais il est beaucoup plus petit. La distance entre n'importe quelle onde P et n'importe quelle onde T sera assez faible, MAIS 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 juste à côté l'une de l'autre, mais comme cette séquence est prévisible, elle sera plus facile à lire.

Par ailleurs, il existe probablement une solution basée sur les calculs pour résoudre ce problème. Cependant, à mon avis, l'ajustement des courbes et les intégrales rendent ce problème encore plus compliqué. La fonction de distance que j'ai écrite trouvera la différence de surface ce qui revient à soustraire l'intégrale des deux courbes.

Il est peut-être possible de sacrifier les calculs de départ en faveur de l'itération par 1 point à la fois et donc d'effectuer O(n) calculs de distance, où n est le nombre de points dans le graphique. Si vous aviez une liste de tous ces calculs de distance et que vous saviez qu'il y a 50 séquences pQt, vous connaîtriez les 50 distances les plus courtes que les séquences pQt peuvent atteindre. ne se chevauchent pas où tous les emplacements des ondes p. Bingo ! Comment est-ce pour la simplicité ? Cependant, la contrepartie est une perte d'efficacité due à l'augmentation du nombre de calculs de distance.

8voto

nacmartin Points 1522

Vous pouvez utiliser corrélation croisée . Prenez un échantillon modèle de chaque motif et mettez-les en corrélation avec le signal. Vous obtiendrez des pics là où la corrélation est élevée. Je m'attends à de bons résultats avec cette technique pour l'extraction des ondes qrs et t. Ensuite, vous pouvez extraire les ondes p en recherchant les pics sur le signal de corrélation qui sont avant les qrs.

La corrélation croisée est un algorithme assez facile à mettre en œuvre. En gros :

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 dans r (valeurs supérieures à un seuil, par exemple)

7voto

Brad Gilbert Points 12724

La première chose que je ferais est de simplifier les données.

Au lieu d'analyser des données absolues, analysez la quantité de changement d'un point de données à un autre.

Voici un rapide coup d'œil qui prendra ; des données séparées en entrée, et sortir le 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 le résultat :

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;

<em>Il y a des nouvelles lignes insérées dans le texte ci-dessus qui ne sont pas présentes à l'origine dans la sortie.</em>


Une fois que vous avez 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 site 20 et -35 les points de données résultent des données originales commençant et finissant avec 0 .

Pour trouver les autres points de données, vous devrez vous fier au filtrage.


Si vous regardez la première vague p, vous pouvez clairement voir un modèle.

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 _________/

Il n'est pas aussi facile de voir le modèle de la deuxième vague p, cependant. C'est parce que la deuxième vague est plus étalée.

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 vague 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 trouverez les ondes t d'une manière similaire aux ondes p. La principale différence est le moment où elles se produisent.


Ces informations devraient être suffisantes pour vous permettre de commencer.

Les deux phrases en une ligne sont données à titre d'exemple et ne sont pas recommandées pour un usage quotidien.

4voto

Vivin Paliath Points 40975

Ces deux autres pics et vallées aigus sont-ils également des complexes de QRS ?

De mémoire, je pense que ce que vous devez faire, c'est calculer la pente de ce graphique à chaque point. Ensuite, vous devez également voir à quelle vitesse la pente change (dérivée seconde ? ??). Si le changement est brutal, vous savez que vous avez atteint une sorte de pic. Bien sûr, vous voulez limiter la détection du changement, donc vous pouvez faire quelque chose comme "si la pente change de X sur un intervalle de temps T", afin de ne pas détecter les petites bosses dans le graphique.

Cela fait un moment que je n'ai pas fait de maths... et cela ressemble à 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 aussi essayer de faire une moyenne des signaux, je pense. Par exemple, en faisant la moyenne des 3 ou 4 derniers points de données. I pensez à vous pouvez aussi détecter les changements brusques de cette façon.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X