6.16. Křivky a integrace

Matematické stránky pokrývaly operace, které přijímají pole a produkují pole (nebo skalár) – aritmetiku, redukce, broadcasting. Tato stránka pokrývá jinou třídu operací: takové, které berou pole jako navzorkovanou funkci a kladou otázky o funkci samotné. Interpolaci mezi vzorky, proložení křivky jimi, integraci pod nimi, jejich konvoluci s jiným bufferem.

Všechny tyto přijímají vstupy typu ndarray a vrací buď skalár typu float, nebo ndarray typu float.

6.16.1. Interpolace

interp() provádí jednorozměrnou lineární interpolaci. xp je monotónně rostoucí jednorozměrné pole nezávislých hodnot; fp jsou odpovídající závislé hodnoty; x je místo, kde se má interpolant vyhodnotit:

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])

Mimo rozsah [xp[0], xp[-1]] je výsledek oříznut na fp[0] respektive fp[-1]; klíčová slova left= a right= tyto koncové body přepisují.

Na kameře se používá k přemapování kalibrační tabulky na libovolné pozice vzorků – tabulky teplota-napětí z termistoru, nelineární křivky odezvy pixelů, gama vyhledávání po kanálech. Jedno volání knihovny, jeden průchod vstupy, žádná smyčka v Pythonu.

6.16.2. Prokládání a vyhodnocování polynomů

polyfit() proloží datové body (x, y) polynomem stupně deg metodou nejmenších čtverců a vrací koeficienty (nejvyšší stupeň první):

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)

Když je x vynecháno, použije se range(len(y)) – užitečné pro rychlé proložení polynomu pravidelně navzorkovaným bufferem bez přidružené osy x:

np.polyfit(y, 2)

polyval() vyhodnocuje polynom, jehož koeficienty jsou p, v bodě x. Vstup x může být skalár (vrací float) nebo ndarray (vrací ndarray):

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

Přirozeným spárováním je zavolat polyfit jednou v době kalibrace, uložit koeficienty a volat polyval k vyhodnocení výsledné křivky v každém snímku. Krok vyhodnocení polynomu je hrstka operací s čísly float na vzorek, což je levné i na nejmenších kamerách.

6.16.3. Konvoluce

convolve() vrací plnou diskrétní lineární konvoluci dvou jednorozměrných polí. Implementován je pouze režim full; délka výstupu je len(a) + len(v) - 1. Výsledek nařezejte pro stejný efekt jako režimy same a valid, které nabízí desktopové numpy

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])

Užitečné pro krátké FIR filtry a vyhlazovací jádra (box, trojúhelník, gauss), kde je sestavování SOS řetězce přehnané. Doba běhu je úměrná součinu délek obou polí – v pořádku u krátkých jader, ale u dlouhých se rychle stane dražší než konvoluce přes FFT.

6.16.4. Lichoběžníková integrace

trapz() integruje navzorkovanou funkci složeným lichoběžníkovým pravidlem:

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

Předejte dx=, když je rozestup vzorků rovnoměrný a záleží jen na kroku; předejte x=, když vzorky nejsou rovnoměrně rozmístěné. Správné volání pro integraci již zachycených dat ze senzoru, kde analytická forma není k dispozici.

Pro vzorková data, která byla pásmově omezena (například audio buffer po antialiasingovém filtru), konverguje lichoběžníkové pravidlo jako druhá mocnina počtu vzorků, což znamená, že zdvojnásobení délky bufferu sníží chybu čtyřnásobně.

Když integrand není buffer vzorků, ale funkce Pythonu, kterou aplikace umí vyhodnotit v libovolných bodech, je správným voláním jiná rodina řešičů.