Подсчитайте волны на графике, используя Python - PullRequest
2 голосов
/ 04 августа 2020

Я только что создал график, который выглядит как показано ниже; Я пытаюсь подсчитать, сколько полных волн на этом графике. Согласно аннотации, должно быть 7 полных волн. Я пытался сгладить график, но ничего не вышло. Я также исследовал find_peaks в scipy, но это не похоже на то, что применимо к этой ситуации, поскольку одна волна может иметь несколько пиков.

enter image description here

EDIT:

This question comes from a problem in reality: figuring out the number of shelves in the picture (see below):

enter image description here

After thresholding, I get the data file below:

Original: file-1

Среднее значение по строкам: файл-2

Результат файла-2 на графике, показанном в начале.

1 Ответ

1 голос
/ 04 августа 2020

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

Первый вариант - использовать scipy.signal.find_peaks. Зная свои данные здесь, вы можете использовать некоторые параметры: по моему опыту, рост, расстояние и известность являются наиболее полезными. Есть красивое объяснение о параметрах find_peaks. Это позволит правильно определить пики в большинстве случаев, но требует времени для соответствующей установки аргументов.

Аналогичное решение с scipy.signal.find_peaks_cwt, здесь (в большинстве случаев) вам нужно будет отрегулировать параметр ширины, который (из документации):

1-мерный массив ширины, используемый для вычисления матрицы CWT. В общем, этот диапазон должен охватывать ожидаемую ширину интересующих пиков.

Но опять же, это требует некоторых предварительных знаний о ваших данных.

Поскольку у вас есть периодi c данные , может быть, вы можете использовать БПФ, чтобы найти характеристики c частот, чтобы настроить параметры внутри find_peaks и find_peaks_cwt. Поскольку вы не предоставили набор данных, у меня есть только синтетические c данные. Обратите внимание, что я возвращаю len(peaks) - 1, потому что обычно на границах учитывается дополнительный период.

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

# some generic data
x = np.linspace(0, 1000, 10000)
y = 250 + 100 * np.sin(0.08 * x) - np.random.normal(30, 20, 10000)

def count_waves_1(x, y):
    peaks, props = find_peaks(y, prominence=120, height= np.max(y) / 10, distance=200)
    # here you can make use of props to filter the peaks by different properties,
    # for example extract only the n largest prominence peak:
    #
    # ind = np.argpartition(props["prominences"], -n_largest)[-n_largest:]
    # peaks = peaks[ind]

    plt.plot(x, y)
    plt.plot(x[peaks], y[peaks], 'ro')
    return len(peaks) - 1

first_solution = count_waves_1(x, y)


def count_waves_2(x, y):
    peaks = find_peaks_cwt(y, widths=np.arange(100, 200))
    plt.plot(x, y)
    plt.plot(x[peaks], y[peaks], 'ro')
    return len(peaks) - 1

second_solution = count_waves_2(x, y)

print(first_solution, second_solution)

...