3xmaker,人机协作共融万物互联,柔性可穿戴人机交互感知与测量!

  1. 设计指南
  2. |
  3. 新品速递
  4. |
  5. 联系我们
机器人+
传感器+
柔性/印刷电子+
增强现实+
人机交互感知+
网站首页
/
智造案例
/
智造

给圣诞老人一个惊喜:基于树莓派和深度学习 AI的圣诞老人检测机

来源:3XMaker   发布时间:2018年12月22日

给圣诞老人一个惊喜:基于树莓派和深度学习 AI的圣诞老人检测机

http://www.3xmaker.com/UploadFiles/2019-03/20193265525423380.jpg

热门美剧《硅谷》中的人物创建了一个不是热狗”APP,可以确定输入的照片是热狗还是不是热狗。这篇文章介绍如何使用KerasRaspberry Pi上运行一个识别圣诞老人的深度神经网络,仅仅用130行代码,成功在圣诞老人来你家时点亮圣诞树同时播放圣诞歌曲来迎接!来试试看~

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

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

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

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

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

从磁盘加载Keras模型

访问树莓派相机模块/usb网络摄像头

应用深度学习来检测圣诞老人是否在框内

如果发现圣诞老人,就可以访问GPIO pin并播放音乐

那么让我们开始吧!

什么是Not Santa检测器?

http://www.3xmaker.com/UploadFiles/2019-03/20193267055999400.jpg

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

不是圣诞老人检测器灵感来自HBO美剧《硅谷》。剧中人物创建了一个App,可以确定输入的照片是热狗还是不是热狗。这个节目显然是在取笑美国硅谷的创业文化:

对机器学习和深度学习的炒作

讽刺大量手机App都毫无用处(但发明者相信他们的App将会改变世界)。

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

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

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

为深度学习配置树莓派

在树莓派上安装KerasTensorFlow

部署一个预训练的卷积神经网络到你的树莓派上

一旦检测到,就执行一个给定的动作

硬件配置

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

http://www.3xmaker.com/UploadFiles/2019-03/20193264422012731.jpg

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

遵循这个教程,你需要:

树莓派3(同时强烈推荐树莓派3入门套件)

一个树莓派相机模块或一个USB相机。

适用树莓派的3D圣诞树

一组音箱

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

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

http://www.3xmaker.com/UploadFiles/2019-03/20193268566386543.jpg

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

怎样在树莓派上安装TensorFlowKeras?

http://www.3xmaker.com/UploadFiles/2019-03/20193262597425624.jpg

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

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

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

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

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

帮助

1

2

3

4

# set size to absolute value, leaving   empty (default) then uses computed value

#   you most likely don't want   this, unless you have a special disk situation

# CONF_SWAPSIZE=100

CONF_SWAPSIZE=1024

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

帮助

1

2

$ sudo /etc/init.d/dphys-swapfile stop

$ sudo /etc/init.d/dphys-swapfile start

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

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

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

帮助

1

$ mkvirtualenv not_santa -p python2

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

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

帮助

1

2

$ cd ~/.virtualenvs/not_santa/lib/python2.7/site-packages

$ ln -s   /usr/local/lib/python2.7/site-packages/cv2.so cv2.so

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

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

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

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

帮助

1

$ workon not_santa

然后,你会在bash提示符开头看到not_santa

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

帮助

1

$ pip install numpy

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

帮助

1

$ sudo pip install RPi.GPIO gpiozero

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

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

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

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

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

帮助

1

2

$ wget https://github.com/samjabrahams/tensorflow-on-raspberry-pi/releases/download/v1.1.0/tensorflow-1.1.0-cp27-none-linux_armv7l.whl

$ pip install tensorflow-1.1.0-cp27-none-linux_armv7l.whl

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

帮助

1

2

$ sudo apt-get install libhdf5-serial-dev

$ pip install h5py

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

帮助

1

2

3

$ pip install pillow imutils

$ pip install scipy --no-cache-dir

$ pip install keras

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

帮助

1

2

3

4

5

6

7

8

9

10

11

12

13

14

$ workon not_santa

$ python

>>> import h5py

>>> from gpiozero import LEDBoard

>>> from gpiozero.tools import random_values

>>> import cv2

>>> import imutils

>>> import keras

Using TesnsorFlow backend.

>>> print("OpenCV version:   {}".format(cv2.__version__))

'3.3.1'

>>> print("Keras version:   {}".format(keras.__version__))

'2.0.8'

>>> exit()

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

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

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

打开/etc / dphys-swapfile

重置CONF_SWAPSIZE100MB

重新启动交换服务器

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

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

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

帮助

1

2

3

4

5

6

7

8

9

10

11

12

# import the necessary packages

from keras.preprocessing.image import img_to_array

from keras.models import load_model

from gpiozero import LEDBoard

from gpiozero.tools import random_values

from imutils.video import VideoStream

from threading import Thread

import numpy as np

import imutils

import time

import cv2

import os

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

keras:用于预处理输入帧进行分类,并从磁盘加载预训练的模型。

gpiozero:用于访问3D圣诞树。

imutils:用于访问视频流(无论是树莓派相机模块还是USB)。

threading:用于non-blocking操作,尤其是当我们要点亮圣诞树或播放音乐的同时不阻塞主线程的执行。

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

帮助

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

def light_tree(tree, sleep=5):

    # loop over all   LEDs in the tree and randomly blink them with

    # varying   intensities

    for led in tree:

        led.source_delay   = 0.1

        led.source   = random_values()

 

    # sleep for a bit   to let the tree show its Christmas spirit for

    # santa clause

    time.sleep(sleep)

 

    # loop voer the   LEDs again, this time turning them off

    for led in tree:

        led.source   = None

        led.value   = 0

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

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

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

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

http://www.3xmaker.com/UploadFiles/2019-03/20193263957603139.jpg

6Raspberry Pi3D圣诞树

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

帮助

1

2

3

4

5

def play_christmas_music(p):

    # construct the   command to play the music, then execute the

    # command

    command = "aplay   -q {}".format(p)

    os.system(command)

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

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

帮助

1

2

3

4

5

6

7

8

9

10

11

12

# define the paths to the Not Santa Keras   deep learning model and

# audio file

MODEL_PATH = "santa_not_santa.model"

AUDIO_PATH = "jolly_laugh.wav"

 

# initialize the total number of frames   that *consecutively* contain

# santa along with threshold required to   trigger the santa alarm

TOTAL_CONSEC = 0

TOTAL_THRESH = 20

 

# initialize is the santa alarm has been   triggered

SANTA = False

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

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

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

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

帮助

1

2

3

4

5

6

# load the model

print("[INFO] loading   model...")

model = load_model(MODEL_PATH)

 

# initialize the christmas tree

tree = LEDBoard(*range(2, 28), pwm=True)

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

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

然后初始化视频流:

帮助

1

2

3

4

5

# initialize the video stream and allow   the camera sensor to warm up

print("[INFO] starting video   stream...")

vs = VideoStream(src=0).start()

# vs =   VideoStream(usePiCamera=True).start()

time.sleep(2.0)

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

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

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

帮助

1

2

3

4

5

6

# loop over the frames from the video   stream

while True:

    # grab the frame   from the threaded video stream and resize it

    # to have a   maximum width of 400 pixels

    frame = vs.read()

    frame = imutils.resize(frame,   width=400)

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

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

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

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

帮助

1

2

3

4

5

6

7

8

9

10

11

# prepare the image to be classified by   our deep learning network

image = cv2.resize(frame, (28, 28))

image = image.astype("float") /   255.0

image = img_to_array(image)

image = np.expand_dims(image, axis=0)

 

# classify the input image and initialize   the label and

# probability of the prediction

(notSanta, santa) = model.predict(image)[0]

label = "Not Santa"

proba = notSanta

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

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

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

帮助

1

2

3

4

5

6

7

8

9

10

# check to see if santa was detected   using our convolutional

# neural network

if santa > notSanta:

    # update the   label and prediction probability

    label = "Santa"

    proba = santa

 

    # increment the   total number of consecutive frames that

    # contain santa

    TOTAL_CONSEC += 1

83行检查圣诞老人的概率是否大于notSanta。如果是,就继续更新labelproba,然后递增TOTAL_CONSEC85-90行)。

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

帮助

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

# check to see if we should raise the   santa alarm

if not SANTA and TOTAL_CONSEC >= TOTAL_THRESH:

    # indicate that   santa has been found

    SANTA = True

 

    # light up the   christmas tree

    treeThread = Thread(target=light_tree,   args=(tree,))

    treeThread.daemon   = True

    treeThread.start()

 

    # play some   christmas tunes

    musicThread = Thread(target=play_christmas_music,

        args=(AUDIO_PATH,))

    musicThread.daemon   = False

    musicThread.start()

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

创建并启动一个treeThread来闪烁圣诞树灯(98-100行)。

创建并启动一个musicThread在后台播放音乐(103-106行)。

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

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

否则(SANTATrueTOTAL_THRESH未满足),我们将TOTAL_CONSEC重置为零,并将SANTA重置为False

帮助

1

2

3

4

5

# otherwise, reset the total number of   consecutive frames and the

# santa alarm

else:

    TOTAL_CONSEC = 0

    SANTA = False

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

帮助

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

    # build the label   and draw it on the frame

    label = "{}:   {:.2f}%".format(label, proba * 100)

    frame = cv2.putText(frame,   label, (10, 25),

        cv2.FONT_HERSHEY_SIMPLEX,   0.7, (0, 255, 0), 2)

 

    # show the output   frame

    cv2.imshow("Frame",   frame)

    key = cv2.waitKey(1)   & 0xFF

  

    # if the `q` key   was pressed, break from the loop

    if key == ord("q"):

        break

 

# do a bit of cleanup

print("[INFO] cleaning up...")

cv2.destroyAllWindows()

vs.stop()

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

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

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

完成!

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

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

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

http://www.3xmaker.com/UploadFiles/2019-03/20193265525423380.jpg

7:我,Adrian Rosebrock,扮成圣诞老人。我将亲自测试使用深度学习,KerasPythonOpenCV构建的不是圣诞老人检测器。

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

http://www.3xmaker.com/UploadFiles/2019-03/20193267816866453.jpg

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

 


上一篇:选择困难症福音: DIY“囚徒困境”抢答器
下一篇:隔空操控:用Arduino实现无线手套体验VR游戏

南京合越智能,增强智造,增强感知,增强交互!

业务合作

(我们会第一时间与您联系)

联系方式

  1. 微信:13815863530(手机同号)
  2. QQ:38260484
  3. 3XMaker@163.com
Copyright@ 2016-2025 南京合越智能科技有限公司 苏ICP备18068961号