This shows you the differences between two versions of the page.
ps:labs_python:09 [2023/12/12 12:00] ionut.gorgos |
ps:labs_python:09 [2023/12/13 09:00] (current) ionut.gorgos |
||
---|---|---|---|
Line 1: | Line 1: | ||
===== Laboratorul 09. ===== | ===== Laboratorul 09. ===== | ||
- | <hidden> | ||
==== Convoluția, filtre FIR și metoda de proiectare folosind ferestre ==== | ==== Convoluția, filtre FIR și metoda de proiectare folosind ferestre ==== | ||
- | Prezentarea PowerPoint pentru acest laborator poate fi găsită aici: [[https://docs.google.com/presentation/d/16NWgSnRxFygNBcrHc7IvEfMR_MzZxyu7/edit?usp=sharing&ouid=110538702824281541719&rtpof=true&sd=true|aici]] | ||
În acest laborator vom face câteva exerciții pentru a ne familiariza cu operația de convoluție precum și cu filtre cu răspunsul finit la impuls (finite impulse response - FIR) și cu metode de proiectare a acestora prin metode folosind ferestre. | În acest laborator vom face câteva exerciții pentru a ne familiariza cu operația de convoluție precum și cu filtre cu răspunsul finit la impuls (finite impulse response - FIR) și cu metode de proiectare a acestora prin metode folosind ferestre. | ||
Line 20: | Line 18: | ||
În general presupunem că secvența h(k) are un număr $M$ finit și, în general, mic de elemente. | În general presupunem că secvența h(k) are un număr $M$ finit și, în general, mic de elemente. | ||
- | /*<hidden>*/ In our context, these elements will usually be the //taps// of a filter, and the convolution operation will be used to filter an input sequence x(n), as we shall see in the following exercises. /*</hidden>*/ | ||
Rezolvați următoarele exerciții: | Rezolvați următoarele exerciții: | ||
Line 28: | Line 25: | ||
- Înlocuiți x(n) cu secvența de impuls cu 9 elemente [0, 0, 0, 0, 1, 0, 0, 0, 0] și efectuați convoluția cu aceeași secvență h(k) ca mai sus. Ce obțineți ca y(n)? Cum se numește aceasta? | - Înlocuiți x(n) cu secvența de impuls cu 9 elemente [0, 0, 0, 0, 1, 0, 0, 0, 0] și efectuați convoluția cu aceeași secvență h(k) ca mai sus. Ce obțineți ca y(n)? Cum se numește aceasta? | ||
- Încercați operațiile de mai sus folosind funcția //np.convolve// din NumPy sau //signal.convolve// din //scipy.signal//. Obțineți aceleași rezultate? Care sunt diferențele? | - Încercați operațiile de mai sus folosind funcția //np.convolve// din NumPy sau //signal.convolve// din //scipy.signal//. Obțineți aceleași rezultate? Care sunt diferențele? | ||
+ | - [<color red>BONUS</color>] Teorema Convoluției. Convoluția în timp [ $h(k) \ast x(n)$ ] este echivalentă cu înmulțirea element cu element a spectrelor în frecvență [ $H(m) \cdot X(m)$ ] și invers. Pentru a testa asta faceți următorii pași: | ||
+ | * Folosiți secvența h(k) = [0.1, 0.2, 0.2, 0.2, 0.1], dar adăugați încă 59 de zerouri la finalul ei, precum am făcut în laboratoarele precedente. | ||
+ | * Aplicați FFT peste această secvență și afișați spectrul ei (cu stem). | ||
+ | * Aplicați FFT peste sinusoida de la subpunctul 3 și afișați spectrul ei (cu stem). | ||
+ | * Înmulțiți element cu element cele două spectre și afișați rezultatul cu stem. S-a modificat ceva? | ||
+ | * Reveniți în domeniul timp folosind //ifft// și //np.real//. | ||
+ | * Comparați rezultatul de mai sus cu cel al funcției //np.convolve// din NumPy sau //signal.convolve//, setând parametrul //mode='full'// și păstrând doar primele N elemente. Obțineți aceleași rezultate? Care sunt diferențele? | ||
<note tip> | <note tip> | ||
Line 46: | Line 50: | ||
- Trunchiați secvența hk(n) prin selectarea a doar //L=65// de eșantioane din centru(32 din stânga maximului funcției sinc, maximul funcției, și 32 de eșantioane din dreapta). Aceasta corespunde multiplicării secvenței hk(n) cu o fereastră dreptunghiulară centrată în punctul maxim al funcției sinc. Plotați secvența. | - Trunchiați secvența hk(n) prin selectarea a doar //L=65// de eșantioane din centru(32 din stânga maximului funcției sinc, maximul funcției, și 32 de eșantioane din dreapta). Aceasta corespunde multiplicării secvenței hk(n) cu o fereastră dreptunghiulară centrată în punctul maxim al funcției sinc. Plotați secvența. | ||
- Aplicați DFT(//fft//) pe secvența trunchiată, adică cea înmulțită cu fereastra dreptunghiulară (care conține doar 1) și plotați spectrul (cu //plot//). Rețineți: este important aici, precum și la primul plot pentru filtru trece-jos ideal, să notăm axa frecvențelor (axa x) ca o funcție de $F_s$, adică de la //0// la //1//. Vedeți diferențe față de filtrul ideal trece-jos? Acestea sunt efectele ferestrei dreptunghiulare. | - Aplicați DFT(//fft//) pe secvența trunchiată, adică cea înmulțită cu fereastra dreptunghiulară (care conține doar 1) și plotați spectrul (cu //plot//). Rețineți: este important aici, precum și la primul plot pentru filtru trece-jos ideal, să notăm axa frecvențelor (axa x) ca o funcție de $F_s$, adică de la //0// la //1//. Vedeți diferențe față de filtrul ideal trece-jos? Acestea sunt efectele ferestrei dreptunghiulare. | ||
- | - Folosiți aceeași secvență trunchiată (hk(n)), dar înmulțiți-o cu o fereastră precum //Blackman// (//blackman// în Python). Efectuați din nou DFT și plotați spectrul (cu //plot//). Arată mai bine?. | + | - Folosiți aceeași secvență trunchiată (hk(n)), dar înmulțiți-o cu o fereastră precum //Blackman// (//np.blackman// în Python). Efectuați din nou DFT și plotați spectrul (cu //plot//). Arată mai bine?. |
- În final, folosiți ca intrare sinusoida din Exercițiul 1 ca x(n) și filtrați-o printr-o convoluție cu secvența obținută mai sus după folosirea ferestrei Blackman(folosiți funcția //np.convolve// din NumPy sau //signal.convolve// din //scipy.signal//). Plotați intrarea și ieșirea în aceeași figură folosind //stem// pentru a observa efectele filtrului. | - În final, folosiți ca intrare sinusoida din Exercițiul 1 ca x(n) și filtrați-o printr-o convoluție cu secvența obținută mai sus după folosirea ferestrei Blackman(folosiți funcția //np.convolve// din NumPy sau //signal.convolve// din //scipy.signal//). Plotați intrarea și ieșirea în aceeași figură folosind //stem// pentru a observa efectele filtrului. | ||
Line 52: | Line 56: | ||
[<color red>2p</color>] | [<color red>2p</color>] | ||
- | Putem descrie un filtru (sistem liniar) cu feedback(IIR având termenii $a_i$ mai jos) sau fără feedback (FIR) folosind o ecuație cu diferențe precum: | + | Putem descrie un filtru (sistem liniar) cu feedback (IIR având termenii $a_i$ mai jos) sau fără feedback (FIR) folosind o ecuație cu diferențe precum: |
$y(n) = b_0 \cdot x(n) + b_1 \cdot x(n-1) + \ldots + b_q \cdot x(n-q) + a_1 \cdot y(n-1) + \ldots + a_p \cdot y(n-p)$ | $y(n) = b_0 \cdot x(n) + b_1 \cdot x(n-1) + \ldots + b_q \cdot x(n-q) + a_1 \cdot y(n-1) + \ldots + a_p \cdot y(n-p)$ | ||
Putem reprezenta întârzierile $x(n-1)$ ca $z^{-1} \cdot x(n)$, unde $z=e^{j2\pi}$. | Putem reprezenta întârzierile $x(n-1)$ ca $z^{-1} \cdot x(n)$, unde $z=e^{j2\pi}$. | ||
Apoi, obținem o ecuație care depinde doar de $x(n)$ și $y(n)$ și obținem funcția de transfer a filtrului $H(z) = \frac{Y(z)}{X(z)}$ precum: | Apoi, obținem o ecuație care depinde doar de $x(n)$ și $y(n)$ și obținem funcția de transfer a filtrului $H(z) = \frac{Y(z)}{X(z)}$ precum: | ||
+ | |||
$H(z) = \frac{\sum_{k=0}^q b_k \cdot z^{-k}}{1 - \sum_{k=1}^p a_k \cdot z^{-k}}$ | $H(z) = \frac{\sum_{k=0}^q b_k \cdot z^{-k}}{1 - \sum_{k=1}^p a_k \cdot z^{-k}}$ | ||
- | În Python, puteți folosi funcția //fir1// pentru a obține rapid elementele $b_i$ ale unui filtru FIR trece-jos, trece-bandă sau trece-sus(ignorați coeficienții $a_i$ deocamdată). Apoi puteți folosi funcția //filter// pentru a filtra orice secvență folosind coeficienții $b_i$ dați de //fir1//, iar $a_0=1$. | + | În Python, puteți folosi funcția //signal.firwin// din SciPy, pentru a obține coeficienții ($b_i$) ai unui filtru FIR trece-jos, trece-bandă sau trece-sus(ignorați coeficienții $a_i$ deocamdată). Apoi puteți folosi funcția //signal.lfilter// din SciPy, pentru a filtra orice secvență folosind coeficienții $b_i$ dați de //signal.firwin//, iar $a_0 = 1$. |
+ | |||
+ | Pentru acest exercițiu, trebuie să proiectați filtre FIR trece-jos (folosiți cutoff = 0.1), trece-bandă (folosiți cutoff = [0.2, 0.5]) și trece-sus (folosiți cutoff = 0.75). Puteți alege //numtaps = 65//. Apoi folosiți funcția //signal.lfilter// pentru a testa filtrele cu niște sinusoide ca în Exercițiul 1, cu $f=3$ kHz, $15$ kHz, $30$ kHz. Afișați cu stem, în subplot-uri sinusoidele inițiale și pe cele filtrate. | ||
+ | Pentru răspunsul în frecvență, vă puteți folosi de următorul cod: | ||
- | Pentru acest exercițiu, folosiți funcția //fir1// pentru a proiecta filtre FIR trece-jos, trece-bandă și trece-sus. Apoi folosiți funcția //filter// pentru a testa filtrele cu niște sinusoide ca în Exercițiul 1, cu $f=3$ kHz, $15$ kHz, $30$ kHz . Puteți verifica designul filtrelor folosind //freqz//. | ||
- | <code python>freqz(b,1);</code> | ||
- | /*<hidden>*/ | ||
- | <note warning>Pentru a putea folosi funcțiile //fir1// și //freqz// trebuie să instalați pachetul signal din Octave. | ||
<code python> | <code python> | ||
- | pkg install -forge -nodeps signal | + | freq, H = signal.freqz(b_low, 1, fs=fs) |
+ | plt.figure() | ||
+ | plt.plot(freq, 20 * np.log10(abs(H))) | ||
+ | plt.xlabel('Frequency [Hz], from 0 to fs/2') | ||
+ | plt.ylabel('Amplitude [dB]') | ||
+ | plt.title('Digital Filter Frequency Response') | ||
+ | plt.grid() | ||
+ | plt.show() | ||
</code> | </code> | ||
- | , iar apoi să-l încărcați: | + | , unde b_low sunt coeficienții $b_i$ ai unui filtru FIR trece-jos. |
- | <code python> | + | |
- | pkg load signal | + | |
- | </code> | + | |
- | </note> | + | |
- | /*</hidden>*/ | + | |
- | Pentru răspunsul la impuls puteți folosi: | + | === Exercițiul 4 -- Proiectarea rapidă de filtre FIR/IIR folosind MATLAB === |
- | <code python>stem(b);</code> | + | [<color red>BONUS</color>] |
- | Ar trebui să vedeți sinc-ul digital. | + | |
- | Pentru răspunsul în frecvență, vă puteți folosi de următorul cod: | + | În acest exercițiu, încercăm să urmăm pașii de la exercițiul 3, dar în **MATLAB**. Pentru a accesa MATLAB, puteți folosi MATLAB instalat pe PC-urile din laborator sau să folosiți **MATLAB Online**, din browser. Pentru MATLAB Online, trebuie să vă creați un cont cu adresa de e-mail de la facultate pe site-ul [[https://www.mathworks.com/mwaccount/register|acesta]]. |
- | <code python> | + | În MATLAB, puteți folosi funcția //fir1// pentru a obține rapid elementele $b_i$ ale unui filtru FIR trece-jos, trece-bandă sau trece-sus. Apoi puteți folosi funcția //filter// pentru a filtra orice secvență folosind coeficienții $b_i$ dați de //fir1//, iar $a_0 = 1$. |
- | [H, freq] = freqz(b,1,N, fs); | + | |
- | figure; | + | Pentru acest exercițiu, folosiți funcția //fir1// pentru a proiecta filtre FIR trece-jos, trece-bandă și trece-sus. Apoi folosiți funcția //filter// pentru a testa filtrele cu aceleași secvențe ca în exercițiul precedent. Puteți verifica designul filtrelor folosind tool-ul //fvtool//. |
- | plot(freq, abs(H)); | + | |
- | xlabel('Frequency (Hz)'); | + | |
- | ylabel('Frequency response'); | + | |
- | </code> | + | |
- | </hidden> | + | De asemenea puteți folosi tool-ul MATLAB //fdatool// pentru a proiecta și analiza rapid performanțele filtrelor FIR și IIR: |
+ | - Generați un filtru FIR trece-jos folosind o fereastră Kaiser, având Fs = 48000 Hz, Fc = 10000 Hz, cu N=10 coeficienți(ordin) | ||
+ | - Generați un filtru IIR trece-jos (Butterworth sau Chebyshev type I) cu aceiași parametri. | ||
+ | - Comparați amplitudinea răspunsului. | ||
+ | - Încercați să creați un filtru FIR cu un răspuns similar cu al unui filtru IIR, prin creșterea numărului de coeficienți. | ||
+ | |||
+ | După proiectarea filtrelor precum ați dorit, le puteți salva (File->Generate MATLAB Code) și să le folosiți direct în alte scripturi MATLAB pentru a filtra diverse semnale. | ||