Вопрос

Я могу написать что-нибудь сам, найдя пересечение нуля первой производной или что-то в этом роде, но это кажется достаточно распространенной функцией, чтобы ее можно было включить в стандартные библиотеки.Кто-нибудь знает об одном?

Мое конкретное приложение представляет собой двумерный массив, но обычно его используют для поиска пиков в БПФ и т. д.

В частности, в задачах такого рода имеется несколько сильных пиков, а затем множество более мелких «пиков», вызванных просто шумом, который следует игнорировать.Это всего лишь примеры;не мои фактические данные:

1-мерные пики:

FFT output with peaks

2-мерные пики:

Radon transform output with circled peak

Алгоритм поиска пиков должен найти местоположение этих пиков (а не только их значения) и в идеале найти истинный межвыборочный пик, а не только индекс с максимальным значением, возможно, используя квадратичная интерполяция или что-то.

Обычно вас интересуют только несколько сильных пиков, поэтому их следует выбирать либо потому, что они превышают определенный порог, либо потому, что они являются первыми. н пики упорядоченного списка, ранжированные по амплитуде.

Как я уже сказал, я сам знаю, как написать нечто подобное.Я просто спрашиваю, есть ли уже существующая функция или пакет, которые хорошо работают.

Обновлять:

я перевел сценарий MATLAB и для одномерного случая это работает прилично, но могло быть и лучше.

Обновленное обновление:

Шестенбе создал лучшую версию для 1-D случая.

Это было полезно?

Решение

Я не думаю, что то, что вы ищете, предоставлено SciPy.В такой ситуации я бы написал код сам.

Сплайн-интерполяция и сглаживание из scipy.interpolate довольно хороши и могут быть весьма полезны для подбора пиков и последующего определения местоположения их максимума.

Другие советы

Я рассматриваю аналогичную проблему и обнаружил, что некоторые из лучших ссылок взяты из химии (из обнаружения пиков в данных массовых характеристик).Хороший подробный обзор алгоритмов поиска пиков читайте этот.Это один из лучших и понятных обзоров методов поиска пиков, с которыми мне приходилось сталкиваться.(Вейвлеты лучше всего подходят для поиска пиков такого типа в зашумленных данных.).

Похоже, ваши пики четко определены и не скрыты в шуме.В этом случае я бы рекомендовал использовать гладкие производные Савтицкого-Голея для поиска пиков (если вы просто дифференцируете приведенные выше данные, вы получите массу ложных срабатываний).Это очень эффективный метод, и его довольно легко реализовать (вам нужен матричный класс с базовыми операциями).Если вы просто найдете пересечение нуля первой производной SG, я думаю, вы будете счастливы.

Функция scipy.signal.find_peaks, как следует из названия, полезен для этого.Но важно хорошо понимать его параметры width, threshold, distance и превыше всего prominence чтобы получить хорошую пиковую экстракцию.

Согласно моим тестам и документации, концепция известность это «полезная концепция», позволяющая сохранять хорошие пики и отбрасывать шумные пики.

Что (топографическая) известность?Это «минимальная высота, необходимая для спуска, чтобы добраться с вершины на любую возвышенность», как это можно увидеть здесь:

enter image description here

Идея заключается в следующем:

Чем выше известность, тем «важнее» пик.

Тест:

enter image description here

Я намеренно использовал (шумную) изменяющуюся по частоте синусоиду, поскольку она вызывает множество трудностей.Мы видим, что width параметр здесь не очень полезен, потому что если вы установите минимум width слишком высок, то он не сможет отслеживать очень близкие пики в высокочастотной части.Если вы установите width слишком низкий уровень приведет к появлению множества нежелательных пиков в левой части сигнала.Та же проблема с distance. threshold сравнивается только с непосредственными соседями, что здесь бесполезно. prominence тот, который дает лучшее решение.Обратите внимание, что вы можете комбинировать многие из этих параметров!

Код:

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

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()

В scipy есть функция с именем scipy.signal.find_peaks_cwt Кажется, это подходит для ваших нужд, однако у меня нет опыта работы с ним, поэтому я не могу рекомендовать..

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

Для тех, кто не уверен, какие алгоритмы поиска пиков использовать в Python, вот краткий обзор альтернатив: https://github.com/MonsieurV/py-findpeaks

Хочу себе эквивалент MatLab findpeaks функция, я обнаружил, что функция обнаружения_пиков от Маркоса Дуарте – хороший улов.

Довольно прост в использовании:

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))

Что даст вам:

detect_peaks results

Надежное обнаружение пиков в спектре было достаточно изучено, например, все работы по синусоидальному моделированию музыкальных/аудио сигналов в 80-х годах.Поищите в литературе «Синусоидальное моделирование».

Если ваши сигналы такие же чистые, как в примере, простая фраза «дайте мне что-нибудь с амплитудой выше, чем у N соседей» должна работать достаточно хорошо.Если у вас есть зашумленные сигналы, простой, но эффективный способ — вовремя посмотреть на ваши пики и отследить их:затем вы обнаруживаете спектральные линии вместо спектральных пиков.IOW, вы вычисляете БПФ в скользящем окне вашего сигнала, чтобы получить набор спектра во времени (также называемый спектрограммой).Затем вы смотрите на эволюцию спектрального пика во времени (т.е.в последовательных окнах).

Существуют стандартные статистические функции и методы для поиска выбросов в данных, что, вероятно, и есть то, что вам нужно в первом случае.Использование деривативов решит вашу вторую проблему.Однако я не уверен в методе, который решает как непрерывные функции, так и выборочные данные.

Прежде всего, определение «пика» является расплывчатым, если не учитывать дополнительные уточнения.Например, для следующей серии вы бы назвали 5-4-5 одну вершину или две?

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

В этом случае вам понадобятся как минимум два порога:1) высокий порог, только выше которого экстремальное значение может регистрироваться как пик;и 2) низкий порог, при котором крайние значения, разделенные небольшими значениями ниже него, станут двумя пиками.

Обнаружение пиков — хорошо изученная тема в литературе по теории экстремальных значений, также известная как «декластеризация экстремальных значений».Его типичные применения включают идентификацию опасных событий на основе непрерывных измерений переменных окружающей среды, например.анализ скорости ветра для обнаружения штормовых явлений.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top