3xmaker,人機(jī)協(xié)作共融萬物互聯(lián),柔性可穿戴人機(jī)交互感知與測量!

  1. 設(shè)計指南
  2. |
  3. 新品速遞
  4. |
  5. 聯(lián)系我們
機(jī)器人+
傳感器+
柔性/印刷電子+
增強(qiáng)現(xiàn)實(shí)+
人機(jī)交互感知+
網(wǎng)站首頁
/
智造案例
/
智造

給圣誕老人一個驚喜:基于樹莓派和深度學(xué)習(xí) AI的圣誕老人檢測機(jī)

來源:3XMaker   發(fā)布時間:2018年12月22日

給圣誕老人一個驚喜:基于樹莓派和深度學(xué)習(xí) AI的圣誕老人檢測機(jī)

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

熱門美劇《硅谷》中的人物創(chuàng)建了一個不是熱狗”APP,可以確定輸入的照片是熱狗還是不是熱狗。這篇文章介紹如何使用KerasRaspberry Pi上運(yùn)行一個識別圣誕老人的深度神經(jīng)網(wǎng)絡(luò),僅僅用130行代碼,成功在圣誕老人來你家時點(diǎn)亮圣誕樹同時播放圣誕歌曲來迎接!來試試看~

今天這篇文章是使用KerasRaspberry Pi上運(yùn)行深度神經(jīng)網(wǎng)絡(luò)的一個完整指南。

我把這個項目當(dāng)做一個不是圣誕老人Not Santa)檢測器,教你如何實(shí)際地實(shí)現(xiàn)它(并且過程中樂趣無窮)。

第一部分,我們說一下什么是圣誕老人檢測器(可能你不熟悉熱播美劇《硅谷》里的不是熱狗識別App,現(xiàn)在已經(jīng)有人把它實(shí)現(xiàn)了)

然后,我們將通過安裝TensorFlowKeras和其他一些條件來配置樹莓派進(jìn)行深度學(xué)習(xí)。

樹莓派為深度學(xué)習(xí)配置好之后,我們將繼續(xù)構(gòu)建一個Python腳本,它可以:

從磁盤加載Keras模型

訪問樹莓派相機(jī)模塊/usb網(wǎng)絡(luò)攝像頭

應(yīng)用深度學(xué)習(xí)來檢測圣誕老人是否在框內(nèi)

如果發(fā)現(xiàn)圣誕老人,就可以訪問GPIO pin并播放音樂

那么讓我們開始吧!

什么是Not Santa檢測器?

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

1HBO美劇《硅谷》里的不是熱狗識別應(yīng)用程序

不是圣誕老人檢測器靈感來自HBO美劇《硅谷》。劇中人物創(chuàng)建了一個App,可以確定輸入的照片是熱狗還是不是熱狗。這個節(jié)目顯然是在取笑美國硅谷的創(chuàng)業(yè)文化:

對機(jī)器學(xué)習(xí)和深度學(xué)習(xí)的炒作

諷刺大量手機(jī)App都毫無用處(但發(fā)明者相信他們的App將會改變世界)。

今天,我們決定做一個不是圣誕老人檢測器,它可以檢測出圣誕老人是否在一個圖像/視頻框中。

為那些不熟悉圣誕老人的人簡單說明一下,圣誕老人是一個詼諧、肥胖、白胡子、虛構(gòu)的西方文化人物,會在圣誕前夜給小孩子送禮物。

不過,我們這個App并不完全是為了好玩和諷刺。我們將學(xué)習(xí)一些實(shí)用的技能,包括:

為深度學(xué)習(xí)配置樹莓派

在樹莓派上安裝KerasTensorFlow

部署一個預(yù)訓(xùn)練的卷積神經(jīng)網(wǎng)絡(luò)到你的樹莓派上

一旦檢測到,就執(zhí)行一個給定的動作

硬件配置

但是在編寫代碼之前,讓我們先來說一下我們需要的硬件。

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

2不是圣誕老人檢測器的設(shè)置包括樹莓派3、揚(yáng)聲器、3D圣誕樹和一個網(wǎng)絡(luò)攝像頭,為了檢測圣誕老人,樹莓派在Python腳本中用Keras實(shí)現(xiàn)LeNet

遵循這個教程,你需要:

樹莓派3(同時強(qiáng)烈推薦樹莓派3入門套件)

一個樹莓派相機(jī)模塊或一個USB相機(jī)。

適用樹莓派的3D圣誕樹

一組音箱

當(dāng)然,這些不是全部必須的。只要有一個樹莓派+相機(jī)模塊/usb攝像頭,就能全部設(shè)置好(但是必須修改代碼,這樣它就不會試圖訪問GPIO pins或通過音箱播放音樂)

你的設(shè)置應(yīng)該與上面的圖2相似,把揚(yáng)聲器、3D圣誕樹和網(wǎng)絡(luò)攝像頭連接在一起。我還推薦使用HDMI監(jiān)視器+鍵盤來測試并調(diào)試腳本:

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

3:我的深度學(xué)習(xí)設(shè)置包括樹莓派和組件,以及鍵盤、鼠標(biāo)和一個小的HDMI顯示器。這樣設(shè)置好后,圣誕老人來到我的圣誕樹前放禮物時一定能抓到他。

怎樣在樹莓派上安裝TensorFlowKeras?

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

關(guān)于如何使用Kera來訓(xùn)練卷積神經(jīng)網(wǎng)絡(luò),以確定圣誕老人是否處于輸入的圖像中,可以參考[1]

我們將采用預(yù)訓(xùn)練的模型,并將其部署到樹莓派上。正如我之前提到的,樹莓派不適合訓(xùn)練神經(jīng)網(wǎng)絡(luò)。但是,樹莓派可以部署訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)(當(dāng)然,模型需要能夠適應(yīng)很小的內(nèi)存占用空間)。

我假設(shè)你已經(jīng)在樹莓派上安裝了OpenCV。如果還沒有,可以看[2]的教程。

建議增加樹莓派的交換空間,這能使你能夠使用Raspberry Pi SD卡來增加內(nèi)存(當(dāng)嘗試在內(nèi)存限制的樹莓派上編譯和安裝大型庫時,這是一個關(guān)鍵步驟)。

要增加交換空間,打開 /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。然后,重新啟動交換服務(wù)器:

幫助

1

2

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

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

注意:增加交換空間容易燒毀存儲卡,因此請確保恢復(fù)這個更改并在完成后重啟交換服務(wù)器。

然后,我們開始配置開發(fā)環(huán)境。

首先,使用Python 2.7創(chuàng)建一個名為not_santaPython虛擬環(huán)境:

幫助

1

$ mkvirtualenv not_santa -p python2

請注意,-p開關(guān)指向python2,指示Python 2.7將用于虛擬環(huán)境。

還要確保你已經(jīng)把cv2.so綁定到not_santa虛擬環(huán)境中:

幫助

1

2

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

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

同樣,要再次確認(rèn)已經(jīng)用Python 2.7綁定編譯了OpenCV,還要仔細(xì)檢查cv2.so文件的路徑,以防安裝路徑與我的演示有不同。

如果你編譯了Python 3 + OpenCV綁定,創(chuàng)建了sym-link,然后試圖將cv2導(dǎo)入你的Python shell,你會得到一個令人困惑的路徑回溯,說導(dǎo)入失敗。

重要說明:對于接下來的幾個pip命令,要確保你處于not_santa環(huán)境,否則你會把這些包安裝到樹莓派的系統(tǒng)Python中。

要進(jìn)入環(huán)境,只需在bash提示符下使用workon命令:

幫助

1

$ workon not_santa

然后,你會在bash提示符開頭看到not_santa

確保使用以下命令在not_santa環(huán)境中安裝NumPy

幫助

1

$ pip install numpy

由于我們將訪問該項目的GPIO pins,因此需要同時安裝RPi.GPIOgpiozero

幫助

1

$ sudo pip install RPi.GPIO gpiozero

現(xiàn)在在樹莓派上安裝TensorFlow。問題是沒有一個官方的(Google發(fā)布的)TensorFlow發(fā)行版,那就要在樹莓派上從頭開始編寫TensorFlow,參考[3]

或者我們可以使用預(yù)先編譯的二進(jìn)制文件Sam AbrahamsGitHub上有[4])。

問題是只有兩種類型的預(yù)編譯的TensorFlow二進(jìn)制文件,一個用于Python 2.7,另一個用于Python 3.4

Raspbian Stretch發(fā)行版附帶了Python 3.5,因此,我們的版本不匹配。為了避免Python 3.4Python 3.5之間的麻煩,我決定堅持使用Python 2.7安裝。

讓我們繼續(xù),使用以下命令為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。這些庫將允許我們從磁盤加載預(yù)訓(xùn)練的模型:

幫助

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環(huán)境中)并執(zhí)行以下命令:

幫助

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()

如果一切按計劃進(jìn)行,你應(yīng)該看到使用TensorFlow后端導(dǎo)入的Keras

正如上面的輸出所示,你還應(yīng)該仔細(xì)檢查OpenCV綁定(cv2)是否可以導(dǎo)入。

最后,不要忘記通過以下方式將交換空間從1024MB減到100MB

打開/etc / dphys-swapfile

重置CONF_SWAPSIZE100MB

重新啟動交換服務(wù)器

在樹莓派運(yùn)行Keras + 深度學(xué)習(xí)模型

現(xiàn)在我們準(zhǔn)備使用KerasTensorFlow和樹莓派來編寫一個Not Santa檢測器。再次,我會假設(shè)你的硬件設(shè)置和我的一樣,如果不一樣,你需要修改下面的代碼。

首先,請打開一個新文件,將其命名為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:用于預(yù)處理輸入幀進(jìn)行分類,并從磁盤加載預(yù)訓(xùn)練的模型。

gpiozero:用于訪問3D圣誕樹。

imutils:用于訪問視頻流(無論是樹莓派相機(jī)模塊還是USB)。

threading:用于non-blocking操作,尤其是當(dāng)我們要點(diǎn)亮圣誕樹或播放音樂的同時不阻塞主線程的執(zhí)行。

然后,定義一個函數(shù)來點(diǎn)亮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函數(shù)接受一個tree參數(shù)(被設(shè)為一個LEDBoard對象)。

首先,我們循環(huán)tree中的所有LED,并隨機(jī)點(diǎn)亮每個LED,以產(chǎn)生閃爍效果(17-19行)。

我們讓燈亮一段時間(第23行),然后再次循環(huán)LED,然后把它關(guān)掉(26-28行)。

下面是一個打開3D圣誕樹燈的例子:

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

6Raspberry Pi3D圣誕樹

當(dāng)檢測到圣誕老人時,下一步是播放音樂

幫助

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函數(shù)中,對aplay命令進(jìn)行系統(tǒng)調(diào)用,從而能夠像從命令行那樣播放音樂文件。

然后,讓我們硬編碼將使用的配置:

幫助

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行將硬編碼到預(yù)訓(xùn)練的Keras模型和音頻文件的路徑。文末的下載可以獲取音頻文件。

初始化用于檢測的參數(shù),包括TOTAL_CONSECTOTAL_THRESH。這兩個值表示包含圣誕老人的幀的數(shù)量以及我們將分別播放音樂和打開樹的閾值(第43行和第44行)。

最后的初始化是SANTA = False,一個boolean(第47行)。我們稍后將在腳本中使用SANTA變量作為狀態(tài)標(biāo)志。

接下來,加載預(yù)訓(xùn)練的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模型已經(jīng)保存到了磁盤上[1],那么我們把它加載到樹莓派上。第51行使用Keras load_model函數(shù)加載了模型。

54行實(shí)例化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)

要訪問攝像機(jī),在imutils包中使用VideoStream

重要提示:如果你想在本項目中使用PiCamera模塊(而不是USB攝像頭),只需注釋第58行并取消第59行的注釋即可。

Sleep 兩秒鐘,以便相機(jī)預(yù)熱(第60行),然后開始循環(huán)播放幀:

幫助

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行,我們開始循環(huán)播放視頻幀,直到滿足停止條件(稍后在腳本中顯示)。

首先,通過調(diào)用vs.read來獲取一個frame(第66行)。

然后調(diào)整framewidth= 400,保持縱橫比(第67行)。在喂入神經(jīng)網(wǎng)絡(luò)模型之前預(yù)處理這個frame。稍后,我們將顯示框架以及文本標(biāo)簽。

然后預(yù)處理圖像,并通過Keras +深度學(xué)習(xí)模型進(jìn)行預(yù)測:

幫助

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行預(yù)處理圖像并準(zhǔn)備分類。然后,我們查詢model.predictimage作為參數(shù)。這向神經(jīng)網(wǎng)絡(luò)發(fā)送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。如果是,就繼續(xù)更新labelproba,然后遞增TOTAL_CONSEC85-90行)。

如果連續(xù)提供了足夠的“Santa”幀,就需要觸發(fā)圣誕老人警報:

幫助

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達(dá)到TOTAL_THRESH閾值,就有兩個操作要執(zhí)行:

創(chuàng)建并啟動一個treeThread來閃爍圣誕樹燈(98-100行)。

創(chuàng)建并啟動一個musicThread在后臺播放音樂(103-106行)。

這些線程將獨(dú)立運(yùn)行,不停止腳本的正向執(zhí)行(即非阻塞操作)。

在第95行,我們將我們的SANTA狀態(tài)標(biāo)志設(shè)置為True,意味著我們在輸入框架中找到了圣誕老人。 在循環(huán)的下一個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

最后,我們使用生成的文本標(biāo)簽將框架顯示在屏幕上:

幫助

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,可以在框架頂部顯示標(biāo)簽(以圣誕節(jié)為主題的綠色),然后將框架顯示在屏幕上(116-120行)。

無限while loop 的退出條件是在鍵盤上按下“q”鍵(121-125行)。如果循環(huán)的退出條件滿足,則在腳本退出之前,break并執(zhí)行第129行和第130行的一些清理。

完成!

回頭看看這130行代碼,這個框架/模板也可以很容易地用于樹莓派上的其他深度學(xué)習(xí)項目。

現(xiàn)在,讓我們來抓那個胖胖的,有胡子的,快活的圣誕老人吧!

深度學(xué)習(xí)+ Keras +樹莓派結(jié)果

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

7:我,Adrian Rosebrock,扮成圣誕老人。我將親自測試使用深度學(xué)習(xí),KerasPythonOpenCV構(gòu)建的不是圣誕老人檢測器。

然后,我把相機(jī)朝著客廳里的圣誕樹上的樹莓派:

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

8:圣誕樹將作為測試已經(jīng)部署到樹莓派上的Not Santa深度學(xué)習(xí)模型的背景。

如果圣誕老人來為給我的好孩子們送禮物,我想確保通過閃爍3D圣誕樹燈和播放圣誕歌曲來歡迎他。

然后,我使用以下命令啟動了Not Santa深度學(xué)習(xí)+ Keras檢測器:

幫助

1

$ python not_santa_detector.py

Not Santa 檢測器啟動并運(yùn)行后,我就開始行動:

親愛的圣誕老人:如果你讀到了這里,要知道我會用樹莓派找到你哦!

參考:
[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實(shí)現(xiàn)無線手套體驗(yàn)VR游戲

南京合越智能,增強(qiáng)智造,增強(qiáng)感知,增強(qiáng)交互!

業(yè)務(wù)合作

(我們會第一時間與您聯(lián)系)

聯(lián)系方式

  1. 微信:13815863530(手機(jī)同號)
  2. QQ:38260484
  3. 3XMaker@163.com
Copyright@ 2016-2025 南京合越智能科技有限公司 蘇ICP備18068961號
主站蜘蛛池模板: 永善县| 木兰县| 凤凰县| 常山县| 祥云县| 天台县| 潼关县| 富宁县| 七台河市| 南安市| 西充县| 深水埗区| 山西省| 宜丰县| 彭州市| 天祝| 通州市| 黄石市| 黔西县| 富宁县| 金门县| 巴塘县| 吉林市| 旌德县| 吉安市| 孟津县| 淅川县| 大邑县| 巴南区| 湘阴县| 桂平市| 息烽县| 牟定县| 开原市| 江山市| 收藏| 福鼎市| 丰台区| 合肥市| 双桥区| 北宁市|