Преобразование линии Хафа, вероятностное преобразование линии Хафа в OpenCV

задняя часть

Преобразование линии Хафа, вероятностное преобразование линии Хафа в OpenCV

В этом блоге будет представлен Python, Hough Transform в OpenCV. В том числе о том, что такое преобразование Хафа, вероятностное преобразование Хафа и как использовать cv2.HoughLines(), cv2.HoughLinesP() для обнаружения линий на изображениях.

1. Рендеринг

Рендеринг исходного изображения VS преобразования Хафа выглядит следующим образом:

Все линии, обнаруженные на рисунке, включая углы 0°180° (красная линия, проходящая через точку ниже начала координат) и угол -180°0° (зеленая линия, проходящая через точку выше начала координат).在这里插入图片描述Рендеринг исходного изображения по сравнению с вероятностным преобразованием Хафа выглядит следующим образом:Эффект вероятностного преобразования Хафа может устанавливать размер промежутка между линиями и обнаруживать небольшие короткие линии;在这里插入图片描述

2. Принцип

Можно использовать любую строкуy=mx+cтакже может быть представлен (ρ, θ),ρ=xcosθ+ysinθ. ρ в пикселях, а θ в радианах.

Если линия проходит ниже начала координат, ее ρ положительно и угол равен (0, 180), если линия проходит выше начала координат, ρ отрицателен и угол равен (-180, 0). Любая вертикальная линия равна 0 градусов, а горизонтальная линия равна 90 градусам.

在这里插入图片描述

2.1 Что такое преобразование Хафа?

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

lines = cv2.HoughLines(edges, 1, np.pi / 180, 200)

  • края: входное изображение (бинарное изображение, поэтому примените пороговое или осторожное обнаружение края перед применением поиска преобразования hough)
  • 1: точность ρ, ρ в пикселях и θ в радианах.
  • np.pi/180: точность тета
  • 200: Порог, предполагающий линию обнаружения, указывающий наименьшую длину обнаруженной строки, линии с длиной менее 200 пикселей будут отброшены;
  • lines: возвращает значение (ρ, θ), где ρ — в пикселях, а θ — в радианах.

2.2 Что такое вероятностное преобразование Хафа?

Вероятностное преобразование Хафа — это оптимизация преобразования Хафа.

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

  • Возвращаемое значение преобразования Хафа равно (ρ, θ), а вероятностное преобразование Хафа напрямую возвращает конечные точки линии для упрощения работы;

lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength, maxLineGap)

  • edages, 1, np.pi/180 согласуются с преобразованием Хафа, которое представляет собой входное двоичное изображение, точность ρ, точность θ соответственно.
  • minLineLength: минимальная длина строки. Строки меньше этой длины будут отброшены;
  • maxLineGap: максимально допустимый интервал между сегментами линии, рассматриваемыми как одна линия.
  • линии: он напрямую возвращает две конечные точки линии.

3. Исходный код

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

# 霍夫变换(可检测任意形状)

# lines = cv2.HoughLines(edges, 1, np.pi / 180, 200)
# - edges:输入图像(二值图像,因此在应用hough变换查找之前,先应用阈值或canny边缘检测)
# - 1: ρ精度,ρ以像素为单位,θ以弧度为单位。
# - np.pi/100: 角度,θ精度
# - 200:阈值,假设检测线,表示被检测到的线的最短长度
# - lines: 返回值(ρ,θ),ρ以像素为单位,θ以弧度为单位。
#
# 概率霍夫变换(Probablistic Hough Transform)是霍夫变换(Hough Transform)的优化。
# 霍夫变换拿线的所有点参与计算,而概率霍夫变换不考虑所有的点,而是只考虑点的一个随机子集,这对于线检测是足够的。
# lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength, maxLineGap)
# - edages、1、np.pi/180 跟霍夫变换一致,分别为输入二值图像、ρ精度、θ精度
# - minLineLength:最小线条长度。小于此长度的线段将被丢弃;
# - maxLineGap:直线段之间允许的最大间距,将其视为单线。
# - lines:它直接返回两条线的端点。

import cv2
import imutils
import numpy as np

img = cv2.imread('hf1.jpg')
cv2.imshow("origin", imutils.resize(img, width=400))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)

print(np.pi / 180, np.pi / 360)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 200)

for i, line in enumerate(lines):
    for rho, theta in line:
        # print(rho, theta * 180 - 180)
        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))
        
        # 弧度转角度
        degree = theta * 180 - 180
        if (degree > 180):
            degree = degree - 360
        print(rho, degree)
        
        if rho > 0 and degree > 0:  # 经过原点下方的点,角度为正(0,180)
            cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
        else:  # 经过原点上方的点,角度为负(-180,0)
            cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

cv2.imwrite('houghlines_hf.jpg', img)
cv2.imshow("hf_res", imutils.resize(img, width=400))
cv2.waitKey(0)

3.2 Вероятностное преобразование Хафа

# 概率霍夫变换

# 霍夫变换(可检测任意形状)
# lines = cv2.HoughLines(edges, 1, np.pi / 180, 200)
# - edges:输入图像(二值图像,因此在应用hough变换查找之前,先应用阈值或canny边缘检测)
# - 1: ρ精度
# - np.pi/100:θ精度
# - 200:阈值,假设检测线,表示被检测到的线的最短长度
# - lines: 返回值(ρ,θ),ρ以像素为单位,θ以弧度为单位。

# 概率霍夫变换(Probablistic Hough Transform)是霍夫变换(Hough Transform)的优化。
# 霍夫变换拿线的所有点参与计算,而概率霍夫变换不考虑所有的点,而是只考虑点的一个随机子集,这对于线检测是足够的。
# lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength, maxLineGap)
# - edages、1、np.pi/180 跟霍夫变换一致,分别为输入二值图像、ρ精度、θ精度
# - minLineLength:最小线条长度。小于此长度的线段将被丢弃;
# - maxLineGap:直线段之间允许的最大间距,将其视为单线。
# - lines:它直接返回两条线的端点。

# 概率霍夫变换(Probablistic Hough Transform)是霍夫变换(Hough Transform)的优化。
# 霍夫变换拿线的所有点参与计算,而概率霍夫变换不考虑所有的点,而是只考虑点的一个随机子集,这对于线检测是足够的。

import cv2
import imutils
import numpy as np

img = cv2.imread('hf1.jpg')
cv2.imshow("origin", imutils.resize(img, width=400))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)

minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 10, minLineLength, maxLineGap)

# 只绘制第一条线
# for x1, y1, x2, y2 in lines[0]:
#     cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

print(len(lines))
# 绘制所有检测结果
for i, line in enumerate(lines):
    for x1, y1, x2, y2 in line:
        cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imwrite('houghlines_hfp.jpg', img)
cv2.imshow("hfp_res", imutils.resize(img, width=400))
cv2.waitKey(0)

Ссылаться на