У меня есть единственный размерный массив значений с плавающей точкой (c#, удваивается к вашему сведению), и я должен найти "пик" значений... как будто графическим.
Я не могу только принять самое высокое значение, поскольку пик является на самом деле плато, которое имеет маленькие колебания. Это плато посреди набора шума. Я смотрю, находят решение, которое дало бы мне центр этого плато.
Массив в качестве примера мог бы быть похожим на это:
1,2,1,1,2,1,3,2,4,4,4,5,6,8,8,8,8,7,8,7,9,7,5,4,4,3,3,2,2,1,1,1,1,1,2,1,1,1,1
где пик находится где-нибудь в полужирном разделе.
Какие-либо идеи?
Сначала вам нужно определить, что вы подразумеваете под словом «маленький». Скажем, «небольшое» отклонение от максимума определяется как любое значение, находящееся в пределах ± от максимума. Затем легко определить плато.
Пропустите данные, чтобы определить максимум, а затем выполните второй проход, чтобы определить все значения, которые находятся в пределах ± от максимума.
Очевидно, что точное решение зависит от деталей. Если ваш дистрибутив всегда хороший, как в вашем примере, вы можете иметь:
def GetPeak(l):
large = max(l) * 0.8
above_large = [i for i in xrange(len(l)) if l[i] > large]
left_peak = min(above_large)
right_peak = max(above_large)
return (left_peak, right_peak)
Обнаружение пиков - это один из этапов фазовой корреляции и других алгоритмов оценки движения, используемых в таких местах, как сжатие видео. Один из подходов таков: рассмотрите кандидата на пик и окно с определенным количеством соседей. Теперь установите квадратичную функцию, используя стандартную регрессию. Пик с субпиксельной точностью равен максимуму подобранной квадратичной.
Вы можете применить фильтр низких частот к вашему входному массиву, чтобы сгладить небольшие колебания, а затем найти пик в отфильтрованных данных. Самым простым примером, вероятно, является "коробчатый" фильтр, где выходное значение является суммой входных значений в пределах определенного расстояния от текущей позиции массива. В псевдокоде это будет выглядеть примерно так:
for i = 0, samplecount-1
if (i < boxcar_radius) or (i >= (samplecount - boxcar_radius)) then
filtered_data[i] = 0 // boxcar runs off edge of input array, don't use
else
filtered_data[i] = 0
for j = i-boxcar_radius, i+boxcar_radius
filtered_data[i] = filtered_data[i] + input_data[j]
endfor
endif
endfor
Если у вас есть представление о том, насколько широким будет "плато", вы можете выбрать радиус боксара (примерно половина ожидаемой ширины плато) для обнаружения особенностей в соответствующем масштабе.