英文全称 Hough Line Transform,是用来做直线检测的方法。
使用前提条件是必须 边缘检测已经完成

霍夫线变换的原理

一条直线在图像二维空间可由两个变量表示。如:

  • 1、在笛卡尔坐标系,可由参数: 斜率和截距(m,b)表示。
  • 2、在极坐标系,可由参数: 极径和极角(r, θ)表示。

HoughLines()函数

1
2
3
4
void HoughLines( InputArray image, OutputArray lines,  
double rho, double theta, int threshold,
double srn = 0, double stn = 0,
double min_theta = 0, double max_theta = CV_PI );

参数说明

src:输入图像,必须8-bit的灰度图像。
lines:输出的极坐标来表示直线,经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量(ρ,θ)表示,其中,ρ是离坐标原点((0,0)(也就是图像的左上角)的距离。 θ是弧度线条旋转角度(0是垂直线,π/2是水平线)。
rho:生成极坐标时候的像素扫描步长,一般取值为 1 ,不要大于图像尺寸的一半。
theta:生成极坐标时候的角度步长,一般取值CV_PI/180,即表示一度。
threshold:阈值,只有获得足够交点的极坐标点才被看成是直线。
srn:是否应用多尺度的霍夫变换,如果不是,设置0表示经典霍夫变换,多尺度表示的是使用图像金字塔,即多尺度图上进行霍夫变换。
stn:是否应用多尺度的霍夫变换,如果不是,设置0表示经典霍夫变换。
min_theta:表示角度扫描范围最小值,在 0 ~180 之间, 默认即可。
max_theta:表示角度扫描范围最大值,在 0 ~180 之间, 默认即可。

代码测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/usr/bin/python
# coding=utf-8

import cv2
from matplotlib import pyplot as plt

import numpy as np

img = cv2.imread('pictures/picture.jpeg')
origin = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 将图像转换为RGB格式 原因:matplotlib 的颜色通道是GBR,不是一般的RGB
plt.subplot(231),plt.imshow(origin),plt.title('Origin')

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  # 灰度图像
plt.subplot(232),plt.imshow(gray, cmap='gray'),plt.title('Gray')

canny = cv2.Canny(gray, 100, 200)  # 开启Canny边缘检测
plt.subplot(233),plt.imshow(canny, cmap='gray'),plt.title('Canny')

# HoughLines
line1 = origin.copy()
lines = cv2.HoughLines(canny, 1, np.pi/180, 100)  # 计算Line
for line in lines:
    rho,theta = line[0]
    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(line1, (x1, y1), (x2, y2), (255, 0, 0), 2)  
plt.subplot(234),plt.imshow(line1),plt.title('Hough Lines')

plt.suptitle('Hough Lines samples')
plt.show()

HoughLinesP()函数

1
2
3
void HoughLinesP( InputArray image, OutputArray lines,  
double rho, double theta, int threshold,
double minLineLength = 0, double maxLineGap = 0 );

参数说明

image:输入图像,即源图像,需为8位的单通道二进制图像。
lines:经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2)  表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的结束点。
rho:以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。
theta:以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
threshold:累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
minLineLength:表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。默认0。
maxLineGap:允许将同一行点与点之间连接起来的最大的距离。默认0。

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/python
# coding=utf-8

import cv2
from matplotlib import pyplot as plt

import numpy as np

img = cv2.imread('pictures/picture.jpeg')
origin = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 将图像转换为RGB格式 原因:matplotlib 的颜色通道是GBR,不是一般的RGB
plt.subplot(231),plt.imshow(origin),plt.title('Origin')

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  # 灰度图像
plt.subplot(232),plt.imshow(gray, cmap='gray'),plt.title('Gray')

canny = cv2.Canny(gray, 100, 200)  # 开启Canny边缘检测
plt.subplot(233),plt.imshow(canny, cmap='gray'),plt.title('Canny')

#HoughLinesP
line2 = origin.copy()
lines2 = cv2.HoughLinesP(canny, 1, np.pi / 180, 100, 100, 10)  # 计算Line
for line in lines2:
    x1, y1, x2, y2 = line[0]
    cv2.line(line2, (x1, y1), (x2, y2), (255, 0, 0), 2)  # 绘制Line
plt.subplot(235),plt.imshow(line2),plt.title('Hough Lines P')

plt.suptitle('Hough Lines samples')
plt.show()

测试结果