Skip to main content

L'identification actionnée par l'AI avec le Pidentifier !

Main7_7ef258b90ccfd829445a4bd1f55989b50c986db7.jpg

Réalisez un système d'identification d'objets avec le Raspberry Pi 3 modèle B doté d'une clé Movidius d'Intel, d'un Pmod HAT, d'une caméra Pi et d'un Pmod OLED de Digilent .

Vous pensez que l'intelligence artificielle et les réseaux de neurones profonds (DNN) sont l'apanage d'experts en ingénierie, sciences et mathématiques ? Eh bien, s'il est vrai que la création de réseaux de neurones n'est pas pour les cœurs fragiles et que la formation dans ce domaine nécessite du temps et des ressources importantes, il est heureusement possible d'utiliser des réseaux existants formés avec des jeux d'images et, grâce à la clé de Movidius NCS et à son SDK, de créer relativement facilement des applications simples capables de les exploiter et de les déployer sur des plates-formes compacts de faible capacité telles que le Raspberry Pi.

Cet article examine comment vous pouvez rapidement assembler un système autonome intégrant une caméra et un module OLED compact, qui capturent les images et les chargent pour qu'elles soient traitées et exécutées par GoogLeNet dans un NCS, avant d'en afficher le meilleur résultat sur le module OLED.

Matériel

Hardware_05c34bbbdcade3bff5844e1a69e2b3c2cfa6d8c4.jpg

Ce projet utilise un Raspberry Pi 3 modèle B exécutant Raspbian Stretch, avec la caméra officielle Raspberry Pi. Outre ce matériel et la clé NCS Movidius d'Intel, nous disposons également du HAT DesignSpark Pmod et du PmodOLEDrgb Digilent pour l'affichage des résultats.

Après installation de Raspbian et démarrage du Pi, il est toujours conseillé de commencer par effectuer une mise à jour afin de travailler avec les versions les plus récentes des suites logicielles.

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

Nous devrons également activer l'interface de la caméra et le SPI du module OLED.

pi@pidentifier:~$ sudo raspi-config
  • Option 5 - Interface
  • P1 - Caméra
  • Active → YES
  • Option 5 - Interface
  • P4 - SPI
  • Active → YES

Configurations logicielles

APIP_pip3-install_744bf09fc835293e9aea3b817d17cd08d66afd12.jpg

On peut obtenir la plupart des configurations logicielles via le système de gestion de paquets 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

Utilisez ensuite le gestionnaire de paquets Python pour installer la prise en charge d'OpenCV.

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

Installez uniquement le composant API du SDK NC de Movidius. Remarque : il est peut-être possible d'installer le SDK complet sur un Raspberry Pi, mais cette action est généralement déconseillée, car il est beaucoup plus rapide de procéder à la compilation requise sur un PC, puis de copier le fichier graphique binaire.

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

Le Bibliothèque de prise en charge de HAT DesignSpark Pmod peut être installé via une seule commande.

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

Pour finir, le SDK NC de Movidius devra être installé intégralement sur un autre ordinateur exécutant Ubuntu, afin que nous puissions compiler des modèles à utiliser sur le Raspberry Pi.

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

Test du matériel

APIP_hello_ncs_52a23ea13b9df92f86bd11024bf679f53f422f3d.jpg

Si l'on commence par tester le fonctionnement de la caméra Pi.

pi@pidentifier:~$ raspivid -d

La vidéo doit apparaître à l'écran.

On peut ensuite exécuter le Hello World du NCS pour confirmer son bon fonctionnement.

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_33230e05b13883dd959b69dce263940fe52d7e90.jpg

Pour tester le PmodOLEDrgb en cas de création d'un fichier intitulé helloOLED.py avec le contenu suivant :

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

Exécutez ensuite ce qui suit.

pi@pidentifier:~$ python3 helloOLED.py

La documentation relative au module Pmod et d'autres exemples sont disponibles sur ReadTheDocs.

Modèle de compilation

APIP_makeExamples_508b99045c1e4f9c20cc80fbbd43cb339bd1b1f6.jpg

Nous utiliserons un modèle formé copié du modèle décrit dans l'article de GoogLeNet. Mais il devra d'abord être compilé sur la machine Ubuntu sur laquelle nous avons effectué une installation complète du SDK NC. Nous compilerons tous les exemples fournis avec le SDK en même temps. Notez que le NC doit être branché sur cet ordinateur lors de la compilation.

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

Application

Passons maintenant à la création de l'application.

Il est nécessaire de copier le fichier graphique binaire nouvellement compilé du modèle GoogLeNet depuis l'ordinateur Ubuntu sur le Raspberry Pi.

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

Ensuite, en cas d'utilisation d'un éditeur de texte pour la création d'un nouveau fichier sur le Raspberry Pi intitulé pidentify (remplacez « vi » par votre éditeur préféré) :

pi@pidentifier:~$ vi pidentify

On peut commencer par saisir ce qui suit pour importer les bibliothèques Python requises.

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

Il convient ensuite de définir certains paramètres d'entrée 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'

Remarque : c'est ici que devront être effectuées les modifications si l'on souhaite utiliser un autre réseau neuronal.

Les deux lignes suivantes vont créer une instance de la caméra Raspberry Pi configurée avec la résolution qui convient à notre réseau neuronal.

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

On ouvre ensuite le NCS pour obtenir une poignée de périphérique.

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

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

Il convient également de créer une instance de DesignSpark Pmod OLEDrgb.

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

Une fois effectuée la configuration initiale de l'appareil, on peut maintenant charger le fichier graphique sur le NCS.

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

graph = ncs.AllocateGraph( blob )

Et on peut charger les catégories de réseau.

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

Créons une fonction pour charger une image sur le NCS, exécuter l'inférence et renvoyer le meilleur résultat.

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

Créons aussi une fonction simple pour écrire du texte sur l'écran du module PmodOLEDrgb.

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

Pour finir, créons la boucle principale.

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

Cette action capture une image, affiche la meilleure inférence, se met en pause pendant deux secondes, puis recommence

Si l'on enregistre maintenant le fichier pour en faire un fichier exécutable.

pi@pidentifier:~$ chmod +x pidentify

Le test

Test_ff5dbb53aba4e768380088e90f911bef7dab8b66.jpg

Passons maintenant à la partie excitante : le test !

pi@pidentifier:~$ ./pidentify

Après un court instant, il affiche la meilleure inférence, qui doit s'actualiser toutes les quelques secondes. À ce stade, il est important de noter que le réseau a été formé avec des images faisant partie d'une catégorie parmi mil catégories, ce qui explique les limitations de sa capacité de classement. En outre, sa précision d'inférence pour le meilleur résultat (seul le meilleur résultat est affiché) est de 68,7 %, pour atteindre 88,9 % pour les cinq meilleurs résultats.

Améliorations possibles

Nous avons pu créer rapidement une application simple intégrant une caméra Raspberry Pi, le NCS Movidius d'Intel et un HAT Pmod avec écran OLEDrgb, grâce à la disponibilité du support Python et aux exemples fournis. Il est tout à fait possible d'améliorer l'application et d'expérimenter pour le plaisir. Vous pouvez par exemple effectuer les actions suivantes :

      • essai de différents réseaux. Pour cela, il devrait suffire de copier les fichiers graphiques binaires compilés et d'actualiser les paramètres d'entrée NCS correspondants ;
      • utilisation d'un flux vidéo au lieu de captures fixes. Le NC App Zoo inclut un exemple d'application stream_infer qui pourrait en être la base ;
      • utilisation de plusieurs NCS. Ici aussi, le NC App Zoo inclut un exemple de code ;
      • optimisation des paramètres de capture de la caméra ;
      • amélioration du formatage du texte affiché ;

pour les plus aventureux, formation d'un modèle avec vos propres données/lots d'images !

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.

Commentaires

DesignSpark Electrical Logolinkedin