6.16. Curbe și integrare

Paginile de matematică au acoperit operații care iau un tablou la intrare și produc un tablou (sau scalar) la ieșire – aritmetică, reduceri, difuzare. Această pagină acoperă o clasă diferită de operații: cele care tratează tabloul ca pe o funcție eșantionată și pun întrebări despre funcția însăși. Interpolarea între eșantioane, ajustarea unei curbe la ele, integrarea sub ele, convoluția lor cu un alt tampon (buffer).

Toate acestea acceptă intrări ndarray și returnează fie un scalar float, fie un ndarray de tip float.

6.16.1. Interpolare

interp() realizează interpolare liniară unidimensională. xp este un tablou 1-D monoton crescător de valori independente; fp sunt valorile dependente corespunzătoare; x este locul unde trebuie evaluat interpolantul:

xp = np.array([0.0, 1.0, 2.0, 3.0])
fp = np.array([10.0, 20.0, 25.0, 30.0])
x  = np.array([0.5, 1.5, 2.5])

np.interp(x, xp, fp)
# array([15.0, 22.5, 27.5])

În afara intervalului [xp[0], xp[-1]], rezultatul este limitat la fp[0] și, respectiv, fp[-1]; cuvintele-cheie left= și right= suprascriu acele capete.

Folosită pe cameră pentru a remapa un tabel de calibrare la poziții de eșantion arbitrare – un tabel temperatură-tensiune de la un termistor, o curbă de răspuns neliniară a pixelilor, o căutare gamma per canal. Un singur apel de bibliotecă, o singură trecere peste intrări, fără buclă Python.

6.16.2. Ajustare și evaluare polinomială

polyfit() ajustează un polinom de grad deg la punctele de date (x, y) prin metoda celor mai mici pătrate și returnează coeficienții (gradul cel mai mare primul):

x = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
y = np.array([0.0, 1.1, 3.9, 9.1, 15.8])

coeffs = np.polyfit(x, y, 2)
# array([1.0, 0.0, 0.0])  (approximately)

Atunci când x este omis, se folosește range(len(y)) – util pentru ajustarea rapidă a unui polinom la un tampon eșantionat regulat, fără o axă x asociată:

np.polyfit(y, 2)

polyval() evaluează polinomul ai cărui coeficienți sunt p la x. Intrarea x poate fi un scalar (returnează un float) sau un ndarray (returnează un ndarray):

p = np.polyfit(x, y, 2)
fitted = np.polyval(p, x)

Împerecherea naturală este să apelezi polyfit o singură dată la momentul calibrării, să stochezi coeficienții și să apelezi polyval pentru a evalua curba rezultată la fiecare cadru. Pasul de evaluare polinomială este un mic număr de operații float per eșantion, ceea ce este ieftin chiar și pe cele mai mici camere.

6.16.3. Convoluție

convolve() returnează convoluția liniară discretă de lungime completă a două tablouri 1-D. Doar modul full este implementat; lungimea ieșirii este len(a) + len(v) - 1. Feliază rezultatul pentru același efect ca modurile same și valid pe care le oferă numpy pentru desktop:

a = np.array([1.0, 2.0, 3.0])
v = np.array([0.5, 0.5])

np.convolve(a, v)
# array([0.5, 1.5, 2.5, 1.5])

Util pentru filtre FIR scurte și nuclee de netezire (box, triunghi, gaussian) unde configurarea unui lanț SOS este excesivă. Timpul de rulare este proporțional cu produsul lungimilor celor două tablouri – bine pentru nuclee scurte, dar devine rapid mai costisitor decât o convoluție FFT pentru cele lungi.

6.16.4. Integrare trapezoidală

trapz() integrează o funcție eșantionată prin regula trapezoidală compusă:

x = np.linspace(0, np.pi, num=128)
y = np.sin(x)
np.trapz(y, x)             # ~ 2.0

Transmite dx= atunci când spațierea eșantioanelor este uniformă și contează doar pasul; transmite x= atunci când eșantioanele nu sunt distanțate uniform. Apelul potrivit pentru integrarea datelor de senzor deja capturate, unde forma analitică nu este disponibilă.

Pentru date de eșantion care au fost limitate în bandă (un tampon audio după un filtru anti-aliasing, de exemplu), regula trapezoidală converge ca pătratul numărului de eșantioane, ceea ce înseamnă că dublarea lungimii tamponului reduce eroarea de patru ori.

Atunci când integrandul nu este un tampon de eșantioane, ci o funcție Python pe care aplicația o poate evalua în puncte arbitrare, o familie diferită de rezolvatoare este apelul potrivit.