Преобразование Хафа

Автор статьи: Рустем Галиев

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)

Изображение, которое мы импортируем

Вызовем детектор границ 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, давайте взглянем на него

Преобразование Хафа — медленный алгоритм, потому что мы голосуем за каждый пиксель и учитываем все голоса для построения линии.

Чтобы иметь более быструю в вычислительном отношении версию, мы можем использовать вероятностное преобразование Хафа. Требуется только определенное количество голосов пикселей, чтобы достичь консенсуса по параметрам линии.

Это ускоряет вычисления в ситуациях, когда мы можем компенсировать некоторую точность для скорости.

Давайте посмотрим на вероятностное преобразование Хафа для нахождения прямых линий:

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

Мы можем распространить преобразование Хафа на любую геометрическую форму. Для круга нужны три параметра, чтобы определить уникальный круг. Таким образом, нам пришлось бы вычислять три параметра на пиксель. Поскольку это неэффективно в вычислительном отношении, OpenCV находит градиент ребер. В этой реализации количество параметров равно двум.

Функция HoughCircles в OpenCV имеет множество параметров, поэтому было бы целесообразно обратиться к значениям параметров из документации OpenCV.

Преобразование Хафа для кругов с использованием HoughCircles:

col_img= cv2.imread('circles.jpg') img = cv2.imread('circles.jpg',0) filtered= cv2.bilateralFilter(img,9,75,75)

Изображение, которое мы импортируем

Для вызова функции 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:

Заключение

Мы научились определять прямые линии и окружности с помощью преобразования Хафа. Это одна из фундаментальных концепций компьютерного зрения.

В завершение расскажу пару слов об открытом уроке, посвященном диффузионным моделям, который пройдет 12 июля. На нем вы узнаете:

  • По каким принципам строится любая диффузионная модель и как устроена популярная генеративная модель Stable Diffusion;

  • Какие задачи можно решать с помощью модели Stable Diffusion.

Записаться на урок можно на странице курса «Компьютерное зрение».


ссылка на оригинал статьи https://habr.com/ru/companies/otus/articles/745946/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *