大约十年前,当谷歌还在试验一辆原型车的时候,我想到了自己的第一辆自动驾驶汽车,当时我立刻被这个想法迷住了。不可否认的是,我必须等待一段时间,直到这些概念向社区开放,现在看来等待确实是值得的!我最近试验了一些与计算机视觉有关的自动驾驶汽车概念,里面包括车道检测,它实际上是设计任何一款自主汽车的核心概念。以下是我们将在本视频中构建的车道检测系统:https://youtu.be/sYhZbhT-Smw很酷,对吧?在这个教程中,我会使用OpenCV库进行车道检测和自动驾驶汽车。当然,在本教程中,我们还将引入Python代码。

目录

  1. 车道检测概念解释
  2. 问题陈述
  3. 什么是帧掩码?
  4. 车道检测的图像预处理
  5. 用OpenCV在Python中实现车道检测

车道检测概念解释

那么什么是车道检测?以下是百度百科对车道的定义:

车道,又称行车线、车行道,是用在供车辆行经的道路,在一般公路和高速公路都有设置,高速公路对车道使用带有法律性质的规则,例如行车道和超车道。


对其进行定义是很重要的,因为它使我们能够继续进行车道检测概念。我们在建立一个系统时不能有任何含糊不清的地方。正如我前面提到的,车道检测是自动驾驶汽车的关键组成部分,这是驾驶场景理解的重要研究课题之一。一旦获得车道位置,车辆就知道去哪里,并避免撞上其他车道或离开道路。这样可以防止驾驶员/车辆系统偏离车道。以下是一些随机道路图像(第一行)及其检测到的车道(第二行):


问题陈述

我们希望执行的任务是实时检测视频中的车道。我们可以通过多种方式进行车道检测,我们可以使用基于学习的方法,例如在带注释的视频数据集上训练深度学习模型,或者使用预训练好的模型。然而,也有更简单的方法来执行车道检测。在本文中,我将向你展示如何在不使用任何学习模型的情况下完成此任务。但是我们将使用Python中流行的OpenCV库。下面是我们将要处理视频的一个帧:


正如我们在这张图片中看到的,我们有四条车道被白色的车道标线隔开。所以,要检测车道,我们就必须检测车道两边的白色标记。这就引出了一个关键问题——我们如何检测车道标线?除了车道标线之外,场景中还有许多其他对象,如道路上有车辆、路侧护栏、路灯等。在视频中,每一帧都会有场景变化,这很好地反映了真实的驾驶情况。因此,在解决车道检测问题之前,我们必须找到一种方法来忽略驾驶场景中不需要的对象。我们现在能做的一件事就是缩小感兴趣的领域。与其使用整个帧,不如只使用帧的一部分。在下面的图像中,除了车道的标记之外,其他所有内容都隐藏了。当车辆移动时,车道标线将或多或少地落在该区域内:


在下一节中,我将向你展示如何编辑视频帧以选择特定区域。你还将了解一些必要的图像预处理操作。

什么是帧掩码(Frame Mask)?

在这里,帧掩码只是一个NumPy数组。当我们想对图像应用掩码时,只需将图像中所需区域的像素值更改为0、255或任何其他数字。下面给出了一个图像掩蔽的例子,图像中某个区域的像素值已设置为0:


这是一种非常简单但有效的从图像中去除不需要的区域和对象的方法。

车道检测的图像预处理

我们将首先对输入视频中的所有帧应用掩码,然后我们将应用图像阈值化和霍夫线变换来检测车道标线。

图像阈值化

在这种方法中,灰度图像的像素值根据阈值被指定为表示黑白颜色的两个值之一,因此如果一个像素的值大于一个阈值,它被赋予一个值,否则它被赋予另一个值。


如上所示,对蒙版图像应用阈值后,我们只得到输出图像中的车道标线。现在我们可以通过霍夫线变换很容易地检测出这些标记。

霍夫线变换

霍夫线变换是一种检测任何可以用数学方法表示形状的方法。例如,它可以检测矩形、圆、三角形或直线等形状。我们感兴趣的是检测可以表示为直线的车道标线。这是相关文档:https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_houghlines/py_houghlines.html在执行图像阈值化后对图像应用霍夫线变换将提供以下输出:


我们需要对所有帧执行此过程,然后将生成的帧缝合到新视频中。

用OpenCV在Python中实现车道检测

是时候用Python实现这个车道检测项目了!我推荐使用Google Colab,因为构建车道检测系统需要计算能力。首先导入所需的库:

import osimport reimport cv2import numpy as npfrom tqdm import tqdm_notebookimport 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 frameplt.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()

# 应用该多边形作为掩码img = cv2.bitwise_and(col_images[idx][:,:,0], col_images[idx][:,:,0], mask=stencil)# plot masked frameplt.figure(figsize=(10,10))plt.imshow(img, cmap= "gray")plt.show()

图像预处理

我们必须对视频帧执行一些图像预处理操作来检测所需的车道。预处理操作包括:

  1. 图像阈值化
  2. 霍夫线变换
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 = 0for 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中的车道检测系统。

结尾

在本教程中,我们介绍了一种简单的车道检测技术。我们没有使用任何模型或复杂的图像特征,相反,我们的解决方案完全基于某些图像预处理操作。但是,在很多情况下,这个解决方案都无法工作。例如,当没有车道标线,或者道路上的车辆太多时,该系统将失败。在车道检测中有更复杂的方法来克服这些问题。原文链接:https://www.analyticsvidhya.com/blog/2020/05/tutorial-real-time-lane-detection-opencv/留言送书福利

感谢大家的走心留言,每一条小编都认真阅读了,会继续努力哒。

这次没被抽中的朋友不要气馁~ 我们会坚持不定期推出留言送书活动,多多留言会增加中奖概率的。恭喜下面留言的两位读者,分别获赠书籍《Python数据分析与可视化从入门到精通》一本。请联系小编:mthler

☆ END ☆如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 mthler」,每日朋友圈更新一篇高质量博文(无广告)。扫描二维码添加小编↓

python获取数组中大于某一阈值的那些索引值_使用Python+OpenCV进行实时车道检测...相关推荐

  1. python获取数组中大于某一阈值的那些索引值_Python NumPy 高级索引——整数组索引、布尔索引及花式索引...

    NumPy 除了之前文章中介绍的用整数和切片的索引外,数组还可以由整数数组索引.布尔索引及花式索引. 整数数组索引 整数索引有助于基于 N 维索引来获取数组中任意元素.每个整数数组表示该维度的下标值. ...

  2. python获取数组中大于某一阈值的那些索引值_java矩阵计算及其在统计中的应用(一)...

    该文介绍了java colt和commons-math3的一些矩阵计算API,并且使用colt库简单实现了基于法方程组法的最小二乘法,结构方程模型的梯度下降参数估计,广义混合效应模型(多层广义线性模型 ...

  3. python获取数组中最多的元素

    获取数组中数量最多的元素,也就是最频繁的那个元素,方法有很多,下面是3种最简单的: 1.用max函数 sample = [1,2,3,3,3,4,5,5] max(set(sample), key=s ...

  4. 使用Python+OpenCV进行实时车道检测

    大约十年前,当谷歌还在试验一辆原型车的时候,我想到了自己的第一辆自动驾驶汽车,当时我立刻被这个想法迷住了.不可否认的是,我必须等待一段时间,直到这些概念向社区开放,现在看来等待确实是值得的! 我最近试 ...

  5. python获取数组中最多的元素(用max函数)

    sample1 = [1,2,3,3,3,4,5,5] max(set(sample1),key=sample1.count)

  6. python 获取字符串中的字典_python cookies提取——从字符串到字典(一行Python代码)...

    def extract_cookies(cookie): """从浏览器或者request headers中拿到cookie字符串,提取为字典格式的cookies&quo ...

  7. python取出数组大于某值_Python替换NumPy数组中大于某个值的所有元素实例

    我有一个2D(二维) NumPy数组,并希望用255.0替换大于或等于阈值T的所有值.据我所知,最基础的方法是: shape = arr.shape result = np.zeros(shape) ...

  8. 获取数组中元素值为偶数的累加和与元素值为奇数的累加和,并计算他们之间的差值

    /*** 1.获取数组中元素值为偶数的累加和与元素值为奇数的累加和,并计算他们之间的差值* 1.定义int getNum(int[] arr)静态方法,该方法要求完成* 1.1 获取指定数组arr中元 ...

  9. python获取数组长度_Python返回数组(List)长度的方法

    原博文 2016-03-16 11:53 − 其实很简单,用len函数: >>> array = [0,1,2,3,4,5]>>> print len(array) ...

最新文章

  1. DevOps火爆,招人却太难了!
  2. python排课问题_排课问题分析
  3. 一起学设计模式-观察者模式
  4. win10安装mysql5.6,mysql启动时,闪退
  5. 二分+最大化最小值 River Hopscotch POJ - 3258
  6. some useful tricks
  7. ECShop如何设置默认的配送方式和支付方式
  8. iso安装器_U盘安装优麒麟20.04系统,Ubuntu通用
  9. Axure| 旋转控件或者图片
  10. PaddleOCR详解和识别图片中文字
  11. 第一周 1.17-1.19
  12. 记录下公司刻录新版本/repo_kitkat 命令
  13. react 数据可视化_使用d3创建数据可视化并在2020年做出React
  14. springboot整合ActiveMQ(点对点和发布订阅)
  15. 并不对劲的方格取数问题
  16. 传奇私服游戏支付接口申请(已解决)
  17. 闻灾情 忆国殇 山河呜咽 寄哀思
  18. 基于Detectron2模型和深度学习方法的改进森林火灾检测方法
  19. 如何分析安卓系统日志
  20. Minitab 软件部署指南详情

热门文章

  1. 最早做无糖茶的统一茶里王,是怎样错过年轻人的?
  2. 以高端牌乘风破浪的飞鹤,究竟是“实力派”还是“偶像派”?
  3. java io--内存操作流_JavaIO——内存操作流、打印流
  4. 启动计算机引导win10,教您win10引导项丢失怎么办
  5. CTF- Reverse迷宫题类型方法特征讲解
  6. 【Python教程】常见字符串去除空格的教程
  7. 四种高性能数据类型,Python collections助你优化代码、简洁任务
  8. python中实现延时回调普通函数示例代码
  9. 平顶山学院计算机专业是几本,平顶山学院是几本_是二本还是三本大学?
  10. python报错:TypeError: cant multiply sequence by non-int of type float(bug)(csdn标题没法用英文引号,以后注意别搜引号)