Определение начала наступления полезного сигнала по модальным частотам
У меня есть сигнал, например такой:
Я разбиваю сигнал на отрезки по 1 секунде. В каждом отрезке я раскладываю сигнал в ряд Фурье и определяю модальную (т. е. имеющую наибольшую амплитуду) частоту. У меня получается набор отрезков и модальные частоты на этих отрезках. Например, вот так:
Видно, что, когда наступает полезный сигнал(поезд, электричка и т.д.) доминируют низкие частоты 5-6 Гц. Во всё остальное время доминируют высокие частоты шума. Мне нужно в автоматическом режиме определять начала и концы наступлений полезного сигнала. Как мне это сделать? Есть идея со скользящим окном, но не могу понять, что какой конкретно критерий начала и конца участков с полезным сигналом. Подскажите, пожалуйста, алгоритм по которому это можно сделать.
Ответы (2 шт):
Если ваш первый график относится к реальному сигналу, то стоит использовать мощность сигнала (интеграл или сумма signal^2 по интервалу), а частоты использовать как подтверждение достоверности.
Если будете опираться на частоты, постройте спектрограмму - набор амплитуд Фурье-преобразований для последовательных (или перекрывающихся) интервалов, и оцените отношение мощности каждого спектра в нужном интервале частот (скажем, 5-15 гц) к общей мощности (нулевой, и, наверное, первый отсчет непременно удаляйте из подсчёта). Где это отношение выше порога (заависит от ваших конкретных данных) - преобладают низкие частоты.
Заметьте, что мода не очень для вашей задачи подходит.
Ну вот вам пример. Размер окна и величину отсечения нужно подбирать. Чем больше окно, тем оно лучше сглаживает выбросы, но тем больше и запаздывание обнаружения. Ну и отсечение тоже нужно подбирать из таких же примерно соображений.
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
data = np.array([50]*40+[5]*15+[50]*30+[5]*10+[50]*40)
data += np.random.randint(2, size=(len(data)))
data[45] = 30
data[50] = 40
data[90] = 25
series = pd.Series(data)
roll = series.rolling(3).mean()
found = roll < 20
result = (found != found.shift(-1))[:-1]
startstop = result[result].index
plt.figure()
plt.bar(range(len(data)), data)
plt.scatter(startstop, data[startstop], color='red', marker='*')
plt.savefig('data.png')
plt.figure()
roll.plot()
plt.scatter(startstop, roll[startstop], color='red', marker='*')
plt.savefig('dataroll.png')
for a, b in zip(startstop[::2], startstop[1::2]):
print(f'{a}:{b}')
# 41:54
# 86:94