随着全球科技的飞速发展,无论是汽车行业还是其他的各行各业,紧跟时代脚步的重要性都是不容置疑的。近年来,自动驾驶汽车得到了很高的关注,但是理想和现实的差距却犹如天堑。在这样的背景下,我们决定将项目目标放在 Lyft 自动驾驶汽车的 3D 目标检测上。
为什么至今还没有无人驾驶汽车?
自动驾驶汽车是现代社会讨论最多的的技术之一。尽管许多公司都声称他们的驾驶辅助技术为“自动驾驶(autopilot)”,然而真正无需司机存在的自动驾驶汽车,还未在公共道路上出现。
来源:http://post.toutptit-toutbio.com/page-3/self-driving-car-timeline-28811.html
目前,全自动驾驶是处于汽车无人驾驶分级中的第四级。无人驾驶总共有五个等级:
1.最低等级是零级,汽车没有任何驾驶辅助技术。这一类包含了目前在美国公路上的大部分车辆。
2.等级一是汽车拥有一定驾驶辅助系统,例如盲点信息系统(BLIS),自适应巡航控制系统(ACC),自动紧急制动系统(AEB)。近些年发售的新车中大多都包含这类系统,这些驾驶辅助系统只会在检测到其他车辆时才会介入。
3.等级二的车辆可以控制方向盘、刹车和油门,包含诸如通用的 Super Cruise 和特斯拉的 Autopilot 系统。
4.等级三的系统是类似奥迪的交通拥堵辅助系统(Traffic Jam Assist),在时速 37 mph(60 km/h)以下时是可以完全自动驾驶的。
5.等级四的车辆是目前包括 Lyft、Uber 以及 Waymo 在全球范围内测试的自动驾驶车辆。等级四的车辆虽然是全自动驾驶,但必须有人类司机随时准备在难以驾驶的情况下接管。
6.等级五是全自动驾驶,无需人工接管。这其中最著名的应该是谷歌在几年前才推出的无人车。然而就算是这种无人车,它也是只能在规定的路线上行驶,因此也不能真正地称其为全自动。
有这么多划分自动驾驶车辆水平的智能等级,让人不禁怀疑为何现在无论是在当地车行或者是特斯拉线上都没有在销售真正的自动驾驶汽车。这一问题的主要原因可以用两大技术难点解释:
1.感知:对车辆周围环境的感知识别。
2.预测:对目标行为的预测。
由于感知系统是导致自动化驾驶发展缓慢的根本原因,我们决定将研究的重点放在提升车辆对周围环境的感知能力上。
感知问题
在研究目标上,我们选择感知系统而不是预测系统的另一个原因是,真正的自动驾驶汽车应该可以成为人类驾驶员更安全的选择。然而,自动驾驶仍然导致了一起死亡事件发生。事发原因是一辆 Uber 无人驾驶汽车因感知系统出现问题而致使一名行人被撞身亡。由此可见,感知问题对自动驾驶汽车而言不止是兴趣问题,更是生死攸关之事。
鉴于车辆感知问题的重要性,我们通过调查发现目前共有四种不同技术帮助车辆感知周围物体,分别是超声波、激光雷达、雷达和相机。这其中,激光雷达和相机是最重要的,超声波传感器主要用于停车感应,而雷达则是只用于 ACC 的长距离追踪。在现代系统中,相机通常都只是用来监控道路标线,在仪表盘上显示诸如限速等标识。而在自动驾驶车辆上,相机可以被用作是感知系统算法的输入,尽管这会很复杂。
在另一方面,激光雷达传感器是车辆探测周围物体的主要途径。激光雷达作为新时代的声纳系统,其工作原理是通过发射激光束,然后测量激光在物体表面反射回来的信号。通过计算测量得到的信号可以得到近乎即时的车辆周围的三维立体点云图,关于这一点,后文会有详细解释。这些三维图像普遍分辨率很低,也不会捕捉过于具体的信息,但却提供了车辆周围物体的大致形状。在了解到无人车感知系统的工作原理之后,下一步我们将调查业内有哪家公司有这方面的相关业务。
为什么选择 Lyft?
在自动驾驶行业竞争的数家公司中,Lyft 的开源平台让我们选择了它。因为相信自动驾驶技术的开发不是一个人或者一家公司能够独自完成的,Lyft 与 Aptiv 和 Waymo 合作开发了无人车的感知系统模型。Lyft 同样赞助了 Kaggle 上的竞赛,我们参加了其中一项比赛,使用 Lyft 提供的数据开发出最好的感知模型的团队可以获得 2.5 万美金奖励。那么就让我们来研究下 Lyft 的数据集吧。
开发数据
Lyft 提供给 Kaggle 竞赛的开发数据总共有 85 GB,其中包含训练数据、测试数据和一个结果示例。这些数据都是通过 Lyft 测试车采集到的三维点云以及摄像头数据。
我们的数据则是采集了十辆测试车行驶在加州帕洛阿尔托道路上,每辆车都在车顶配有七个摄像头以及一个 LiDAR 传感器,另外还有两个小型传感器在头灯下方。
来源:https://mobiag.com/blog/lyft-unveils-a-new-self-driving-car/
这七个摄像头都会以不同的固定角度捕获周围的图像。所得图像有超过 5.5 万个人工标记的 3D 注释,标记内容包含车辆、行人、自行车,详情可见下图中的橙色框。
场景的渲染图像
每个 LiDAR 传感器都将以 360 度的角度发射激光以检测物体并获得其三维空间几何信息。这些 LiDAR 传感器可以按 10Hz 生成一个包含 21.6 万点的点云图。模型的数据输入来自 13 个文件,具体包含以下组成:
样本数据(Sample_data),是由某个特定传感器收集到的数据。
样本注释(Sample_annotation),是对某物体的注释。
实例(instance),是对观察到的所有对象实例的枚举,例如上图中被标记的卡车。
类别(Categories),是观察到的物体的不同类种类。例如车辆、行人等等。
姿态(Ego_pose),是车辆在特定时间点的记录,可以用于对每个样本的映射。
地图数据(Map data),是车辆周围道路的二进制语义图。
校准传感器(Calibrated_sensor),用于校准特定车辆上的特定传感器。提供关于环境的信息,例如某物体的距离和方位,或者是直接测量传感器的位置和方向。calibrated_sensor 所携带的固有属性都是不依赖于外界或者传感器摆放位置的。它们的属性和距离矩阵将被用于和在类似时间戳下生成的三点云结合,并映射到三维的边界框中。
属性(attribute),是实例的属性,在类型一致的情况下可以改变。
所有的这些特征参数以及激光雷达还有图像数据都被分成训练数据和测试数据两部分,这些结合起来组成了这次竞赛提供的数据集。
解决方案
在初步了解到 Lyft 提供的 85 GB 大小数据中都是些什么之后,我们大致分析了激光雷达数据,并将其应用到我们的模型之中。因无法完整地将数据库下载到本地,我们选择使用谷歌云端平台(GCP)来将数据导入到实例之中,并在 GCP 上尝试进行数据分析和模型构建。以上就是我们设置 GCP 的步骤。
探索性分析
在用 Kaggle API 导入数据到 GCP 之后,我们开始处理激光雷达数据。
来源:https://www.mathworks.com/help/driving/ug/coordinate-systems.html
如上图所示,LiDAR 捕捉的主要测量指标有物体的 xyz 坐标以及其长宽高和转角。下面是 LiDAR 测试出的数据,为便于理解附上了简单解释:
1.centre_x,centre_y 以及 centre_z 分别对应某物体在三维平面的坐标。
2.yaw 表示 z 轴转角大小,转角正对车辆或边界框的前方在地面上指向的方向。
3.Length、width 以及 height 代表了被测试物体的边界大小。
我们根据 LiDAR 传感器传出的数据绘制了不同测量指标的分布图,以查看是否可以从中得出结论。我们选择从 x、y 和 z 值开始,然后再继续分析其他变量。
在分析过程中,centre_x 以及 centre_y 的分布显示出 LiDAR 相机的局限之处。相比车辆前后物体而言,车载摄像头更容易捕捉车辆两侧物体,这是因为车辆两侧物体在 LiDAR 中更加清晰也更容易被相机捕捉。相对应的,在车前和车后方的物体通常会和车辆在同一条直线上,因此也就更难被清晰地检测到。车辆两侧近距离的物体相较于 x 轴上的物体更容易被检测到,但同样在两侧但是在远距离的物体会比 x 轴上物体更难被检测到。还有一个限制是,物体如果只是在 x 轴或者 y 轴远方,都会比 x 轴和 y 轴上远方的物体更容易被检测到。
不同类型车辆的频率数
从上图中可以看出,大多数观察到的物体都是车辆。这和真实情况相差无几,相较于其他类型车辆,私家车数量应该是最多的,但这也同样体现出了 LiDAR 传感器的局限所在。
数据处理与转换
因为选择使用激光雷达数据作为神经网络的起始点,我们并没有进一步处理图像和其他的数据。在这一阶段处理完毕所有的激光雷达后,我们才发现因为车上有三个不同位置的激光雷达传感器, 输出数据会有重复捕捉到周围环境而导致不能直接输入到神经网络中。因此,我们对数据进行了转换,并重叠了传感器采集的重复部分。而因为人眼无法直接观察分析激光雷达点云图的重叠部分,所以我们决定利用图片数据,想办法将图片中的信息和激光雷达的点云进行重叠。
场景的数据来自车载七个摄像头,三个激光雷达,所捕捉到的图像是相似时间的不同角度。点云图的信息以 XYZ 轴的方式记录了周围物体的与传感器的距离。然而,这三个传感器都有各自不同的坐标系统,为了让最终数据位置统一,我们需要将三个坐标系统进行转换。
为此,我们对比了 LiDAR 的 2D 像素坐标以及 3D 点云坐标,其关系可以用变换矩阵的形式表示,该矩阵由平移矢量和旋转矩阵组成。
数据转换矩阵
其中,xyz 组成了转换矩阵,而 P 代表了旋转矩阵。旋转矩阵可以由输入文件中的 calibrated_sensor 提供的摄像头和传感器的固定属性算出。
做好数学功课后,我们首先要做的就是提取不同传感器在各个场景中的激光雷达数据。lyft_dataset_sdk 包在提取和组合数据上非常好用。利用上文提到的概念,我们可以使用四元数据包将数据在 python 中进行转换:首先将激光雷达数据从传感器的参照系转换到车的参照系,接着再把车的参照系转换到世界参照系,最终得出俯视图(BEV)。
下一步,对输出进行体素化,得到三维平面的坐标列表(XYZ)。之后通过归一化体素强度创建俯视(BEV)点云,以获得包含三个描述激光雷达点高度差异的通道的 336 x 336 大小的输入。
激光雷达点转换成 BEV
方法选择
在通过预处理数据得到每个激光雷达点的俯视图输入之后,我们分析了各种不同的神经网络,试图找到最适合我们三维物体检测问题的模型。
三维目标检测需要分割和定位,分割又分语义分割和实例分割。我们使用语义分割是因为没有必要在同个分类里定位不同的实例,但这仅限有特定类别的物体。定位则可以让我们精准找到某物体在激光雷达点云中的具体位置。
在决定使用语义分割之后,我们继续确定神经网络的物体检测方法。3D 数据建模的方法有很多,但是并不是所有的方法都能适用于各种不同 3D 数据的,因为根据结果的不同他们会有不同形式的表示方式。我们测试了四种不同方法但它们各有缺陷,下面我们将快速过一遍这四种方式以及它们各自的缺点。
多角度 CNN 是将 3D 点云渲染成 2D 的图像后,再使用二维卷积神经网络对其进行分类。但是将其应用到点分类,场景理解以及形状分类方面却并不容易。
只能在网格上使用的光谱 CNN 在面对非等距形状诸如家具,车辆,人类等目标时则束手无策。
基于特征的 DNN 在将 3D 数据转换成矢量后,提取形状特征,并使用全连接的网络进行形状分类。但是特征并不能准确表达实际的信息。
我们的模型使用的是体素 CNN,在体素化后的 3D 形状上的三维卷积神经网络。其主要缺点是因数据的稀疏性和大量计算导致分辨率不足。但我们处理的物体都很大,我们相信如果我们可以把边框圈在物体周围,那么我们的模型应该可以没问题。下一步就是将 U-net 引入模型。
建模
U-Net 是由 Olaf Ronneberger、Philipp Fischer、Thomas Brox 开发,主要用于生物图像分割的卷积神经网络,名称 U-net 的来源是其对称的 U 型结构。U-net 主要由以下三部分组成:
1.下采样或收缩路径
2.瓶颈
3.上采样或扩张路径
来源:https://arxiv.org/abs/1505.04597
收缩路径有四个子模块,每个子模块包含两个卷积层和一个 max-pooling 层。每次下采样后都会把特征通道加倍,这样可以捕捉到图像中的相关信息。瓶颈有两层使用 dropout 的卷积层。和收缩路径类似,扩张路径同样有四个带卷积层的子模块,并和左侧收缩路径的裁剪特征通道拼合起来。在扩张路径中,图片深度随着图片大小增加递减。这样我们就可以采集到图片的位置信息了。
这种结构的让我们可以更快速精准地进行分割。我们将车辆附近环境的俯视投影输入到 U-Net 架构之中来创建语义图。架构的输出结果是 BEV 中的语义图。下面是一些样本数据点及其对应的处理目标。
输入图像(左)以及处理后的目标(右)
我们将左侧的图像输入到架构中,用以创建右侧目标。那么既然知道了模型的输入,那么处理后的目标是如何生成的呢?
神经网络的输出是 BEV 中的目标区域,可以从图 A 中看出,并不是所有的预测都是 ground truth。
图 A 可视化预测,图 B 阈值预测,图 C 处理后目标
在示例中,我们使用了像素值为 127.5 来创建二进制目标变量的预测阈值。
评估标准
目标检测模型是通过计算在不同交叉比(IoU)阈值下的平均精度来评估的。2D 边界框的 IoU 是重叠区域的面积除以合并后的总区域面积。IoU 的计算阈值是在 0.55 到 0.95 之间,步长为 0.05。
来源:Kaggle
举例来说,如果 IoU 大于 0.55,那么该物体是在阈值 0.55 时的预测。在不同的阈值下,精度都是通过计算真正例(True Positive,TP),假正例(False Positives,FP)以及假负例(False Negatives,FN),比预测物体和所有 ground-truth 物体。精度是通过真正例比假正例加真正例得出的。每次算法成功预测到物体,真正例(TP)增加。如果预测物体没有相对应的 ground truth,那么就算这次预测为假正例(FP)。模型的评估是通过计算在不同阈值时上述精度值的均值得出的,具体公式如下:
均值绝对精度(mAP)
在 3D 环境中,我们在计算平均精度的同时还评估了 Z 轴上的重叠:Z 轴(目标的高度)一维交汇。
训练阶段 1
Kaggle 比赛过程分为两个阶段,分别是“AHA”时刻之前与之后。之前提到我们神经网络的输入是车辆周围的 BEV 视角,基础模型经过了 10 周期训练后在排行榜上得分大约 0.034,因为是 Kaggle 的竞赛,所以我们对模型训练了 24 x 7 次后将结果上传到 Kaggle 上。我们面临的其中一大挑战就是训练时间,30 个周期需要大约 17 小时,导致我们每天只能修改一到两次,其中比较重要并且大幅提高了我们得分的改变有:
1.在为解决分类不平衡的训练中,将车损失的权重降低到其他类别的 1/5。
2.因为是用鸟瞰图做输入,物体的高度无法得到体现,于是使用其所属类别的假定平均高度代替。
3.在测试过程中,我们修改了很多的参数,包括批次大小,学习率,优化器(Adam 和 RAdam,不是 Adam 大家族)等等。
在这一阶段后,模型已经在 Kaggle 公共排行榜上得分 0.039 了,这时的模型是三周期不同(分别是 8, 9 和 10)模型的集成学习。
训练阶段 2
我们从数据集中提取了对应的自我区域 mask 图,并将其与激光雷达生成的鸟瞰图一起用作是三个附加的通道。
图 A. 鸟瞰图,图 B. Mask 图,图 C. 处理后目标
可以看出,图 B 中的 mask 图是道路及其周围道路的鸟瞰图,这一点让我们在排行榜上的分数直接到达了 0.040。我们还尝试改变学习率、周期、批次大小、优化器等等来进行优化。其中一大难点在于,即使是在 GCP 中,我们也因为内存限制而不能进行交叉验证,这点真的很麻烦。
结果
在多次的尝试后,模型在集成了 8、9、10、29 以及 30 这五种不同周期时表现最佳。在下图的损耗 vs 周期的折线图中可以看出,在一定的周期之后,损耗就会稳定下来。
一些模型的周期 vs 损耗图
下面是我们最终神经网络做出的一些预测,都显示在 mask 图和鸟瞰图上。
鸟瞰图(左)以及 mask 图(右)上的预测
上图的俯视视角里有很多的红点,这些都是模型预测出即将会出现的物体。绿色区域是此时此刻物体存在,但是模型无法对其进行预测。在面对小型物体(例如行人)时就会发生这种情况。最后,黄色点标注的是我们模型的预测与路面实况相符,真正例的情况。最终模型在公共排行榜上得分 0.046(使用 30%测试数据),在私人排行上得分 0.045(使用 70%测试数据)。在 Kaggle 的竞赛在 2019 年 11 月 12 日结束后,我们成功拿到了前 20%的好成绩。
最终得分榜
附上一个我们用最终模型做的预测结果:https://youtu.be/5LN6mFjK6go
挑战
在这次的项目中我们学到了很多,也遇到了很多的挑战,其中一些是:
由于内存的限制,即使是在使用谷歌云端平台的情况下,我们依旧不能进行交叉验证。
同样由于内存的原因,在训练过程中我们的批次数不能超过 32。
我们模型的训练时间非常的长,16 批次训练 30 周期需要大概 16 到 18 小时,集成学习 3 到 4 个模型需要 30-40 分。加起来就需要 20 小时才能完成一次上传。
学习成果
尽管此次学习旅程非常平稳,但我们的模型仍然存在缺陷。在俯视图中,它会漏掉一些小型物体,例如行人、自行车等。这是因为 BEV 中一个像素点大小相当于现实世界中 40 cm x 40cm,这一点我们认为或许可以利用其他现有数据(如图片等)来检测类似物体,在这次的训练中,我们只使用了激光雷达扫描,但是其实还有很多别的数据可以使用。另一个缺陷是我们的模型假定了所有的外界物体都和被测试车辆处于同一高度上,这当然会带来很多的数据错误。
结论
综上,我们认为我们最大的局限在于计算能力。之后从我们教授 Dr. Joydeep Ghosh 那里得知,他的实验室里有个多 GPU 的计算单元,但依旧很难对这类的模型进行调整(他在研究论文中做过类似的实验),至少给了我们一些安慰。
接下来,我们可以尝试其他的模型架构,但愿这些其他的架构加上我们的计算能力的提升能够让我们得到更好的准确率,也能更好地捕捉到行人之类的小型物体。
本文作者:
Alisha Fernandes,Haritha Maheshkumar,Kezhen Yang,Sijo VM, Thirumurugan Vinayagam
原文链接:
https://towardsdatascience.com/3d-object-detection-for-autonomous-vehicles-b5f480e40856
评论