DesignSpark Electrical Logolinkedin
菜单 搜寻
提问问题

13 Mar 2018, 2:23

AI使用Pidentifier進行對象識別! (繁體)

使用Pi 3 Model B,Pi Camera,Intel Movidius NCS,DesignSpark Pmod HAT和Digilent OLED Pmod構建基於樹莓派的對象識別設備

想想人工智能和深度神經網絡(DNNs)是專家工程師,科學家和數學家的儲備嗎?那麼,創建新的神經網絡可能並不是一件容易的事,而訓練它們可能需要大量的時間和資源。然而幸運的是,對於我們來說,我們可以利用已經接受過有用圖像集培訓的現有網絡,以及Movidius NCS和SDK,相對容易地構建簡單的應用程序,並使用這些應用程序,使用緊湊的低功耗計算平台作為樹莓派。
本文將介紹如何快速整合一個集成攝像頭和一個緊湊型OLED模塊的自包含系統,該系統將在NCS上運行的GoogLeNet上捕獲圖像並將其卸載,然後在顯示頂級結果OLED模塊。

硬件

這個項目使用一個運行Raspbian Stretch的Raspberry Pi 3 Model B和官方的Raspberry Pi Camera。除此之外,還有英特爾Movidius NCS,我們也有DesignSpark Pmod HAT和Digilent PmodOLEDrgb來顯示結果。

安裝了Raspbian並啟動了Pi之後,通過升級到最新版本的打包軟件開始是一個不錯的主意

pi@pidentifier:~$ sudo apt-get update
pi@pidentifier:~$ sudo apt-get dist-upgrade

我們還需要為OLED模塊啟用相機接口和SPI

pi@pidentifier:~$ sudo raspi-config
  • Option 5 - Interfacing
  • P1 - Camera
  • Enable → YES
  • Option 5 - Interfacing
  • P4 - SPI
  • Enable → YES

軟件依賴關係

我們可以通過O / S包管理系統獲得大部分的軟件依賴關係。

pi@pidentifier:~$ sudo apt-get install -y build-essential git libusb-1.0-0-dev libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler libatlas-base-dev git automake byacc lsb-release cmake libgflags-dev libgoogle-glog-dev liblmdb-dev swig3.0 graphviz libxslt-dev libxml2-dev gfortran python3-dev python3-pip python3-setuptools python3-markdown python3-pillow python3-yaml python3-pygraphviz python3-h5py python3-nose python3-lxml python3-matplotlib python3-numpy python3-protobuf python3-dateutil python3-skimage python3-scipy python3-six python3-networkx libfreetype6-dev libjpeg-dev python3-gst-1.0 python3-picamera

接下來,使用Python包管理器來安裝對OpenCV的支持。

pi@pidentifier:~$ sudo pip3 install opencv-python

只安裝Movidius NC SDK的API組件。請注意,可能在Raspberry Pi上安裝完整的SDK,但通常不建議這樣做,因為在PC上進行必要的編譯,然後復制二進製圖形文件更為迅速。

pi@pidentifier:~$ mkdir workspace
pi@pidentifier:~$ cd workspace
pi@pidentifier:~$ git clone https://github.com/movidius/ncsdk
pi@pidentifier:~$ cd ncsdk/api/src
pi@pidentifier:~$ make
pi@pidentifier:~$ sudo make install

DesignSpark Pmod HAT支持库可以通過一個命令來安裝。

pi@pidentifier:~$ sudo pip3 install designspark.pmod

最通過一個命令來安裝。後,需要在運行Ubuntu的另一台計算機上完整安裝Movidius NC SDK,以便我們可以編譯樹莓派上使用的模型。

user@laptop:~$ mkdir workspace
user@laptop:~$ cd workspace
user@laptop:~$ git clone https://github.com/movidius/ncsdk 
user@laptop:~$ cd
user@laptop:~$ sudo make install

測試硬件

如果我們開始測試Pi攝像頭是否按預期工作。

pi@pidentifier:~$ raspivid -d

這應該在屏幕上顯示視頻。

接下來,我們可以運行NCS的Hello World來確認它的運行

pi@pidentifier:~$ cd ~/workspace
pi@pidentifier:~$ git clone https://github.com/movidius/ncappzoo
pi@pidentifier:~$ python3 ncappzoo/apps/hello_ncs_py/hello_ncs.py

如果我們用下面的內容創建一個名為helloOLED.py的文件,測試PmodOLEDrgb:

from DesignSpark.Pmod.HAT import createPmod
from luma.core.render import canvas
from luma.oled.device import ssd1331

if __name__ == '__main__':
    try:
        oled = createPmod('OLEDrgb','JA')
        device = oled.getDevice()
        
        with canvas(device) as draw:
            draw.rectangle(device.bounding_box, outline="white", fill="black")
            draw.text((16,20), "Hello, World!", fill="white")
    
        while True:
            pass
    except KeyboardInterrupt:
        pass
    finally:
        oled.cleanup()

然後執行它

pi@pidentifier:~$ python3 helloOLED.py

Pmod模塊的文檔以及其他示例可以在ReadTheDocs上找到

模型編譯

我們將使用一個訓練有素的模型,它是在GoogLeNet論文中描述的模型的複制。但首先,這需要在Ubuntu機器上進行編譯,在那裡我們執行完整的NC SDK安裝。我們將同時編譯隨SDK提供的所​​​​有示例 - 並註意在編譯期間必須將NC插入此計算機。

user@laptop:~$ cd workspace/ncsdk
user@laptop:~$ make examples

應用

現在開始創建應用程序。
我們需要從Ubuntu計算機到Raspberry Pi之間複製GoogLeNet模型的新編譯的二進製圖形。

user@laptop:~$ scp workspace/ncsdk/examples/caffe/GoogLeNet/graph \
user@laptop:~$ pi@pidentifier.local:workspace/ncappzoo/caffe/GoogLeNet/

接下來,如果我們使用文本編輯器在Raspberry Pi上創建一個名為pidentify的新文件(用你最喜歡的編輯器替換“vi”):

pi@pidentifier:~$ vi pidentify

我們可以通過輸入以下內容來導入所需的Python庫

#!/usr/bin/python3
import os
import sys
import time
import numpy

import picamera

import mvnc.mvncapi as mvnc
import skimage
from skimage import io, transform

from DesignSpark.Pmod.HAT import createPmod
from luma.core.render import canvas
from luma.oled.device import ssd1331

接下來,我們需要定義一些NCS輸入參數

NCAPPZOO_PATH           = os.path.expanduser( '~/workspace/ncappzoo' )
GRAPH_PATH              = NCAPPZOO_PATH + '/caffe/GoogLeNet/graph'
IMAGE_PATH              = '/tmp/i-spy.jpg'
IMAGE_MEAN              = [ 104.00698793, 116.66876762, 122.67891434]
IMAGE_STDDEV            = 1
IMAGE_DIM               = ( 224, 224 )

NETWORK_STAT_TXT = NCAPPZOO_PATH + '/apps/stream_infer/googlenet_stat.txt'
NETWORK_CATEGORIES_TXT = NCAPPZOO_PATH + '/apps/stream_infer/googlenet_categories.txt'

請注意,如果要使用不同的神經網絡,這是我們將進行更改的地方。
以下兩行將創建一個樹莓派相機實例配置正確的分辨率為我們的神經網絡

camera = picamera.PiCamera()
camera.resolution = IMAGE_DIM

接下來,我們打開NCS並獲取設備句柄

ncsdevices = mvnc.EnumerateDevices()
if len( ncsdevices ) == 0:
        print( 'No NCS devices found' )
        quit()

ncs = mvnc.Device( ncsdevices[0] )
ncs.OpenDevice()

我們還需要創建一個DesignSpark Pmod OLEDrgb實例

pmoddev = createPmod('OLEDrgb','JA')
oled = pmoddev.getDevice()

通過最初的設備設置,我們現在可以將圖形文件加載到NCS上

with open( GRAPH_PATH, mode='rb' ) as f:
        blob = f.read()

graph = ncs.AllocateGraph( blob )

我們可以加載網絡類別

with open(NETWORK_CATEGORIES_TXT, 'r') as f:
    for line in f:
        cat = line.split('\n')[0]
        if cat != 'classes':
            gNetworkCategories.append(cat)
    f.close()

last = len(gNetworkCategories)-1

我們將創建一個函數將圖像卸載到NCS,運行推理並返回最高結果

def getTopInference(img):
    img = print_img = skimage.io.imread( IMAGE_PATH )
    img = skimage.transform.resize( img, IMAGE_DIM, preserve_range=True )

    img = img[:, :, ::-1]

    img = img.astype( numpy.float32 )
    img = ( img - IMAGE_MEAN ) * IMAGE_STDDEV

    graph.LoadTensor( img.astype( numpy.float16 ), 'user object' )

    output, userobj = graph.GetResult()
    order = output.argsort()
    top = gNetworkCategories[order[last-0]]

    return top

還有一個簡單的功能就是把文本寫到PmodOLEDrgb模塊的屏幕上

def display(message):
    with canvas(oled) as draw:
        draw.text((16,20), message, fill="white")

最後是主循環

try:
    while True:
        camera.capture(IMAGE_PATH)
        thing = getTopInference(IMAGE_PATH)
        display(thing)
        time.sleep(2)

except KeyboardInterrupt:
        pass

finally:
        graph.DeallocateGraph()
        ncs.CloseDevice()
        oled.cleanup()

這將捕捉一個圖像,顯示最高推斷,暫停2秒,然後重複

如果我們現在保存該文件並使其可執行

pi@pidentifier:~$ chmod +x pidentify

考驗它

最後,令人興奮的部分:對它進行所有的測試!

pi@pidentifier:~$ ./pidentify

在短暫的延遲之後,現在應該顯示最高推斷,每隔幾秒更新一次。在這一點上,重要的是要注意,網絡是由1000個類別中的1個圖像進行訓練的,所以它可以分類的是有限的。同樣,前1的推斷準確度 - 我們只顯示最高的結果 - 是68.7%,前5位的推斷準確率高達88.9%

潜在的改進

可以快速地將一個簡單的應用程序集成到一個簡單的應用程序中,這個應用程序集成了一個Raspberry Pi攝像機,Intel Movidius NCS和一個Pmod HAT以及OLEDrgb顯示器,這要歸功於Python支持這些和提供的示例。進一步的實驗肯定有改進的空間和樂趣。這可能包括,例如:

  • 嘗試不同的網絡,這應該只是複制編譯的二進製圖形文件並相應地更新NCS輸入參數
  • 使用視頻流而不是仍然捕獲。 NC應用程序動物園包括一個stream_infer應用程序的例子,可以作為這個基礎
  • 使用多個NCS,NC應用程序動物園再次包含示例代碼
  • 優化相機捕捉參數
  • 更好地顯示文本的格式

或者,即使冒險,也可以在自己的數據/圖像上操練一個模型!

Andrew Back

Blogger, DesignSpark Team

13 Mar 2018, 2:23