目录
效果预览
0.Hough变换的理论基础
0.0 简介
0.1 对直线的分析
1 OpenCV中的Hough直线变换
1.1 HoughLines()
1.1.1 The Standard Hough Transform
1.1.2 Demo
1.2 HoughLinesP()
1.2.1 The Probabilistic Hough Line Transform
1.2.2 Demo
1.3 两个不同的 lines
1.4 绘制直线的数量
3.Demo
GITEE
GITHUB
近期做了一个比较有意思的Demo,基于Hough变换的车道线实时检测。
分为两部分:
1.前向车道线压线实时检测
2.侧向车道线实时检测
环境OpenCV4.1x Pre:安装教程
效果预览
湖大体育馆门前:

侧压线检测:


0.Hough变换的理论基础
0.0 简介
霍夫变换可以解决不限于直线,圆形,椭圆的检测,通过在常见的坐标系中参数方程的刻画,转移到另一个由这些参数构成的坐标系中,通过求交点的方式来判断最终的效果,但是随着几何图形的维度的增加,计算量会以指数级速度上升。
例如直线的刻画:
无论是直角坐标系,使用参数 k & b

还是极坐标系,使用参数 r & theta

(这个公式的推导参考下图)

都只需要两个参数,对应映射到变换空间就是一个二维的平面。
对于一个椭圆:

,其有4个参数,最终映射的到一个4维空间。
0.1 对直线的分析
如果首先分析一条直线:

对于不同的(

,

) 这个公式刻画了经过点(x0, y0)的所有直线。最终要求的目标是找到原来图像中的直线:

对于输入图像的每一点 (x0, y0),都可以在

对应的坐标系中找到一条三角曲线。这条三角曲线遍历了所有的(

,

)(在上面的图像中r对应这里的(

,

)),相当于三角曲线上的每一个点都对应输入图像空间中的一条直线,整条三角曲线上的所有的点对应原来的输入图像空间中过点(x0, y0)的所有的直线。这样,在输入图像中划定了ROI(region of interest)感兴趣区域之后,就对ROI区域中的每一个像素点进行Hough变换,映射到三角函数区域中,在遍历输入图像中的所有的输入像素点之后,得到的三角函数曲线簇会产生若干交点,设置一个threshold,用来找到被大于一定数量三角曲线穿过的Hough变换空间点,最终选择 (
,
),并将这两个参数映射回输入图像空间,就找到了需要发现的直线,检测圆、椭圆等原理相同,但是映射空间会变得更高维(三维、四维),相应的计算量也会加大。
例如:下面取x0 = 3, y0 = 4生成了曲线如下:横坐标为

,纵坐标为


例如:取一系列的不同 (
,
) 最终得到交点:

可以取一个对应的周期并限制正负来得到合适的交点(

,

),然后带入:(r =

)

就求出了输入图像中需要检测的直线的方程为:

1 OpenCV中的Hough直线变换
OpenCV中提供了两个函数用来进行直线检测
1.1 HoughLines()
1.1.1 The Standard Hough Transform

image | 8-bit, single-channel binary source image. The image may be modified by the function. |
lines | Output vector of lines. Each line is represented by a 2 or 3 element vector (ρ,θ) or (ρ,θ,votes) . ρ is the distance from the coordinate origin (0,0) (top-left corner of the image). θ is the line rotation angle in radians ( 0∼vertical line,π/2∼horizontal line ). votes is the value of accumulator. |
rho | Distance resolution of the accumulator in pixels. |
theta | Angle resolution of the accumulator in radians. |
threshold | Accumulator threshold parameter. Only those lines are returned that get enough votes ( >threshold ). |
srn | For the multi-scale Hough transform, it is a divisor for the distance resolution rho . The coarse accumulator distance resolution is rho and the accurate accumulator resolution is rho/srn . If both srn=0 and stn=0 , the classical Hough transform is used. Otherwise, both these parameters should be positive. |
stn | For the multi-scale Hough transform, it is a divisor for the distance resolution theta. |
min_theta | For standard and multi-scale Hough transform, minimum angle to check for lines. Must fall between 0 and max_theta. |
max_theta | For standard and multi-scale Hough transform, maximum angle to check for lines. Must fall between min_theta and CV_PI. |
1.1.2 Demo
将结果存入lines:
// Standard Hough Line Transform
vector<Vec2f> lines; // will hold the results of the detection
HoughLines(dst, lines, 1, CV_PI/180, 150, 0, 0 ); // runs the actual detection借助lines动态数组对结果进行绘制:
// Draw the lines
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line( cdst, pt1, pt2, Scalar(0,0,255), 3, LINE_AA);
}解释:
- dst: Output of the edge detector. It should be a grayscale image (although in fact it is a binary one)
- lines: A vector that will store the parameters (r,θ) of the detected lines
- rho : The resolution of the parameter r in pixels. We use 1 pixel.
- theta: The resolution of the parameter θ in radians. We use 1 degree (CV_PI/180)
- threshold: The minimum number of intersections to "*detect*" a line
- srn and stn: Default parameters to zero. Check OpenCV reference for more info.
1.2 HoughLinesP()
1.2.1 The Probabilistic Hough Line Transform

image | 8-bit, single-channel binary source image. The image may be modified by the function. |
lines | Output vector of lines. Each line is represented by a 4-element vector (x1,y1,x2,y2) , where (x1,y1) and (x2,y2) are the ending points of each detected line segment. |
rho | Distance resolution of the accumulator in pixels. |
theta | Angle resolution of the accumulator in radians. |
threshold | Accumulator threshold parameter. Only those lines are returned that get enough votes ( >threshold ). |
minLineLength | Minimum line length. Line segments shorter than that are rejected. |
maxLineGap | Maximum allowed gap between points on the same line to link them. |
1.2.2 Demo
将结果存入lineP:
// Probabilistic Line Transform
vector<Vec4i> linesP; // will hold the results of the detection
HoughLinesP(dst, linesP, 1, CV_PI/180, 50, 50, 10 ); // runs the actual detection借助lineP动态数组进行检测结果绘制:
// Draw the lines
for( size_t i = 0; i < linesP.size(); i++ )
{
Vec4i l = linesP[i];
line( cdstP, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
}解释:
- dst: Output of the edge detector. It should be a grayscale image (although in fact it is a binary one)
- lines: A vector that will store the parameters (xstart,ystart,xend,yend) of the detected lines
- rho : The resolution of the parameter r in pixels. We use 1 pixel.
- theta: The resolution of the parameter θ in radians. We use 1 degree (CV_PI/180)
- threshold: The minimum number of intersections to "*detect*" a line
- minLinLength: The minimum number of points that can form a line. Lines with less than this number of points are disregarded.
- maxLineGap: The maximum gap between two points to be considered in the same line.
1.3 两个不同的 lines
Output vector of lines. Each line is represented by a 4-element vector (x1,y1,x2,y2) , where (x1,y1) and (x2,y2) are the ending points of each detected line segment. |
参数lines为输出直线向量描述。
两个函数对应的lines的数据类型不同:
// HoughLines()
vector<Vec2f> lines;// HoughLinesP()
vector<Vec4i> linesP;函数HoughLines()对应的lines向量使用上面分析的极坐标参数表示(ρ,θ) ,要换算为熟悉的直角坐标理解需要借助:

函数HoughLinesP()每一条直线是由一个4元素向量(x1, y1, x2, y2)构成的,被检测到的直线的端点分别为(x1, y1)、(x2, y2)。
之后的代码中会看到有Vec2f、Vec4i这两种数据类型分别用于两种不同函数的Lines向量类型。
Vec2f 对应 Vec<float, 2>类型。
Vec4i本身是一个模板参数类 Vec的模板参数为int,4的时候使用typedef起的别名。


这个模板类中已经重载了上面列举出来的种种操作符号operator +、-、*、+=、-=、!=。
Vec类常被用来描述多通道的像素数组类型。
1.4 绘制直线的数量
从上面的分析看出,最终得到的line Vector,无论是Vec2f还是Vec4i类型,每一个元素都是一条直线,只是最终绘制的时候
“解码”的方式不同,HoughLinesP()不需要进行极坐标换算回直角坐标这一步,一行就搞定了。
通过设置threshold的值来调整检测到的直线的数量,增加threshold的值,减少检测直线的数量,反之增加。
3.Demo
GITEE
GITHUB
















