您的位置:首页 > 编程语言 > ASP

​用树莓派(Raspberry Pi)和机器学习制作一个DIY车牌阅读器

2020-03-24 12:16 591 查看


全文共7733字,预计学习时长23分钟 来源:Pexels

 

几个月前,笔者有一些想法,想让自己的车能检测和识别物体。笔者之所以有如此想法,主要是因为已经见识了特斯拉的能力,虽然并不想马上买一辆特斯拉(不得不说,Model 3看起来一天比一天诱人),但笔者认为应该尝试实现自己的梦想。

 

所以,笔者实施了这个想法。

  动图来自结果的预测视频。

下文记录了项目中的每个步骤。如果只想看到检测器运行的视频或者GitHub链接,请跳到底部。

 

第一步,确定项目范围

 

起初,笔者思考了这样一个系统应该有什么能力。如果说笔者这辈子学到了什么,那就是从小范围开始永远是最好的策略:小步走。所以,除了车道保持任务(每个人都已经做过),笔者只是想在驾驶时简单地识别车牌。此识别过程包括两个步骤:

 

1、检测车牌。

2、识别每个车牌边框内的文字。

 

笔者认为,如果能做到这一点,那么继续进行其他任务应该是相当容易的(比如确定碰撞风险、距离等)。甚至可以创建一个向量空间来表示环境,这就十分炫酷了。

 

在过于担心细节之前,笔者需要:

 

·       一个机器学习模型,将未标记图像作为输入并检测车牌。

·       一些硬件。粗略地说,需要一个连接到一个或多个摄像机的计算机系统来查询模型。

 

首先着手构建对象检测的正确模型。

 

第二步,选择正确模型

 

经过仔细研究,决定采用以下机器学习模型:

 

1.   YOLOv3——这是迄今为止速度最快的模型,具有可与其他先进模型相媲美的映射。这个模型是用来检测对象的。

2.   CRAFT文本检测器——用于检测图像中的文本。

3.   CRNN ——一个循环的CNN(卷积神经网络)模型。它必须进行循环,因为它需要将检测到的字符按正确的顺序组成单词。

 

这三个模型如何协同?操作流程如下:

 

1.   首先,YOLOv3模型在摄像头接收到的每一帧中检测每个车牌的边框。不建议预测的边框非常精确,超过检测到的对象的范围较为合适。如果范围太狭窄,那么可能会影响后续进程的性能。这与下面的模型是并行不悖的。

2.   CRAFT文本检测器从YOLOv3接收裁剪后的车牌。如果裁剪的帧太狭窄,那么很有可能会漏掉车牌的部分文字,导致预测失败。但当边框较大时,可以让CRAFT模型检测字的位置。这可以非常精确地预测每个字的位置。

3.   最后,可以将CRAFT中每个单词的边框输入CRNN模型来预测实际单词。

 

有了基本的模型架构,接下来可以解决硬件了。

 

第三步,设计硬件

 

当笔者知道自己需要一些简单的东西时,便想起了旧爱:树莓派。它有足够的计算能力来用合适的帧数对帧进行预处理,它也有Pi Camera。Pi Camera是树莓派的摄像机系统。它有一个非常棒的存储库,而且非常成熟。

 

至于互联网接入,可以只用一个EC25-E来实现4G接入,也有来自笔者曾经的项目的一个GPS模块嵌入。

 

笔者决定从外壳开始。把它挂在汽车的后视镜上应该会很好用,所以最后设计了一个双组件支撑结构:

 

1.   后视镜一侧,树莓派+GPS模块+4G模块。可以查看笔者关于EC25-E模块的文章,看看笔者对GPS和4G天线的选择。

2.   在另一侧,将用一个球关节臂来支撑Pi Camera进行定位。

 

这些支架/外壳将用笔者信任的Prusa i3 MK3S 3D打印机打印。

  图1—树莓派+4G/GPS防护外壳 图2—用球关节支撑Pi Camera进行定位

 

图1和图2显示了实施时的结构。请注意,C型夹持器是可插拔的,所以已经打印的支架不附带树莓派的外壳和Pi Camera的支架。它们有一个插座,可将支架插入其中。如某一个读者决定复制该项目,这是非常有用的。只需调整支架,使其适应汽车后视镜。目前,笔者车上(是一台路虎神行者)的夹持器功能良好。

  图3—PiCamera支架结构的侧视图

  图4—Pi Camera支架结构以及树莓派夹持器的正视图

  图5—对摄像机视野的预测

  图6—4G/GPS模块、Pi Camera和树莓派的嵌入式系统的特写照片

 

显然,这些需要一些时间来建模。笔者需要几次迭代来使结构更加坚固。笔者在200微米的层高使用了PETG材料。PETG能够在80-90摄氏度中运行,并且抗紫外线辐射性很强,虽然不如ASA。

 

第四步,训练模型

 

一旦有了硬件,就开始训练模型。

 

不出所料,最好不要自己重新创造,而是尽可能重复使用别人的。这就是迁移学习的全部内容——利用来自其他非常庞大的数据集的见解。笔者几天前在这篇文章中读到了关于迁移学习的一个例子。文中谈到了一个哈佛医学院的附属团队,该团队能够微调一个模型,“从胸片中预测长期死亡率,包括非癌症死亡”。他们只有5万张标记图像的小数据集,但是使用的预训练模型(Inception-v4)是在大约1400万张图像上训练的。他们只花了不到一小部分的原始模型所需的训练成本(时间和金钱方面),而且已经达到了相当高的精确度。

 

笔者也打算这么做。

 

YOLOv3

 

笔者在网上寻找预先训练过的车牌模型,没有最初预期的那么多,但找到了一个在大约3600张车牌图像上训练过的模型。它并不多,但也比什么都没有强,而且除此之外,它也是在Darknet的预训练模型上训练的,可以使用。

 

而且因为笔者已经有了一个可以录制的硬件系统,所以笔者决定在镇上驾驶几个小时,收集帧,来对上述模型进行微调。

 

笔者使用VOTT对收集到的帧进行注释(当然还有车牌)。最后创建了一个由534幅图像组成的小数据集,其中带有标记的车牌边框。

 

然后笔者找到了YOLOv3网络在Keras上的应用。用它来训练数据集,然后把笔者的模型再放到这个库中,这样其他人也可以使用它。笔者在测试集上得到的映射是90%,在如此小的数据集上能有如此表现已经很不错了。

 

CRAFT以及CRNN

 

在无数次尝试寻找一种好的网络来识别文本之后,笔者偶然发现了keras-ocr,它是CRAFT和CRNN包的一个灵活版本。而且它还附带了他们预先训练好的模型。那太棒了。笔者决定不对模型进行微调,让它们保持原样。

 

最重要的是,用keras-ocr预测文本非常简单。基本上只是几行代码。可以去他们的主页看看是怎么做的。

 

第五步,将笔者的车牌部署到检测器模型

 

可以采用两种主要的模型部署方法:

 

1、在本地处理所有推理。

2、在云端处理所有推理。

 

这两种方法都有一些困难。第一种方法意味着要有一个庞大的“大脑”计算机系统,这很复杂而且昂贵。第二个挑战涉及延时和基础设施,特别是用GPU进行推理。

 

笔者在研究中,偶然发现了一个叫做cortex的开源项目。这是相当新鲜的,但它作为人工智能开发工具下一步的进化肯定是有一定意义的。

 

从根本上说,cortex是一个用于将机器学习模型部署为一键切换的生产web服务的平台。这意味着笔者可以专注于应用程序,剩下的事情交给cortex来管理。在本例中,它完成了AWS上的所有配置,而笔者要做的唯一一件事就是使用模板模型来编写预测器。更牛的是,每个模型只要写几十行即可。

 

这是GitHub库中cortex在终端中的作用。除了美丽和简单,笔者想不出还能用什么词来形容:

  图源: Cortex GitHub

 

由于这个计算机视觉系统不是自动驾驶使用的,延迟对笔者来说就不那么重要了,笔者可以用cortex来解决这个问题。如果它是自动驾驶系统的一部分,那么使用通过云提供商提供的服务就不是一个好主意,至少目前不是。

 

使用cortex部署机器学习模型仅需以下步骤:

 

1.   确定cortex.yaml文件,这是API的配置文件。每个API将处理一种类型的任务。笔者指定的yolov3 API用于检测指定帧上车牌的边框,而crnn API用于通过CRAFT文本检测器和CRNN来预测车牌。

2.   确定每个API的预测器。基本上,就是在cortex中定义一个特定类的预测法以接收一个有效负载(所有检测的部分已经由平台处理),使用有效负载预测结果,然后返回预测。就这么简单!

 

在不深入讨论笔者是如何完成这一工作的具体细节的情况下(为了保持文章的适当长度),这里有一个经典虹膜数据集的预测器示例。cortex实现这两个API的链接可以在这里的存储库中找到,这个项目的所有其他资源都在本文末尾。

 

#predictor.pyimport boto3import picklelabels = ["setosa", "versicolor","virginica"]class PythonPredictor:    def __init__(self, config):        s3 = boto3.client("s3")       s3.download_file(config["bucket"], config["key"],"model.pkl")        self.model =pickle.load(open("model.pkl", "rb"))    def predict(self, payload):        measurements = [            payload["sepal_length"],           payload["sepal_width"],           payload["petal_length"],           payload["petal_width"],        ]        label_id =self.model.predict([measurements])[0]        return labels[label_id]
 

然后做一个预测,只需使用curl,就像这样

 

curl http://***.amazonaws.com/iris-classifier     -X POST -H "Content-Type:application/json"     -d  {"sepal_length": 5.2,"sepal_width": 3.6, "petal_length": 1.4,"petal_width": 0.3}
 

做出的预测就像这个“Setosa”。非常简单!

 

第六步,开发客户端

 

通过cortex完成部署,笔者可以继续设计客户端——这是比较棘手的部分。

 

笔者想出了以下结构:

 

1.   以30帧每秒的速度从Pi Camera以相当高的分辨率(800x450或480x270)收集帧,并将每个帧推入公用队列。

2.   在一个单独的进程中,笔者将从队列中取出帧,并将它们分发给不同工作线程。

3.   每个工作线程(或笔者所称的推理线程)都将向cortex API发出API请求。首先,向yolov3API发出一个请求,然后,如果检测到任何车牌,则向crnn API发出另一个带有一批裁剪过的车牌的请求。作出的响应将包含文本格式的预测车牌。

4.   将每个检测到的车牌(有或无识别的文本)推送到另一个队列,最终将其广播到浏览器页面。同时,还将车牌预测推送到另一个队列,以便稍后将它们保存到磁盘(csv格式)。

5.   广播队列将接收一串无序帧。它的用户的任务是在每次向客户端广播新帧时将它们放在一个非常小的缓冲区中(只有几个帧大小),从而重新排序它们。这个用户正在另一个进程上单独运行。该用户还必须尝试将队列上的大小保持在指定值,以便帧能够以一致的帧数(即30帧每秒)显示。显然,如果队列大小减少,那么帧数就会成比例减少,反之亦然,当队列大小增加时,帧数也会成比例增加。最初,笔者想实现一个滞后函数,但笔者认为它会给工作流造成极大影响。

6.   同时,主进程中会有另一个线程运行,从另一个队列和GPS数据中提取预测。当客户端接收到终止信号时,预测、GPS数据和时间也转存到csv文件中。

 

下图是客户端与AWS上的云API相关的流程图。

  图7——cortex提供的云API相关的客户端流程图

 

在本例中,客户端是树莓派,推理请求发送到的云API是由AWS(Amazon Web Services)上的cortex提供的。

 

客户端的源代码也可以在其GitHub 存储库中进行查看。

 

必须克服的一个困难是4G的带宽。最好降低此应用程序所需的带宽,以减少可能的问题或对可用数据的过度使用。笔者决定在Pi Camera上使用非常低的分辨率:480x270(可以使用小分辨率,因为Pi Camera的视野非常窄,所以仍然可以很容易地识别车牌)。然而,即使在该分辨率下,帧的JPEG在10兆比特处为约100千字节。乘以30帧/秒,得到3000千字节,大约是24兆字节/秒,这还不包括HTTPoverhead——这是一个很大的数目。

 

笔者采用了以下策略:

 

·       将宽度降至416像素,这正是YOLOv3模型调整图像大小的结果。尺寸保持完好。

·       将图像转换为灰度。

·       移除图像顶部45%的部分。一般认为车牌不会出现在车架的顶部,因为汽车不会飞起来,对吧?从笔者观察到的情况来看,剪掉45%的图像并不会影响预测器的性能。

·       再次将图像转换为JPEG,但质量较低。

 

得到的框架大小约为7-10KB,非常好。这相当于2.8 兆字节/秒。但是算上所有的overhead,它大约是3.5兆字节/秒(也包括响应)。

 

对于crnn API,裁剪后的车牌根本不需要太多,即使不用压缩技巧。每一部分大约为2-3千字节。

 

总而言之,要以30帧/秒的速度运行,推理API所需的带宽约为6兆字节/秒。这个数字可以接受。

 

结论

这确实行之有效!

 

上述是通过cortex运行推理的实时示例。笔者需要大约20个配备GPU的实例才能顺利运行。根据集群的延迟,可能需要更多或更少的实例。从捕获帧到广播到浏览器窗口之间的平均延迟约为0.9秒,而且推理还可以更深入,这真是太神奇了。

 

文本识别部分可能不是最好的,但它至少证明了这一点——通过提高视频的分辨率,或者通过缩小摄像机的视野,或者通过微调,它可以精确得多。

 

高GPU可以通过优化来减少。例如,转换模型以使用混合/全半精度(FP16/BFP16)。一般来说,使用混合精度的模型对精度的影响最小,因此并不需要进行太多的权衡。

 

T4和V100 GPU具有特殊的张量核心,用于在半精度类型上进行超快的矩阵乘法。在T4上,半精度运算比单精度运算的加速比约为8倍,在V100上,半精度运算比单精度运算的加速比约为10倍。这是一个数量级的差异,意味着一个已转换为使用单精度/混合精度的模型可以少花多达8倍的时间来进行推理,而在V100上则少花十分之一的时间。

 

笔者还没有转换模型以使用单精度/混合精度,因为这超出了这个项目的范围。就笔者而言,这只是一个优化问题。笔者最有可能在cortex 0.14版本发布时完成这项工作(如果有真正的多进程支持和基于队列的自动缩放),这样笔者也可以利用多进程网络服务器。

 

总而言之,如果所有优化都到位,将集群的规模从20个配备GPU的实例减少到只有一个实际上是可行的。如果优化得当,甚至连一个配备GPU的实例都不用。

 

为了更加节约成本,在AWS上使用Elastic Inference可以减少高达75%的成本,这是一个很大的数目!形象地说,可以花一毛钱就拥有一个用于实时处理流的管道。不幸的是,目前cortex还无法支持Elastic Inference,但可以看到这一点在不久的将来就能实现,因为它已经进入了他们的视野中。参见cortexlabs/cortex/issues/618。

 

注意:YOLOv3和CRNN模型,可以通过在更大的数据集(大约50-100K样本)上对其进行微调来改进。此处,帧的尺寸还可以进一步减小,以减少数据的使用,而不对精确度造成很大影响:“补偿某处,以便从其他地方取走”。这与转换所有这些模型以使用半精度类型(以及可能的Elastic Inference)相结合,可以形成一种非常有效或降低成本的推理机器。

 

更新

  来源:Pexels

cortex的0.14版本支持网络服务器的多进程工作器,笔者能够将yolov3 API的GPU实例数量从8个减少到2个,将crnn API(在CRNN和CRAFT模型上运行推理)的GPU实例数量从12个减少到10个。这意味着实例的总数减少了40%,这是一个非常好的增益。所有这些实例每个都配备了单个T4 GPU和4个vCPU。

 

笔者发现最需要计算的模型是CRAFT模型,它是建立在约138兆的VGG-16模型之上的。请记住,由于在一次拍摄中可以有多个检测到的车牌,因此通常需要对每一帧进行多次推理。这大大增加了对它的计算需求。从理论上讲,应该取消CRAFT模型,并且改进(微调)CRNN模型,以更好地识别车牌。这样,crnn API就可以缩小很多——只缩小到1或2个实例。

 

结语(包含如何将5G应用其中)

 

笔者看到设备开始越来越依赖云计算,特别是对于计算能力有限的边缘设备。而且由于5G目前正在部署,理论上应该会让云更接近这些受计算限制的设备。因此,云的影响力应该随之增长。5G网络越可靠、越普及,人们就越有信心将所谓的关键任务(比如自动驾驶汽车)的计算卸载到云端。

 

笔者在这个项目中学到的另一件事是,随着在云中部署机器学习模型的流线型平台的出现,使得更多事情变得如此容易。5年前,这将是一个相当大的挑战:但现在,一个人就可以在相对较短的时间内做这么多事情。

 

资源

 

·查看所有3D打印夹持器的SLDPRT/SLDASM/STL/gcode。https://www.dropbox.com/sh/fw16vy1okrp606y/AAAwkoWXODmoaOP4yR-z4T8Va?dl=0

·查看本项目的客户端实施。https://github.com/RobertLucian/cortex-license-plate-reader-client

·查看本项目的cortex实施。https://github.com/cortexlabs/cortex/tree/master/examples/tensorflow/license-plate-reader

·查看YOLOv3模型的Keras存储库。https://github.com/experiencor/keras-yolo3

·查看CRAFT 文本检测器+ CRNN 文本识别器的存储库。https://github.com/faustomorales/keras-ocr

·查看欧洲车牌数据集(由笔者的Pi Camera捕获的534个样本组成)。https://github.com/RobertLucian/license-plate-dataset

·查看可以找到Keras(License_Plate.h5)和SavedModel(YOLOv3文件夹/zip)格式的YOLOv3模型。https://www.dropbox.com/sh/4ltffycnzfeul01/AACe85GoIzlmjEnIhuh5JQPma?dl=0

 
推荐阅读专题

留言点赞发个朋友圈我们一起分享AI学习与发展的干货编译组:杨月、齐欣相关链接:https://towardsdatascience.com/i-built-a-diy-license-plate-reader-with-a-raspberry-pi-and-machine-learning-7e428d3c7401如转载,请后台留言,遵守转载规范推荐文章阅读ACL2018论文集50篇解读EMNLP2017论文集28篇论文解读2018年AI三大顶会中国学术成果全链接ACL2017论文集:34篇解读干货全在这里10篇AAAI2017经典论文回顾长按识别二维码可添加关注读芯君爱你

  • 点赞
  • 收藏
  • 分享
  • 文章举报
读芯术 发布了924 篇原创文章 · 获赞 2869 · 访问量 55万+ 他的留言板 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: