Skip navigation

Színhasonlóság

Áttekinté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

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ó

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

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

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

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

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

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

  • 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!