OpenCV利用霍夫变换实现交通车道线检测
作者:肖爱Kun
一、霍夫变换
经典霍夫变换用来检测图像中的直线,后来霍夫变换经过扩展可以进行任意形状物体的识别,例如圆和椭圆。霍夫变换运用两个坐标空间之间的变换,将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。
二、霍夫变换直线检测的原理
(1)图像空间中的点与参数空间中的直线一一对应
在图像空间直角坐标系x-y中,一条直线在直角坐标系下可以表示为:y = k x + b;其中常数k和b是参数,表示直线的斜率和截距。过某一点A ( x 0 , y 0 ) 的所有直线的参数均满足方程:y 0 = k ∗x 0 + b ;即过图像上的一点A ( x 0 , y 0 )可以确定N条直线。
如果我们将方程改写为:b=-kx0+y0;那么该方程在参数空间k-b中就对应了一条直线。也就是说,图像空间直角坐标系x-y中的点( x 0 , y 0 ) ;对应了参数空间k-b中的直线 b = − k ∗ x 0 + y 0 ;因此可以得到结论,图像空间中的点与参数空间中的直线一一对应。
直线y=kx+b上再增加一个点 B(x1, y1),B点在图像空间直角坐标系可以确定N条直线,那么点B ( x 1 , y 1 ) ,但是在参数空间也有一条对应的直线,与A ( x 0 , y 0 ) 确定的直线相较于M点。
(2)图像空间中的直线与参数空间中的点一一对应
图像空间直角坐标系x-y中的点A(x0,y0)和点B(x1,y1),在参数空间坐标系k-b中对应的直线相交于一点,这也就是说AB所确定的直线,在参数空间坐标系中对应着唯一一个点,而这个点的坐标值( k 0 , b 0 ) 也就是直线AB的参数。这就是直线检测任务中的对偶性,这个性质也为我们解决直线检测任务提供了方法,也就是把图像空间中的直线对应到参数空间中的点,最后通过统计特性来解决问题。假如图像空间中有两条直线,那么最终在参数空间中就会对应到两个峰值点,依此类推。
参数空间选择了笛卡尔直角坐标系是为了解释偶性和霍夫变换的基本原理,但在实际应用中,参数空间是不能选择直角坐标系的,原始图像直角坐标空间中的特殊直线x=c(c为常数,垂直x轴,直线的斜率为无穷大)是没办法在基于直角坐标系的参数空间中表示的,一般我们采用极坐标方式作为参数空间。
空间直角坐标系与极坐标系的转换
在下图中可以看出,参数空间的每个点(r,θ)都对应了图像空间直角坐标系的一条直线,或者说图像空间的一个点在参数空间中就对应为一条曲线。参数空间采用极坐标系,这样就可以在参数空间表示图像空间直角坐标系中的所有直线了。此时图像空间直角坐标系x-y上的一个点对应到参数空间(极坐标系ρ-θ)上是一条曲线,确切的说是一条正弦曲线。
经过变换,图像空间中的每个点(x,y)就被映射为一个(r,θ)极坐标空间中的正弦曲线。而图像空间直角坐标系中共线的点所对应的参数空间中正弦曲线相交于一点(r’,θ’)。这样就把在图像空间中检测直线的问题,转化为在极坐标参数空间中寻找通过点(r,θ)的最多正弦曲线数量的问题。霍夫空间中,曲线的交点次数越多,所代表的参数越确定(相交的曲线都是图像空间直角坐标系上的点),画出的图形越饱满。空间直角坐标系上一条直线上的所有点都转化为参数空间上的曲线,曲线一定会交于一个共同点。
三、霍夫变换直线检测 API函数接口
OpenCV支持三种霍夫直线检测算法:
1)Standard Hough Transform(SHT,标准霍夫变换)
2)Multiscale Hough Transform(MSHT,多尺度霍夫变换)
3)Progressive Probability Houth Transform(PPHT,渐进概率式霍夫变换)
(1)标准霍夫变换直线检测 cv::HoughLines从平面坐标转换到霍夫空间,最终输出是 (θ,rθ) 表极坐标空间。
霍夫直线变换API函数接口
cv::HoughLines( InputArray src, // 输入图像,必须8-bit的灰度图像 OutputArray lines, // 输出的极坐标来表示直线 ,经过调用HoughLines函数后储存了霍夫线变换检测到线条 //的输出矢量(每一条线由具有两个元素的矢量(rho,theta)表示) double rho, // 生成极坐标时候的像素扫描步长 double theta, //生成极坐标时候的角度步长,一般取值CV_PI/180 int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线 double srn=0;// 是否应用多尺度的霍夫变换,如果不是设置0表示经典霍夫变换 double stn=0;//是否应用多尺度的霍夫变换,如果不是设置0表示经典霍夫变换 double min_theta=0; // 表示角度扫描范围 0 ~180之间, 默认即可 double max_theta=CV_PI ) // 一般情况是有经验的开发者使用,需要自己反变换到平面空间
HoughLines函数输出检测到直线的矢量表示集合,每一条直线由具有两个元素的矢量(ρ, θ)表示,其中ρ表示直线距离原点(0, 0)的长度,θ表示直线的角度(以弧度为单位)。HoughLines函数无法输出图像空间中线段的长度。
(2)HoughLinesP:渐进概率式霍夫变换
cv::HoughLinesP( InputArray src, // 输入图像,必须8-bit的灰度图像 OutputArray lines, // 输出的极坐标来表示直线 double rho, // 生成极坐标时候的像素扫描步长 double theta, //生成极坐标时候的角度步长,一般取值CV_PI/180 int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线 double minLineLength=0;// 最小直线长度 double maxLineGap=0;// 最大间隔 )
渐进概率式霍夫变换直线检测 cv::HoughLinesP最终输出是直线的两个点。HoughLinesP能够检测出线端,即能够检测出图像中直线的两个端点,确切地定位图像中的直线。
四、霍夫直线变换实现车道线的检测
(1)彩色图像RBG转化为灰度图Gray,opencv上需要注意颜色空间是RGB还是BGR,CImg中RGB分别对应0,1,2通道。
(2)因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波(或者高斯滤波)去噪,平滑图像,消除图像噪声。
(3)图像边缘提取(梯度算子、拉普拉斯算子、canny边缘检测算法)
(4)图像二值化(判断此处是否为边缘点,就看灰度值==255),在高斯去噪和边界提取之后都需要二值化。
(5)映射到霍夫空间(此处准备两个容器,一个CImg用来展示hough-space概况,一个数组hough-space用来储存voting的值,因为投票过程往往有某个极大值超过255,多达几千,不能直接用灰度图来记录投票信息)。
(6)取局部极大值,设定阈值,过滤低于阈值的像素,排除干扰直线
(7)绘制直线。
代码实现
#include"stdafx.h" #include<opencv2\imgproc\imgproc.hpp> #include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using namespace std; using namespace cv; int main() { Mat Image = imread("F:/photo/cdjc.jpg", 0); Mat CannyImg; Canny(Image, CannyImg, 140, 250, 3); imshow("CannyImg", CannyImg); Mat DstImg; cvtColor(Image, DstImg, COLOR_GRAY2BGR); vector<Vec4i> Lines; HoughLinesP(CannyImg, Lines, 1, CV_PI / 360, 170, 30, 15); for (size_t i = 0; i < Lines.size(); i++) { line(DstImg, Point(Lines[i][0], Lines[i][1]), Point(Lines[i][2], Lines[i][3]), Scalar(0, 0, 255), 2, 8); } imshow("HoughLines_Detect", DstImg); waitKey(0); return 0; }
图像处理效果
到此这篇关于OpenCV利用霍夫变换实现交通车道线检测的文章就介绍到这了,更多相关OpenCV车道线检测内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!