Alakfelismerés megértése és megvalósítása Hough-transzformáció segítségével OpenCV és Python segítségével

Feature Image

A mai napon megtanuljuk, hogyan lehet egy képen vonalakat és köröket felismerni a Hough-transzformációnak nevezett technika segítségével.

Mi az a Hough-tér?

Mielőtt elkezdenénk a Hough-transzformációt képekre alkalmazni, meg kell értenünk, mi az a Hough-tér, és ezt egy példa segítségével fogjuk megtanulni.

Paramétertér

Mikor képekkel dolgozunk, elképzelhetjük a képet egy 2d mátrixként néhány x és y koordináta felett, amely alatt egy vonalat leírhatunk y = mx + b

Paramétertér

Paramétertér

De a paramétertérben, amit Hough-térnek fogunk nevezni, ugyanezt a vonalat ábrázolhatom m vs b helyett, így a vonal jellemzése a képtérben, egyetlen pont lesz a m-b pozícióban a Hough-térben.

Hough tér

Hough tér

De van egy problémánk azonban, a y = mx + b esetében nem tudunk függőleges egyenest ábrázolni, mivel a meredeksége végtelen. Tehát szükségünk van egy jobb módú parametrizálásra, polárkoordinátákra (rho és theta).

Hough-tér

  • rho: az egyenesnek az origótól való távolságát írja le
  • theta: a vízszintestől távolodó szöget írja le
egyenes polárkoordinátái

egyenes polárkoordinátái

Egy nagyon fontos megfigyelés azonban, hogy mi történik, ha egy egyenes körül több pontot veszünk, és átalakítjuk a Hough-térünkbe.

Pontok és vonal viszonya a Hough-térben

Pontok és vonal viszonya a Hough-térben

Egyetlen pont a képtérben egy görbére fordítható a Hough-térben, azzal a sajátossággal, hogy a képtérben egy vonal közötti pontokat több görbe fogja ábrázolni egyetlen érintési ponttal.

És ez lesz a célunk, hogy megtaláljuk azokat a pontokat, ahol egy görbecsoport metszi egymást.

Mi a Hough-transzformáció?

A Hough-transzformáció egy olyan jellemző-kivonási módszer, amely egyszerű alakzatok, például körök, vonalak stb. felismerésére szolgál egy képen.

Az “egyszerű” jellemzőt az alakzat paraméterek szerinti ábrázolásából vezetjük le. Egy “egyszerű” alakzat csak néhány paraméterrel reprezentálható, például egy egyenes reprezentálható a meredekségével és a metszéspontjával, vagy egy kör, amelyet x, y és sugárral lehet reprezentálni.

A vonalas példánkban a Hough-transzformáció feladata a képen lévő pontok feldolgozása és az értékek kiszámítása a Hough-térben.

A transzformáció végrehajtásához szükséges algoritmus, majd a metsző görbék megtalálása kicsit bonyolult, ezért nem tartozik e bejegyzés tárgykörébe. Viszont megnézzük ennek az algoritmusnak egy implementációját, amely az OpenCV könyvtár része.

A vonalak felismerése OpenCV-vel

Az OpenCV-ben a Hough-transzformációval történő vonalfelismerés a HoughLines és HoughLinesP (Probabilistic Hough Transform) függvényekben van implementálva. Mi ez utóbbira koncentrálunk.

A függvény a következő paramétereket várja:

  • image: 8 bites, egycsatornás bináris forráskép. A képet a függvény módosíthatja.
  • lines: Vonalakból álló kimeneti vektor. Minden vonalat egy 4 elemű vektor (x_1, y_1, x_2, y_2) reprezentál, ahol (x_1,y_1) és (x_2, y_2) az egyes felismert vonalszakaszok végpontjai.
  • rho: Az akkumulátor távolsági felbontása pixelben.
  • theta: Az akkumulátor szögfelbontása radiánban.
  • threshold: Akkumulátor küszöbérték paraméter. Csak azok a sorok kerülnek vissza, amelyek elegendő szavazatot kapnak
  • minLineLength: Minimális sorhossz. Az ennél rövidebb vonalszakaszok elutasításra kerülnek.
  • maxLineGap: Az ugyanazon a vonalon lévő pontok közötti legnagyobb megengedett távolság, hogy összekapcsolja őket.

Túl bonyolult? egyszerűbb egy példával:

# Read image img = cv2.imread('lanes.jpg', cv2.IMREAD_COLOR)# Convert the image to gray-scalegray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# Find the edges in the image using canny detectoredges = cv2.Canny(gray, 50, 200)# Detect points that form a linelines = cv2.HoughLinesP(edges, 1, np.pi/180, max_slider, minLineLength=10, maxLineGap=250)# Draw lines on the imagefor line in lines: x1, y1, x2, y2 = line cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 3)# Show resultcv2.imshow("Result Image", img)

És itt az eredmény:

 Vonalfelismerési példa

Vonalfelismerési példa

Ez nagyon fontos, hogy valóban csak élekkel rendelkező képet használjunk a Hough-transzformáció paramétereként, különben az algoritmus nem fog rendeltetésszerűen működni.

Körök detektálása OpenCV segítségével

A folyamat nagyjából ugyanúgy zajlik, mint a vonalak esetében, azzal a különbséggel, hogy ezúttal egy másik függvényt fogunk használni az OpenCV könyvtárból. Most a HoughCircles-t fogjuk használni, amely a következő paramétereket fogadja:

  • image: 8 bites, egycsatornás, szürkeárnyalatos bemeneti kép.
  • circles: A megtalált körök kimeneti vektora. Minden vektor 3 elemű lebegőpontos vektorként van kódolva (x, y, sugár).
  • circle_storage: C függvényben ez egy memóriatároló, amely a talált körök kimeneti sorozatát tartalmazza.
  • method: Használandó észlelési módszer. Jelenleg az egyetlen implementált módszer a CV_HOUGH_GRADIENT , amely alapvetően 21HT
  • dp: Az akkumulátor felbontásának és a kép felbontásának inverz aránya. Például, ha dp=1 , az akkumulátor felbontása megegyezik a bemeneti kép felbontásával. Ha dp=2 , akkor az akkumulátor fele akkora szélességű és magasságú.
  • minDist: Az észlelt körök középpontjai közötti minimális távolság. Ha a paraméter túl kicsi, akkor egy igaz kör mellett több szomszédos kör is tévesen felismerhető. Ha túl nagy, néhány kör kimaradhat.
  • param1: Az első módszer-specifikus paraméter. CV_HOUGH_GRADIENT esetén ez a Canny() élérzékelőnek átadott kettő közül a magasabb küszöbérték (az alacsonyabb kétszer kisebb).
  • param2: Második módszer-specifikus paraméter. CV_HOUGH_GRADIENT esetén ez a körközéppontok felhalmozási küszöbértéke a felismerési szakaszban. Minél kisebb, annál több hamis kör kerülhet felismerésre. A nagyobb akkumulátorértékeknek megfelelő körök kerülnek először visszaküldésre.
  • minRadius: Minimális körsugár.
  • maxRadius: Maximális körsugár.

Ne feledjük, hogy a paramétereknek másnak kell lenniük, mivel a kört nem írhatjuk le ugyanazzal a paraméterezéssel, mint amit az egyeneseknél használtunk, hanem egy olyan egyenletet kell használnunk, mint a (x - x0)^^2 + (y - y0)^^2 = r^^2.

És a kódhoz:

# Read image as gray-scaleimg = cv2.imread('circles.png', cv2.IMREAD_COLOR)# Convert to gray-scalegray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# Blur the image to reduce noiseimg_blur = cv2.medianBlur(gray, 5)# Apply hough transform on the imagecircles = cv2.HoughCircles(img_blur, cv2.HOUGH_GRADIENT, 1, img.shape/64, param1=200, param2=10, minRadius=5, maxRadius=30)# Draw detected circlesif circles is not None: circles = np.uint16(np.around(circles)) for i in circles: # Draw outer circle cv2.circle(img, (i, i), i, (0, 255, 0), 2) # Draw inner circle cv2.circle(img, (i, i), 2, (0, 0, 255), 3)

Megjegyezzük, hogy az előző példához képest itt nem alkalmazunk semmilyen élfelismerő funkciót. Ennek oka, hogy a HoughCircles függvény beépített canny-felismeréssel rendelkezik.

És az eredmény:

Körfelismerési példa

Körfelismerési példa

Következtetés

A Hough-transzformáció kiváló technika egyszerű alakzatok felismerésére a képeken, és számos alkalmazása van, az orvosi alkalmazásoktól kezdve, mint a röntgen, CT és MRI elemzés, az önvezető autókig. Ha többet szeretne megtudni a Hough-térről, javaslom, hogy ténylegesen futtassa a kódot, próbálja ki saját maga a különböző konfigurációkat, és további információkért nézze meg az OpenCV dokumentációját.

Köszönöm az olvasást!

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.