![](https://habrastorage.org/getpro/habr/upload_files/da5/ee5/dd9/da5ee5dd9e0f576c2aac42d3ff1ca9c3.jpg)
Автор статьи: Рустем Галиев
IBM Senior DevOps Engineer & Integration Architect. Официальный DevOps ментор и коуч в IBM
Сегодня мы рассмотрим преобразование Хафа — популярный метод обнаружения фигур среди граней и границ. Также поговорим про использование преобразования Хафа для обнаружения линий и кругов (хотя в целом, его можно расширить до любой формы). Статья будет интересна прежде всего начинающим специалистам по компьютерному зрению.
Преобразование Хафа — это алгоритм, используемый для поиска геометрических фигур на изображении. На основе искомой формы выбирается определенное количество параметров. Эти параметры необходимы для определения формы. Скажем, для прямой линии y=mx+c
у нас есть два параметра. Мы также можем написать линию в форме полярных координат, где два параметра — ро и тета.
Затем находим значения параметров для каждого пикселя. Для конкретной прямой должна быть уникальная пара параметров. Таким образом, все точки на этой линии будут иметь одну и ту же пару параметров.
Так мы голосуем за каждую пару параметров, полученных из пикселей изображения. Пара с наибольшим количеством голосов соответствует прямой линии. Если на изображении несколько линий, скажем, 10, мы считаем, что 10 точек, получивших наибольшее количество голосов, представляют эти линии. Затем эти линии строятся с использованием параметров.
Давайте создадим файл Python, с которым мы будем работать:touch hough_transform.py
Посмотрим на преобразование Хафа для прямой линии. Для импорта библиотек и входного изображения:
import numpy as np
import cv2
img = cv2.imread('sudoku.jpg')
filtered= cv2.bilateralFilter(img,9,75,75)
Изображение, которое мы импортируем
![](https://habrastorage.org/getpro/habr/upload_files/4b2/f38/342/4b2f38342cd7c55af4d1bea834b847a1.png)
Вызовем детектор границ Canny и функции HoughLines:
edges = cv2.Canny(filtered,50,200,apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180,200)
Для вывода найденных строк, если они есть:
for i in range(len(lines[:,0,0])):
for rho,theta in lines[i]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img,(x1,y1),(x2,y2),(255,0,0),2)
cv2.imwrite('hough.jpg',img)
Запустим кодpython hough_transform.py
Мы получили файл hough.jpg
, давайте взглянем на него
![](https://habrastorage.org/getpro/habr/upload_files/864/c68/fe6/864c68fe693367d827fa2214793e8804.png)
Преобразование Хафа — медленный алгоритм, потому что мы голосуем за каждый пиксель и учитываем все голоса для построения линии.
Чтобы иметь более быструю в вычислительном отношении версию, мы можем использовать вероятностное преобразование Хафа. Требуется только определенное количество голосов пикселей, чтобы достичь консенсуса по параметрам линии.
Это ускоряет вычисления в ситуациях, когда мы можем компенсировать некоторую точность для скорости.
Давайте посмотрим на вероятностное преобразование Хафа для нахождения прямых линий:
img = cv2.imread('sudoku.jpg')
filtered= cv2.bilateralFilter(img,9,75,75)
edges = cv2.Canny(filtered,50,200,apertureSize = 3)
Для определения параметров HoughLinesP
и вызова HoughLinesP
мы используем следующие строки кода:
MinLineLength = 100
MaxLineGap = 10
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,MinLineLength,MaxLineGap)
Для вывода найденных строк, если они есть:
for i in range(len(lines[:,0,0])):
for x1,y1,x2,y2 in lines[i]:
cv2.line(img,(x1,y1),(x2,y2),(255,0,0),2)
cv2.imwrite('probab_hough.jpg',img)
Запустим: python hough_transform.py
У нас появится файл probab_hough.jpg
![](https://habrastorage.org/getpro/habr/upload_files/2f9/bf4/1d3/2f9bf41d383870d2f7e2749539c5531b.png)
Мы можем распространить преобразование Хафа на любую геометрическую форму. Для круга нужны три параметра, чтобы определить уникальный круг. Таким образом, нам пришлось бы вычислять три параметра на пиксель. Поскольку это неэффективно в вычислительном отношении, OpenCV находит градиент ребер. В этой реализации количество параметров равно двум.
Функция HoughCircles
в OpenCV имеет множество параметров, поэтому было бы целесообразно обратиться к значениям параметров из документации OpenCV.
Преобразование Хафа для кругов с использованием HoughCircles:
col_img= cv2.imread('circles.jpg')
img = cv2.imread('circles.jpg',0)
filtered= cv2.bilateralFilter(img,9,75,75)
Изображение, которое мы импортируем
![](https://habrastorage.org/getpro/habr/upload_files/64e/468/3aa/64e4683aa5da048549c6924c16bd0b5f.png)
Для вызова функции HoughCircles
:
circles = cv2.HoughCircles(filtered,cv2.HOUGH_GRADIENT,1,20,param1=55,param2=40,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
Для вывода найденных кругов:
for i in circles[0,:]:
cv2.circle(col_img,(i[0],i[1]),i[2],(0,255,0),2)
#draws the circumference of the circle
cv2.circle(col_img,(i[0],i[1]),2,(0,0,255),3)
#draws the centre of the circle
cv2.imwrite('hough_circles.jpg',col_img)
Запустим код: python hough_transform.py
И получим hough_circles.jpg:
![](https://habrastorage.org/getpro/habr/upload_files/460/7f2/391/4607f23913575c16da3039f1669c398b.png)
Заключение
Мы научились определять прямые линии и окружности с помощью преобразования Хафа. Это одна из фундаментальных концепций компьютерного зрения.
В завершение расскажу пару слов об открытом уроке, посвященном диффузионным моделям, который пройдет 12 июля. На нем вы узнаете:
По каким принципам строится любая диффузионная модель и как устроена популярная генеративная модель Stable Diffusion;
Какие задачи можно решать с помощью модели Stable Diffusion.
Записаться на урок можно на странице курса «Компьютерное зрение».