Stosowanie filtra w scipy.signal: Używać lfilter czy filtfilt?

21

Widziałem w wątku SO sugestię użycia, filtfiltktóra zamiast tego wykonuje filtrowanie wstecz / do przodu lfilter.

Jaka jest motywacja do zastosowania jednej z innymi technikami?

Bar
źródło
Filtrowanie jest wolniejsze
Aaron
możliwy duplikat Jaka jest zaleta filtru MATLAB
Matt L.
1
@Aaron filtfiltwykonuje ten sam filtr dwa razy, w przeciwnych kierunkach, więc nie jest to wolniejsze niż lfilterdwukrotne wykonywanie w jednym kierunku, w ten sposób uzyskałbyś tę samą odpowiedź częstotliwościową.
endolith
Tak, to wszystko, co miałem na myśli. Jest dwa razy wolniejszy.
Aaron,
Jestem w tym nowy i rozglądałem się, by użyć filtfilt. @endolith powiedział, że scipy.signal używa oryginalnego sygnału. Nie jestem pewien, co oznacza oryginalny sygnał i jak go otrzymujemy. Mam plik wav, który ładuję do mojego systemu, ale nie sądzę, że jest to oryginalny sygnał, ponieważ jest on podzielony na tablicę liczb i liczbę próbek. Proszę, jeśli ktoś może pomóc. Dziękuję Ci!
Arunima Pathania

Odpowiedzi:

30
  • filtfiltto filtrowanie fazy zerowej, które nie przesuwa sygnału podczas filtrowania. Ponieważ faza jest zerowa na wszystkich częstotliwościach, jest również fazą liniową. Filtrowanie wstecz w czasie wymaga przewidywania przyszłości, więc nie można go stosować w rzeczywistych aplikacjach „online”, tylko do przetwarzania nagrań sygnałów offline.

  • lfilterto tylko przyczynowe filtrowanie z wyprzedzeniem, podobne do prawdziwego filtra elektronicznego. To nie może być faza zerowa. Może być fazą liniową (symetryczna FIR), ale zwykle nie jest. Zwykle dodaje różne wielkości opóźnienia przy różnych częstotliwościach.

Przykład i obraz powinny uczynić to oczywistym. Chociaż wielkość odpowiedzi częstotliwościowej filtrów jest identyczna (lewy górny i prawy górny), dolnoprzepustowy zero-fazowy pokrywa się z oryginalnym sygnałem, tylko bez zawartości wysokiej częstotliwości, podczas gdy minimalne filtrowanie fazowe opóźnia sygnał w sposób przyczynowy :

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")
endolit
źródło
4
lfilterniekoniecznie jest to faza minimalna, może być czymkolwiek zależnym od współczynników filtra, ale w każdym razie jest to przyczynowość , co filtfiltnie jest. Zatem wynik porównania, który filtfiltma zerowe opóźnienie i lfilterzawsze dodaje pewne opóźnienie, nie jest do końca prawdziwy, ponieważ filtfiltw pierwszym rzędzie nie ma związku przyczynowego. Liczy się to, że filtfiltnie powoduje żadnych zniekształceń fazowych, podczas lfiltergdy (chyba, że ​​jest stosowany jako filtr FIR fazy liniowej, tj. Z mianownikiem = 1).
Matt L.
Warto również zauważyć, że filtrowanie N-tego rzędu filtfiltodpowiada filtrowaniu za pomocą (2N-1) rzędu lfilter.
Thomas Arildsen
@ThomasArildsen Czy to nie tylko 2N? Właśnie to pokazałem w skrypcie
endolith
@ArunimaPathania Powinieneś komentować pod moją odpowiedzią, a nie pod pytaniem. „Oryginalny sygnał” oznacza po prostu sygnał, który filtrujesz. Możesz filtrować za pomocą lfilterlub filtfilt. Zachowują się inaczej, jak pokazano
endolith
7

Odpowiedź @endolith jest kompletna i poprawna! Przeczytaj najpierw jego post, a następnie ten oprócz niego. Z powodu mojej niskiej reputacji nie byłem w stanie odpowiedzieć na komentarze, w których @Thomas Arildsen i @endolith spierają się o efektywną kolejność filtrów uzyskaną przez filtfilt:

  • lfilter stosuje dany filtr, aw przestrzeni Fouriera jest to jak RAZ zastosowanie funkcji transferu filtra.

  • filtfiltzastosuj dwukrotnie ten sam filtr, a efekt jest podobny do zastosowania funkcji przenoszenia filtra SQUARED. W przypadku filtra Butterworth ( scipy.signal.butter) z funkcją przesyłania

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

efektywny zysk będzie

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

2n2n1

G(n)filtfiltG(2n).
drgrujic
źródło
1
Staraj się nie dodawać komentarzy jako odpowiedzi. Witamy jednak w SE.DSP i otrzymaj ode mnie +1. Myślę, że to dodaje do odpowiedzi ... przynajmniej postaraj się uzyskać wystarczającą liczbę przedstawicieli, aby skomentować! :-)
Peter K.
Nie sądzę, że to prawda. G (n) to wzmocnienie amplitudy filtra. Jeśli kaskadujesz złożoną funkcję transferu, myślę, że zadziała to do 2n.
Mike
Potwierdziłem za pomocą szybkiej symulacji, że Butterworth 6. rzędu daje ten sam G (ω) co 2 x (Butterworth 3. rzędu) kaskadowo, ale z częstotliwością odcięcia 3. rzędu skalowaną o 1,6. Wyniki są identyczne, z wyjątkiem skalowania częstotliwości odcięcia. Tak więc kolejność skaluje się z 2n, ale należy pamiętać, że pasmo przepustowe zmniejszy się podczas kaskady i wymaga kompensacji. Ktoś może wyjaśnić teorię, ale tak naprawdę nie chcę przejść przez całą matematykę.
Mike