Filtry
Spis treści
AS/ Funkcja przejścia i filtry
Cyfrowe filtry liniowe niezmiennicze w czasie [math]x[n] \longrightarrow \boxed{LTI} \longrightarrow y[n][/math] opisuje liniowe równanie różnicowe o stałych współczynnikach
- [math] \displaystyle y[n] = \sum_{k=1}^K a_k y[n-k] + \sum_{l=0}^L b_l x[n-l] [/math]
gdzie [math]a_i[/math] i [math]b_i[/math] to współczynniki, [math]x[n][/math] to sygnał wejściowy, a [math]y[n][/math] — wyjście; w ogólniejszej postaci można je zapisać jako
- [math] \displaystyle \sum_{k=0}^K a_k y[n-k] = \sum_{l=0}^L b_l x[n-l] [/math]
Funkcja przejścia (transfer function)
Stosując transformatę [math]Z[/math] możemy powyższe równanie z dziedziny czasu przenieść do dziedziny częstości:
- [math] \displaystyle \mathcal{Z}\left\{\sum_{k=0}^K a_k y[n-k] \right\} = \mathcal{Z}\left\{ \sum_{l=0}^L b_l x[n-l] \right\} [/math]
- [math] \displaystyle \sum_{k=0}^K a_k \mathcal{Z}\left\{ y[n-k]\right\} = \sum_{l=0}^L b_l \mathcal{Z} \left\{x[n-l]\right\} [/math]
- [math] \displaystyle \sum_{k=0}^K a_k z^{-k} Y(z) = \sum_{l=0}^L b_l z^{-l} X(z) [/math]
- [math] \displaystyle Y(z) \sum_{k=0}^K a_k z^{-k} = X(z) \sum_{l=0}^L b_l z^{-l} [/math]
Dla systemu przyczynowego dostajemy:
- [math] \displaystyle \frac{Y(z)}{X(z)} \equiv H(z) = \frac{\sum_{l=0}^L b_l z^{-l}}{\sum_{k=0}^K a_k z^{-k}} [/math]
Filtry
Funkcja przejścia [math]H(z)[/math] pozwala spójnie przedstawić działanie filtra LTI na sygnał [math]x[/math] w przestrzeni transformaty [math]\mathcal{Z}[/math]:
- [math] \displaystyle Y(z)=H(z)X(z)=\frac{b_0 + b_1 z^{-1}+\dots +b_{L} z^{-L}}{a_0+a_1 z^{-1}+\dots +a_{K} z^{-K}}X[z] [/math]
gdzie [math]X(z)[/math] to transformata [math]\mathcal{Z}[/math] filtrowanego sygnału (wejścia), [math]Y(z)[/math] — wyjścia, a [math]H(z)[/math] to wprowadzona powyżej funkcja przejścia filtra. Filtrowanie w przestrzeni transformaty Z odpowiada przemnożeniu transformaty sygnału przez transformatę funkcji przejścia filtru. Zobaczmy, co się stanie z widmem sygnału po przefiltrowaniu.
Weźmy w tym celu [math]z = e^{i\omega}[/math]. Wówczas transmitancja jest funkcją częstości [math]\omega[/math]. Konkretnej częstości [math]\omega_k[/math] przypisuje ona liczbę zespoloną, którą można wyrazić jako [math]A_k e^{i \phi_k}[/math].
- [math] \displaystyle Y[e^{i\omega}]=H[e^{i\omega}]X[e^{i\omega}]=\frac{b_0+b_1 e^{-i\omega}+\dots +b_L e^{-i L\omega}}{a_0+a_1 e^{-i\omega}+\dots +a_K e^{-i K\omega}}X[e^{i\omega}] [/math]
W dziedzinie częstości sygnał wyrażony jest przez współczynniki Fourierowskie. Dla konkretnej częstości współczynnik taki [math]X_k = |X_k| e^{i \theta_k}[/math] (liczba zespolona) mówi z jaką amplitudą i jaką fazą exponens zespolony o danej częstości ([math]z_k = e^{i\omega_k}[/math]) wchodzi w skład sygnału.
Działanie filtru na sygnał w dziedzinie częstości polega na przemnożeniu składowej sygnału o częstości [math]f_k[/math] przez liczbę [math]A_k e^{i \phi_k}[/math]:
- [math]Y(f_k) = A_k e^{i \phi_k} |X_k| e^{i \theta_k} = A_k |X_k| e^{i ( \phi_k +\theta_k)} e^{i 2\pi f_k} [/math]
W wyniku filtrowania sinusoidalna składowa sygnału o danej częstości może zmienić amplitudę i fazę, ale nie zmienia częstości. Zera i bieguny filtra to odpowiednio miejsca zerowe licznika i mianownika funkcji przenoszenia.
Finite Impulse Response (FIR) — filtr o skończonej odpowiedzi impulsowej
Jeśli w równaniu
- [math] \displaystyle \sum_{k=0}^K a_k y[n-k] = \sum_{l=0}^L b_l x[n-l] [/math]
położymy [math]a_i = 0[/math] poza [math]a_0=1[/math], dostaniemy
- [math] \displaystyle y[n] = \sum_{l=0}^L b_l x[n-l] [/math]
W funkcji przejścia mianownik będzie stały i dostaniemy
[math] \displaystyle Y[z]=H[z]X[z]=\left(b_0+b_1 z^{-1}+\dots +b_L z^{-L}\right) X[z] [/math]
a w dziedzienie czasu, z pełnego równania
- [math] \displaystyle y[n] = b_0 x[n]+ b_1 x[n-1] + \dots + b_L x[n-L] \,\,\, - \,\,\, a_1 y[n-1] - \dots - a_K y[n-K] [/math]
pozostaje
- [math] \displaystyle y(n) = b_0 *x[n] + b_1 *x[n-1] + \dots + b_L *x[n-L] [/math]
Jeśli współczynniki [math]b_i[/math] zapiszemy jako sekwencję [math]b[i][/math], działanie takiego filtra LTI na sygnał [math]x[n][/math] w dziedzinie czasu będze wyglądała tak:
- [math] \displaystyle y(n) = b[0]*x[n] + b[1]*x[n-1] + \dots + b[L]*x[n-L] = b[n]*x[n] [/math]
Taki filtr nazywamy filtrem o skończonej odpowiedzi impulsowej (Finite Impulse Response, FIR), bo odpowiedź na impuls kończy się po [math]L[/math] próbkach. Inna nazwa to średnia biegnąca (Moving Average, MA).
Infinite Impulse Response (IIR) — filtr o nieskończonej odpowiedzi impulsowej
Jeśli w równaniu
- [math] \displaystyle \sum_{k=0}^K a_k y[n-k] = \sum_{l=0}^L b_l x[n-l] [/math]
położymy [math]b_i = 0[/math] poza [math]b_0=1[/math], dostaniemy
- [math] \displaystyle \sum_{k=0}^K a_k y[n-k] = x[n] [/math]
w funkcji przejścia licznik będzie stały
- [math] \displaystyle Y[z]=H[z]X[z]=\frac{1}{a_0+a_1 z^{-1}+\dots +a_{K} z^{-K}}X[z] [/math]
Operacja splotu działa tu na sekwencji wyjściowej:
- [math] y[n] = x[n] - a[1]*y[n-1] - \dots - a[n_a]*y[n-K] [/math]
Taki filtr ten nazwać można filtrem rekursywnym lub autoregresyjnym (AR).
W praktyce filtry IIR są zwykle implementowane jako połączenie członów AR i MA, czyli:
- [math] \begin{array}{ll} y[n] = b[0]*x[n] &+ b[1]*x[n-1] + \dots + b[L]*x[n-L]\\ &- a[1]*y[n-1] - \dots - a[K]*y[n-K] \end{array} [/math]
Tę wersję filtru nazywamy filtrem o nieskończonej odpowiedzi impulsowej (Infinite Impulse Response IIR) bo potencjalnie raz wzbudzony może dowolnie długo produkować niezerowe wyjście. Faza filtrowanego sygnału zaburzana jest nieliniowo (nonlinear phase filter)
Liniowe i nieliniowe przesunięcie fazy
Jeśli współczynniki filtra FIR tworzą sekwencję symetryczną bądź antysymetryczną, oparty na nich filtr o skończonej odpowiedzi impulsowej będzie liniowo przesuwał fazę filtrowanego sygnału (linear phase filter) — cały sygnał skutkiem filtrowania jest przesunięty w czasie o ok. połowę długości filtra FIR.
Rzędem filtru nazywamy maksymalne opóźnienie w próbkach potrzebne do wytworzenia nowej próbki wyjściowej. Dla filtrów FIR jest on równy liczbie [math]L[/math]. Dla filtrów IIR jest to większa z liczb [math]L, K[/math].
kod (uproszczony) |
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(0.0, 3, 0.01)
s1 = np.sin(2 * np.pi * t)
s2= np.sin(2 * np.pi * t + np.pi/2)
s3= np.sin(2*2 * np.pi * t)
s4= np.sin(2*2 * np.pi * t + np.pi/2)
s5= np.sin(2*2 * np.pi * t + 2*np.pi/2)
fig1, ax1 = plt.subplots(3, 1)
ax1[0].plot(t, s1)
ax1[1].plot(t, s3)
ax1[2].plot(t, s1+s3, 'r')
ax1[0].set_title('sin(wt)')
ax1[1].set_title('sin(2wt)')
ax1[2].set_title('sin(wt) + sin(2wt)')
fig2, ax2 = plt.subplots(3, 1)
ax2[0].plot(t, s2)
ax2[1].plot(t, s4)
ax2[2].plot(t, s2+s4, 'r')
ax2[0].set_title('sin(wt+pi/2)')
ax2[1].set_title('sin(2wt+pi/2)')
ax2[2].set_title('sin(wt+pi/2) + sin(2wt+pi/2)')
fig3, ax3 = plt.subplots(3, 1)
ax3[0].plot(t, s2)
ax3[1].plot(t, s5)
ax3[2].plot(t, s2+s5, 'r')
ax3[0].set_title('sin(w(t+pi/2))')
ax3[1].set_title('sin(2wt+2*pi/2)')
ax3[2].set_title('sin(wt+pi/2) + sin(2wt+2*pi/2)')
plt.show()
|
kod generujący obrazki |
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(0.0, 3, 0.01)
s1 = np.sin(2 * np.pi * t)
s2 = np.sin(2 * np.pi * t + np.pi / 2)
s3 = np.sin(2 * 2 * np.pi * t)
s4 = np.sin(2 * 2 * np.pi * t + np.pi / 2)
s5 = np.sin(2 * 2 * np.pi * t + 2 * np.pi / 2)
def fix_axes():
for i in range(0, 3):
ax[i].set_yticks([0], [])
ax[i].set_xlim([0, 3])
ax[i].grid(True)
ax[i].set_frame_on(False)
ax[i].tick_params(length=0)
ax[i].set_ylim(-2, 2)
fig1, ax = plt.subplots(3, 1, dpi=200)
ax[0].plot(t, s1)
ax[1].plot(t, s3)
ax[2].plot(t, s1 + s3, 'r')
ax[0].set_title('sin( $\omega$t )', loc='left')
ax[1].set_title('sin( 2*$\omega$t )', loc='left')
ax[2].set_title('sin( $\omega$t ) + sin( 2*$\omega$t )', loc='left')
fix_axes()
for i in range(0, 3):
ax[i].set_xticks(np.arange(.25, 3, 1), [])
plt.show()
fig2, ax = plt.subplots(3, 1, dpi=200)
ax[0].plot(t, s2)
ax[1].plot(t, s4)
ax[2].plot(t, s2 + s4, 'r')
ax[0].set_title('sin( $\omega$t + $\pi$/2 )', loc='left')
ax[1].set_title('sin( 2*$\omega$t + $\pi/2$ )', loc='left')
ax[2].set_title('sin( $\omega$t + $\pi$/2 ) + sin( 2*$\omega$t + $\pi$/2 )', loc='left')
fix_axes()
for i in range(0, 3):
ax[i].set_xticks(np.arange(0, 3, 1), [])
plt.show()
fig3, ax = plt.subplots(3, 1, dpi=200)
ax[0].plot(t, s2)
ax[1].plot(t, s5)
ax[2].plot(t, s2 + s5, 'r')
ax[0].set_title('sin( $\omega$(t + $\pi$/2) )', loc='left')
ax[1].set_title('sin( 2*$\omega$t + 2*$\pi$/2 )', loc='left')
ax[2].set_title('sin( $\omega$t + $\pi$/2 ) + sin( 2*$\omega$t + 2*$\pi$/2 )', loc='left')
fix_axes()
for i in range(0, 3):
ax[i].set_xticks(np.arange(0, 3, 1), [])
plt.show()
|