Színhasonlóság

Áttekintés

Elrejtés

A színhasonlóság-alapú szegmentálás fontosabb észrevételei az alábbiak:

  • Színek hasonlóságát az RGB helyett a HSV színtérben érdemes végezni. Ott a színek, mint vektorok távolsága jobban közelíti az emberi érzet alapján hasonlónak látottakat.
  • Hasonló színek így egy-egy intervallumban találhatók. Intervallum-alapú szűrésre az OpenCV az cv2.inRange() függvényt biztosítja.
  • Alaposabb vizsgálatot igényel, hogy konkrét esetekben milyen intervallumokat használjunk? A példaprogramok segítséget nyújtanak ehhez,
  • A csatornák közül a H (Hue) speciális, mivel [0, 180) értéktartománnyal bír, és körkörös az értelmezése. Ez külön vizsgálatokat igényel.

Videó anyag

Elrejtés

A témakörhöz tartozó példaprogramok működéséről az alábbi videóban kapunk további ismertetőt:

  • KfGyak_10_03_HSV.mp4

HSV színreprezentáció

Elrejtés

Egy korábbi részben láttuk, hogy színes képeken is végezhetünk küszöbölést, amivel egyszerű szegmentálási feladatok megoldhatók. Abban a példában a vörös, zöld és kék alapszínek előfordulásainak logikai kombinációit vizsgáltuk.

Színek hasonlóságán alapuló döntéseket általában nem az RGB, hanem a HSV (Hue, Saturation, Value) színtérben érdemes végeznünk. A "Hue" csatorna a színárnyalatot, a "Saturation" a színtelítettséget, a "Value" pedig a fényességet adja meg. Alacsony S érték esetén a fehér színnel erősen elegyedik az eredmény, növekvő értékek egyre kisebb fehér komponenest hordoznak (egyre telítettebb a szín). A Value 0 értékénél fekete színt kapunk, bármi is a másik két érték. Magasabb értékek egyre fényesebb színt adnak.

A Hue esetén fontos, hogy az értékek értelmezése körkörös, vagyis a legnagyobb V érték szomszédja a legkisebb érték. Emiatt a HSV színpalettát körként szokás ábrázolni.

A színtér konverziót egyszerűen elvégezhetjük az OpenCV cvtColor() függvényével, a korábban látott módon. Esetünkben a cv2.COLOR_BGR2HSV konstant kell használnunk. Az OpenCV esetében a H csatorna értéke [0, 179] közötti egész, a másik két csatorna a teljes [0, 255] egész értékű tartományt kihasználja. (Más képfeldolgozó vagy grafikus rendszerek eltérő HSV értéktartományt használhatnak. Export-import esetén erre figyeljünk.)

A HSV színtér értelmezését a 10_03_a_hsv_circle_visualization.py példaprogram mutatja be. Az ablakban megjelenő kör a Hue és Saturation paraméterek szerint változó színeket mutatja. A Value csatorna értéke a felső csúszkával állítható.

Feladat

Elrejtés

Futtassuk a példaprogramot, kattintunk különféle színekre, és értelmezzük a HSV értékek jelentését!

Az alábbi képernyőképeken a 80, 160 és 240 Value értékhez tartozó HS köröket látjuk. Magasabb Value érték fényesebb színeket eredményez.

    

A körön belül a bal egérgombbal kattintva kiválaszthatunk egy színt, aminek a HSV színkódját a program a konzolra írja.

A példában a H: 22 S: 185 V: 240 érték vizualizációját látjuk.

A H érték 22, ami a kör középpontjából a színhez tartozó képpontba húzott fehér szakasz és a vízszintes tengely (fekete vonal) bezárt szög értékenek a fele. (Azért a fele, mert a maximális H érték 180, ami a teljes körhöz tartozik.) A fehér vonalhoz így egy 44 fok irányú szakasz tartozik. Az ábrán jól látható a 179 és 0 értékek szomszédossága is.

Az S érték 185, ami a kör középpontjának és a színhez tartozó képpont normalizált távolsága. (Normalizált: A kör külső kerületén a távolság 255 érték.) Nagyobb értékhez telítetebb szín tartozik. 0 körüli érték esetén erős a fehér színnel való elegyítés.

A V érték 240, ami majdnem maximális fényességet jelez.

Színhasonlóság HSV-ben

Elrejtés

HSV színtérben az egymáshoz hasonló színek, legalábbis ahogyan az emberi látás érzékeli őket, közeli HSV értékeken jelennek meg. (Ez nem igaz az RGB színtérre, ezért is térünk át HSV-re.) Így ha csatornánként egy-egy értéktartományra szűrünk, vagyis csak azokat a képpontokat tekintjük objektumpontnak, amelyek mindhárom csatorna esetén a csatornához tartozó intervallumon belüli értékkel rendelkeznek, egy egyszerű globális szegmentálást érhetünk el.

OpenCV esetében többcsatornás képekre intervallumokon alapuló szűrést a cv2.inRange() függvénnyel végezhetünk.

dst = cv2.inRange(src, lowerb, upperb)

A dst az eredmény bináris kép, az src a bemeneti többcsatornás kép. A lowerb és az upperb paraméterek Numpy tömbként a csatornánkénti minimális és maximális értékeket adják meg.

Példaprogram

Elrejtés

A 10_03_b_segment_color_hsv.py példaprogram egy konkrét példát mutat be. Gyümölcsöket ábrázoló képen a narancsok, a citrom és a pomelo szegmentálását hajtjuk végre HSV intervallumok szűrésével.

A főprogramunk betölti a képet, egy képsimítás után átalakítja HSV színtérbe, majd három HSV tartományon szűrést végez.

img = cv2.imread('fruits_h.jpg')
cv2.imshow('origImg', img)

blurred = cv2.GaussianBlur(img, (5, 5), sigmaX=2.0, sigmaY=2.0)
imgHSV = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)

# Narancsok
hsv_segment((10, 20), (205, 255), (155, 255), 'Narancs')


# Citrom
hsv_segment((20, 30), (160, 255), (175, 255), 'Citrom')


# Pomelo
hsv_segment((20, 55), (70, 255), (60, 150), 'Pomelo')

A szegmentálást végző, paraméterezhető függvény:

# HSV intervallum szegmentalas
def hsv_segment(interval_H, interval_S, interval_V, wndtitle):

global imgHSV

minHSV = np.array([interval_H[0], interval_S[0], interval_V[0]])
maxHSV = np.array([interval_H[1], interval_S[1], interval_V[1]])
segmented = cv2.inRange(imgHSV, minHSV, maxHSV)
cv2.imshow(wndtitle, segmented)

Az eredmény nem tökéletes, de például morfológiai műveletekkel tovább javítható.

Intervallumok meghatározása

Elrejtés

Jogosan merül fel kérdésként, hogy hogyan is határozzuk meg ezeket az intervallumokat?

Első lépésként a kérdéses szín HSV reprezentációját kell megtudnunk. Ezt az RGB színkód ismeretében megkaphatjuk például az alábbi módon:

color_bgr = np.uint8([[[0, 255, 0]]])
color_hsv = cv2.cvtColor(color_bgr, cv2.COLOR_BGR2HSV)
print(color_bgr[0][0], '->', color_hsv[0][0])

Eredményképpen itt a maximális intenzitású zöld szín [60, 255, 255] HSV kódját kapjuk.

A kívánt színérték körüli tartományok meghatározása erősen alkalmazásfüggő. Irányelvként próbálhatunk az alábbi módon választani.

  • A H érték esetén próbáljunk 10, 20, vagy 30 nagyságú tartományt megadni. Figyelni kell arra, hogy a H érték értelmezése körkörös, vagyis a 0 értékhez a 179 érték szomszédnak számít! Intervallum alul- vagy túlcsordulás esetén két intervallumot kell figyelni!
  • Az S érték esetén kiindulásként próbálhatjuk a [100, 255] tartományt. Vagy ha RGB színértéket alakítottunk át, annak S értékéből akár 50 értéket kivonva megadni a minimumot. A maximum értéket vehetjük 255-re, mivel ez az adott színárnyalat maximális telítettségét jelenti.
  • A V érték színtén próbálható például a [100, 255] intervallummal, vagy az átalakított szín V értékénél 50-nel kisebb és nagyobb értékkel.

Konkrét kép esetén próbálhatunk interaktív módszerrel tartományokat meghatározni. Ehhez a 10_03_c_segment_color_hsv_circle_interactive.py példaprogram ad segítséget.

10_03_c_segment_color_hsv_interactive.py

Elrejtés

A program használata:

  • A program a fruits.jpg képet tölti be és jeleníti meg. Egéresemény kezelést rendelünk az ablakhoz, ahol a bal egérgomb lenyomására, felengedésére, és az egér mozgatására fogunk reagálni.
  • A megjelenő palette nevű ablakban a HSV színpalettát láthatjuk. A paletta alsó részen a Value érték szerinti skála jelenik meg. A fekete színű vonal az aktuális V értéket jelzi.
  • A betöltött kép ablakában bal egérgombbal kattintva az ott található szín HSV színértéke körül képzünk intervallumokat, alapértelmezetten [H-5, H+5], [S-50, 255], [V-50, V+50] módon. A kiszámolt tartomány határok a konzolra íródnak. Frissül a HSV paletta kép is, ahol fekete vonallal berajzolásra kerül az aktuális H és S érték, az alsó skálán pedig beállítódik az aktuális V érték. A kiszámolt H tartomány határokat fehér színű vonalakkal ábrázoljuk. Az S érték határok zöld és vörös körrel jelenik meg. A V határok az alsó skálán zöld és vörös vonalkákkal ábrázolódnak.
  • A tartományok mérete a h, H, s, S, v, V billentyűkkel utólagosan módosítható. A módosítás hatása rögtön látszik a szegmentálási eredményben és a HSV palettán is.
  • A kép ablakban a bal egérgomb lenyomásával és lenyomva tartva mozgatásával, majd felengedésével egy téglalap alakú területet jelölhetünk ki. Ezen területen kiszámításra kerülnek a minimális és maximális H, S és V értékek, amivel elvégezzük a szűrést. Ezek az intervallumhatárok is kiíródnak a konzolra, és utólagosan a billentyűkkel a határok módosíthatók.

H érték intervallumának megfelelő kezelése

A H érték körkörös értelmezése miatt további vizsgálatokat kell végeznünk. Amennyiben például a vörös szín szerinti szűrést szeretnénk elvégezni, ott a vizsgált tartomány átcsordul a 0-179 értéken. Az alábbi példában a színtartományra a program a [-6, 12] határokat adja.

A probléma az, hogy negatív értékek nem fordulnak elő a H csatornán, azok 180 alatti pozitív értékek lesznek. Az eredményt ilyen esetben az alábbi két intervallum szűrésének logikai VAGY műveletével kapjuk meg: [174, 179] és [0, 12]. Egy lépésben nem tudjuk elvégezni.

Hasonló a helyzet, ha 179 értéknél magasabb maximumot kapunk. Azok az értékek 0 feletti egészek lesznek, és az előző esethez hasonlóan két intervallumot kell vizsgálnunk.

A régió-alapú statisztika problémája

A példaprogram régió kijelölésen alapuló paraméter beállítását is érinti a H érték specialitása. Amennyiben a kijelölt területen vörös színárnyalatok helyezkednek el, könnyen előfordulhat, hogy 0 feletti pozitív, és a negatív értékeknek megfelelő, 180 alatti pozitív értékek szerepelnek benne. A minimum és maximum számítás viszont a teljes [0, 179] tartományt adhatja ilyenkor eredményül, amiben az összes szín szerepel. További megfontolásokat igényel a megfelelő H intevallumok meghatározása (kettő kell). A példaprogramunk ezzel nem foglalkozik.

Feladatok

Elrejtés

  • Teszteljük a példaprogramot a car_numberplate_rs.jpg képre is! Szegmentáljunk különböző színű területeket!
  • Válasszunk további képeket, ahol a színhasonlóság alapján történő szegmentálás jól használható és teszteljük a szegmentálást!
  • Gondoljuk át, hogyan lehetne jobban megoldani a régió kijelölés esetén az intervallum meghatározást! Valósítsuk meg!