【圣诞特辑】Keras+树莓派,130行代码找到圣诞老人

今天这篇文章是使用Keras在Raspberry Pi上运行深度神经网络的一个完整指南。

我把这个项目当做一个“不是圣诞老人”(Not Santa)检测器,教你如何实际地实现它(并且过程中乐趣无穷)。

第一部分,我们说一下什么是“圣诞老人检测器”(可能你不熟悉热播美剧《硅谷》里的“不是热狗”识别App,现在已经有人把它实现了)。

然后,我们将通过安装TensorFlow、Keras和其他一些条件来配置树莓派进行深度学习。

树莓派为深度学习配置好之后,我们将继续构建一个Python脚本,它可以:

  • 从磁盘加载Keras模型
  • 访问树莓派相机模块/usb网络摄像头
  • 应用深度学习来检测圣诞老人是否在框内
  • 如果发现圣诞老人,就可以访问GPIO pin并播放音乐

那么让我们开始吧!

什么是Not Santa检测器?

图1:HBO美剧《硅谷》里的“不是热狗”识别应用程序

“不是圣诞老人”检测器灵感来自HBO美剧《硅谷》。剧中人物创建了一个App,可以确定输入的照片是“热狗”还是“不是热狗”:

这个节目显然是在取笑美国硅谷的创业文化:

  • 对机器学习和深度学习的炒作
  • 讽刺大量手机App都毫无用处(但发明者相信他们的App将会“改变世界”)。

今天,我们决定做一个“不是圣诞老人”检测器,它可以检测出圣诞老人是否在一个图像/视频框中。

为那些不熟悉圣诞老人的人简单说明一下,圣诞老人是一个诙谐、肥胖、白胡子、虚构的西方文化人物,会在圣诞前夜给小孩子送礼物。

不过,我们这个App并不完全是为了好玩和讽刺。我们将学习一些实用的技能,包括:

  • 为深度学习配置树莓派
  • 在树莓派上安装Keras和TensorFlow
  • 部署一个预训练的卷积神经网络到你的树莓派上
  • 一旦检测到,就执行一个给定的动作

硬件配置

但是在编写代码之前,让我们先来说一下我们需要的硬件。

图2:“不是圣诞老人”检测器的设置包括树莓派3、扬声器、3D圣诞树和一个网络摄像头,为了检测圣诞老人,树莓派在Python脚本中用Keras实现LeNet。

遵循这个教程,你需要:

  • 树莓派3(同时强烈推荐树莓派3入门套件)
  • 一个树莓派相机模块或一个USB相机。
  • 适用树莓派的3D圣诞树
  • 一组音箱

当然,这些不是全部必须的。只要有一个树莓派+相机模块/usb摄像头,就能全部设置好(但是必须修改代码,这样它就不会试图访问GPIO pins或通过音箱播放音乐)。

你的设置应该与上面的图2相似,把扬声器、3D圣诞树和网络摄像头连接在一起。我还推荐使用HDMI监视器+键盘来测试并调试脚本:

图3:我的深度学习设置包括树莓派和组件,以及键盘、鼠标和一个小的HDMI显示器。这样设置好后,圣诞老人来到我的圣诞树前放礼物时一定能抓到他。

怎样在树莓派上安装TensorFlow和Keras?

关于如何使用Kera来训练卷积神经网络,以确定圣诞老人是否处于输入的图像中,可以参考[1]:

我们将采用预训练的模型,并将其部署到树莓派上。正如我之前提到的,树莓派不适合训练神经网络。但是,树莓派可以部署训练好的神经网络(当然,模型需要能够适应很小的内存占用空间)。

我假设你已经在树莓派上安装了OpenCV。如果还没有,可以看[2]的教程。

建议增加树莓派的交换空间,这能使你能够使用Raspberry Pi SD卡来增加内存(当尝试在内存限制的树莓派上编译和安装大型库时,这是一个关键步骤)。

要增加交换空间,打开 /etc/dphys-swapfile 然后编辑CONF_SWAPSIZE变量:

我将交换空间从100MB增加到了1024MB。然后,重新启动交换服务器:

注意:增加交换空间容易烧毁存储卡,因此请确保恢复这个更改并在完成后重启交换服务器。

然后,我们开始配置开发环境。

首先,使用Python 2.7创建一个名为not_santa的Python虚拟环境:

请注意,-p开关指向python2,指示Python 2.7将用于虚拟环境。

还要确保你已经把cv2.so绑定到not_santa虚拟环境中:3

同样,要再次确认已经用Python 2.7绑定编译了OpenCV,还要仔细检查cv2.so文件的路径,以防安装路径与我的演示有不同。

如果你编译了Python 3 + OpenCV绑定,创建了sym-link,然后试图将cv2导入你的Python shell,你会得到一个令人困惑的路径回溯,说导入失败。

重要说明:对于接下来的几个pip命令,要确保你处于not_santa环境,否则你会把这些包安装到树莓派的系统Python中。

要进入环境,只需在bash提示符下使用workon命令:

然后,你会在bash提示符开头看到“(not_santa)”。

确保使用以下命令在not_santa环境中安装NumPy:

由于我们将访问该项目的GPIO pins,因此需要同时安装RPi.GPIO和gpiozero:

现在在树莓派上安装TensorFlow。问题是没有一个官方的(Google发布的)TensorFlow发行版,那就要在树莓派上从头开始编写TensorFlow,参考[3]。

或者我们可以使用预先编译的二进制文件Sam Abrahams(GitHub上有[4])。

问题是只有两种类型的预编译的TensorFlow二进制文件,一个用于Python 2.7,另一个用于Python 3.4

Raspbian Stretch发行版附带了Python 3.5,因此,我们的版本不匹配。为了避免Python 3.4和Python 3.5之间的麻烦,我决定坚持使用Python 2.7安装。

让我们继续,使用以下命令为Python 2.7安装TensorFlow:

TensorFlow编译和安装好后(我花了大约一个小时),然后需要安装HDF5和H5py。这些库将允许我们从磁盘加载预训练的模型:

最后,让我们安装Keras和这个项目所需的其他条件:

为了测试你的配置,请打开一个Python shell(在not_santa环境中)并执行以下命令:

如果一切按计划进行,你应该看到使用TensorFlow后端导入的Keras。

正如上面的输出所示,你还应该仔细检查OpenCV绑定(cv2)是否可以导入。

最后,不要忘记通过以下方式将交换空间从1024MB减到100MB:

  • 打开/ etc / dphys-swapfile
  • 重置CONF_SWAPSIZE为100MB。
  • 重新启动交换服务器

在树莓派运行Keras +深度学习模型

图5:使用Keras和Python在Raspberry Pi上运行深度学习模型。

现在我们准备使用Keras,TensorFlow和树莓派来编写一个Not Santa检测器。再次,我会假设你的硬件设置和我的一样,如果不一样,你需要修改下面的代码。

首先,请打开一个新文件,将其命名为not_santa_detector.py,插入以下代码:

第2-12行处理输入,特别是:

  • keras:用于预处理输入帧进行分类,并从磁盘加载预训练的模型。
  • gpiozero:用于访问3D圣诞树。
  • imutils:用于访问视频流(无论是树莓派相机模块还是USB)。
  • threading:用于non-blocking操作,尤其是当我们要点亮圣诞树或播放音乐的同时不阻塞主线程的执行。

然后,定义一个函数来点亮3D圣诞树:

light_tree函数接受一个tree参数(被设为一个LEDBoard对象)。

首先,我们循环tree中的所有LED,并随机点亮每个LED,以产生“闪烁”效果(17-19行)。

我们让灯亮一段时间(第23行),然后再次循环LED,然后把它关掉(26-28行)。

下面是一个打开3D圣诞树灯的例子:

图6:Raspberry Pi的3D圣诞树

当检测到圣诞老人时,下一步是播放音乐

在play_christmas_music函数中,对aplay命令进行系统调用,从而能够像从命令行那样播放音乐文件。

然后,让我们硬编码将使用的配置:

第38行和第39行将硬编码到预训练的Keras模型和音频文件的路径。文末的下载可以获取音频文件。

初始化用于检测的参数,包括TOTAL_CONSEC和TOTAL_THRESH。这两个值表示包含圣诞老人的帧的数量以及我们将分别播放音乐和打开树的阈值(第43行和第44行)。

最后的初始化是SANTA = False,一个boolean(第47行)。我们稍后将在脚本中使用SANTA变量作为状态标志。

接下来,加载预训练的Keras模型并初始化圣诞树:

Keras允许我们将模型保存到磁盘以供将来使用。Not Santa模型已经保存到了磁盘上[1],那么我们把它加载到树莓派上。第51行使用Keras load_model函数加载了模型。

第54行实例化tree对象。如图所示,tree是gpiozero包中的一个LEDBoard对象。

然后初始化视频流:

要访问摄像机,在imutils包中使用VideoStream

重要提示:如果你想在本项目中使用PiCamera模块(而不是USB摄像头),只需注释第58行并取消第59行的注释即可。

Sleep 两秒钟,以便相机预热(第60行),然后开始循环播放帧:

第63行,我们开始循环播放视频帧,直到满足停止条件(稍后在脚本中显示)。

首先,通过调用vs.read来获取一个frame(第66行)。

然后调整frame为 width= 400,保持纵横比(第67行)。在喂入神经网络模型之前预处理这个frame。稍后,我们将显示框架以及文本标签。

然后预处理图像,并通过Keras +深度学习模型进行预测:

第70-73行预处理图像并准备分类。然后,我们查询model.predict与image作为参数。这向神经网络发送image,返回包含类概率的tuple(第77行)。

我们将label初始化为“Not Santa”,并将概率proba初始化为第78和79行中notSanta的值。

我们来看看圣诞老人是否在图像中:

在83行检查圣诞老人的概率是否大于notSanta。如果是,就继续更新label和proba,然后递增TOTAL_CONSEC(85-90行)。

如果连续提供了足够的“Santa”帧,就需要触发圣诞老人警报:

如果SANTA为False,并且TOTAL_CONSEC达到TOTAL_THRESH阈值,就有两个操作要执行:

  • 创建并启动一个treeThread 来闪烁圣诞树灯(98-100行)。
  • 创建并启动一个musicThread在后台播放音乐(103-106行)。

这些线程将独立运行,不停止脚本的正向执行(即非阻塞操作)。

在第95行,我们将我们的SANTA状态标志设置为True,意味着我们在输入框架中找到了圣诞老人。 在循环的下一个loop中,我们将像第93行那样查看这个值。

否则(SANTA为True或TOTAL_THRESH未满足),我们将TOTAL_CONSEC重置为零,并将SANTA重置为False:

最后,我们使用生成的文本标签将框架显示在屏幕上:

概率的值被附加到包含“圣诞老人”或“不是圣诞老人”的label(第115行)。

然后使用OpenCV的cv2.putText,可以在框架顶部显示标签(以圣诞节为主题的绿色),然后将框架显示在屏幕上(116-120行)。

无限while loop 的退出条件是在键盘上按下“q”键(121-125行)。如果循环的退出条件满足,则在脚本退出之前,break并执行第129行和第130行的一些清理。

完成!

回头看看这130行代码,这个框架/模板也可以很容易地用于树莓派上的其他深度学习项目。

现在,让我们来抓那个胖胖的,有胡子的,快活的吧!

深度学习+ Keras +树莓派结果

图7:我,Adrian Rosebrock,扮成圣诞老人。我将亲自测试使用深度学习,Keras,Python和OpenCV构建的“不是圣诞老人”检测器。

然后,我把相机朝着客厅里的圣诞树上的树莓派:

图8:圣诞树将作为测试已经部署到树莓派上的Not Santa深度学习模型的背景。

如果圣诞老人来为给我的好孩子们送礼物,我想确保通过闪烁3D圣诞树灯和播放圣诞歌曲来欢迎他。

然后,我使用以下命令启动了Not Santa深度学习+ Keras检测器:


1


$ python not_santa_detector.py

Not Santa 检测器启动并运行后,我就开始行动:

亲爱的圣诞老人:如果你读到了这里,要知道我会用树莓派找到你哦!

参考:

[1]https://www.pyimagesearch.com/2017/12/11/image-classification-with-keras-and-deep-learning

[2]https://www.pyimagesearch.com/2017/10/09/optimizing-opencv-on-the-raspberry-pi

[3]https://github.com/samjabrahams/tensorflow-on-raspberry-pi/blob/master/GUIDE.md

[4]https://github.com/samjabrahams/tensorflow-on-raspberry-pi

原文地址:https://www.pyimagesearch.com/2017/12/18/keras-deep-learning-raspberry-pi/

原文发布时间为:2017-12-23

本文作者:鲁道夫

本文来自合作伙伴新智元,了解相关信息可以关注“AI_era”微信公众号

原文链接:【圣诞特辑】Keras+树莓派,130行代码找到圣诞老人

时间: 2024-09-28 17:38:45

【圣诞特辑】Keras+树莓派,130行代码找到圣诞老人的相关文章

只需 130 行代码,用 GAN 生成二维样本的小例子

50行GAN代码的问题 Dev Nag 写的 50 行代码的 GAN,大概是网上流传最广的,关于GAN最简单的小例子.这是一份用一维均匀样本作为特征空间(latent space)样本,经过生成网络变换后,生成高斯分布样本的代码.结构非常清晰,却有一个奇怪的问题,就是判别器(Discriminator)的输入不是2维样本,而是把整个mini-batch整体作为一个维度是batch size(代码中batch size等于cardinality)那么大的样本.也就是说判别网络要判别的不是一个一维的

Keras 之父讲解 Keras:几行代码就能在分布式环境训练模型 | Google I/O 2017

作为号称是 TensorFlow 最好用.对新手最友好的 API,一起来看看它的神通在哪里. Francois Chollet:对许多使用场景而言,canned estimator 是相当不错的选择.但如果你要做的事并没有现成的 canned estimator,怎么办?如果需要写自己的定制模型呢?这时,就到了 Keras API 派上用场的时候. 什么是 Keras API? 简而言之,它就是一个用于创建 TensorFlow 模型的高级 API,你可以与它一起使用 estimator cla

不到 200 行代码,教你如何用 Keras 搭建生成对抗网络(GAN)

生成对抗网络(Generative Adversarial Networks,GAN)最早由 Ian Goodfellow 在 2014 年提出,是目前深度学习领域最具潜力的研究成果之一.它的核心思想是:同时训练两个相互协作.同时又相互竞争的深度神经网络(一个称为生成器 Generator,另一个称为判别器 Discriminator)来处理无监督学习的相关问题.在训练过程中,两个网络最终都要学习如何处理任务. 通常,我们会用下面这个例子来说明 GAN 的原理:将警察视为判别器,制造假币的犯罪分

用“Keras”11行代码构建CNN

更多深度文章,请关注:https://yq.aliyun.com/cloud 卷积神经网络(CNN)是一种特殊的深层的神经网络模型,为什么说它是特殊的神经网络模型呢?一是它的神经元间的连接是非全连接的,另一点是因为同一层中某些神经元之间的连接的权重是共享的.它的这些特点成功的降低了网络模型的复杂度以及减少了权值的数量,这也使得它的网络结构更类似于生物神经网络.今天我们就来用keras来实现CNN,keras是基于Theano和TensorFlow的深度学习库. 我曾经演示过如何使用TensorF

从把三千行代码重构成15行代码谈起

从把三千行代码重构成15行代码谈起 如果你认为这是一个标题党,那么我真诚的恳请你耐心的把文章的第一部分读完,然后再下结论.如果你认为能够戳中您的G点,那么请随手点个赞. 把三千行代码重构为15行 那年我刚毕业,进了现在这个公司.公司是搞数据中心环境监控的,里面充斥着嵌入式.精密空调.总线.RFID的概念,我一个都不懂.还好,公司之前用Delphi写的老客户端因为太慢,然后就搞了个Webform的替代,恰好我对Asp.Net还算了解,我对业务的不了解并不妨碍我称成为这个公司的一个程序员.小公司也有

手把手,74行代码实现手写数字识别

1. 引言:不要站在岸上学游泳 "机器学习"是一个很实践的过程.就像刚开始学游泳,你在只在岸上比划一堆规定动作还不如先跳到水里熟悉水性学习来得快.以我们学习"机器学习"的经验来看,很多高大上的概念刚开始不懂也没关系,先写个东西来跑跑,有个感觉了之后再学习那些概念和理论就快多了.如果别人已经做好了轮子,直接拿过来用则更快.因此,本文直接用Michael Nielsen先生的代码(github地址: https://github.com/mnielsen/neural-

两千行代码的PHP学习笔记汇总_php技巧

本文汇总了PHP学习中常见的各类问题,约有两千多行代码,都是非常实用的技巧.分享给大家供大家参考.具体如下: //语法错误(syntax error)在语法分析阶段,源代码并未被执行,故不会有任何输出. /* [命名规则] */ 常量名 类常量建议全大写,单词间用下划线分隔 // MIN_WIDTH 变量名建议用下划线方式分隔 // $var_name 函数名建议用驼峰命名法 // varName 定界符建议全大写 // <<<DING, <<<'DING' 文件名建议

GAN 很复杂?如何用不到 50 行代码训练 GAN(基于 PyTorch)

本文作者为前谷歌高级工程师.AI 初创公司 Wavefront 创始人兼 CTO Dev Nag,介绍了他是如何用不到五十行代码,在 PyTorch 平台上完成对 GAN 的训练.雷锋网编译整理. Dev Nag 什么是 GAN? 在进入技术层面之前,为照顾新入门的开发者,雷锋网先来介绍下什么是 GAN. 2014 年,Ian Goodfellow 和他在蒙特利尔大学的同事发表了一篇震撼学界的论文.没错,我说的就是<Generative Adversarial Nets>,这标志着生成对抗网络

《高性能科学与工程计算》——第2章 串行代码基本优化技术2.1 标量剖析

第2章 串行代码基本优化技术 在千核级并行计算机时代,有些观点认为编写高效串行代码在许多领域已经有些过时了.因为增加更多CPU以获得大规模并行能力要比投入大量精力优化串行代码简单得多.这似乎是一个合理的理论,5.3.8节的论述中也体现了对这种观点的支持.然而,本书认为程序在单处理器上的性能优化毫无疑问是最重要的,如果通过一些简单的优化方法就可以实现两倍加速比,那么用户会更倾向于使用较少的CPU.这样不仅可把宝贵的计算资源释放给其他用户或项目,而且还可以使投入大量资金购买的硬件获得更加有效的利用.