180 votes

Algorithme de recherche de pics pour Python/SciPy

Je peux écrire quelque chose moi-même en trouvant les passages à zéro de la dérivée première ou quelque chose comme ça, mais cela semble être une fonction suffisamment commune pour être incluse dans les bibliothèques standard. Quelqu'un en connaît une ?

Mon application particulière est une matrice 2D, mais elle est généralement utilisée pour trouver des pics dans les FFT, etc.

Plus précisément, dans ce type de problèmes, il y a plusieurs pics forts, puis beaucoup de "pics" plus petits qui sont simplement causés par le bruit et qui doivent être ignorés. Il ne s'agit que d'exemples, pas de mes données réelles :

Pics unidimensionnels :

FFT output with peaks

Pics bidimensionnels :

Radon transform output with circled peak

L'algorithme de recherche de pics trouverait l'emplacement de ces pics (et pas seulement leurs valeurs) et, idéalement, trouverait le véritable pic inter-échantillon, et pas seulement l'indice avec la valeur maximale, probablement à l'aide des méthodes suivantes interpolation quadratique ou quelque chose comme ça.

En général, on ne s'intéresse qu'à quelques pics forts, qui sont choisis soit parce qu'ils sont supérieurs à un certain seuil, soit parce qu'ils sont les premiers à être atteints. n les pics d'une liste ordonnée, classés par amplitude.

Comme je l'ai dit, je sais comment écrire quelque chose comme ça moi-même. Je demande simplement s'il existe une fonction ou un paquet préexistant connu pour bien fonctionner.

Mise à jour :

I traduit un script MATLAB et cela fonctionne décemment pour le cas 1-D, mais pourrait être mieux.

Mise à jour :

sixtenbe a créé une meilleure version pour le cas 1-D.

0 votes

@endolith Avez-vous le fichier MATLAB original que vous avez traduit en python pour cela ? Merci !

0 votes

2 votes

49voto

Paul Points 3767

Je me penche sur un problème similaire et j'ai découvert que certaines des meilleures références proviennent de la chimie (de la recherche de pics dans les données de spectres de masse). Pour un bon examen approfondi des algorithmes de recherche de pics, lire ce . Il s'agit de l'une des revues les plus claires des techniques de recherche de pics que j'ai rencontrées. (Les ondelettes sont les meilleures pour trouver des pics de ce genre dans des données bruyantes).

Il semble que vos pics soient clairement définis et ne soient pas cachés dans le bruit. Dans ce cas, je vous recommande d'utiliser les dérivées lisses de Savtizky-Golay pour trouver les pics (si vous vous contentez de différencier les données ci-dessus, vous aurez un tas de faux positifs). C'est une technique très efficace et assez facile à mettre en œuvre (vous avez besoin d'un cours de matrice avec des opérations de base). Si vous trouvez simplement le passage à zéro de la première dérivée S-G, je pense que vous serez satisfait.

2 votes

Je recherchais une solution générale, et non une solution qui ne fonctionne que sur ces images particulières. J'ai adapté un script de MATLAB en Python et cela fonctionne décemment.

1 votes

C'est vrai. Matlab est une bonne source pour les algorithmes. Quelle technique le script utilise-t-il ? (BTW, SG est une technique très générale).

2 votes

Je l'ai mis en lien ci-dessus. Il recherche simplement les maxima locaux qui sont plus grands qu'un certain seuil au-dessus de leurs voisins. Il existe certainement de meilleures méthodes.

21voto

Hanan Shteingart Points 116

Il existe une fonction dans scipy nommée scipy.signal.find_peaks_cwt qui semble convenir à vos besoins, mais je n'ai pas d'expérience dans ce domaine et je ne peux donc pas vous le recommander.

http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks_cwt.html

12 votes

Oui, ça n'existait pas quand j'ai demandé ça, et je ne sais toujours pas comment l'utiliser.

1 votes

Vous l'avez ajouté il y a un moment, mais ça a marché à merveille. Son utilisation est simple comme bonjour. Il suffit de passer dans le tableau, et un autre tableau (par exemple np.arange(1,10)) qui liste toutes les largeurs de pics que vous souhaitez ; avantage intéressant pour filtrer les pics minces ou larges si nécessaire. Merci encore !

6voto

David Cournapeau Points 21956

La détection des pics dans un spectre de manière fiable a fait l'objet de nombreuses études, par exemple tous les travaux sur la modélisation sinusoïdale des signaux musicaux/audio dans les années 80. Cherchez "Modélisation sinusoïdale" dans la littérature.

Si vos signaux sont aussi propres que dans l'exemple, un simple "donnez-moi quelque chose avec une amplitude supérieure à N voisins" devrait fonctionner raisonnablement bien. Si vous avez des signaux bruyants, une méthode simple mais efficace consiste à observer vos pics dans le temps, pour les suivre : vous détectez alors des lignes spectrales au lieu de pics spectraux. Autrement dit, vous calculez la FFT sur une fenêtre glissante de votre signal, pour obtenir un ensemble de spectres dans le temps (également appelé spectrogramme). Vous regardez ensuite l'évolution du pic spectral dans le temps (c'est-à-dire dans des fenêtres consécutives).

0 votes

Regarder les pics dans le temps ? Détecter des lignes spectrales ? Je ne suis pas sûr de ce que cela signifie. Cela fonctionnerait-il pour des ondes carrées ?

0 votes

Oh, vous parlez d'utiliser la STFT au lieu de la FFT. Cette question ne concerne pas spécifiquement les FFT, c'est juste un exemple. Il s'agit de trouver les pics dans n'importe quel tableau général 1D ou 2D.

2voto

nullpointer Points 112

Il existe des fonctions et des méthodes statistiques standard pour trouver les valeurs aberrantes des données, ce qui est probablement ce dont vous avez besoin dans le premier cas. L'utilisation des dérivées résoudrait le second cas. Je ne suis cependant pas sûr d'une méthode qui résout à la fois les fonctions continues et les données échantillonnées.

1voto

EOL Points 24342

Je ne pense pas que ce que vous recherchez soit fourni par SciPy. Dans cette situation, j'écrirais le code moi-même.

L'interpolation par spline et le lissage de scipy.interpolate sont très intéressants et pourraient être utiles pour ajuster les pics et ensuite trouver l'emplacement de leur maximum.

25 votes

Je m'excuse, mais je pense que cela devrait être un commentaire, et non une réponse. Il suggère simplement de l'écrire soi-même, avec une vague suggestion de fonctions qui pourraient être utiles (celles de la réponse de Paul sont beaucoup plus pertinentes, d'ailleurs).

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