目录

效果预览

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:安装教程

相关技术文档参考:官方文档 官方API手册


效果预览

 

 

湖大体育馆门前: 

 

opencv找图大漠找图_OpenCV

侧压线检测:

opencv找图大漠找图_图像空间_02

opencv找图大漠找图_图像空间_03

 

0.Hough变换的理论基础

0.0 简介

霍夫变换可以解决不限于直线,圆形,椭圆的检测,通过在常见的坐标系中参数方程的刻画,转移到另一个由这些参数构成的坐标系中,通过求交点的方式来判断最终的效果,但是随着几何图形的维度的增加,计算量会以指数级速度上升。

例如直线的刻画:

无论是直角坐标系,使用参数 k & b

opencv找图大漠找图_图像空间_04

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

opencv找图大漠找图_OpenCV_05

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

opencv找图大漠找图_OpenCV_06

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

对于一个椭圆:

opencv找图大漠找图_OpenCV_07

,其有4个参数,最终映射的到一个4维空间。

 


0.1 对直线的分析

如果首先分析一条直线:

opencv找图大漠找图_OpenCV_05

对于不同的(

opencv找图大漠找图_图像空间_09

,

opencv找图大漠找图_图像空间_10

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

opencv找图大漠找图_opencv找图大漠找图_11

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

opencv找图大漠找图_OpenCV_05

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

opencv找图大漠找图_图像空间_09

,

opencv找图大漠找图_图像空间_10

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

opencv找图大漠找图_图像空间_09

,

opencv找图大漠找图_图像空间_10

)),相当于三角曲线上的每一个点都对应输入图像空间中的一条直线,整条三角曲线上的所有的点对应原来的输入图像空间中过点(x0, y0)的所有的直线。这样,在输入图像中划定了ROI(region of interest)感兴趣区域之后,就对ROI区域中的每一个像素点进行Hough变换,映射到三角函数区域中,在遍历输入图像中的所有的输入像素点之后,得到的三角函数曲线簇会产生若干交点,设置一个threshold,用来找到被大于一定数量三角曲线穿过的Hough变换空间点,最终选择 (

opencv找图大漠找图_图像空间_17

,

),并将这两个参数映射回输入图像空间,就找到了需要发现的直线,检测圆、椭圆等原理相同,但是映射空间会变得更高维(三维、四维),相应的计算量也会加大。

 

例如:下面取x0 = 3, y0 = 4生成了曲线如下:横坐标为

opencv找图大漠找图_图像空间_09

,纵坐标为

opencv找图大漠找图_图像空间_10

opencv找图大漠找图_图像空间_20

例如:取一系列的不同  (

opencv找图大漠找图_图像空间_17

,

) 最终得到交点:

opencv找图大漠找图_opencv找图大漠找图_22

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

opencv找图大漠找图_图像空间_09

,

opencv找图大漠找图_图像空间_10

),然后带入:(r =

opencv找图大漠找图_图像空间_10

)

opencv找图大漠找图_opencv找图大漠找图_11

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

opencv找图大漠找图_Line_27

 

 

1 OpenCV中的Hough直线变换 

 OpenCV中提供了两个函数用来进行直线检测

1.1 HoughLines()

1.1.1 The Standard Hough Transform

opencv找图大漠找图_图像空间_28

 

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

opencv找图大漠找图_opencv找图大漠找图_29

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向量使用上面分析的极坐标参数表示(ρ,θ) ,要换算为熟悉的直角坐标理解需要借助:

opencv找图大漠找图_opencv找图大漠找图_11

函数HoughLinesP()每一条直线是由一个4元素向量(x1, y1, x2, y2)构成的,被检测到的直线的端点分别为(x1, y1)、(x2, y2)。

之后的代码中会看到有Vec2f、Vec4i这两种数据类型分别用于两种不同函数的Lines向量类型。

Vec2f 对应 Vec<float, 2>类型。

Vec4i本身是一个模板参数类 Vec的模板参数为int,4的时候使用typedef起的别名。

 

opencv找图大漠找图_opencv找图大漠找图_31

opencv找图大漠找图_opencv找图大漠找图_32

这个模板类中已经重载了上面列举出来的种种操作符号operator +、-、*、+=、-=、!=。

Vec类常被用来描述多通道的像素数组类型。

1.4 绘制直线的数量

从上面的分析看出,最终得到的line Vector,无论是Vec2f还是Vec4i类型,每一个元素都是一条直线,只是最终绘制的时候

“解码”的方式不同,HoughLinesP()不需要进行极坐标换算回直角坐标这一步,一行就搞定了。

通过设置threshold的值来调整检测到的直线的数量,增加threshold的值,减少检测直线的数量,反之增加。

 

3.Demo

GITEE 

GITHUB