大约十年前,谷歌的人还在尝试原型车的时候,我预见到了自己的第一辆自动驾驶车。 我很快就被这个想法迷住了。 不可否认,这些概念必须等一会儿才能向社区开放,但现在看来值得等待
最近,我们实验了几个与计算机视觉相关的自动驾驶汽车的概念。 这包括车道检测。 请考虑一下。 这实际上是设计哪种自主汽车的中心概念。
用该视频构建的车道检测系统如下所示。 https://youtu.be/sYhZbhT-Smw
很帅,不是吗? 在本教程中,您将使用OpenCV库进行车道检测和自动驾驶车辆。 当然,在本教程中,还将引入Python代码。
目录
要理解车道检测的概念理解问题,什么是框架屏蔽? 车道检测的图像预处理用OpenCV用Python实现车道检测理解车道检测的概念
,什么是车道检测? 以下是百度百科对车道的定义。车道也称为行车道、车道,是车辆通行的道路。 一般道路和高速道路上都有设置,高速道路对车道有行驶车道和超车车道等法律上的规定使用。
定义这个很重要。 因为我们可以继续车道检测的概念。 我们在建立系统的时候不能有模糊的地方。
综上所述,车道检测是自动驾驶车和自动驾驶车的重要组成部分。 这是理解驾驶场景的重要研究课题之一。 获得车道位置后,车辆将知道要去哪里,以免撞到其他车道或远离道路。 这样可以防止驾驶员/车辆系统偏离车道。
以下是几个随机道路图像(第1行)及其检测到的车道)第2行)。
理解问题
我们要执行的任务是实时检测视频中的车道。 我们可以用各种方法进行车道检测。 可以使用基于学习的方法,例如在带注释的视频数据集上训练深度学习模型,或使用预训练的模型。但是,也有执行车道检测的更简单的方法。 本文将向您展示如何在不使用深度学习模式的情况下完成这项任务。 但是,使用Python中受欢迎的OpenCV库。
以下是我们接下来要处理的视频的一帧。
正如在这张照片中看到的,我们有四条车道被白色车道隔开。 所以,要检测车道,就必须检测车道两侧的白色标记。 这是个重要的问题。如何检测——车道标线?
除了车道标线以外,场景中还有许多对象。 道路上有车辆、路边护栏、路灯等,在视频中,每个框架的场景都有变化。 这很好地反映了实际的驾驶状况。
因此,在解决车道检测问题之前,必须找到忽略驾驶场景中不需要的对象的方法。
我们现在能做的事情之一就是缩小感兴趣的领域。 与其使用整个框架,不如只使用框架的一部分。 在下面的图像中,除了车道上的标记以外,所有的标记都是隐藏的。 车辆移动时,车道标线或多或少都会落在这个区域内。
下一节将演示如何编辑视频帧以选择特定的区域。 我还知道一些必要的图像预处理操作。
什么是帧掩码(Frame Mask)?
在这里,帧遮罩只是一个NumPy数组。 如果要对图像应用蒙版,只需将图像中所需区域的像素值更改为0、255或其他数字。 图像遮罩的示例如下所示。 图像中区域的像素值设置为0。
虽然这很简单,但它是一种有效地从图像中移除不需要的区域和对象的方法。
车道检测的图像预处理
对输入视频的所有帧应用遮罩。 然后,应用图像的阈值化和漂亮的涂层线变换检测车道标线。right">图像阈值化
在这种方法中,灰度图像的像素值根据阈值被指定为表示黑白颜色的两个值之一。因此,如果一个像素的值大于一个阈值,它被赋予一个值,否则它被赋予另一个值。
如上所示,对蒙版图像应用阈值后,我们只得到输出图像中的车道标线。现在我们可以通过清脆的外套线变换很容易地检测出这些标记。
清脆的外套线变换
清脆的外套线变换是一种检测任何可以用数学方法表示的形状的方法。
例如,它可以检测矩形、圆、三角形或直线等形状。我们感兴趣的是检测可以表示为直线的车道标线。
这是相关文档:https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html
在执行图像阈值化后对图像应用清脆的外套线变换将提供以下输出:
我们需要对所有帧执行此过程,然后将生成的帧缝合到新视频中。
用OpenCV在Python中实现车道检测
是时候用Python实现这个车道检测项目了!我推荐使用Google Colab,因为构建车道检测系统需要计算能力。
首先导入所需的库:
import os import re import cv2 import numpy as np from tqdm import tqdm_notebook import matplotlib.pyplot as plt读取视频帧
我已经从这个YouTube视频中抽取了一些视频片段。你可以从这个链接下载:https://drive.google.com/file/d/1e4cc4zFFna3Owyym6aq7ZXoquHA2l95O/view?usp=sharing。
# 获取帧的文件名 col_frames = os.listdir('frames/') col_frames.sort(key=lambda f: int(re.sub('D', '', f))) # 加载帧 col_images=[] for i in tqdm_notebook(col_frames): img = cv2.imread('frames/'+i) col_images.append(img)让我们绘制一个帧:
# 指定一个索引 idx = 457 # plot frame plt.figure(figsize=(10,10)) plt.imshow(col_images[idx][:,:,0], cmap= "gray") plt.show()帧掩码创建
我们感兴趣的区域是一个多边形。我们想掩盖除了这个区域以外的一切。因此,我们首先必须指定多边形的坐标,然后使用它来准备帧掩码:
# 创建0矩阵 stencil = np.zeros_like(col_images[idx][:,:,0]) # 指定多边形的坐标 polygon = np.array([[50,270], [220,160], [360,160], [480,270]]) # 用1填充多边形 cv2.fillConvexPoly(stencil, polygon, 1) # 画出多边形 plt.figure(figsize=(10,10)) plt.imshow(stencil, cmap= "gray") plt.show()图像预处理
我们必须对视频帧执行一些图像预处理操作来检测所需的车道。预处理操作包括:
图像阈值化清脆的外套线变换1.图像阈值化
# 应用图像阈值化 ret, thresh = cv2.threshold(img, 130, 145, cv2.THRESH_BINARY) # 画出图像 plt.figure(figsize=(10,10)) plt.imshow(thresh, cmap= "gray") plt.show()2.清脆的外套线变换
lines = cv2.HoughLinesP(thresh, 1, np.pi/180, 30, maxLineGap=200) # 创建原始帧的副本 dmy = col_images[idx][:,:,0].copy() # 清脆的外套线 for line in lines: x1, y1, x2, y2 = line[0] cv2.line(dmy, (x1, y1), (x2, y2), (255, 0, 0), 3) # 画出帧 plt.figure(figsize=(10,10)) plt.imshow(dmy, cmap= "gray") plt.show()现在我们将对每个帧应用所有这些操作。我们还将结果帧保存在新目录中:
cnt = 0 for img in tqdm_notebook(col_images): # 应用帧掩码 masked = cv2.bitwise_and(img[:,:,0], img[:,:,0], mask=stencil) # 应用图像阈值化 ret, thresh = cv2.threshold(masked, 130, 145, cv2.THRESH_BINARY) # 应用清脆的外套线变换 lines = cv2.HoughLinesP(thresh, 1, np.pi/180, 30, maxLineGap=200) dmy = img.copy() #画出检测到的线 try: for line in lines: x1, y1, x2, y2 = line[0] cv2.line(dmy, (x1, y1), (x2, y2), (255, 0, 0), 3) cv2.imwrite('detected/'+str(cnt)+'.png',dmy) except TypeError: cv2.imwrite('detected/'+str(cnt)+'.png',img) cnt+= 1视频准备
# 输入帧的路径 pathIn= 'detected/' #输出视频路径 pathOut = 'roads_v2.mp4' # 视频每秒的帧数 fps = 30.0 from os.path import isfile, join # 获取帧的文件名 files = [f for f in os.listdir(pathIn) if isfile(join(pathIn, f))] files.sort(key=lambda f: int(re.sub('D', '', f)))接下来,我们将把检测到的车道上的所有帧放入一个列表中:
frame_list = [] for i in tqdm_notebook(range(len(files))): filename=pathIn + files[i] #读取每一个文件 img = cv2.imread(filename) height, width, layers = img.shape size = (width,height) #将帧插入图像数组 frame_list.append(img)最后,我们现在可以使用下面的代码将帧合并为视频:
# 写入视频 out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'DIVX'), fps, size) for i in range(len(frame_array)): out.write(frame_array[i]) out.release()这就完成了Python中的车道检测系统。
结尾
在本教程中,我们介绍了一种简单的车道检测技术。我们没有使用任何模型或复杂的图像特征。相反,我们的解决方案完全基于某些图像预处理操作。
但是,在很多情况下,这个解决方案都无法工作。例如,当没有车道标线,或者道路上的车辆太多时,该系统将失败。在车道检测中有更复杂的方法来克服这些问题。