SciPy medfil неверный результат

Привет любителям питона!

В настоящее время я работаю с фильтрацией сигналов в исследовательских целях и решил использовать SciPy. Ничего особенного, просто автоматизация рутинной работы.

Итак, вот код

from scipy.signal import medfilt
print(medfilt([2,6,5,4,0,3,5,7,9,2,0,1], 5))

Но дело в том, что возвращаемая последовательность вычисляется неправильно

SciPy: [ 2. 4. 4. 4. 4. 4. 5. 5. 5. 2. 1. 0.]
Me   : [ 5. 4.5 4. 4. 4. 4. 5. 5. 5. 2. 1.5 1.]

Похоже, разработчики пакета напутали одну деталь. Когда апертура (ядро в терминах SciPy) больше, чем окно для анализа, существует другое правило фильтрации.

Например, с kernel=5 отфильтрованная подпоследовательность [2, 6, 5] имеет медиану 5, а не 2, как вычислил SciPy, не так ли? И точно так же, если kernel=5 для подпоследовательности [2,6,5,4] медианы равны 5 и 4, нам нужно взять среднее между ними, поэтому медиана равна 4,5.

Может кто-нибудь объяснить мне, кто получил правильный результат в этом случае?


person im_infamous    schedule 05.07.2014    source источник


Ответы (1)


Я считаю, что и у вас, и у SciPy есть правильные результаты. Разница в том, что происходит на границах, но я считаю, что и вы, и SciPy сделали правильный выбор.

Вопрос заключается в том, что должно произойти, когда ваше скользящее окно находится на краях, и нет достоверных данных, которые можно использовать для заполнения вашего скользящего окна.

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

Вместо этого SciPy предпочла расширить сигнал на любом краю, дополнив его нулями. Итак, на границах SciPy, по сути, вычисляет

>>> np.median([0, 0, 2, 6, 5])
2.0
>>> np.median([0, 2, 6, 5, 4])
4.0
>>> np.median([9, 2, 0, 1, 0])
1.0
>>> np.median([2, 0, 1, 0, 0])
0.0

Причина, по которой SciPy делает это, почти наверняка связана со скоростью: он оптимизирован для многократного повторения одного и того же, и гораздо проще оптимизировать median для целой группы 5-элементных массивов, чем для целого. кучу 5-элементных массивов, а также два 4-элементных массива и два 3-элементных массива. Определенно можно привести аргумент в пользу того, что он должен дополняться не нулями, а граничными значениями, но следует отметить, что ни одна граничная стратегия не будет идеальной; идеальный способ решения проблем с границами будет зависеть от вашего конкретного сигнала.

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

  • Избегайте обработки границ с последующей обрезкой границы сигнала или без нее.
  • Получение записей из других мест в сигнале. Например, для изображений могут быть выбраны записи от дальней горизонтальной или вертикальной границы.
  • Уменьшение окна рядом с границами, чтобы каждое окно было заполнено (как вы сделали).

В конце концов, вам действительно нужно попробовать разные варианты и посмотреть, что лучше всего подходит для вашего сигнала. Основное предположение такого рода фильтрации заключается в том, что ваш сигнал будет довольно большим, и проблема с границей никогда не должна быть такой критической (поскольку большая часть сигнала не существует на границе). Было бы неплохо, если бы SciPy позволял вам выбирать, что он должен делать на границах!

person tbekolay    schedule 05.07.2014
comment
Просто чтобы немного расширить этот ответ, те, кто ищет альтернативные функции скользящей медианы, могут изучить: скользящую медиану Pandas: pandas.pydata.org/pandas-docs/stable/ и scipy.ndimage: docs.scipy.org/doc/scipy-0.15.1/reference/generated/ - person ConnectedSystems; 20.07.2015