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().

Dvije vodoravne gradijentne trake na vrhu koje predstavljaju izvorne slike A i B -- A ide od tamnog prema svijetlom slijeva nadesno, B ide od svijetlog prema tamnom slijeva nadesno. Ispod njih, pet gradijentnih traka koje predstavljaju rezultat svake parne operacije primijenjene na A i B: A.add(B) izgleda jednoliko bijelo jer svaki položaj zbroji preko 255 i odreže se; A.sub(B) je nula na lijevoj polovici i posvjetljuje prema desnoj; A.difference(B) prikazuje oblik slova V, svijetao na svakom kraju i taman u sredini; A.min(B) je taman na krajevima i svjetliji u sredini; A.max(B) je svijetao na krajevima i siv u sredini.

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.