web-dev-qa-db-fra.com

Algorithme de recherche de crête pour Python/SciPy

Je peux écrire quelque chose moi-même en trouvant des passages par zéro de la première dérivée, mais cela semble être une fonction assez commune pour être incluse dans des bibliothèques standard. Quelqu'un en sait un?

Mon application particulière est un tableau 2D, mais il serait généralement utilisé pour rechercher 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 qu'il convient d'ignorer. Ce ne sont que des exemples; pas mes données réelles:

Pics unidimensionnels:

 FFT output with peaks

Pics bidimensionnels:

Radon transform output with circled peak

L'algorithme de recherche de crête trouverait l'emplacement de ces pics (pas seulement leurs valeurs) et, idéalement, rechercherait le vrai pic inter-échantillon, pas seulement l'indice avec la valeur maximale, probablement à l'aide de interpolation quadratique ou de quelque chose.

En règle générale, vous ne vous préoccupez que de quelques pics forts. Ils sont donc choisis soit parce qu’ils dépassent un certain seuil, soit parce qu’ils sont les premiers n d'une liste ordonnée, classés par amplitude.

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

Mettre à jour:

J'ai traduit un script MATLAB et cela fonctionne décemment pour le cas 1D, mais pourrait être meilleur.

Mise à jour:

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

106
endolith

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

L’interpolation et le lissage des splines de scipy.interpolate sont assez agréables et pourraient être très utiles pour ajuster les pics et ensuite trouver l’emplacement de leur maximum.

8
Eric O Lebigot

Je suis en train de regarder un problème similaire, et j'ai trouvé que certaines des meilleures références venaient de la chimie (de la recherche de pics dans les données de masse). Pour un bon examen approfondi des algorithmes de recherche de pics, lisez ceci . 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 type dans les données bruitées.).

Il semble que vos pics soient clairement définis et ne soient pas cachés dans le bruit. Ceci étant le cas, je vous recommanderais d’utiliser des dérivées lisses de Savtizky-Golay pour trouver les pics (si vous ne faites que différencier les données ci-dessus, vous aurez un fouillis de faux positifs). C'est une technique très efficace et assez facile à mettre en œuvre (vous avez besoin d'une classe de matrice avec les opérations de base). Si vous trouvez simplement le passage par zéro du premier dérivé de S-G, je pense que vous serez heureux.

42
Paul

Dans scipy, il existe une fonction nommée scipy.signal.find_peaks_cwt qui semble correspondre à vos besoins, mais je n’ai pas d’expérience avec elle et je ne peux donc pas vous le recommander.

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

18
Hanan Shteingart

Pour ceux qui ne savent pas exactement quels algorithmes de recherche de pics utiliser en Python, voici un aperçu rapide des alternatives: https://github.com/MonsieurV/py-findpeaks

Voulant me procurer un équivalent de la fonction MatLab findpeaks, j'ai constaté que la fonction detect_peaks de Marcos Duarte est un bon choix.

Assez facile à utiliser:

import numpy as np
from vector import vector, plot_peaks
from libs import detect_peaks
print('Detect peaks with minimum height and distance filters.')
indexes = detect_peaks.detect_peaks(vector, mph=7, mpd=2)
print('Peaks are: %s' % (indexes))

Ce qui vous donnera:

 detect_peaks results

14
Yoan Tournade

La fonction scipy.signal.find_peaks , comme son nom l'indique, est utile pour cela. Mais il est important de bien comprendre ses paramètres width, threshold, distanceet surtout prominence pour obtenir un bon pic d'extraction.

Selon mes tests et la documentation, le concept de proéminence est "le concept utile" pour conserver les bons sommets et rejeter les sommets bruyants.

Quelle est la proéminence (topographique) ? C'est "la hauteur minimale nécessaire pour descendre du sommet à un terrain plus élevé", comme on peut le voir ici:

 enter image description here

L'idée est:

Plus la notoriété est élevée, plus le sommet est "important".

Tester:

 enter image description here

J'ai utilisé exprès une sinusoïde (bruyante) à fréquence variable, car elle présente de nombreuses difficultés. Nous pouvons voir que le paramètre width n'est pas très utile ici, car si vous définissez une valeur minimale width trop élevée, il ne pourra pas suivre les pics très proches dans la partie haute fréquence. Si vous définissez width trop bas, vous aurez plusieurs pics indésirables dans la partie gauche du signal. Même problème avec distance. threshold se compare uniquement aux voisins directs, ce qui n’est pas utile ici. prominence est celui qui donne la meilleure solution. Notez que vous pouvez combiner plusieurs de ces paramètres!

Code:

import numpy as np
import matplotlib.pyplot as plt 
from scipy.signal import find_peaks, find_peaks_cwt

x = np.sin(2*np.pi*(2**np.linspace(2,10,1000))*np.arange(1000)/48000) + np.random.normal(0, 1, 1000) * 0.15
peaks, _ = find_peaks(x, distance=20)
peaks2, _ = find_peaks(x, prominence=1)      # BEST!
peaks3, _ = find_peaks(x, width=20)
peaks4, _ = find_peaks(x, threshold=0.4)     # Required vertical distance to its direct neighbouring samples, pretty useless
plt.subplot(2, 2, 1)
plt.plot(peaks, x[peaks], "xr"); plt.plot(x); plt.legend(['distance'])
plt.subplot(2, 2, 2)
plt.plot(peaks2, x[peaks2], "ob"); plt.plot(x); plt.legend(['prominence'])
plt.subplot(2, 2, 3)
plt.plot(peaks3, x[peaks3], "vg"); plt.plot(x); plt.legend(['width'])
plt.subplot(2, 2, 4)
plt.plot(peaks4, x[peaks4], "xk"); plt.plot(x); plt.legend(['threshold'])
plt.show()
11
Basj

La détection des pics dans un spectre de manière fiable a été assez étudiée, par exemple tous les travaux sur la modélisation sinusoïdale pour les signaux de musique/audio dans les années 80. Recherchez "Modélisation sinusoïdale" dans la littérature.

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

6
David Cournapeau

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

1
nullpointer

Tout d’abord, la définition de «pic» est vague si elle n’est pas précisée. Par exemple, pour les séries suivantes, appelez-vous les 5-4-5, un pic ou deux?

1-2-1-1-1-1-5-4-5-1-1-5-1

Dans ce cas, vous aurez besoin d'au moins deux seuils: 1) un seuil haut uniquement au-dessus duquel une valeur extrême peut être enregistrée comme une crête; et 2) un seuil bas de sorte que les valeurs extrêmes séparées par de petites valeurs situées au-dessous deviendront deux pics.

La détection des pics est un sujet bien étudié dans la littérature sur la théorie des valeurs extrêmes, également connu sous le nom de "décomposition des valeurs extrêmes". Ses applications typiques incluent l'identification des événements dangereux sur la base de lectures continues de variables environnementales, par exemple. analyser la vitesse du vent pour détecter les tempêtes.

0
Ian Liu