基于OpenCV的视频道路车道检测

基于OpenCV的视频道路车道检测

  • 前言
  • 综述
  • 运行方法
  • 车道检测的实现
    • 路面图像二值化
    • 基于透视变换提取车道区域
    • 基于二次多项式拟合车道线
    • 基于二次多项式拟合车道线
    • 计算曲率半径与车辆的偏移距离
    • 用车道区域标注原始图像
  • 总结

前言

本篇博客转载于博主@Ginomica

综述

据统计近年来将近一半的交通事故与车辆行驶偏离正常车道有关。驾驶员注意力不集中或者疲劳驾驶,导致车辆无意识的偏离是交通事故的主要原因,由此汽车驾驶过程中车道偏离的自动检测也成为业界研究热点。

基于以上的实际需要,本设计完成了一种基于视频道路的车道检测方法,用于对车道的信息进行检测。主要研究内容如下:

  1. 利用颜色空间变换、Sobel算子创建阈值化二值图像,检测出的目标线可能是车道线的一部分;
  2. 应用透视变换校正二值图像,获得车道的鸟瞰图,裁剪原始图像中最有可能具有车道线像素的区域;
  3. 基于二次多项式对车道线进行拟合,确定车道边界;
  4. 确定车道曲率和车辆相对于中心的位置,使用从透视变换计算出的逆矩阵对原始图像进行覆盖;
  5. 向原始图像添加文本以显示车道线的曲率半径和车辆偏移距离。

运行方法

python line_fit_video.py

下面是项目文件的功能说明,项目文件已经上传至GitHub与码云。
https://gitee.com/Ginomica/lane_detection

Input_Video.mp4 - 输入视频
Output_Video.mp4 - 输出视频
combined_thresh.py - 路面图像二值化实现
perspective_transform.py - 透视变换实现
line_fit.py - 基于二次多项式拟合车道线及曲率半径、车辆偏移距离实现
line_fit_video.py - 主文件

车道检测的实现

路面图像二值化

创建一个阈值化的二值图像,将未失真的图像作为输入。目标是识别可能是车道线一部分的像素。特别是执行以下操作:

  1. 应用以下带阈值的过滤器,以创建对应于每个单独过滤器的独立二进制图像: 图像上的绝对水平Sobel算子; Sobel算子在水平和垂直方向,并计算其大小; Sobel算子计算梯度的方向;
  2. 把图像从RGB空间转换到HLS空间,阈值化S通道;
  3. 将上述二进制图像合并,创建最终的二进制图像。

下图所示便是利用多个过滤器的Sobel算子来对图像进行二值化处理的最终结果。 路面图像二值化 图一表示绝对水平Sobel算子过滤器相对应的二值图像 图二表示水平方向和垂直方向的Sobel算子过滤器相对应的二值图像 图三表示梯度方向的Sobel算子过滤器相对应的二值图像 图四表示HLS空间且对S通道设置阈值的过滤器相对应的二值图像 图五表示原图像 图六表示结合以上的二值图像创建的最终的二值图像
基于OpenCV的视频道路车道检测_第1张图片

基于透视变换提取车道区域

给定阈值的二值图像,下一步是执行透视变换。目标是转换图像,使我们获得车道的鸟瞰图,这使我们能够将曲线拟合到车道线【例如多项式拟合】。同时裁剪原始图像中最有可能有车道线像素的区域。

为了完成透视变换,使用OpenCV的getPerspectiveTransform()和warpPerspective()函数。同时对透视变换的源点和目标点进行了硬编码。源点和目的点通过人工检查直观地确定。

下图所示便是透视变换后的图像与透视空间逆变换后的图像。 基于透视变换提取车道区域 基于透视变换提取车道区域
基于OpenCV的视频道路车道检测_第2张图片
基于OpenCV的视频道路车道检测_第3张图片

基于二次多项式拟合车道线

给定上一步变换后的二进制图像,现在为左右车道线拟合一个二阶多项式。

计算图像下半部分的直方图,将图像分成9个水平切片,从底部开始,在直方图的左峰和右峰周围围起一个200像素宽的窗口【将直方图垂直拆分为两半】,在水平窗口切片上查找可能是左车道和右车道一部分的像素,像素最多的位置作为车道线的起始位置,然后自定义窗口大小和个数向上做滑窗操作,滑动窗口自下往上计算在滑动窗口中的投影值, 取投影值最大的列和滑动窗口底边所在的行作为透视空间中的车道线坐标点,求出每个窗口中像素点的x和y坐标作为车道线的x,y坐标,当前窗口像素的平均x坐标作为下一个滑窗的中心位置。给定左车道线和右车道线候选像素,利用滑动窗口和车道线的坐标用cv2.fitpoly()函数拟合二阶多项式,表示估计的左车道线和右车道线。

滑窗的方法通常用于第一帧或者检测失败重新开始的检测方式,对计算资源浪费过多,检测时间长。由于连续帧图像之间相差不大,之后几帧的图像可以只对第一帧拟合的曲线周围检测,设置周围的margin,然后在该范围内寻找下一帧曲线的像素点从而拟合曲线。在最后处理每一帧图像时要设置标志位检测是否检测到拟合的曲线,检测到的话用tune_fit()方法,否则的话要用滑窗的方法重新寻找车道线。

由于我们的目标是从视频流中找到车道线,所以我们可以利用视频帧之间的时间相关性。给定从先前视频帧计算的多项式拟合,实现的方法是从先前预测的车道线水平搜索+ / -100像素。然后我们只需对快速搜索中找到的像素执行二阶多项式拟合。如果我们找不到足够的像素,我们可以返回一个错误【例如return None】,并且函数的调用方将忽略当前帧(即保持车道线不变),并确保在下一帧上执行完全搜索。总的来说,这将提高车道检测的速度。利用时间相关性的另一个好处是平滑多项式拟合参数,这样做的好处是使检测器对噪声输入更为鲁棒。对于最近的5个视频帧,使用了多项式系数的简单移动。

下图所示便是利用滑动窗口检测车道线的位置与二次多项式拟合后的左右车道线。
基于OpenCV的视频道路车道检测_第4张图片

基于二次多项式拟合车道线

计算曲率半径与车辆的偏移距离

给出了左车道线和右车道线的多项式拟合,根据这里给出的公式计算每条线的曲率半径。将距离单位从像素转换为米,假设垂直方向每720像素30米,水平方向每700像素3.7米。最后平均左右车道线的曲率半径,并在最后的视频标注曲率半径值。

从给定的左车道线和右车道线拟合的多项式中计算出车辆的偏移量。车辆中心的偏移量在最后进行了注释。在把像素转换成米时利用同样的假设。为了计算车辆与车道线中心的偏移量,假设车辆的中心是图像的中心,计算左车道线底部x值和右车道线底部x值的平均值作为车道的中心。偏移量就是车辆的中心x值【即图像的中心x值】减去车道的中心x值。

用车道区域标注原始图像

给定以上所有内容,我们可以用车道面积以及关于车道曲率和车辆偏移的信息来注释原始图像。

  1. 创建一个空白图像,并绘制我们的拟合线【估计左右车道线】;
  2. 填充线条之间的区域【绿色】;
  3. 使用从透视变换计算的逆变换矩阵来取消上面的透视变换效果,使其与原始图像的透视对齐;
  4. 在原始图像上覆盖上述信息;
  5. 向原始图像添加文本以显示车道曲率和车辆偏移。
    用车道区域标注原始图像
    基于OpenCV的视频道路车道检测_第5张图片

总结

本设计基于OpenCV实现了对视频道路的车道检测。基于HLS颜色空间和 Sobel边缘提取方法设置一定的阈值范围来对图像其进行有效分割,检测车道线的大概位置,接着基于透视变换在透视变换空间中提取车道线的坐标点,并用二次多项式拟合车道线,从给定的左车道线和右车道线拟合的多项式中计算出左右车道线的曲率半径、车辆的偏移量,并在原始图像上面对这些信息进行标注,有效地实现了对于车道的检测,鲁棒性较好。但是仍然存在着不足之处:当在有裂缝的道路上进行检测时,裂缝可能被误认为是车道线导致检测失误;前面的其他车辆也有可能诱使车道检测认为它是车道的一部分,导致检测失败。为了使车道检测系统鲁棒性更佳,我们可以结合深度学习中语义分割的方法对以上的问题进行解决,语义分割是在像素级别上的分类,属于同一类的像素都要被归为一类,因此语义分割是从像素级别来理解图像的,例如基于深度学习的语义分割来查找可能是车道的像素。

文章转载于:https://gitee.com/Ginomica/lane_detection

Authors
duxiaobai

你可能感兴趣的:(人工智能,opencv,计算机视觉,python)