自动驾驶算法———车道检测(一)

 

在本章中,我将指导您构建一个简单但有效的车道检测管道,并将其应用于Carla 模拟器中捕获的图像。管道将图像作为输入,并产生车道边界的数学模型作为输出。图像由行车记录仪(固定在车辆挡风玻璃后面的摄像头)捕获。车道边界模型是一个多项式

图片

在这里,x𝑥和𝑦y以米为单位。它们在道路上定义了一个坐标系,如图1所示。

管道由两个步骤组成

  • 使用神经网络,检测图像中车道边界的像素

  • 将车道边界像素与道路上的点关联起来,

    图片

        然后拟合多项式。

该方法的灵感来自参考文献[ GBN+19 ]中描述的“基线”方法,其性能接近最先进的车道检测方法。

图 1道路坐标系。该视角称为鸟瞰图

01

图像基础

为了表示图像,我们使用形状为 (H,W,3) 的三维数组。我们称该数组有 H 行、W 列和 3 个颜色通道(红色、绿色和蓝色)。让我们用 Python 加载图像并查看一下!

import numpy as npimport matplotlib.pyplot as pltfrom pathlib import Pathimport cv2img_fn = str(Path("images/carla_scene.png"))img = cv2.imread(img_fn)# opencv (cv2) stores colors in the order blue, green, red, but we want red, green, blueimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)plt.imshow(img)plt.xlabel("$u$") # horizontal pixel coordinateplt.ylabel("$v$") # vertical pixel coordinate
print("(H,W,3)=",img.shape)
(H,W,3)= (512, 1024, 3)

让我们检查一下第 100 行和第 750 列的像素:

u,v = 750, 100img[v,u]
array([28, 59, 28], dtype=uint8)

这意味着 处的像素具有红色强度 28、绿色强度 59 和蓝色强度 28。因此,它是绿色的。如果我们看一下图像,这是有道理的,因为 处有一棵树。此外,上面的输出“ ”告诉我们红色、绿色和蓝色强度存储为 8 位无符号整数,即。因此,它们是 0 到 255 之间的整数。u,v = 750, 100u,v = 750, 100dtype=uint8uint8

下面的示意图总结了我们迄今为止学到的关于存储数字光栅图像的知识:

如果您的数字图像是由相机拍摄的,那么数字图像中的像素与相机图像传感器中的“传感器像素”之间存在直接对应关系。

图像传感器由二维光电传感器阵列组成。每个光电传感器通过光电效应将入射光转换为电能,然后通过模数转换器将其转换为数字信号。为了获得颜色信息,一个“传感器像素”被分成 2×2 的光电传感器网格,并在这 4 个光电传感器前面放置不同的颜色滤镜。一个光电传感器仅通过蓝色滤镜接收光,一个仅通过红色滤镜接收光,两个通过绿色滤镜接收光。将这 4 个测量值结合起来可得到一个颜色三重奏:。这就是所谓的拜耳滤镜。(red_intensity, green_intensity, blue_intensity)

针孔相机模型

想象一下将图像传感器放在物体前面。

图片

您将无法捕捉到如此清晰的图像,因为图像传感器上的某个点会受到整个环境光线的照射。现在想象一下将图像传感器放在一个带有非常小的针孔(也称为光圈)的盒子里。

图片

现在大部分光线都被挡住了,我们在图像传感器上得到了正确的图像。图像被上下翻转了,但这不应该困扰我们。在理想针孔的情况下,图像传感器上的每个点都只会被来自外部的一束光线击中。

理想针孔:一个很好的近似值

在现实世界中,孔的尺寸不能太小,因为进入盒子的光线不够。此外,我们还会遭受衍射的影响。孔也不能太大,因为来自不同角度的光线会照射到图像传感器上的同一点,图像会变得模糊。为了防止模糊,真实的相机中会安装镜头。我们将在本节讨论的针孔相机模型不包括镜头的影响。然而,事实证明,它非常接近带镜头的相机,也是相机的事实模型。因此,在下文中,我们可以继续将针孔视为理想的针孔

下面的草图介绍了图像平面

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

图片

练习:将车道边界投影到图像

现在你应该开始做你的第一个练习了。对于这个练习,我为你准备了一些

数据。我使用安装在车辆上的相机传感器在 Carla 模拟器中捕捉到了一张

图片:

图片

图片

参考

  • HZ03

  • Richard Hartley 和 Andrew Zisserman。计算机视觉中的多

    视图几何。剑桥大学出版社,2003 年。

02

车道边界分割

对于车道检测流程,我们想要训练一个神经网络,该神经网络会获取一张图像,并估计每个像素属于左车道边界的概率、属于右车道边界的概率以及不属于任何车道边界的概率。这个问题称为语义分割。

先决

对于本节,我假设以下内容

  1. 你知道什么是神经网络,并且之前自己训练过一个

  2. 你知道语义分割的概念

如果你不满足先决条件 1,我建议你查看以下免费资源之一

  • CS231n:用于视觉识别的卷积神经网络

  • 对于这门优秀的斯坦福课程,你可以在网上找到所有的学习材料。课程笔记还没有完成,但确实存在的笔记非常好!请注意,当你点击详细课程大纲时,你可以看到所有讲座的幻灯片。你可能想使用2017 年的版本,因为其中包含讲座视频。但是,对于练习,你应该使用2020版本(与 2017 年非常相似),因为你可以在Google Colab中进行编程。Google Colab 让你可以在 Google 服务器上免费使用 GPU(深度学习所需的昂贵硬件)。即使你不想使用 Colab,2020 年的课程也有更好的本地工作说明(包括 anaconda)。对于你可以在 tensorflow 和 pytorch 之间选择的练习,我建议你使用 pytorch。如果你真的渴望尽快回到这门课程,你可以在了解语义分割后停止 CS231n。

  • 为程序员提供实用的深度学习

  • 如果您的背景更多的是编码而不是数学/科学,那么我推荐这门课程。您可以在这里找到视频讲座,在这里找到用 jupyter 笔记本编写的书(如果您喜欢,还有一个印刷版本)。我建议使用 Google Colab 进行练习。fastai 课程使用 fastai 库进行讲授,该库可帮助您使用很少的代码行来训练 pytorch 模型。即使您选择不研究 fastai 课程,我也建议您查看fastai 库,因为它使训练模型变得非常容易。也许先从阅读计算机视觉教程开始)。

关于先决条件 2 ,我推荐Jeremy Jordan 撰写的这篇关于语义分割的非常好的博客文章(主要基于 CS231n)。

最后,你需要有 GPU 才能进行练习。但拥有GPU 并不是先决条件。你可以使用Google Colab,它允许你在 Google 服务器上运行 Python 代码。要在 Colab 上访问 GPU,你应该点击“运行时”,然后点击“更改运行时类型”,最后选择“GPU”作为“硬件加速器”。有关如何使用 Colab 的更多详细信息,请参阅附录。

练习:训练神经网络进行车道边界

车道分割模型应将形状为 (512,1024,3) 的图像作为输入。这里,512 是图像高度,1024 是图像宽度,3 代表红、绿、蓝三个颜色通道。我们使用形状为 (512,1024) 的输入图像和相应的标签来训练模型,其中label[v,u]可以取值为 0、1 或 2,表示像素(𝑢,𝑣)是“无边界”、“左边界”还是“右边界”。

模型的输出应是output形状为 (512,1024,3) 的张量。

  • 这个数字output[v,u,0]给出了像素(𝑢,𝑣)不属于任何车道边界的一部分。

  • 这个数字output[v,u,1]给出了像素(𝑢,𝑣)是左车道边界的一部分。

  • 这个数字output[v,u,2]给出了像素(𝑢,𝑣)是右侧车道边界的一部分。

  • 收集训练

    我们可以使用 Carla 模拟器收集训练数据。我写了一个collect_data.py脚本

    请注意,从四个数据项(图像、车道边界、交通矩阵、标签图像)中,只有图像和标签图像对于训练我们的深度学习模型是必要的。

    所有数据均在“Town04”Carla 地图上收集,因为这是唯一一张有可用高速公路的地图(“Town06”的高速公路要么完全笔直,要么有 90 度转弯)。为简单起见,我们只为高速公路构建一个系统。因此,我们只使用地图中道路曲率较低的部分,不包括城市道路。

    地图的一部分被任意选为“验证区”。在此区域中创建的所有数据的文件名都添加了字符串“validation_set”。

    现在您需要将一些训练数据导入到您的机器上!我建议您下载我使用脚本为您创建的一些训练数据collect_data.py。但如果您真的想要,您也可以自己收集数据。

    推荐:下载数据

    只需继续打开中的启动代码code/exercises/lane_detection/lane_segmentation.ipynb即可。它将有一个 Python 实用函数,可为您下载数据。

    替代方案:自己生成数据

    • 存储来自相机传感器的图像

    • 存储从 Carla 高清地图获得的车道边界的世界坐标

    • 存储变换矩阵𝑇𝑐𝑤将世界坐标映射到相机参考系中的坐标

    • 存储标签图像,该图像是根据车道边界坐标和变换矩阵创建的,如上一节练习中所示

    • 在 Carla 地图上创建一辆

    • 将 RGB 摄像头传感器安装到车辆上

    • 将车辆移动到不同的位置并

  • 模型

    为了创建和训练模型,您可以选择任何您喜欢的深度学习框架。

    如果你需要一些指导,我建议使用 fastai。你可以使用fastai 文档中的语义分割示例,根据手头的数据集稍微修改一下,它就可以正常工作了!如果你愿意,你可以得到一些提示:

    没有提示

    好的,没有提示。如果您遇到困难,请尝试查看“有限提示”或“详细提示”。

    基本提示高级提示

    存储你的模型

    您将需要训练好的模型来进行接下来的练习。因此,请将训练好的模型保存到磁盘。在 pytorch 中,您可以通过 执行此操作torch.save。对于 fastai,您可以执行torch.save(learn.model, './fastai_model.pth')

    可选:参与 kaggle 活动

    我为你准备的训练数据也可以在kaggle上找到。如果你愿意,你可以用 kaggle 笔记本在线创建你的模型。他们还提供免费的 GPU 访问。一旦你对你的解决方案感到满意,可以考虑在 kaggle 上发布你的笔记本。我很想看到它😃。

具体指引详见《https://thomasfermi.github.io/Algorithms-for-Automated-Driving/LaneDetection/Segmentation.html》

03

从像素转换米

图片

图片

图片

图片

图片

图片

import numpy as npimport matplotlib.pyplot as plt

从车道边界分割中,我们知道我们的语义分割模型将以摄像头图像作为输入,并返回output形状为 (H,W,3) 的张量。具体来说,像素prob_left = output[v,u,1](𝑢,𝑣)是左车道边界的一部分。我将output[v,u,1]神经网络为一些示例图像计算的张量保存在 npy 文件中。让我们来看看。

prob_left = np.load("../../data/prob_left.npy")plt.imshow(prob_left, cmap="gray")plt.xlabel("$u$");plt.ylabel("$v$");

图片

上图显示prob_left[v,u]了每个(u,v)。现在想象一下,(u,v,prob_left[v,u])我们不是使用三元组,而是使用三元组(x,y,prob_left(x,y)),其中(𝑥,𝑦)是道路上的坐标,如图19所示。如果我们有这些三元组,我们可以过滤所有较大的(x,y,prob_left[x,y])prob_left[x,y]。我们将获得一个点列表(𝑥𝑖,𝑦𝑖)它们是左车道边界的一部分,我们可以使用这些点来拟合多项式𝑦𝑙(𝑥)!但从 到(u,v,prob_left[v,u])实际上(x,y,prob_left[x,y])并不难,因为你uv_to_roadXYZ_roadframe_iso8855在上一个练习中实现了该函数。此函数将(𝑢,𝑣)进入(𝑥,𝑦,𝑧)(注意𝑧=0对于道路像素)

这意味着我们可以开始编写一些代码来收集三元组(x,y,prob_left[x,y])

import syssys.path.append('../../code')from solutions.lane_detection.camera_geometry import CameraGeometrycg = CameraGeometry()
xyp = []for v in range(cg.image_height):    for u in range(cg.image_width):        X,Y,Z= cg.uv_to_roadXYZ_roadframe_iso8855(u,v)        xyp.append(np.array([X,Y,prob_left[v,u]]))xyp = np.array(xyp)

图片

x_arr, y_arr, p_arr = xyp[:,0], xyp[:,1], xyp[:,2]mask = p_arr > 0.3coeffs = np.polyfit(x_arr[mask], y_arr[mask], deg=3, w=p_arr[mask])polynomial = np.poly1d(coeffs)

让我们绘制多项式:​​​​​​​

x = np.arange(0,60,0.1)y = polynomial(x)plt.plot(x,y)plt.xlabel("x (m)"); plt.ylabel("y (m)"); plt.axis("equal");

图片

管道封装成一个

您现在已经了解了车道检测流程的两个步骤:车道边界分割和多项式拟合。为了便于将来使用,将整个流程封装到一个类中会很方便。在下面的练习中,您将实现这样一个LaneDetector类。现在,让我们看一下LaneDetector实际操作的示例解决方案。首先,我们加载一个图像​​​​​​​

import cv2img_fn = "images/carla_scene.png"img = cv2.imread(img_fn)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)plt.imshow(img);

图片

现在我们导入该类LaneDetector并创建它的一个实例。为此,我们指定使用 pytorch 函数存储的模型的路径save。​​​​​​​

from solutions.lane_detection.lane_detector import LaneDetectormodel_path ="../../code/solutions/lane_detection/fastai_model.pth"ld = LaneDetector(model_path=model_path)

从现在开始,我们可以通过将任何图像(与训练集没有太大差别)传递给实例来获取车道边界多项式ld

poly_left, poly_right = ld(img)

图片

Reference

https://thomasfermi.github.io/Algorithms-for-Automated-Driving/LaneDetection/InversePerspectiveMapping.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/375808.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一图展示免费开源的分布式版本控制系统​Git

文章目录 前言一、安装Git二、Git配置三、git命令 前言 Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。 一、安装Git Windows操作系统…

MFC扩展库BCGControlBar Pro v35.0 - 可视化管理主题等全新升级

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中,并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.0已全新发布了,这个版本改进类Visual Studio 2022的视觉主题、增强对多个…

大模型时代的目标检测

https://zhuanlan.zhihu.com/p/663703934https://zhuanlan.zhihu.com/p/6637039341.open set/open word/ood 这个任务是指在实际应用上可以检测任何前景物体,但是有些不需要预测类别,只要检测出框就行。在很多场合也有应用场景,有点像类无关…

ASP.NET MVC Lock锁的测试

思路:我们让后台Thread.Sleep一段时间,来模拟一个耗时操作,而这个时间可以由前台提供。 我们开启两个或以上的页面,第一个耗时5秒(提交5000),第二个耗时1秒(提交1000)。 期望的测试结果: 不加Lock锁&…

短视频矩阵搭建,用云微客获客更方便

你的同行都爆单了,你还在问什么是矩阵?让我来告诉你。短视频矩阵是短视频获客的一种全新玩法,是以品牌宣传、产品推广为核心的一个高端布局手段,也是非常省钱的一种方式。 1.0时代,一部手机一个账号;2.0时代…

nx上darknet的使用-目标检测-自定义训练与制作预训练模型

目录 1 训练yolov4-tiny 1.1 文件准备 1.1.1 Annotations 1.1.2 JPEGImages 1.1.3 labels 1.1.4 trained_models 1.1.5 classes.name 1.1.6 create_labels_txt.py 1.1.7 custom_training.data 1.1.8 get_labels.py 1.1.9 get_train_val.py 1.1.10 train…

鼠标怎么挑选

我们平时工作中经常要用到鼠标,那么哪种鼠标比较好。我们今天就来研究下。 手感要好 鼠标最重要的就是手感。这个看参数看不出来。最好能到实体店里面去体验一下,自己上手试一下。 如果现在都是在网上买了,去实体店过于麻烦,并且…

【系统架构设计】计算机组成与体系结构(三)

计算机组成与体系结构(三) 计算机系统组成存储器系统主存储器辅助存储器Cache存储器Cache 基本原理映射机制直接映射全相联映射组相联映射 替换算法写操作 流水线(计算)流水线周期流水线执行时间流水线的吞吐率流水线的加速比 计算…

暑期备考美国数学竞赛AMC8和AMC10:吃透1850道真题和知识点

距离接下来的AMC8、AMC10美国数学竞赛还有几个月的时间,实践证明,做真题,吃透真题和背后的知识点是备考AMC8、AMC10有效的方法之一。 通过做真题,可以帮助孩子找到真实竞赛的感觉,而且更加贴近比赛的内容,…

python自动化之用flask库写一个登陆接口(代码示例)

用到的库: 1、flask(写接口) 2、cerberus(校验数据) 实现效果:输入账号和密码,校验数据类型是否是字符串,如果是,返回登陆成功;如果不是,返回数…

apache:the requested operation has failed使用httpd -t

Apache24\bin cmd 回车 httpd -t 因为我重新压缩了,记住,重新压缩要使用原路径, 因为你安装的 时候使用的是原路径 还是不行就改个端口,切记修改配置文件httpd.conf先把Tomcat停了 Define SRVROOT "F:\Apache\Apache24&q…

Electron运行报错:Error Cannot find module ‘node_moduleselectroncli.js‘

Electron运行报错:Error: Cannot find module ‘node_modules\electron\cli.js’ 顾名思义,命令行执行Electron .时候,会优先从项目目录查找对应依赖,如果是报错显示是找不到项目目录下的依赖,我们可以从安装在全局的…

【活动预告】Apache IoTDB TsFile 智慧能源应用“上会”啦!

2024 年,站在中国数字经济产业升级和数据要素市场化建设的时代交汇点上,为进一步推动全球数据库产业进步,由中国通信标准化协会、大数据技术标准推进委员会主办的“2024 可信数据库发展大会”将于 2024 年 7 月 16-17 日,在北京朝…

【运维】项目运维方案(word原件)

1. 文档介绍 2. 人员与责任 3. 运维过程内容 4. 运维资源 5. 运维服务规划保障 6. 事件处置 7. 质量改进 8. 运维边界及内容 获取方式: 本文末个人名片直接获取。

安装jenkins最新版本初始化配置及使用JDK1.8构建项目详细讲解

导读 1.安装1.1.相关网址1.2.准备环境1.3.下载安装 2. 配置jenkins2.1.安装插件2.2.配置全局工具2.3.系统配置 3. 使用3.1.配置job3.2.构建 提示:如果只想看如何使用jdk1.8构建项目,直接看3.1即可。 1.安装 1.1.相关网址 Jenkins官网:https…

了解并缓解 IP 欺骗攻击

欺骗是黑客用来未经授权访问计算机或网络的一种网络攻击,IP 欺骗是其他欺骗方法中最常见的欺骗类型。通过 IP 欺骗,攻击者可以隐藏 IP 数据包的真实来源,使攻击来源难以知晓。一旦访问网络或设备/主机,网络犯罪分子通常会挖掘其中…

Mac M1安装配置Hadoop+Flink SQL环境

Flink 1.18.1 Hadoop 3.4.0 一、准备工作 系统:Mac M1 (MacOS Sonoma 14.3.1) JDK:jdk1.8.0_381 (注意:尽量一定要用JDK8,少用高版本) Scala:2.12 JDK安装在本机的/opt/jdk1.8.0_381.jdk/C…

uniapp微信小程序 TypeError: $refs[ref].push is not a function

我的写法 this.$refs.addPopup.open();报错 打印出来是这样的 解决 参考未整理 原因 在当前页面使用的v-for循环 并且循环体内也有组件使用了ref(而我没有把每个ref做区别命名) 这样就导致了我有很多同名的ref,然后就报错了 解决办法&a…

值得关注的数据资产入表

不错的讲解视频,来自:第122期-杜海博士-《数据资源入表及数据资产化》-大数据百家讲坛-厦门大学数据库实验室主办第122期-杜海博士-《数据资源入表及数据资产化》-大数据百家讲坛-厦门大学数据库实验室主办-20240708_哔哩哔哩_bilibili

C语言 | Leetcode C语言题解之第231题2的幂

题目&#xff1a; 题解&#xff1a; const int BIG 1 << 30;bool isPowerOfTwo(int n) {return n > 0 && BIG % n 0; }