最近,Mapbox 的 Android 工程师 Antonio 使用计算机视觉和机器学习技术,为他的女儿 Violeta 重新制作了一台遥控车。接下来我们看看 Antonio 是如何实现是:

今年上半年的一天,我和女儿 Violeta 在玩着她爷爷奶奶送给她的遥控车。为了学习如何操控它, Violeta “有条不紊”地开着车撞向每一个家具,结果就在某一个“砰”声后,遥控车罢工了。我们打开了遥控车内部,瞧瞧是哪儿出了问题——幸好只是一根电线松了,几分钟后,我就搞定它了。

然而,这个小插曲却引起了我的思考。这些用集成电路板做的小玩具生产成本低但是修起来却未必那么容易。

如果下一次把车里的零件撞坏了,我们又修不了,那该怎么办?

在那段时间,安卓刚刚发布了 Android Things, 是安卓开发的“小周边”,在树莓派(Raspberry Pi) 和类似的 IoT 设备上运行。我对安卓非常熟悉,所以我做了个决定,相信你们也能猜到:我决定重新制造一台“不怕撞”的遥控车。

硬件

分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第1张图片

硬件方面,我是用现成的组件组装的,这样如果有部件损坏,更换起来比较方便。以下是我的简短的购物单(总价略高于100美元):

一个树莓派(Raspberry Pi)(大约35美元);
一个马达控制器(22美元)—— 马达不能直接连接在树莓派上;
一个便携式充电器(用来为树莓派和马达充电)(30美元);
最后,是一个支撑框架。Junior Runt Rover 是一个不错的选择(28美元),当然你也可以从别的玩具上拆一个下来。
分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第2张图片

通过一个安卓系统下的配套应用程序可以控制遥控车,该控制通过一个本地服务器实现。然而,我不得不告诉你,用一个复古的任天堂控制器一定会有趣的多(当然你的预算得调高35美元)。

将这些组件直接拼装在一起即可,拼装过程我另有记录。此外,还有一些注意的地方:

关于焊接:我还未找到一台与树莓派兼容且已焊接的马达控制器。你可能需要从床底翻出你的焊台或者问朋友借一台。焊接本身不难,但是你可能需要提前练习一下,毕竟零件都太小了。

超越树莓派:Android Things 是 IoT 设备上一个抽象的图层,虽然树莓派广受兴趣爱好者的欢迎,但其它设备也同样支持,而且不需要改一行代码。到目前为止,我的最爱还是 NXP Pico. 它的优势在于高速的内存(这样你就不需要再额外买一张 SD 卡),并且它带有一个模组化系统。如果你想要将你的硬件项目实体化,那么哪些实体产品设备会用到这种模块(是不是似乎看到了商机……)

一开始,我以为我女儿会害怕我自制的遥控车,没想到她毫不畏惧,还很喜欢带着它“跌跌撞撞”闯荡世界。看,领居家的猫也很喜欢它……

软件

设计软件时,发生了一些我计划外的事。在我已经制作完成一辆可以运行的遥控车时,Udacity 公司发布了一个自驾车“nanodegree”项目,来展示自动驾驶汽车的工作原理。

他们运用了计算机视觉(Computer Vision)和深度学习(Deep Learning)技术来使自动驾驶汽车识别道路和人行道。这些技术都从实用角度出发,让你在模拟器甚至在车子里都可以进行编程。

有很长一段时间,自动驾驶汽车技术于我而言就是一个未知的匣子,我渴望探索,因此我毫不犹豫报名了相关课程并申请加入了遥控车项目。

在课程中你第一个学到的是自动驾驶汽车识别物体的两种方式(通常两种方法结合使用):计算机视觉技术(Computer Vision)和机器学习技术(Machine Learning)。

无论你使用哪种技术,你都需要一个摄像头来探测车前的情况。这并不困难。现在你只要花30美金就能买到一个800万像素的可直接连接树莓派或其它设备的摄像头。

计算机视觉技术(Computer Vision)

计算机视觉技术是最为直观的技术。它的主要原理是从车上的摄像头提取关于街道的信息并进行图像过滤和转化(这里就需要车内摄像头有足够的高度来拍摄一个比较好的视角)。

为了使这样的分析可行,并且使车子可以对分析结果有实时的应对,我使用了一种同地图 SDK 很类似的方法:花了一番功夫在C++上(使用开源的计算机视觉技术代码),并在Java端展示了所用的方法,藉此,安卓系统可以做出判断是直行或转弯。

一旦这一步完成了,我们就做得差不多了。那我们就从项目测试套件开始吧,下面这张图展示了测试的一部分:

分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第3张图片

1、将获取的画面转化成图片,这张图看起来就像是从摄像头拍摄的照片。(如果你熟悉开源计算机视觉技术代码的话,你就能知道这结合了 “getPerspectiveTransform” 和 “warpPerspective”)。这一步清除了画面中所有的无关物体,从而使车子可以集中于眼前的道路:

分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第4张图片

2、进行色差阈分析使车子从获取的画面中识别出路线。根据你设计的路线颜色(比如我这里是亮×××)可以选择不同的色彩空间。鉴于 HSV 色彩空间更符合人类识别、感知颜色的方式,你可以将开源计算机视觉技术中默认的 BGR 色彩空间改成 HSV 色彩空间,利用 HSV 中的色相和饱和度范围还可以更容易地过滤具体的颜色。

分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第5张图片

3、最后,我们需要绘制分布图来找到最佳的位置定位(如下图所示的垂直蓝线):

分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第6张图片

好了,做完上面几步,你的小车就能听你的话看准自己的车道了!

接下来,我们要为小车安装雷达定位器了 :-)

你想知道从小车的摄像头里看出去是怎样的吗?那不妨来看看这个视频吧(https://www.youtube.com/watch?v=dRzs0s_xFaw).这是你在 Udacity 训练中要做的一个练习。

机器学习技术(Machine Learning)

另一种让小车自动驾驶的方法就是机器学习技术(Machine Learning)(又称:深度学习卷积神经网络)。深度学习技术目前已经成为自动驾驶汽车发展中十分重要的一种方法。大部分情况下,你都会用真实数据构建一个模型来区分交通信号,或是通过克隆学习真实情况下的汽车行为使自动驾驶汽车能够做出即时的驾驶判断。你会找上千张照片,然后将其中你想让汽车学习的部分进行编码(比如,每个车轮的转速)。

这样做的问题在于设计一个卷积神经网络并不是容易事,而且对于我要达成的目标而言太小题大做了。

所以,我换了一种方法。我参考 NVIDIA 发布的公开的相关研究报告后(点击可查看完整研究报告),选用了其中一种网络架构。这种架构由九层组成,包括一个标准化层,五个卷积层,三个全连接层:

分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第7张图片

使用 Keras 这样的工具,只需要几行代码就能实现。

需要注意的是,这里用的都是 Python 语言而非 Java,其主要原因有两个:

一方面,近来 Python 似乎已成为运用机器学习技术时实际使用的语言。它有很大的程序库和相关文档记载,而且像在使用 TensorFlow 这类框架时也经常使用它。

另一方面,谁都不愿意在小容量的树莓派上调试模型,实在太慢、太不方便了。所以很多人会选择用一个更强大的笔记本电脑或是一个云端的服务器(比如许多 Mapboxers 会这么做:mapbox/morecs#54)。

社区

分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第8张图片

在我研究过程中最棒的就是能够认识这群热衷于自己造自动驾驶汽车(“机器车”)的狂热爱好者。这起初只是 Chris Anderson 在加利福尼亚州奥克兰市发起的一场同好聚会,没想到迅速扩散到了其他地方。

你可能因为《连线》杂志或是“开始DIY无人驾驶飞机”这样的事情知道 Chris Anderson 的名字。他说他的志向就是“用‘DIY’去攻克世界上所有著名的大型产业,并看看会怎么样”。

下面这张图表是最近一次机器车同好小聚上,大家对比的计算机视觉技术和机器学习技术。你可以发现,两种技术方法表现都很好。虽然计算机视觉技术更快地取得优势,但机器学习技术也不逊色,很快地追了上去:
分享 | 撞坏遥控车后,有个技术大牛爸爸是种怎样的体验_第9张图片

写在最后

如果你想了解更多关于自动驾驶汽车,或是他们的小兄弟机器车的信息,不妨看看下面几条:
如果你熟悉 Java/ Android, 可以参考这个说明来搭建你自己的安卓机器车。
如果你更喜欢用 Python,那建议你可以从儿童单车项目开始。它的编程和搭建更加复杂(它需要可打印的3D模型),但也的确非常值得你这样的投入。

如果你有任何问题,或者分享有关遥控车、计算机视觉(Computer Vision)和深度学习(Deep Learning)技术方面的内容,随时欢迎联系 Mapbox 公众号。