文 / Miguel de Andrés-Clavera,产品经理,Google PI
在本文中,我想与大家分享我们用 TensorFlow Lite 为今年 Google I/O 大会构建并展示的演示。很遗憾今年没能够进行现场演示,期待这篇文章能为您带来乐趣与启发!
Pixelopolis 概览
Pixelopolis 是一套由 TensorFlow Lite 构建的无人驾驶微型汽车。每辆微型汽车都装配有一部 Pixel 手机,使用手机上的摄像头检测和理解周围的信号。手机使用了 Pixel Neural Core 芯片(Edge TPU 支持的端侧机器学习),可感应车道、避免碰撞和读取交通标志。
边缘计算是这类项目的理想实现选择。由于延迟问题,不推荐使用基于云来进行视频处理和检测物体。而设备端操作将大幅提升速度。
用户可以通过“站点”(手机端的一个应用)与 Pixelopolis 进行交互,选择车辆的目的地。车辆将自动导航到该目的地,并在应用显示车辆行程的实时视频流,这样用户便可以查看车辆周围及所检测到的物体。
△ 站点应用界面(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 球体(具有不同的旋转模式和曝光值)、随机的环境亮度和颜色以及随机出现的车辆。
训练
△ 第一层神经网络的输出
由于我们仅使用模拟器来训练机器学习模型,方案有可能在现实环境中无法奏效,或无法一次尝试就成功。在我们的实验中,车辆在轨道上行驶数秒后便会因各种原因偏离轨道。
△ 早期版本中玩具车偏离了轨道
后来,我们发现这是由于我们大多使用直线轨道训练模型。为解决这种数据不均衡的问题,我们在场景中添加了各种形状的曲线。
△(左)方形轨道与(右)弯曲轨道
修正数据集不均衡的问题后,车辆便开始能够在弯道处正确转向。
△ 车辆在弯道处成功转弯
使用最终轨道设计进行训练
△ 最终的轨道设计
我们开始为车辆设计更复杂的路况,如:在轨道上添加多个路口,更多可选择的路线,我们希望车辆能够应对这些新路况。但是,我们立即遇到了新的问题:当车辆试图在路口处转弯时,由于看到轨道外的随机出现的物体而转向并撞到了侧方轨道。
△ 在具有多种路线的轨道中训练模型
我们测试了多种解决方案,并选择了最为简单有效的一种。我们仅裁剪图像底部 ¼ 的部分,并将其录入到车道保持模型中,然后将模型输入尺寸调整为 120x40,有效地化解了上述问题。
△ 裁剪图像底部以实现车道保持
目标检测
我们使用目标检测是出于两个目的。一是定位。每辆车都需要通过检测周围环境中的物体来获知其在城市中的位置(在本例中,我们所检测的是城市中的交通标志)。另一个则是检测其他车辆,以免车辆相撞。
选择目标检测器模型时,TensorFlow 目标检测模型库中已 提供 了许多模型。但针对 Pixel 4 Edge TPU 设备,我们使用了 ssd_mobilenet_edgetpu 模型。
Pixel 4 的“Neural Core” Edge TPU 上使用 ssd_mobilenet_edgetpu 模型可实现目前最快的 MobileNet 目标检测。每帧仅用时 6.6 毫秒,该检测速度对于实时应用的要求而言已绰绰有余。
△ Pixel 4 Edge TPU 模型性能
数据标注和模拟
我们使用模拟器和真实场景中的图像数据来训练模型。接下来,我们使用 Unreal Engine 4 开发了自己的模拟器。模拟器会生成随机物体和随机背景,以及可在 TensorFlow 目标检测 API 中使用的 Pascal VOC 格式注解文件。
△ 使用 UE4 的目标检测模拟器
对于从真实场景拍摄的图像,我们需要使用 labelImg 工具进行手动标注。
△ 使用 labelImg 执行数据标注
训练
△ 损失报告
我们使用 TensorBoard 来监控训练进度及评估 mAP(平均精度,需要手动执行该步骤)。
△ TensorBoard 界面
△ 检测结果和实际标签
TensorFlow Lite
由于我们希望在运行 Android 的 Pixel 4 设备上运行机器学习模型,需将模型转换为 .tflite 格式。当然,对于 iOS 和其他设备(包括微控制器)也可使用 TensorFlow Lite。以下是我们执行的步骤:
车道保持
首先,我们使用以下代码将车道保持模型从 .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 项目着手。
目标检测
我们必须将模型 checkpoint (.ckpt) 转换为 TensorFlow Lite 格式 (.tflite)
- 使用 export_tflite_ssd_graph.py 脚本将 .ckpt 转换为 .pb 文件(TensorFlow 目标检测 API 中已提供该脚本)
- 使用 toco: TensorFlow Lite Converter 将 .pb 转换为 .tflite 格式
使用 Neural Core
我们使用 此处 提供的 Android 示例项目。然后,我们使用以下代码修改了 delegate 以使用 Pixel 4 Edge TPU。
Interpreter.Options tfliteOptions = new Interpreter.Options();
nnApiDelegate = new NnApiDelegate();
tfliteOptions.addDelegate(nnApiDelegate);
tfLite = new Interpreter(loadModelFile(assetManager, modelFilename),tfliteOptions);
实时视频流
在用户选择目的地后,车辆将开始无人驾驶。车辆行驶期间会将其周围影像以视频流传输到“站点”手机。刚开始实现此部分时,我们意识到无法流式传输原始的视频流,因为需要在多部车载手机和“站点”手机之间传输,数据量很大。因此我们将原始图像帧压缩为 JPEG 格式,然后以 HTTP Content-type:multipart/x-mixed-replace 的 http 协议流式传输 JPEG。这样,我们就可以同时传输多个视频流,且设备之间无明显延迟。
服务器应用
服务器堆栈
服务器端使用 NodeJS 与 MongoDB。
叫车
由于站点和车辆数量众多,我们需要找到匹配两者的有效方案。我们构建了类似热门打车应用的预订系统。我们的预订系统包含 3 个步骤。首先,车辆连接到服务器,并告知服务器车辆已准备好,可供预订。然后,站点 App 连接到服务器,并向服务器查询车辆。最后,服务器将查找准备就绪的车辆并将两者匹配,并为匹配好的站点 App 和车辆 App 储存设备 ID。
导航
△ 节点/连线
由于将有多辆车穿梭于城市各处,我们需要找到一种有效的导航方法。我们采用了“节点/连线”的概念。节点是地图上的一处地点,连线是两个节点之间的路径。然后,我们将每个节点映射到城市中的实际标志处。
△ 轨道和标志位置俯视图
在站点应用中选择目的地后,站点便会向服务器发送节点 ID,接着,服务器将返回一个包含节点及其属性列表的对象,以便车辆知道行程目的地以及将看到的预期标志。
电子设备
部件
我们首先使用 NUCLEO-F411RE 作为开发板。我们选择使用 Dynamixel 配置电机。
△ NUCLEO-F411RE
我们设计并开发了用于诸如电机等其他组件的屏蔽罩,以精简车辆底盘内的布线量。屏蔽罩包含三个部分:1) 电池电压测量电路,2) 带 MOSFET 的 On/Off 开关,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 的开发者学习社区中提供的大量机器学习模型和教程来进一步学习相关知识。
如果您对制造无人驾驶汽车兴趣浓厚,并且想要深入了解机器学习和深度学习如何推动无人驾驶汽车行业的发展,请查看 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。
原文:Sharing Pixelopolis, a self-driving car demo from Google I/O built with TF-Lite
中文:TensorFlow 公众号