https://blog.tensorflowcn.cn/2020/07/pixelopolis-self-driving-car-demo-tensorflow-lite.html
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs4gaxC1c-8T8Ei8rgaCqf6BoyUQRfPllTIcLCnkECygff-sSAHYUfJBu4Z4ZGtSwksvzRki32WFGSYiFPtlv19oacze5SpcU9c4spZF8a2KMU3hzT2LD7G3TwDglWqHj6JFEFZSdZbGo/s1600/106.gif
作者:Miguel de Andrés-Clavera,Google PI 产品经理
在这篇文章中,我想与大家分享今年我们在 Google I/O 上构建并计划展示的,使用
TensorFlow Lite 的演示。我真希望我们有机会面对面见面,但我希望你依然会觉得这篇文章很有趣!
Pixelopolis
Pixelopolis 是一个互动式装置,展示了由
TensorFlow Lite 驱动的自动驾驶微型汽车。每辆车都配备了它自己的 Pixel 手机,手机使用摄像头来检测和理解周围环境的信号。为了识别车道、避免碰撞和读取交通标志,手机使用在
Pixel 神经核心 上运行的机器学习,该核心包含
Edge TPU 的版本。
这种
边缘计算 实现是实现像这样的项目的良好选择。由于延迟,使用基于云的方法处理视频和检测物体要困难得多。如果可以的话,在设备上进行处理要快得多。
用户可以通过一个“站点”(在手机上运行的应用程序)与 Pixelopolis 进行交互,在那里他们可以选择汽车将要行驶的目的地。汽车将导航到目的地,在行驶过程中,应用程序会显示来自汽车的实时流媒体视频——这使得用户可以看到汽车所看到的内容和检测到的内容。正如你从下面的 gif 中看到的,Pixelopolis 具有内置的多语言支持。
|
站点应用程序 |
|
汽车应用程序 |
工作原理
使用移动设备的前置摄像头,我们可以在设备上实时进行车道保持、定位和目标检测。不仅如此,在我们的案例中,Pixel 4 还通过 USB-C 控制电机和其他电子元件,因此汽车可以在检测到其他汽车时停止,或者在需要时在右交叉路口转弯。
如果你对技术细节感兴趣,这篇文章的其余部分将描述汽车的主要组件以及我们构建它的过程。
车道保持
我们探索了各种车道保持模型。作为基线,我们使用 CNN 来检测每一帧中的交通线并在每一帧调整方向盘,这很好用。我们通过添加 LSTM 和使用多个先前帧来改进它。在做了一些额外的实验之后,我们遵循了与这篇
论文 类似的模型架构。
|
CNN 模型输入和输出 |
模型架构
net_in = Input(shape = (80, 120, 3))
x = Lambda(lambda x: x/127.5 - 1.0)(net_in)
x = Conv2D(24, (5, 5), strides=(2, 2),padding="same", activation='elu')(x)
x = Conv2D(36, (5, 5), strides=(2, 2),padding="same", activation='elu')(x)
x = Conv2D(48, (5, 5), strides=(2, 2),padding="same", activation='elu')(x)
x = Conv2D(64, (3, 3), padding="same",activation='elu')(x)
x = Conv2D(64, (3, 3), padding="same",activation='elu')(x)
x = Dropout(0.3)(x)
x = Flatten()(x)
x = Dense(100, activation='elu')(x)
x = Dense(50, activation='elu')(x)
x = Dense(10, activation='elu')(x)
net_out = Dense(1, name='net_out')(x)
model = Model(inputs=net_in, outputs=net_out)
数据收集
在我们能够使用此模型之前,我们需要找到一种方法从汽车中收集图像数据进行训练。问题是,当时我们没有汽车或赛道可以使用。因此,我们决定使用模拟器。我们选择了 Unity 以及来自 Udacity 的这个
模拟器项目 来进行车道保持数据收集。
|
模拟器中赛道上的多个航点 |
通过在赛道上设置多个航点,
汽车机器人 能够驾驶到不同的位置,并为我们收集数据。在这个模拟器中,我们每 50 毫秒收集一次图像数据和转向角。
图像增强
|
使用各种环境进行数据增强 |
由于我们在模拟器中进行所有数据收集,我们需要在场景中创建各种环境,因为我们希望我们的模型能够处理不同的照明、背景环境和其他噪声。我们在场景中添加了这些变量:随机 HDRI 球体(具有不同的旋转和曝光值)、随机亮度和颜色以及随机车辆。
训练
|
第一个神经网络层的输出 |
仅使用模拟器训练 ML 模型并不意味着它实际上会在现实世界中起作用,至少第一次不会。汽车在轨道上行驶了几秒钟,然后就因为各种原因驶离轨道。
|
玩具车早期版本驶离轨道 |
后来,我们发现我们只使用大部分直线轨道来训练模型。为了解决这种不平衡的数据问题,我们添加了各种形状的曲线。
|
(左)方形赛道,(右)弯曲赛道 |
在修复了不平衡的数据集后,汽车开始正确地转弯。
|
汽车成功地转弯 |
使用最终赛道设计进行训练
|
最终赛道设计 |
我们开始为汽车创造更复杂的情况,例如在赛道中添加多个交叉路口。我们还添加了更多路线路径,使汽车能够处理这些新的条件。然而,我们马上就遇到了新问题,汽车在试图在交叉路口转弯时撞到了侧边轨道,因为它看到了轨道外的一些随机物体。
|
使用额外的路线训练模型 |
我们测试了许多解决方案,并选择了最简单、最有效的一种。我们只裁剪了图像底部的 1/4,并将其馈送到车道保持模型,然后将模型输入大小调整为 120x40,它就完美地工作了。
|
裁剪图像底部部分以进行车道保持 |
目标检测
我们使用目标检测来实现两个目的。一个是用于定位。每辆车都需要通过检测环境中的物体来了解自己在城市中的位置(在本例中,我们检测城市中的交通标志)。另一个目的是检测其他汽车,这样它们就不会相互碰撞。
在选择目标检测模型时,TensorFlow 目标检测模型库中已经有许多模型
可用。但是,对于 Pixel 4 Edge TPU,我们使用 ssd_mobilenet_edgetpu 模型。
在 Pixel 4 的“神经核心”Edge TPU 上
ssd_mobilenet_edgetpu 模型是目前最快的 mobilenet 目标检测模型。它每帧仅需 6.6 毫秒,对于实时应用程序来说绰绰有余。
|
Pixel 4 Edge TPU 模型性能 |
数据标注和模拟
我们使用模拟和真实场景的图像数据来训练模型。接下来,我们使用
虚幻引擎 4 为此开发了自己的模拟器。模拟器生成具有随机背景的随机物体,以及一个以 Pascal VOC 格式的标注文件,该文件用于
TensorFlow 目标检测 API 中。
|
使用 UE4 的目标检测模拟器 |
对于从真实场景拍摄的图像,我们必须使用 labelImg 工具进行手动标注。
|
使用 labelImg 进行数据标注 |
训练
|
损失报告 |
我们使用
TensorBoard 来监控训练进度。我们用它来评估 mAP(平均精度均值),这通常需要手动完成。
|
TensorBoard |
|
检测结果和真实值 |
TensorFlow Lite
由于我们希望在运行 Android 的 Pixel 4 上运行我们的 ML 模型,因此我们需要将所有模型转换为 .tflite。当然,你也可以使用 TensorFlow Lite 来定位 iOS 和其他设备(包括微控制器)。以下是我们执行的步骤
车道保持
首先,我们使用以下方法将车道保持模型从 .h5 转换为 .tflite
import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_keras_model_file("lane_keeping.h5")
model = converter.convert()
file = open("lane_keeping.tflite",'wb')
file.write( model )
file.close()
现在,我们已经准备好将模型用于 Android 项目。接下来,我们在应用程序中构建一个车道保持类。我们从
这里 的示例 Android 项目开始。
目标检测
我们必须将模型检查点(.ckpt)转换为 TensorFlow Lite 格式(.tflite)
- 使用 export_tflite_ssd_graph.py 脚本将 .ckpt 转换为 .pb 文件(脚本已在 TensorFlow 目标检测 API 中提供)
- 使用 toco:TensorFlow Lite 转换器将 .pb 转换为 .tflite 格式
使用神经核心
我们使用来自
这里 的 Android 示例项目。然后,我们修改了委托以使用 Pixel 4 Edge TPU,代码如下。
Interpreter.Options tfliteOptions = new Interpreter.Options();
nnApiDelegate = new NnApiDelegate();
tfliteOptions.addDelegate(nnApiDelegate);
tfLite = new Interpreter(loadModelFile(assetManager, modelFilename),tfliteOptions);
实时视频流
用户选择目的地后,汽车将开始自动驾驶。在驾驶过程中,汽车会将它所看到的内容作为视频流传输到站点手机上。当我们开始实施这部分时,我们马上就意识到,由于需要在多个汽车手机和站点手机之间传输大量数据,因此无法传输原始视频流。我们使用的解决方案是,首先将原始图像帧压缩为 JPEG 格式以减少数据量,然后使用
multipart/x-mixed-replace 作为 HTTP 内容类型,通过 http 协议传输 JPEG 缓冲区。这样,我们就可以同时实现多个视频流,并且设备之间的延迟几乎不可察觉。
服务器应用程序
服务器堆栈
我们使用 NodeJS 作为服务器应用程序,使用 MongoDB 作为数据库。
叫车
由于我们有多个站点和车辆,我们需要找到一种方法将它们连接在一起。我们构建了一个类似于流行的汽车应用程序的预订系统。我们的预订系统分为三个步骤。首先,汽车连接到服务器并告诉服务器它已准备好被预订。其次,站点连接到服务器并向服务器请求一辆车。第三,服务器查找已准备好的汽车,并将它们连接在一起,并存储来自站点和汽车应用程序的 device_id。
导航
|
节点/边缘 |
由于我们将有一支汽车车队在城市中行驶,我们需要找到一种方法来导航它们。我们使用节点/边缘概念。节点是地图上的一个位置,边缘是两个节点之间的路径。然后,我们将每个节点映射到城市中的实际标志。
|
轨道和标志位置的俯视图 |
当在站点应用程序上选择目的地时,站点将向服务器发送 node_id,服务器将返回一个对象,该对象指示节点列表及其属性,以便汽车知道要驾驶到哪里以及将看到的预期标志。
电子设备
部件
我们从
NUCLEO-F411RE 开始作为我们的开发板。我们选择了
Dynamixel 作为电机。
|
NUCLEO-F411RE |
我们设计并开发了用于电机等附加组件的屏蔽,以减少汽车底盘内部的电线数量。屏蔽分为三个部分:1) 电压电池测量,2) 带有 MOSFET 的开关,3) 按钮。
|
(左) 屏蔽和电机,(右) 电源插座、电源开关、使能电机按钮、复位电机按钮、板状态 LED、电机状态 LED |
在后期阶段,我们希望使汽车更小,因此我们从 NUCLEO-F411RE 迁移到 NUCLEO-L432KC,因为它占地面积更小。
|
NUCLEO-L432KC |
汽车底盘和外部
第一代
|
第一代设计 |
我们使用 PLA 材料设计并 3D 打印了汽车底盘。前轮是转向轮。
第二代
|
第二代设计 |
我们在板上添加了一个电池测量电路,并在手机从板上分离时切断电源。
第三代
|
第三代设计 |
我们添加了状态 LED,以便我们可以轻松地调试板的状态。从之前的版本开始,我们遇到了电机过热的问题,因此在这个版本中,我们通过在电机上添加一个风扇来改善通风。我们还在板上添加了 USB Type-C 电源传输,以便手机可以使用汽车电池。
第四代
|
第四代设计 |
我们将所有控制按钮和状态 LED 迁移到汽车后部,以便于访问。
第五代
|
第五代设计 |
这是最终版本,我们需要尽可能减少汽车占地面积。首先,我们将板从 NUCLEO-F411RE 更改为 NUCLEO-L432KC,以实现更小的占地面积。其次,前轮已更改为球形转向轮。第三,我们将板的位置重新排列到汽车顶部,并将电池堆叠在板下方。最后,我们移除了 USB Type-C 电源传输,因为我们希望通过将所有电池功率提供给板和电机而不是手机来延长行驶时间。
性能指标
路线图
我们计划在许多方面改进这种体验。
电池
目前,电机和控制器板由三组 3000mAh 锂离子电池供电,我们有一个充电电路来处理充电过程。当我们想要充电时,我们需要将汽车移到充电站,并将电源适配器插入汽车后部进行充电。这有很多弊端,因为汽车在充电时无法在轨道上运行,而且充电时间为几个小时,相当长。
|
3000mAh 锂离子电池 (左),18650 锂离子电池 (右) |
我们希望通过将电池更改为 18650 电池单元来简化这个过程。这种电池类型用于笔记本电脑、工具和电动自行车等电子设备,因为它们在小巧的外形尺寸下具有高容量。这样,我们就可以通过弹出新电池来轻松地更换电池,并将空电池放在电池充电器中充电,而无需将汽车留在充电站。
本地化
|
使用 SLAM 的本地化 |
本地化对于此安装非常重要,我们希望通过在应用程序中添加 SLAM 来使其更强大。我们相信这将显着改善转向机制。
了解更多
感谢您的阅读!使用手机摄像头、TensorFlow 和一点想象力,您可以做很多事情。希望这篇文章能为您自己的项目提供一些想法 - 我们在做这个项目中学到了很多东西,也希望您在做自己的项目时也能学到很多。这篇文章提供了链接,让您深入了解所有不同的领域,您可以在
TensorFlow Hub 上找到开发者社区提供的许多 ML 模型和教程。
如果您对建造自动驾驶汽车充满热情,并希望更多地了解机器学习和深度学习如何推动自动驾驶汽车行业的发展,请查看 Udacity 的
自动驾驶汽车纳米学位课程。它非常适合希望接受自动驾驶汽车所有方面的全面培训的工程师和学生,包括计算机视觉、传感器融合和本地化。
致谢
如果没有以下优秀的、才华横溢的人,这个项目将无法实现:Sina Hassani、Ashok Halambi、Pohung Chen、Eddie Azadi、Shigeki Hanawa、Clara Tan Su Yi、Daniel Bactol、Kiattiyot Panichprecha、Praiya Chinagarn、Pittayathorn Nomrak、Nonthakorn Seelapun、Jirat Nakarit、Phatchara Pongsakorntorn、Tarit Nakavajara、Witsarut Buadit、Nithi Aiempongpaiboon、Witaya Junma、Taksapon Jaionnom 和 Watthanasuk Shuaytong。