Introducere în Python

În acest laborator vom încerca să ne familiarizăm cu limbajul de programare Python și vom folosi câteva elemente pe care le vom utiliza in cadrul laboratoarelor de procesarea semnalelor. Majoritatea tehnicilor de procesare de semnal pot fi executate ca operații pe vectori și matrici, deci Python este o unealtă foarte folositoare pentru a face aceste operații.

Laboratoarele se pot face utilizând Google Colab (care ne oferă un notebook Python în browser în care putem rula cod fără a ne mai preocupa de setup), sau Pycharm (care este un IDE dedicat pentru Python).

Vom folosi ultima versiune de Python 3.11

Google Colab

Download Pycharm - folosiți versiunea Community care este gratuită

1. Obișnuiți-vă cu mediul de lucru: spațiul de lucru (workspace), editarea scriptului, consola.

Pentru procesarea semnalelor ne vom folosi de bibliotecile scipy și numpy. Aceastea ne vor ajuta să aplicăm o mulțime de operații matematice vectoriale. Putem defini elementele pe care le folosim cel mai des, precum vectorii și matricele, folosindu-ne de aceaste biblioteci.

Va trebui să importați bibliotecile de care aveți nevoie pentru a le folosi

import numpy as np
import scipy as sp

2. Vectori

Semnalele pot fi reprezentate ca secvențe de valori, unde în Python se face, de obicei, prin vectori sau matrice. Să începem cu vectorii.

Pentru a beneficia de performanță și de operațiile matematice din $numpy$, vom încerca să folosim mereu numpy arrays.

3. Matrice

În Python, putem implementa o matrice ca o listă de liste. Putem trata fiecare element ca o linie a matricei.

Spre exemplu, X = [[1, 2], [4, 5], [3, 6]] va reprezenta o matrice de 3 pe 2 (3 linii și 2 coloane). Prima linie poate fi selectată ca X[0], iar primul element de pe prima linie poate fi selectat ca X[0][0].

În continuare ne vom folosi de numpy.array pentru a crea și a manipula matrice(2D array) sau putem folosi o clasă deprecated, numpy.matrix.

4. Transpusa

Transpusa unei matrice poate fi obținută prin aplicarea funcției transpose pe o matrice: 'numpy.transpose'.

Când folosiți vectori (adunare, înmulțire, etc.) trebuie să aveți grijă să folosiți forma potrivită (fie coloană, fie linie).

5. Alte modalități pentru a crea vectori și matrice

Creați o secvență de 10 elemente, pornind de la 5.

6. Șiruri de caractere și afișaj

Putem crea într-un mod ușor șiruri de caractere folosind s = 'Hello'.

7. Grafice

În laboratoarele care vor urma va trebui să generăm grafice cu ajutorul cărora vom vizualiza datele noastre.

Vom folosi matplotlib pentru a genera grafice așa că importați această bibliotecă

import matplotlib.pyplot as plt 

Dacă primiți eroare la afișare pe Windows, instalați Microsoft Visual C++ Redistributable

Aici este un exemplu cum ar trebui să arate: Figura 1

8. Câteva exerciții simple de procesare de semnal

Hint: folosiți 'figure', înaintea fiecărei comenzi 'plot' pentru a genera trei grafice diferite sau afișați-le pe toate în același grafic (sau în două grafice, unul pentru sinusoida inițială și altul pentru sinusoida rezultată).

Ar trebui să obțineți ceva de genul: Figura 2

9. O aplicație ușoară

În acestă arhivă data.zip aveți trei imagini, reprezentate ca matrice tridimensionale (o matrice per culoare - R, G, B). Matricile reprezintă o imagine Img_initial care a fost distorsionată prin adăugarea unui zgomot (matricele R1 și R2), prin formula: IR = Img_initial * 0.3 + R1 * 0.3 + R2 * 0.3

Task-ul vostru este să încercați să reconstruiți matricea originală a imaginii și să o afișați. Pentru asta trebuie să faceți pașii următori:

Rețineți că o matrice imagine conține numai valori de la 0 la 255.

10. Row-major

În numpy se foloseste convenția de row-major, deci este indicat să se parcurgă întâi dimensiunea cea mai din dreapta (în cazul matricelor, dimensiunea liniilor). De asemenea, mereu când este posibil, este indicat să se folosească operații vectoriale.

În mod default operatorul '*' va face înmulțire element cu element. Pentru înmulțire de matrici trebuie să folosim funcția 'numpy.dot' sau operatorul '@'.

import numpy as np
import time
 
N = 1000
A = np.random.rand(N, N)
B = np.random.rand(N, N)
C = np.zeros((N, N))
 
time1 = time.time()
for i in range(N):
    for j in range(N):
        C[i, j] = A[i, j] * B[i, j]
 
time_row = time.time() - time1
 
time2 = time.time()
for j in range(N):
    for i in range(N):
        C[i, j] = A[i, j] * B[i, j]
time_column = time.time() - time2
 
time3 = time.time()
C = A * B
time_matrix_operation = time.time() - time3
 
print(f'Timp row-major: {time_row} s')
print(f'Timp column-major: {time_column} s')
print(f'Timp matrix operation: {time_matrix_operation} s')