5.9. Aritmetikai műveletek¶
Az előző szakaszban tárgyalt rajzolási család bele fest egy képbe. Az aritmetikai család két képet egy harmadikba egyesít – összeadja a képpontértékeiket, kivonja egyiket a másikból, minden pozíción a minimumot vagy a maximumot veszi. A képpontonkénti aritmetikai műveletek e kis halmazára épül a képkocka-különbségképzés, a háttérkivonás, az expozíció-rétegzés és néhány további klasszikus minta.
Az aritmetikai család az Image osztályon elég kicsi ahhoz, hogy egyszerre felsoroljuk:
add()– képpontonkéntiself + other, a formátum maximumára csonkítva.sub()– képpontonkéntiself - other, alul0értékre csonkítva.rsub()– képpontonkéntiother - self,0értékre csonkítva (ugyanaz az aritmetika, mint asub, csak az operandusok felcserélve).min()– a két érték képpontonkénti minimuma.max()– képpontonkénti maximum.difference()– képpontonkénti|self - other|, az abszolút különbség.
Plusz két kapcsolódó egyképes művelet:
invert()– minden képpont lecserélése255 - pixelértékre (vagy a formátumnak megfelelő maximumra).
Két forrásgradiens, A és B, valamint az egyes páronkénti műveletek rájuk alkalmazott eredménye. Minden művelet pozícióról pozícióra fut – ami az eredményben bármely helyen megjelenik, az kizárólag az adott helyen lévő két forrásképponttól függ.¶
5.9.1. Két operandusforma¶
A két képet kezelő metódusok mindegyike a második operandusához az alábbi formák bármelyikét elfogadja:
Egy másik, azonos méretű
Image. Az aritmetika pozícióról pozícióra fut – az eredmény az(x, y)pozíción a mindkét kép(x, y)pozícióján lévő forrásképpontokra alkalmazott művelet.Egy skaláris érték – egész szám szürkeárnyalatos esetén,
(r, g, b)tuple RGB565 esetén. Ugyanaz a skalár alkalmazódik minden pozíción.
A skaláris forma akkor hasznos, ha az alkalmazás minden képpontot egy állandó értékkel akar eltolni. Az img.add(40) az egész képet 40-nel világosítja; az img.sub((20, 20, 20)) minden képpontot 20-szal sötétít csatornánként; az img.max(50) minden 50 alatti képpontot 50-re emel, a többit pedig békén hagyja – ez az a fajta művelet, amely a közel feketének mutatkozó érzékelőalapot lapos sötétszürkévé alakítja, hogy a következő szakaszok dolgozhassanak vele.
5.9.2. Csonkolás¶
A képpontértékek minden műveletben a formátum tartományán belül maradnak. Egy 8 bites csatornánál ez 0 – 255 jelent: bármi, ami 255 fölé csordult volna túl, vissza lesz csonkítva 255 értékre, és bármi, ami 0 alá ment volna, fel lesz csonkítva 0 értékre. Nincs átfordulás.
Ez a választás a gyakorlatban számít. Az add által világosított képpontok soha nem hoznak létre hirtelen sötétedési műterméket a világos végen, ahol egyébként a matematika túlcsordulna; a sub által sötétített képpontok soha nem hoznak létre hirtelen világosodási műterméket a sötét végen, ahol egyébként alulcsordulna. Az eredmények vizuálisan értelmesek maradnak némi információveszteség árán a telített szélsőértékeknél.
A csonkolás miatt is adnak vissza a sub és az rsub egymástól eltérő eredményt. Az img_a.sub(img_b) az a azon részét adja, amely világosabb, mint a b, és nullát mindenhol máshol; az img_a.rsub(img_b) a b azon részét adja, amely világosabb, mint az a. Mindkettő hasznos egyoldalú változásészleléshez – ha az alkalmazás csak a világosodott képpontokkal törődik, vagy csak a sötétedett képpontokkal –, de egyik sem ragadja meg a két képkocka közötti összes változást.
5.9.3. A különbségművelet¶
A kétoldalú változásészleléshez a használandó művelet a difference(), amely minden pozíción a |self - other| értéket számítja – az abszolút, előjel nélküli különbséget. Minden olyan képpont, amely bármelyik irányban megváltozott, nem nulla értékként jelenik meg az eredményben, az adott pozíción a változás mértékével arányos nagysággal.
Ez a tulajdonság – pontosan ott nem nulla, ahol a két kép eltér – teszi a difference műveletet a képkockáról képkockára történő változásészlelés igavonójává. Egy indításkor eltárolt referencia-képkocka és egy friss felvétel, a difference műveleten átfuttatva, olyan képet eredményez, amelynek nem nulla képpontjai minden olyan pozíciót megjelölnek, ahol a jelenetben valami megmozdult vagy megváltozott a fényessége.
5.9.4. Hatókörözés maszkkal¶
Az összes aritmetikai metódus elfogadja a régiók és maszkok oldalon bevezetett mask kulcsszavas argumentumot. Ha maszkot adunk át, a művelet csak azokon a pozíciókon fut, ahol a maszk nem nulla; mindenhol máshol a célkép érintetlen marad.
Ez az összeállítás két mintában jelenik meg. Az első egy művelet korlátozása egy ismert területre: például két képkocka összeadása csak egy észlelt jelölő határoló dobozán belül. A második egy összetett képkocka darabonkénti felépítése – min egy képkockasorozat felett egy előtér-maszkon belül, max ugyanazon sorozat felett a kiegészítő maszkon belül – ez a fajta minta.
5.9.5. Helyben, a bemenetek megőrzésével¶
Az aritmetikai metódusok mindegyike a korábban kialakított működési konvenciót követi: mindegyik helyben módosítja a forrásképet, és ugyanazt a képet adja vissza a láncoláshoz. A forrás képpontjai eltűnnek a hívás után – lecserélődnek a műveletnek a második operandusként átadottal szembeni eredményével.
Amikor az alkalmazásnak mindkét bemenetet meg kell őriznie, a biztonságos minta az, hogy az egyiket előbb lemásolja:
diff = current.copy() # leaves current intact
diff.difference(reference) # diff now holds the absolute difference
Ez a minta – másolás, majd művelet – a gerince bármely képkocka-különbségképzési láncnak, ahol a referencia-képkockának túl kell élnie az összehasonlítást, hogy a következő rögzített képkockán újra felhasználható legyen.
Hat kombináló művelettel, két egyképes művelettel, egy abszolút-különbség igavonóval és a hatókörözéshez használt mask kulcsszóval a képpont-aritmetikai eszköztár lefedi a fényesség- és csatornakombinációkat, amelyekre a klasszikus gépi látásnak szüksége van. A felszínen maradó aritmetikaszerű eszközök bitenként, nem pedig értékenként működnek.