DesignSpark Electrical Logolinkedin
Menu Suche
Ask a Question

KI-gestützte Identifikation mit dem Pidentifier!

Aufbau einer Vorrichtung zur Objekterkennung auf Grundlage eines Raspberry Pi mit einem Pi 3 Modell B, Pi-Kamera, Intel Movidius NCS, DesignSpark Pmod HAT und einem Digilent OLED-Pmod.

Sie glauben, künstliche Intelligenz und Deep Neural Networks (DNNs) seien fachkundigen Ingenieuren, Wissenschaftlern und Mathematikern vorbehalten? Nun ja, die Entwicklung neuer neuraler Netzwerke ist vielleicht nichts für schwache Nerven, denn ihr Training kann notorisch zeit- und ressourcenintensiv ausfallen. Glücklicherweise für uns können wir allerdings auf vorhandene Netzwerke zurückgreifen, die in Bezug auf nützliche Bildkategorien bereits ausgebildet sind und (dank Movidius NCS und des dazugehörigen SDK) relativ einfach für die Entwicklung einfacher Anwendungen eingesetzt werden können, die darauf zurückgreifen. Diese Anwendungen können Sie mithilfe kompakter, energiesparender Computing-Plattformen wie dem Raspberry Pi nutzen.

Dieser Beitrag beleuchtet die Frage, wie Sie auf die Schnelle ein eigenständiges System zusammenstellen können, das eine Kamera und ein kompaktes OLED-Modul integriert. Damit können Sie Bilder aufzeichnen und zur Verarbeitung durch GoogLeNet auf einem NCS weiterleiten, bevor das beste Ergebnis auf dem OLED-Modul angezeigt wird.

Hardware

Dieses Projekt baut auf einen Raspberry Pi 3, Modell B, auf dem Raspbian Stretch ausgeführt wird, sowie ferner auf die offizielle Raspberry Pi-Kamera. Darüber hinaus und zusätzlich zum Intel Movidius NCS haben wir auch das DesignSpark Pmod HAT und das Digilent PmodOLEDrgb für die Anzeige der Ergebnisse.

Wenn Raspbian installiert und der Pi gestartet worden ist, sollten Sie am besten auf die jüngsten Versionen der Software im Paket aktualisieren.

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

Außerdem müssen Kamera-Schnittstelle und SPI für das OLED-Modul aktiviert werden.

pi@pidentifier:~$ sudo raspi-config
  • Option 5 – Schnittstelle
  • P1 – Kamera
  • Aktivieren → JA
  • Option 5 – Schnittstelle
  • P4 – SPI
  • Aktivieren → JA

     

     

Softwareabhängigkeiten

Die Mehrzahl der abhängigen Software kann über die Software-Paketverwaltung des Betriebssystems besorgt werden.

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

Im nächsten Schritt verwenden Sie den Python-Paketmanager, um Unterstützung für OpenCV zu installieren.

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

Installieren Sie nur die API-Komponente des Movidius NC-SDK. Beachten Sie, dass es eventuell möglich wäre, das vollständige SDK auf einem Raspberry Pi zu installieren. Das aber ist im Allgemeinen nicht ratsam, denn es geht viel schneller, die erforderliche Kompilierung auf einem PC durchzuführen und die Binärdatei auf das andere System zu kopieren.

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

Die DesignSpark Pmod HAT-Bibliothek für die Laufzeitunterstützung kann mithilfe eines einzigen Befehls installiert werden.

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

Zum Schluss muss noch das Movidius NC-SDK komplett auf einem anderen Computer installiert werden, der unter Ubuntu funktioniert, damit Modelle für den Einsatz auf dem Raspberry Pi kompiliert werden können.

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

Testen der Hardware

Zu Beginn sollte überprüft werden, ob die Pi-Kamera ordnungsgemäß funktioniert.

pi@pidentifier:~$ raspivid -d

Daraufhin sollte auf dem Bildschirm ein Video angezeigt werden.

Im nächsten Schritt wird das „Hallo, Welt!“-Programm ausgeführt, damit das NCS Betriebsbereitschaft signalisieren kann.

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

Zum Testen des PmodOLEDrgb wird eine Datei namens helloOLED.py mit folgendem Inhalt erstellt:

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

Führen Sie anschließend folgende Anweisung aus:

pi@pidentifier:~$ python3 helloOLED.py

Dokumentationen für das Pmod-Modul sind gemeinsam mit weiteren Beispielen unter ReadTheDocs zu finden.

Modell-Kompilierung

Wir werden auf ein geschultes Modell zurückgreifen, das eine Replikation des im GoogLeNet-Dokument beschriebenen Modells darstellt. Aber zunächst muss dieses Modell auf dem Ubuntu-System kompiliert werden, auf dem die vollständige Installation des NC-SDK untergebracht worden ist. Wir kompilieren alle Beispiele gleichzeitig, die zum Lieferumfang des SDK gehören. Beachten Sie aber auch, dass das NC-System während der Kompilierung an diesen Computer angeschlossen sein muss.

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

Anwendung

Jetzt zum Erstellen der Anwendung.

Die gerade eben kompilierte Binärdatei für das GoogLeNet-Modell muss vom Ubuntu-Computer auf den Raspberry Pi kopiert werden.

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

Im nächsten Schritt setzen wir einen Texteditor ein, um auf dem Raspberry Pi eine neue Datei namens „pidentify“ zu erstellen (ersetzen Sie „vi“ durch den Editor Ihrer Wahl):

pi@pidentifier:~$ vi pidentify

Und schon können wir beginnen, die folgenden Anweisungen anzugeben, um die erforderlichen Python-Bibliotheken zu importieren.

#!/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

Als Nächstes müssen einige NCS-Eingabeparameter festgelegt werden.

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'

Beachten Sie, dass an dieser Stelle Änderungen vorzunehmen wären, wenn ein anderes neuronales Netzwerk verwendet werden soll.

Die folgenden beiden Zeilen erstellen eine Instanz für die Raspberry Pi-Kamera, die mit der zutreffenden Auflösung für unser neuronales Netzwerk konfiguriert ist.

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

Als Nächstes öffnen wir das NCS, um einen Geräte-Handle zu bekommen.

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

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

Außerdem müssen wir eine DesignSpark PmodOLEDrgb-Instanz schaffen. 

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

Nachdem die ursprüngliche Einrichtung des Geräts erledigt worden ist, können wir jetzt die graph-Datei auf das NCS laden.

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

graph = ncs.AllocateGraph( blob )

Überdies können wir die Netzwerkkategorien laden.

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

Wir erstellen eine Funktion zum Bereitstellen eines Bildes auf dem NCS, führen die Inferenz durch und geben das beste Ergebnis zurück.

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

Und jetzt eine einfache Funktion zum Schreiben von Text auf dem Bildschirm des PmodOLEDrgb-Moduls. 

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

Zum Schluss die Hauptschleife.

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

Damit wird ein Bild aufgezeichnet, die beste Inferenz angezeigt, eine 2-Sekunden-Pause eingelegt und schließlich wiederholt. 

Wir müssen die Datei nur noch speichern und in eine ausführbare Datei umwandeln.

pi@pidentifier:~$ chmod +x pidentify

Das Ganze auf den Prüfstand stellen

Zum guten Schluss kommt der spannende Teil: Wir probieren die Sache aus!

pi@pidentifier:~$ ./pidentify

Nach einer kurzen Verzögerung sollte die beste Inferenz angezeigt und alle paar Sekunden aktualisiert werden. An diesem Punkt muss unbedingt festgestellt werden, dass die Schulung des Netzwerks mit Bildern aus einer von 1.000 Kategorien durchgeführt wurde. Aus diesem Grund gibt es Grenzen in Hinblick darauf, was klassifiziert werden kann. Darüber hinaus liegt die Genauigkeit der besten Inferenz (und wir zeigen nur das beste Ergebnis) bei 68,7 %, während sie im Rahmen der besten 5 auf 88,9 % ansteigen würde.

Mögliche Verbesserungen

Es war möglich, auf die Schnelle eine einfache Anwendung zusammenzustellen, die eine Raspberry Pi-Kamera, das Intel Movidius NCS und ein Pmod HAT mit OLEDrgb-Anzeige integriert. Das war dank der Python-Unterstützung für dieses und weitere bereitgestellte Beispiele möglich. Ganz bestimmt sind Verbesserungen denkbar, die Raum für weitere unterhaltsame Experimente geben. Wie wäre es zum Beispiel mit folgenden Projekten:

  • Ausprobieren verschiedener Netzwerke. Dazu müssten eigentlich nur die kompilierten Binärdateien auf entsprechende Systeme kopiert und die NCS-Eingabeparameter entsprechend angepasst werden.
  • Verwenden eines Videostreams anstelle von Einzelbildern. Die NC-App Zoo umfasst ein App-Beispiel namens stream_app, das dafür als Basis genutzt werden könnte.
  • Verwenden mehrerer NCS. Wiederum enthält die NC-App Zoo entsprechenden Beispiel-Code.
  • Optimieren der Parameter für die Aufzeichnung der Kamera.
  • Vorteilhafteres Formatieren der angezeigten Texte.

Und für diejenigen, für die es kaum abenteuerlich genug sein kann: Schulen eines Modells auf der Basis Ihrer eigenen Daten/Bildsätze!

Andrew Back

Open source (hardware and software!) advocate, Treasurer and Director of the Free and Open Source Silicon Foundation, organiser of Wuthering Bytes technology festival and founder of the Open Source Hardware User Group.

22 Jan 2018, 11:16

Kommentare