6.1. Zašto polja¶
Klasa Image pravi je alat za rad s pikselima jer svaka njezina metoda djeluje izravno na izvornom međuspremniku piksela kamere u jednom brzom pozivu. Većina onoga što aplikacija radi sa sličicom – određivanje praga, traženje mrlja, detekcija AprilTaga, filtri rubova – već se nalazi ondje.
Ono što biblioteka slika ne izlaže jest ostatak numeričkog posla na koji OpenMV aplikacija nailazi:
međuspremnici senzora koji nisu pikseli – ADC uzorci, osi iz IMU-a (inercijalne mjerne jedinice), audio mikrofona,
izvedeni brojevi iz slike koje nijedna ugrađena metoda ne vraća – stupac histograma, prilagođena mješavina dviju sličica, transformacija po pikselu koju katalog ne pokriva,
malena linearna algebra – kalibracijska matrica koja ispravlja leću, rotacija koja stapa IMU,
matematika obrade signala – frekvencijski sadržaj međuspremnika vibracija, izglađivanje primijenjeno na izlaz senzora, vektor značajki koji klasifikator želi kao ulaz.
Sve ovo želi isti oblik: međuspremnik brojeva s jednom operacijom primijenjenom na svaki element. Python for petlja očiti je način da se to napiše:
for i in range(len(samples)):
samples[i] = samples[i] * cal
Petlja radi. Također je spora. Python je interpretirani jezik, a svaka iteracija Python petlje nosi trošak jednokratnog pokretanja interpretera: traženje samples, čitanje elementa i, množenje, zapisivanje natrag, pomicanje brojača petlje, provjera uvjeta petlje. Na međuspremniku od tisuću uzoraka senzora ti troškovi interpretera zbroje se na desetke milisekundi za ono što je u biti brza operacija.
Taj trošak ugriza svaki put kad skripta dosegne međuspremnik. QVGA sličica u sivim tonovima ima 76.800 piksela; akcelerometar na 100 Hz isporučuje stotinu troosnih uzoraka u sekundi; mikrofon puni međuspremnik od 1024 uzorka svakih 64 ms. Čista Python for petlja nad bilo kojim od njih pretvara posao koji bi trebao trajati nekoliko mikrosekundi u onaj koji traje desetke milisekundi – i otprilike deset puta dulje nad međuspremnikom veličine slike.
6.1.1. Funkcije biblioteke brže su od petlji¶
Rješenje je izraziti operaciju kao jedan poziv funkcije nad cijelim međuspremnikom, umjesto Python petlje nad njegovim elementima. numpy je upravo to: biblioteka matematike polja gdje je svaka operacija jedna već optimizirana funkcija koja prolazi međuspremnik jednom od početka do kraja. np.multiply(samples, cal) množi svaki element samples s cal unutar jednog poziva – istu aritmetiku koju je petlja radila, bez troška interpretera po iteraciji. Isto množenje od 1000 elemenata koje je kao Python petlja trajalo desetke milisekundi kao numpy poziv traje desetke mikrosekundi.
Ovo je dogovor koji numpy nudi posvuda: zbroj, srednja vrijednost, sinus, eksponent, množenje matrica, primitivi obrade signala – svaki je jedna funkcija biblioteke koja djeluje na cijelom međuspremniku odjednom. Cijena je u tome što podaci moraju živjeti u numpyjevom tipu polja, a operacija mora biti izražena nad tim poljem, a ne nad njegovim elementima jednim po jednim.
6.1.2. Zašto lista neće poslužiti¶
Python list ne može zamijeniti. Lista može držati bilo koju mješavinu objekata – cijele brojeve, brojeve s pomičnim zarezom, nizove, druge liste – a funkcija biblioteke koja je čita i dalje mora pogledati svaki utor da otkrije što je u njemu i izvuče vrijednost prije nego što se dogodi ikakva aritmetika. Taj trošak po utoru upravo je cijena koju plaća Python petlja. Liste su pogrešan izbor za brzu matematiku polja.
6.1.3. Zašto ni bytearray nije dovoljan¶
bytearray je pravi oblik – jedan tipizirani međuspremnik, jedan bajt po elementu, sve u jednom neprekinutom bloku. To je ono što većina periferijskih API-ja orijentiranih na bajtove vraća. Ono što mu nedostaje jest matematika. bytearray * 2 ponavlja međuspremnik umjesto da udvostruči svaku vrijednost, a nema razumnog značenja za bytearray + bytearray element po element.
Struktura podataka koja kombinira tipizirani međuspremnik s matematikom po elementima jest ndarray. Što je unutar kutije i kako svako polje oblikuje ponašanje brzog puta temelji su na kojima počiva ostatak ovog poglavlja.