无人驾驶之车道线检测简易版
Posted Young_Gy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无人驾驶之车道线检测简易版相关的知识,希望对你有一定的参考价值。
无人驾驶技术近些年发展迅速。无人车若想实现自动驾驶,从视觉的角度上讲其要先学会观察道路,具体来说,就是检测车道线。包括识别车道线与车的位置关系,是实线还是虚线等。本文将简单介绍车道线检测的基本技术,包括Canny Edges
、Hough Transform
等。
- Pipe Line
- Gray
- Gauss Blur
- Canny Edges
- ROIRegion of Interest Based Edge Filtering
- Hough Transform
- Lane Extrapolation
- 参考
Pipe Line
本文进行车道线检测的pipe line如下,主要使用了opencv
库:
- RGB to GRAY
- Gauss Blur
- Canny Edges
- Hough Transform
- Dram Lines
示例如下:
原始图片:
灰度图片:
高斯模糊图片:
Canny Edges:
多边形截取后的图片:
生成左右两条线:
和原图结合的最终图片:
Gray
通常的彩色图片是三通道的,简便起见,对其做单通道处理,转化为灰色图像。
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import cv2
# Read in and grayscale the image
image = mpimg.imread('image.jpg')
gray = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
转化的经验公式如下,该公式是根据人眼中三种不同的感光细胞的感光强度按比例分配的:
同时需要注意一点,从RGB到灰度图像本质上是建立了一个映射函数。对于确立好的映射函数,我们总能找到RGB空间中不同的点映射之后得到的点却基本相同。理由也很简单,从3通道到1通道肯定伴随着信息的损失。解决办法是不固定映射函数,根据图片做动态的映射函数。
Gauss Blur
高斯模糊就是用高斯核对图片做卷积操作,大小为5的高斯核如下:
- 原理:重新计算图片中每个点的值,计算的时候取该点与周围点的加权平均,权重符合高斯分布。
- 作用:降低图片噪声和减少细节(增强图片在不同scale下的structure),并保留边界。同时Gauss FIlter是一种低通滤波器,只允许低频部分通过,限制高频部分(例如像素值剧烈升高或降低的早点)。
- 效果:像通过半透明的玻璃看图片一样。
# Define a kernel size and apply Gaussian smoothing
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
Canny Edges
高斯模糊
首先,紧接上面的高斯模糊,边缘检测通常对噪声很敏感,所以在边缘检测前要用高斯模糊降噪,这样单独的一个像素噪声在经过高斯平滑后的图像上变得几乎没有任何影响。
计算梯度
边缘检测的本质是计算图片在每个点的梯度(像素值的变化情况),变化值越大表明是边缘的概率越高。 计算梯度的时候使用了卷积,相关计算如下(方向约成【0、45、90、135】之间):
Non-maximum suppression
计算完梯度后,需要进行thin the edge。方法是将每个像素点的梯度值与梯度方向上的两个点进行比较,当且仅当这个点的梯度值最大才保留,否则舍弃。(例如梯度方向是0度,那么将当前梯度值与左右两边的梯度值进行比较,当且仅当当前梯度值最大才保留)
Double threshold
进行Non-maximum suppression后,仍然可能有部分误标记的edge,这些误标记的edge可能来自噪音或者颜色的变化。解决的办法是设置两个阈值low_threshold、high_threshold,当前point的梯度gradient与阈值的关系如下:
- gradient < low_threshold:丢弃
- gradient > high_threshold:保留
- low_threshold < gradient < high_threshold: 当且仅当其存在相连点的梯度大于high_threshold才保留
# Define our parameters for Canny and apply
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
ROI(Region of Interest) Based Edge Filtering
通过Canny进行边缘检测获得边缘后,会发现,获得的边缘不仅包括需要的车道线边缘,同时包括不需要的其他车道以及周围围栏的边缘。去掉这些边缘的办法是确定一个多边形的可视域,只保留可视域部分的边缘信息。其依据是camera相对车是固定的,车相对于车道的相对位置也基本固定,所以车道在camera中基本保持在一个固定区域内。
# Next we'll create a masked edges image using cv2.fillPoly()
mask = np.zeros_like(edges)
ignore_mask_color = 255
# This time we are defining a four sided polygon to mask
imshape = image.shape
vertices = np.array([[(50,imshape[0]),(420, 280), (550, 280), (950,imshape[0])]], dtype=np.int32)
cv2.fillPoly(mask, vertices, ignore_mask_color)
masked_edges = cv2.bitwise_and(edges, mask)
Hough Transform
简介
霍夫变换一种特征提取技术,检测具有特定形状的物体,通常是直线、圆、椭圆。
其原理是将原空间隐射到参数空间,在参数空间进行投票获得所需的图形。
例子
下面以检测图片中的直线为例简单介绍霍夫变换。
原空间中的直线可以映射到参数空间中的点。C。
原空间中的点可以映射到参数空间中的直线。A。
原空间中的点可以映射到参数空间中的直线,参数空间中直线的交点代表原空间中点的连线。C。
原空间中的直线可以映射到参数空间中的点,参数空间中两个点的连线代表原空间中两个直线的交点。A。
如果用y=kx+b
中的k、b作为参数空间中的参数,会遇到竖直线k无穷大的问题,所以采用极坐标表示如下。
采用极坐标后,原空间的点对应参数空间的二次曲线,原空间的直线对应参数参数空间上的点。C。
车道线
无论采用xy坐标还是极坐标,原空间的点都对应参数空间的曲线,原空间的直线都对应着参数空间中曲线的交点。如下图所示,可以根据在参数空间中每个grid相交点的出现次数寻找原空间中的直线。
Hough变换的代码如下,其参数的含义见注释
rho = 2 # distance resolution in pixels of the Hough grid
theta = np.pi/180 # angular resolution in radians of the Hough grid
threshold = 15 # minimum number of votes (intersections in Hough grid cell)
min_line_length = 40 #minimum number of pixels making up a line
max_line_gap = 20 # maximum gap in pixels between connectable line segments
line_image = np.copy(image)*0 # creating a blank to draw lines on
# Run Hough on edge detected image
lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]), min_line_length, max_line_gap)
Lane Extrapolation
通过Hough变换后,得到了很多直线,例如下图:
为了获得左右各一条直线,如下图,还需要额外的工作。
这里介绍一种比较简单的方法:
- 将所有直线按照斜率分成左右两部分。
- 每部分求平均或者median得到加权的直线参数。
- 根据原图片的位置描绘出新参数的直线。
参考
本内容来源于Udacity Self-Driving Car Nano Degree,在此感谢Udacity全体工作人员对在线教育的付出。
以上是关于无人驾驶之车道线检测简易版的主要内容,如果未能解决你的问题,请参考以下文章