Застосування фільтра в scipy.signal: Використовувати lfilter або filtfilt?


21

Я побачив у потоці SO пропозицію використовувати, filtfiltяка виконує фільтрацію назад / вперед замість lfilter.

Яка мотивація використання однієї техніки проти іншої?


Фільтфільт повільніше
Аарон


1
@Aaron filtfiltробить один і той же фільтр двічі в протилежних напрямках, тому це не повільніше, ніж робити lfilterдва рази в одному напрямку, саме так ви отримаєте однакову частотну характеристику.
ендоліт

Так, це все, що я мав на увазі. Це вдвічі повільніше.
Аарон

Я новачок у цьому і роздивлявся, щоб використати фільтфільт. @endolith сказав, що scipy.signal використовує вихідний сигнал. Я не впевнений, що означає оригінальний сигнал і як ми його отримуємо. У мене є wav-файл, який я завантажую у свою систему, але не думаю, що це оригінальний сигнал, оскільки він розбивається на нутризований масив та кількість зразків. Будь ласка, якщо хтось міг допомогти. Дякую!
Arunima Pathania

Відповіді:


30
  • filtfilt- це нульова фаза фільтрації, яка не зміщує сигнал під час фільтрації. Оскільки фаза дорівнює нулю на всіх частотах, вона також є лінійно-фазовою. Фільтрування назад у часі вимагає передбачити майбутнє, тому його не можна використовувати в «онлайн» додатках реального життя, лише для офлайн обробки записів сигналів.

  • lfilterє причинно-наслідковим фільтруванням у прямому часі, подібно до реального електронного фільтра. Це не може бути нульовою фазою. Це може бути лінійно-фазовий (симетричний FIR), але зазвичай це не так. Зазвичай він додає різну кількість затримки на різних частотах.

Приклад і зображення повинні зробити це очевидним. Незважаючи на те, що величина частотного відгуку фільтрів однакова (верхній лівий і верхній правий), нульова фаза низької частоти вирівнюється з вихідним сигналом просто без вмісту високої частоти, тоді як мінімальна фазова фільтрація затримує сигнал причинно-наслідково :

filtfilt vs lfilter

from __future__ import division, print_function
import numpy as np
from numpy.random import randn
from numpy.fft import rfft
from scipy import signal
import matplotlib.pyplot as plt

b, a = signal.butter(4, 0.03, analog=False)

# Show that frequency response is the same
impulse = np.zeros(1000)
impulse[500] = 1

# Applies filter forward and backward in time
imp_ff = signal.filtfilt(b, a, impulse)

# Applies filter forward in time twice (for same frequency response)
imp_lf = signal.lfilter(b, a, signal.lfilter(b, a, impulse))

plt.subplot(2, 2, 1)
plt.semilogx(20*np.log10(np.abs(rfft(imp_lf))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('lfilter')

plt.subplot(2, 2, 2)
plt.semilogx(20*np.log10(np.abs(rfft(imp_ff))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('filtfilt')

sig = np.cumsum(randn(800))  # Brownian noise
sig_ff = signal.filtfilt(b, a, sig)
sig_lf = signal.lfilter(b, a, signal.lfilter(b, a, sig))
plt.subplot(2, 1, 2)
plt.plot(sig, color='silver', label='Original')
plt.plot(sig_ff, color='#3465a4', label='filtfilt')
plt.plot(sig_lf, color='#cc0000', label='lfilter')
plt.grid(True, which='both')
plt.legend(loc="best")

4
lfilterце не обов'язково мінімально-фазовий, він може бути будь-яким, залежно від коефіцієнтів фільтра, але в будь-якому випадку це причинно-наслідковий характер , а filtfiltце не так. Тож результат порівняння, який filtfiltмає нульову затримку і lfilterзавжди додає деяку затримку, не зовсім відповідає дійсності, оскільки filtfiltце в першу чергу безпричинний. Що насправді має значення, це те, filtfiltщо не викликає жодних фазових спотворень, тоді як є lfilter(якщо тільки він не використовується як лінійний фазовий фільтр FIR, тобто з знаменником = 1).
Метт Л.

Варто також зазначити, що фільтрація N-го порядку з filtfiltвідповідає фільтруванню з (2N-1) -го порядку з lfilter.
Томас Арільдсен

@ThomasArildsen Це не просто 2N? Це я продемонстрував у сценарії
ендоліт

@ArunimaPathania Ви повинні коментувати мою відповідь, а не під питанням. "Оригінальний сигнал" означає лише сигнал, який ви фільтруєте. Ви можете фільтрувати за допомогою lfilterабо filtfilt. Вони поводяться по-різному, як показано
ендоліт

7

Відповідь @endolith є повною і правильною! Будь ласка, прочитайте спочатку його допис, а потім цей додаток до нього. Через низьку репутацію я не зміг відповісти на коментарі, де @Thomas Arildsen та @endolith сперечаються щодо ефективного порядку фільтра, отриманого filtfilt:

  • lfilter застосовується заданий фільтр, і в просторі Фур'є це подібно застосуванню функції передачі фільтра ONCE.

  • filtfiltзастосувати один і той же фільтр двічі, і ефект подібний застосуванню функції передачі фільтра ВИСЛОВО. У разі фільтра Баттерворта ( scipy.signal.butter) з функцією передачі

G(n)=11ω2nwhere n is order of filter

ефективний виграш буде

G(n)filtfilt=G(n)2=11ω2n

2n2n1

G(n)filtfiltG(2n).

1
Спробуйте не додавати коментарі як відповіді. Однак, ласкаво просимо до SE.DSP і отримай +1 від мене. Я думаю, що це додає відповіді ... принаймні, намагайся отримати достатню кількість представників для коментарів! :-)
Пітер К.

Я не думаю, що це правда. G (n) - коефіцієнт посилення амплітуди фільтра. Якщо ви каскадуєте складну функцію передачі, я думаю, вона вийде до 2n.
Майк

Я швидко підтвердив, що Баттерворт 6-го порядку дає той же G (ω), що і 2 х (Баттерворт 3-го порядку), але з частотою відсічення 3-го порядку, масштабованою на 1,6. Результати однакові, за винятком масштабування частоти обрізання. Отже, порядок масштабується з 2n, але зауважте, що пропускна здатність зменшиться при каскаді і потребує компенсації. Хтось сміливо пояснює теорію, але я не дуже хочу пройти всю математику.
Майк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.