5.9. Aritmetičke operacije

Obitelj za crtanje iz prethodnog odjeljka boja u sliku. Aritmetička obitelj kombinira dvije slike u treću – zbrajajući njihove vrijednosti piksela, oduzimajući jednu od druge, uzimajući minimum ili maksimum na svakom položaju. Taj mali skup aritmetičkih operacija po pikselu temelj je na kojem se grade razlikovanje sličica (frame differencing), oduzimanje pozadine, slaganje ekspozicija i još nekoliko klasičnih obrazaca.

Aritmetička obitelj na klasi Image dovoljno je mala da se nabroji odjednom:

  • add()self + other po pikselu, odrezano na maksimum formata.

  • sub()self - other po pikselu, odrezano na 0 na donjem kraju.

  • rsub()other - self po pikselu, odrezano na 0 (ista aritmetika kao sub s obrnutim operandima).

  • min() – minimum dviju vrijednosti po pikselu.

  • max() – maksimum po pikselu.

  • difference()|self - other| po pikselu, apsolutna razlika.

Plus dvije srodne operacije na jednoj slici:

  • invert() – zamijeni svaki piksel s 255 - pixel (ili odgovarajućim maksimumom za format).

  • negate() – alias za invert().

Two horizontal gradient bars at the top representing source images A and B -- A going dark to bright left-to-right, B going bright to dark left-to-right. Below them, five gradient bars representing the result of each pairwise operation applied to A and B: A.add(B) appears uniform white because every position sums past 255 and clips; A.sub(B) is zero on the left half and brightens toward the right; A.difference(B) shows a V shape, bright on each end and dark in the middle; A.min(B) is dark on the ends and brighter in the middle; A.max(B) is bright on the ends and grey in the middle.

Dva izvorna gradijenta A i B te rezultat svake parne operacije primijenjene na njih. Svaka operacija izvršava se položaj po položaj – ono što se prikazuje u rezultatu na bilo kojem mjestu ovisi samo o dvama izvornim pikselima na tom mjestu.

5.9.1. Dva oblika operanda

Svaka od metoda nad dvjema slikama prihvaća bilo koji od oblika za svoj drugi operand:

  • Drugu Image istih dimenzija. Aritmetika se izvršava položaj po položaj – rezultat na (x, y) jest operacija primijenjena na izvorne piksele na (x, y) obiju slika.

  • Skalarnu vrijednost – cijeli broj za sive tonove, n-torku (r, g, b) za RGB565. Isti skalar primjenjuje se na svakom položaju.

Skalarni oblik koristan je kada aplikacija želi pomaknuti svaki piksel za konstantan iznos. img.add(40) posvjetljuje cijelu sliku za 40; img.sub((20, 20, 20)) zatamnjuje svaki piksel za 20 po kanalu; img.max(50) podiže svaki piksel ispod 50 na 50, a ostale ostavlja na miru – vrsta operacije koja gotovo crnu razinu poda senzora pretvara u ravnomjernu tamno sivu za naredne faze.

5.9.2. Odrezivanje

Vrijednosti piksela ostaju unutar raspona formata kroz svaku operaciju. Za 8-bitni kanal to znači 0255: sve što bi se prelilo preko 255 odrezuje se natrag na 255, a sve što bi otišlo ispod 0 odrezuje se natrag na 0. Nema preljevanja u krug.

Taj izbor važan je u praksi. add koji posvjetljuje piksele nikad ne stvara nagli artefakt zatamnjenja na svijetlom kraju gdje bi se matematika inače prelila; sub koji zatamnjuje piksele nikad ne stvara nagli artefakt posvjetljenja na tamnom kraju gdje bi se inače podlila. Rezultati ostaju vizualno smisleni po cijenu nešto gubitka informacija na zasićenim ekstremima.

Odrezivanje je i razlog zašto sub i rsub vraćaju različite rezultate jedan od drugoga. img_a.sub(img_b) daje onaj dio a koji je svjetliji od b i nulu svugdje drugdje; img_a.rsub(img_b) daje onaj dio b koji je svjetliji od a. Bilo koji je koristan za jednostrano otkrivanje promjena – ako aplikaciju zanimaju samo pikseli koji su postali svjetliji ili samo pikseli koji su postali tamniji – ali nijedan ne hvata svu promjenu između dviju sličica.

5.9.3. Operacija razlike

Za dvostrano otkrivanje promjena, operacija kojoj treba posegnuti jest difference(), koja izračunava |self - other| na svakom položaju – apsolutnu razliku, bez predznaka. Svaki piksel koji se promijenio u bilo kojem smjeru pojavljuje se kao vrijednost različita od nule u rezultatu, s veličinom razmjernom tome koliko se promijenio na tom položaju.

To svojstvo – vrijednost različita od nule točno ondje gdje se dvije slike razlikuju – jest ono što čini difference radnim konjem otkrivanja promjena od sličice do sličice. Referentna sličica spremljena pri pokretanju i svjež snimak, propušteni kroz difference, daju sliku čiji pikseli različiti od nule označavaju svaki položaj na kojem se nešto u sceni pomaknulo ili promijenilo svjetlinu.

5.9.4. Ograničavanje doseg pomoću maske

Sve aritmetičke metode prihvaćaju ključni argument mask uveden na stranici o područjima i maskama. Kada se proslijedi maska, operacija se izvršava samo na položajima na kojima je maska različita od nule; svugdje drugdje odredišna slika ostaje netaknuta.

Ta se kompozicija pojavljuje u dva obrasca. Prvi je ograničavanje operacije na poznato područje: na primjer zbrajanje dviju sličica samo unutar graničnog okvira otkrivenog markera. Drugi je postupno izgrađivanje složene sličice dio po dio – min preko niza sličica unutar maske prednjeg plana, max preko istog niza unutar komplementarne maske – ta vrsta obrasca.

5.9.5. Na mjestu, uz očuvanje ulaza

Sve aritmetičke metode slijede ranije uspostavljenu radnu konvenciju: svaka mijenja izvornu sliku na mjestu i vraća istu sliku za ulančavanje. Pikseli izvora nestaju nakon poziva – zamijenjeni rezultatom operacije u odnosu na ono što je proslijeđeno kao drugi operand.

Kada aplikacija treba očuvati oba ulaza, siguran obrazac jest najprije kopirati jedan od njih:

diff = current.copy()       # leaves current intact
diff.difference(reference)  # diff now holds the absolute difference

Taj obrazac – kopiraj, pa operiraj – okosnica je svakog cjevovoda za razlikovanje sličica, gdje referentna sličica mora preživjeti usporedbu kako bi se mogla ponovno upotrijebiti na sljedećoj uhvaćenoj sličici.

Sa šest operacija kombiniranja, dvije operacije na jednoj slici, radnim konjem apsolutne razlike i ključnom riječi mask za ograničavanje dosega, alat za pikselsku aritmetiku pokriva kombinacije svjetline i kanala koje klasični strojni vid treba. Preostali alati slični aritmetici rade bit po bit, a ne vrijednost po vrijednost.