1 简介
随着全球经济的快速发展,居民的车辆拥有率也在不断攀升,伴随而来的就是日益严重的交通问题。为了减缓交通运输压力,世界各国都加强了对智能交通系统的研究和建设。交通运输未来的发展趋向于智能化,作为一种新兴产业,智能交通已为我国经济不断发展注入了新的动力。车道偏离预警系统作为 ITS其中的一部分,在车辆偏离车道行驶时,通过发出警告提醒驾驶人员进而避免危险发生。而构成交通环境的基础因素就是车道线,因此车道线的检测尤为重要。本文主要基于 Hough(霍夫)变换原理,以交通视频检测图像为研究对象,对车道检测的关键技术进行了研究。Hough变换作为一种常用的从图像中识别出几何图形的方法,其具有较好鲁棒性,可以在噪声环境比较大的情况下识别出车道直线。 首先,本文大概介绍了智能交通系统及车道预警系统的应用需求,国内外对其的研究及应用现状。针对图像的预处理问题,本文对图像灰度化、灰度的线性变换、图像增强及边缘检测进行了分析与实现,以采集到的车道图像作为实验对象,通过对比实际效果确定了车道预处理的具体流程与方法。通过分析几种交通检测方法及常用车道检测方法,并对 Hough变换进行了测试,通过比较实际效果,充分说明了 Hough变换在车道检测方面的优越性,最终确定将 Hough变换作为主要算法。然后以交通监测视频中提取的背景图像为研究对象,针对车道划分对车道背景主要进行了以下处理:首先将背景车道进行灰度处理,将彩色图片转换为灰度图;其次是将处理后的灰度图进行灰度线性变化和二值化处理,目的是去除车道边缘附近的噪声白点;将生成的二值图进行中值滤波和Roberts边缘检测,然后进行Hough变换拟合出车道线
2 部分代码
function colorAndTypeIdx = videodetectcolorandtype(twoLines_0b, YCbCr) % VIDEODETECTCOLORANDTYPE - Detects if the lane detected is Yellow/White % and Solid/Broken in videoldws demo. % Copyright 2008-2009 The MathWorks, Inc. % twoLines_0b = coordinate points of lines (0 based) % % Here, for a line with start point (r1,c1) and end point (r2,c2), % we form a ROI with points: % (r1,c1-HALF_OFFSET) (r1,c1+HALF_OFFSET) % (r2,c2-HALF_OFFSET) (r2,c2+HALF_OFFSET) % We search for yellow/white color within this ROI INVALID_COLOR = int8(0); WHITE_COLOR = int8(1); YELLOW_COLOR = int8(2); INVALID_MARKING = int8(0); BROKEN_MARKING = int8(1); SOLID_MARKING = int8(2); INVALID_COLOR_OR_TYPE = int8(1);% color=yellow/white; type=broken or solid YELLOW_BROKEN = int8(2); YELLOW_SOLID = int8(3); WHITE_BROKEN = int8(4); WHITE_SOLID = int8(5); lineColorIdx = int8([0 0]); solidBrokenIdx = int8([0 0]); colorAndTypeIdx = int8([0 0]); HALF_OFFSET = int32(10); zeroI32 = int32(0); oneI32 = int32(1); twoI32 = int32(2); rH = int32(size(YCbCr(:,:,1),1)); cW = int32(size(YCbCr(:,:,1),2)); tmpInImage_Y = YCbCr(:,:,1); tmpInImage_Cb = YCbCr(:,:,2); leftC = int32(zeros(rH,1)); rightC = int32(zeros(rH,1)); Rs = int32(zeros(rH,1)); twoLines_1b = twoLines_0b([2 1 4 3], :); for i=oneI32:int32(length(twoLines_1b(:))) twoLines_1b(i) = twoLines_1b(i) + oneI32; end for lineIdx =oneI32:twoI32%1:2 %% one line r1c1r2c2 = twoLines_1b(:,lineIdx) - 1; r1 = r1c1r2c2(1); c1 = r1c1r2c2(2); r2 = r1c1r2c2(3); c2 = r1c1r2c2(4); % make sure r1 is the min (r1,r2) if r1>r2 tmp=r2; r2=r1; r1=tmp; tmp=c2; c2=c1; c1=tmp; end pointNotLine = (r1==r2) && (c1==c2); % find if line is within image: (r1,c1) and (r2,c2) must be within image if ((r1>zeroI32 && r1 <= rH) && (c1>zeroI32 && c1 <= cW) && ... (r2>zeroI32 && r2 <= rH) && (c2>zeroI32 && c2 <= cW)) && ~pointNotLine line_within_image = logical(true); else line_within_image = logical(false); end if (line_within_image) len = r2-r1+oneI32; i=oneI32; % Rs(1:len)=r1:r2 for p=r1:r2 Rs(i) = p; i=i+oneI32; end %leftC(1:len) = int32(linspace(c1-HALF_OFFSET, c2-HALF_OFFSET, len)); %y = linspace(d1, d2, n) %y = [d1+(0:n-2)*(d2-d1)/(floor(n)-1) d2]; quotient = (single(c2-c1))/(single(len)-single(1) + single(eps));%(d2-d1)/(floor(n)-1) for i=oneI32:len leftC(i) = (c1-HALF_OFFSET) + int32((single(i)-single(1))*quotient); rightC(i) = leftC(i)+ twoI32*HALF_OFFSET; if leftC(i) < oneI32 leftC(i) = oneI32; if rightC(i) < oneI32 rightC(i) = oneI32; end end if rightC(i) > cW rightC(i) = cW; end end whiteCount = zeroI32; yellowCount = zeroI32; grayCount = zeroI32; SumOfGotAlLeastOneWhitePixelInTheRow = zeroI32; SumOfGotAlLeastOneYellowPixelInTheRow = zeroI32; for i=oneI32:len gotAlLeastOneWhitePixelInTheRow = logical(false); gotAlLeastOneYellowPixelInTheRow = logical(false); for cv = leftC(i):rightC(i) if tmpInImage_Y(Rs(i), cv) >= single(175/255) whiteCount = whiteCount+oneI32; gotAlLeastOneWhitePixelInTheRow = logical(true); elseif tmpInImage_Cb(Rs(i), cv) >= single(90/255) && tmpInImage_Cb(Rs(i), cv) <= single(127/255) yellowCount = yellowCount+oneI32; gotAlLeastOneYellowPixelInTheRow = logical(true); else grayCount = grayCount+oneI32; end end if gotAlLeastOneWhitePixelInTheRow SumOfGotAlLeastOneWhitePixelInTheRow = SumOfGotAlLeastOneWhitePixelInTheRow+oneI32; end if gotAlLeastOneYellowPixelInTheRow SumOfGotAlLeastOneYellowPixelInTheRow = SumOfGotAlLeastOneYellowPixelInTheRow+oneI32; end end yellowVsTotal = single(yellowCount)/single(grayCount+yellowCount+whiteCount); whiteVsTotal = single(whiteCount)/single(grayCount+yellowCount+whiteCount); if yellowVsTotal > whiteVsTotal lineColorIdx(lineIdx) = YELLOW_COLOR; linearPixelRatio = single(SumOfGotAlLeastOneYellowPixelInTheRow)/single(len); else lineColorIdx(lineIdx) = WHITE_COLOR; linearPixelRatio = single(SumOfGotAlLeastOneWhitePixelInTheRow)/single(len); end %% distinguish solid and broken lane markers % if we use yellowVsTotal(==whiteVsTotal) to find marker type (solid/broken) % it would not give accurate result; because in the patch we are searching % for yellow/white pixel- we do not know what's the pecentage of gray pixels % are there % that's why we are considering a different method; here we try to find one % yellow (==white) pixel in one row; once we find a yellow (==white) pixel % in the row we don't need to find anything in that row of the patch (ROI) if linearPixelRatio > single(0.8) solidBrokenIdx(lineIdx) = SOLID_MARKING; else solidBrokenIdx(lineIdx) = BROKEN_MARKING; end if (lineColorIdx(lineIdx) == YELLOW_COLOR) && (solidBrokenIdx(lineIdx) == BROKEN_MARKING) colorAndTypeIdx(lineIdx) = YELLOW_BROKEN; elseif (lineColorIdx(lineIdx) == YELLOW_COLOR) && (solidBrokenIdx(lineIdx) == SOLID_MARKING) colorAndTypeIdx(lineIdx) = YELLOW_SOLID; elseif (lineColorIdx(lineIdx) == WHITE_COLOR) && (solidBrokenIdx(lineIdx) == BROKEN_MARKING) colorAndTypeIdx(lineIdx) = WHITE_BROKEN; elseif (lineColorIdx(lineIdx) == WHITE_COLOR) && (solidBrokenIdx(lineIdx) == SOLID_MARKING) colorAndTypeIdx(lineIdx) = WHITE_SOLID; end else lineColorIdx(lineIdx) = INVALID_COLOR; solidBrokenIdx(lineIdx) = INVALID_MARKING; colorAndTypeIdx(lineIdx) = INVALID_COLOR_OR_TYPE; end end
3 仿真结果
4 参考文献
[1]王诗旋, 贺新升, 张荣辉,等. 基于Matlab和优化Hough变换的高速公路车道线检测方法[J]. 2021(2011-8):29-29.