今天這篇文章是使用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”微信公衆号