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

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.

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

Комментарии (4)


  1. SomeAnonimCoder
    05.07.2023 11:22
    +4

    Снова статья-пересказ документации. А слабо написать нормально, с объяснением, что внутри у алгоритма, почему он работает, нормально разобрать? Ах, нет, карма и рейтинг сами себя не намайнят, а писать нормальную статью - непозволительно долго. Отличная антиреклама отуса, спасибо!


    1. N-Cube
      05.07.2023 11:22
      -1

      Зря вы так о документации - там намного интереснее, с примерами и фотографиями известной всем Лены :)


  1. N-Cube
    05.07.2023 11:22
    +2

    Совсем скучно получилось. А как насчет кругового преобразования Хафа для решения обратной задачи геофизики (восстановление модели плотности по вертикальной компоненте гравитационного поля на поверхности), да на гугл колаб, да еще с интерактивной 3D визуализацией прямо в ноутбуке: https://colab.research.google.com/drive/1de2GcRBkQIGzFG1cqZRhDJ9DsR2ZHqKx


  1. Cykooz
    05.07.2023 11:22
    +3

    • Как работает автомат?

    • Очень просто. Тра-та-та, и вы убиты.

    Почему линии в тексте называются "строками"? Это какой-то кривой перевод слова lines?

    А как устроено голосование за пиксели? У них есть предвыборная программа, дебаты? При голосовании используется ДЭГ или другая система?