Understanding & Implementing Shape Detection using Hough Transform with OpenCV & Python

Feature Image

Dzisiaj dowiemy się, jak wykrywać linie i okręgi na obrazie za pomocą techniki zwanej transformatą Hougha.

Co to jest przestrzeń Hougha?

Zanim zaczniemy stosować transformatę Hougha do obrazów, musimy zrozumieć, czym jest przestrzeń Hougha, a dowiemy się tego na przykładzie.

Przestrzeń parametryczna

Przy pracy z obrazami możemy sobie wyobrazić, że obraz jest macierzą 2d nad pewnymi współrzędnymi x i y, pod którymi linia mogłaby być opisana jako y = mx + b

Przestrzeń parametryczna

Przestrzeń parametryczna

Ale w przestrzeni parametrycznej, którą nazwiemy przestrzenią Hougha, mogę przedstawić tę samą linię jako m vs b, więc charakterystyka linii w przestrzeni obrazu będzie pojedynczym punktem w pozycji m-b w przestrzeni Hougha.

Przestrzeń Hougha

Przestrzeń Hougha

Mamy jednak problem, z y = mx + b, nie możemy reprezentować pionowej linii, ponieważ jej nachylenie jest nieskończone. Więc potrzebujemy lepszego sposobu parametryzacji, współrzędne biegunowe (rho i theta).

Przestrzeń Hougha

  • rho: opisuje odległość linii od początku
  • theta: opisuje kąt oddalenia od poziomu
Współrzędne biegunowe linii

Współrzędne biegunowe linii

Jedną z bardzo ważnych obserwacji jest to, co dzieje się, gdy weźmiemy wiele punktów wokół linii i przekształcimy w naszą przestrzeń Hougha.

Związek punktów i linii w przestrzeni Hougha

Związek punktów i linii w przestrzeni Hougha

Pojedyncza kropka w przestrzeni obrazu przekłada się na krzywą w przestrzeni Hougha, z tą różnicą, że punkty na linii w przestrzeni obrazu będą reprezentowane przez wiele krzywych z jednym punktem styczności.

I to będzie nasz cel, znalezienie punktów, w których grupa krzywych przecina się.

Co to jest transformata Hougha?

Transformata Hougha jest metodą ekstrakcji cech do wykrywania prostych kształtów, takich jak koła, linie, itp. w obrazie.

„Prosta” cecha jest uzyskiwana przez reprezentację kształtu w kategoriach parametrów. Prosty” kształt będzie reprezentowany tylko przez kilka parametrów, na przykład linia może być reprezentowana przez jej nachylenie i punkt przecięcia lub okrąg, który może być reprezentowany przez x, y i promień.

W naszym przykładzie linii, transformata Hough będzie odpowiedzialna za przetwarzanie kropek na obrazie i obliczanie wartości w przestrzeni Hough.

Algorytm dokonywania transformacji, a następnie znajdowania przecinających się krzywych jest nieco skomplikowany, a zatem wykracza poza zakres tego postu. Przyjrzymy się jednak implementacji tego algorytmu, która jest częścią biblioteki OpenCV.

Wykrywanie linii za pomocą OpenCV

W OpenCV wykrywanie linii za pomocą transformaty Hougha jest zaimplementowane w funkcjach HoughLines i HoughLinesP (Probabilistic Hough Transform). My skupimy się na tej drugiej.

Funkcja ta oczekuje następujących parametrów:

  • image: 8-bitowy, jednokanałowy binarny obraz źródłowy. Obraz ten może być modyfikowany przez funkcję.
  • lines: Wyjściowy wektor linii. Każda linia jest reprezentowana przez 4-elementowy wektor (x_1, y_1, x_2, y_2) , gdzie (x_1,y_1) i (x_2, y_2) są punktami końcowymi każdego wykrytego segmentu linii.
  • rho: Rozdzielczość odległościowa akumulatora w pikselach.
  • theta: Rozdzielczość kątowa akumulatora w radianach.
  • threshold: Parametr progowy akumulatora. Zwracane są tylko te linie, które uzyskają wystarczającą liczbę głosów
  • minLineLength: Minimalna długość linii. Odcinki linii krótsze od niej są odrzucane.
  • maxLineGap: Maksymalna dozwolona przerwa między punktami na tej samej linii, aby je połączyć.

Zbyt skomplikowane? łatwiej będzie na przykładzie:

# 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)

A oto wynik:

Przykład wykrywania linii

Przykład wykrywania linii

Bardzo ważne jest, abyśmy faktycznie użyli obrazu z tylko krawędziami jako parametru dla transformaty Hougha, w przeciwnym razie algorytm nie będzie działał zgodnie z założeniami.

Wykrywanie okręgów za pomocą OpenCV

Proces przebiega mniej więcej tak samo jak w przypadku linii, z tą różnicą, że tym razem użyjemy innej funkcji z biblioteki OpenCV. Użyjemy teraz funkcji HoughCircles, która przyjmuje następujące parametry:

  • image: 8-bitowy, jednokanałowy obraz wejściowy w skali szarości.
  • circles: Wektor wyjściowy znalezionych okręgów. Każdy wektor jest zakodowany jako 3-elementowy wektor zmiennoprzecinkowy (x, y, promień).
  • circle_storage: W funkcji C jest to pamięć, która będzie zawierać wyjściową sekwencję znalezionych okręgów.
  • method: Metoda detekcji, której należy użyć. Obecnie jedyną zaimplementowaną metodą jest CV_HOUGH_GRADIENT , która jest w zasadzie 21HT
  • dp: Odwrotny stosunek rozdzielczości akumulatora do rozdzielczości obrazu. Na przykład, jeśli dp=1 , to akumulator ma taką samą rozdzielczość jak obraz wejściowy. Jeśli dp=2 , to akumulator ma o połowę mniejszą szerokość i wysokość.
  • minDist: Minimalna odległość między środkami wykrytych okręgów. Jeśli parametr jest zbyt mały, oprócz jednego prawdziwego okręgu może zostać fałszywie wykrytych wiele sąsiednich. Jeśli jest zbyt duży, niektóre okręgi mogą zostać pominięte.
  • param1: Pierwszy parametr specyficzny dla metody. W przypadku CV_HOUGH_GRADIENT jest to wyższy próg z dwóch przekazywanych do detektora krawędzi Canny() (niższy jest dwa razy mniejszy).
  • param2: Drugi parametr specyficzny dla metody. W przypadku CV_HOUGH_GRADIENT , jest to próg akumulacji dla środków okręgów na etapie detekcji. Im jest on mniejszy, tym więcej fałszywych okręgów może zostać wykrytych. Kręgi odpowiadające większym wartościom akumulatora będą zwracane w pierwszej kolejności.
  • minRadius: Minimalny promień okręgu.
  • maxRadius: Maksymalny promień okręgu.

Pamiętaj, że parametry muszą być inne, ponieważ nie możemy opisać okręgu za pomocą tej samej parametryzacji, której użyliśmy dla linii, a zamiast tego musimy użyć równania takiego jak (x - x0)^^2 + (y - y0)^^2 = r^^2.

I do kodu:

# 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)

Zauważ, że w porównaniu z poprzednim przykładem, nie stosujemy tutaj żadnej funkcji wykrywania krawędzi. Dzieje się tak dlatego, że funkcja HoughCircles ma wbudowaną funkcję wykrywania Canny.

I wynik:

Przykład wykrywania okręgów

Przykład wykrywania okręgów

Wniosek

Transformacja Hougha jest doskonałą techniką wykrywania prostych kształtów na obrazach i ma wiele zastosowań, począwszy od zastosowań medycznych, takich jak analiza rentgenowska, tomograficzna i rezonansu magnetycznego, a skończywszy na samochodach samojezdnych. Jeśli chcesz dowiedzieć się więcej o przestrzeni Hougha, zalecam, abyś faktycznie uruchomił kod, wypróbował różne konfiguracje samodzielnie i sprawdził dokumentację OpenCV, aby uzyskać dodatkowe informacje.

Dzięki za przeczytanie!

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.