如何通过计算机视觉去识别车道线

描述

因为种种原因导致上个月没有更新推文,所以特此发此推文表示歉意。

今天介绍的是如何通过计算机视觉去识别车道线,其实现在也有各种方法去识别车道线了。这次是基于Matlab的实现,过几天会更新Python版本的实现,虽然用的语言不一样,但是原理都是一样的。

预处理

摄像机获得的视频图像,由于受到周围环境的影响,存在着很多无用信息和各种各样的噪声干扰。为了准确的检测到道路线必须对图像进行预处理。首先,通过灰度化处理将原始彩色图像转换为灰色图像,然后采用大小为5*5的模板进行高斯滤波平滑处理,减小噪声干扰。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。

若使用3×3模板,则计算公式如下

g(x,y)={f(x-1,y-1)+f(x-1,y+1)+f(x+1,y-1)+f(x+1,y+1)+[f(x-1,y)+f(x,y-                                              1)+f(x+1,y)+f(x,y+1)]*2+f(x,y)*4}/16;

其中,f(x,y)为图像中(x,y)点的灰度值,g(x,y)为该点经过高斯滤波后的值

由于天空并不存在车道的感兴趣区域,所以对图片进行了划分,将感兴趣区域划为一个三角形区域。如图1。

图一

预处理代码如下:

%读入RGB图片

I=imread('IMG00061.jpg');

%把RGB图转换为灰度图

I=rgb2gray(I);

%高斯滤波平滑处理

sigma = 1;

gausFilter =fspecial('gaussian', [5,5], sigma);

gaus= imfilter(I, gausFilter,'replicate');

%得到图片的宽和高

[h, w]=size(I);

%k是直线的斜率

%找出图片的感兴趣区域

k = 1.3;

for y=1:h

for x=1:w

if y < x*k + h-k*w || y < -k*x +h

I(y, x) = 0;

end

end

end

边缘检测

由于车道线的灰度比路面更加明亮,以此可以用边缘检测的方法把车道的边缘检测出来。在边缘检测中,我用了‘Sobel’算子。在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量

Sobel卷积因子为:

matlab

该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:

matlab

图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小: 

matlab

通常,为了提高效率 使用不开平方的近似值:

matlab

所得到的结果如图2:

图2

霍夫变换直线检测

有了边缘检测的二值图后可以对图像进行霍夫变换,霍夫变换是图像变换中的经典手段之一,主要用来从图像中分离出具有某种相同特征的几何形状(如,直线,圆等)。霍夫变换的原理是将特定图形上的点变换到一组参数空间上,根据参数空间点的累计结果找到一个极大值对应的解,那么这个解就对应着要寻找的几何形状的参数(比如说直线,那么就会得到直线的斜率k与常数b,圆就会得到圆心与半径等等)。经过霍夫变换后可得到如图3关于ρ和θ的图。

图3

图中最亮的几个点则为峰值,峰值中极有可能存在直线。可以选出一组候选的峰值,然后决定线的起始点和终点。函数houghlines用默认的语法执行这个任务:

lines = houghlines(f, theta,rho, peaks)

或者使用完整的语法形式:

lines = houghlines(...,'FillGap', val1, 'MinLength', val2)

其中,theta和rho是来自函数hough的输出,peaks是函数houghpeaks的输出。

效果

为了美观和效果,我对检测出来的线段进行了延长处理,效果如下图4。

图4

完整代码如下:

clear

close all

%读入RGB图片

I=imread('IMG00061.jpg');

%把RGB图转换为灰度图

I=rgb2gray(I);

%高斯滤波平滑处理

sigma = 1;

gausFilter = fspecial('gaussian', [5,5], sigma);

gaus= imfilter(I, gausFilter, 'replicate');

%得到图片的宽和高

[h, w]=size(I);

%k是直线的斜率

%切图,找出图片的感兴趣区域

k = 1.3;

for y=1:h

for x=1:w

if y < x*k + h-k*w || y < -k*x + h

I(y, x) = 0;

end

end

end

imshow(I)

%用Sobel算子做边缘检测

BW = edge(I,'sobel');

%霍夫变换

[H,T,R] = hough(BW);

imshow(H,[],'XData',T,'YData',R, 'InitialMagnification','fit');

xlabel(' heta'), ylabel(' ho');

axis on, axis normal, hold on;

%找出霍夫变换的峰值

P = houghpeaks(H,2);

%用霍夫变换检测和连接线

lines = houghlines(BW,T,R,P);

figure;

imshow(I); hold on

%画线

for k = 1:length(lines)

p1 = lines(k).point1;

p2 = lines(k).point2;

syms slope b

[b, slope] = solve(slope*p1(1)-p1(2)+b, slope*p2(1)-p2(2)+b);

plot([(h-b)/slope, (0.4*h-b)/slope], [h, 0.4*h], 'g-', 'LineWidth',3);

end

代码中用到的图片:

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分