Azure Custom Vison en action

La plateforme Azure propose de nombreux services cognitifs prêts à l'emploi, permettant d'enrichir facilement vos applications avec des fonctionnalités innovantes.

Dans cet article, nous allons voir comment utiliser le service Custom Vision. Nous allons entrainer un modèle pour l'apprendre à reconnaitre certains types de manteaux. Nous testerons ensuite ce modèle et enfin nous verrons comment l'utiliser au sein d'une application.

 

Prérequis

La partie concernant le notebook peut se faire, entre autres, avec :

Dans cet article, nous allons utiliser la machine virtuelle « Data Science »,

Création d'une machine virtuelle « Data Science »

  • Connectez vous sur le portail Azure : https://portal.azure.com
  • Cliquez sur « Create a resource », puis recherchez la machine virtuelle « Data Science »

 

Sélectionnez la machine « Data Science Virtual Machine for Linux (Ubuntu)  » puis cliquez sur le bouton « Create »

 

 

Remplissez les informations de création de la machine virtuelle

A la fin du process cliquez sur le bouton « Create »

 

Maintenant que la machine virtuelle est créée, nous allons nous connecter sur son server Jupyter. La connexion se fait avec une URL de type :

https://<Your_VM_IPAddress>:8000

Dans le cas de mon exemple cette adresse sera :

https://40.86.210.115:8000

 

L'adresse IP de la machine se trouve sur le portail Azure :

 

Il se peut que la fenêtre suivante s'affiche. Cliquez sur « Details » puis sur « Go on the web page »

 

Dans la fenêtre de connexion, entrez le nom et le mot de passe que vous avez utilisés lors de la création de la machine virtuelle :

Après quelques secondes, vous devez arriver sur la page d'accueil du serveur Jupyter.

Nous allons créer un dossier pour faciliter notre travail. Cliquez sur « New » puis sur « Folder »

 

Cochez la case à gauche du dossier nouvellement créé (le dossier se nomme « Untitled Folder »), puis cliquez sur le bouton « rename » un haut de la page.

Renommez le dossier puis cliquez sur le bouton « Rename »

 

 

Création du notebook

Entrez dans le dossier précédemment créé. Cliquez sur le bouton « New » puis sur « Python 3 »

 

Une fois le Notebook créé, cliquez sur « Untitled » et donnez-lui un nom. Cliquez sur « Rename »

 

Téléchargement des images

Dans la première cellule du Notebook, copiez le code ci-dessous pour récupérer les images d'entrainements et de tests.

! curl -O https://canadastore.blob.core.windows.net/franmerpictures/Pictures.zip

Puis cliquez sur « Run » dans la barre d'outils (ou utilisez la combinaison de touche « Shift Enter » ou « Ctrl Enter »). Pour le reste de l'article, après avoir copié le code dans les cellules, pensez bien à exécuter le code

Si tout se passe bien, le fichier Pictures.zip doit apparaître dans votre dossier

Nous allons maintenant décompresser le fichier. Utilisez la commande-ci-dessous :

! unzip Pictures.zip

 

 

Attention : l'astérisque présent entre les crochets, signifie que le code est en cours d'exécution. Il est de bon aloi d'attendre qu'il disparaisse avant d'exécuter le code d'une autre cellule.

 

 

Trois nouveaux dossiers ont dû apparaître :

Affichage d'une image

Nous allons afficher une image et de voir comment faire des manipulations simples avec. Nous allons utiliser la librairie « matplotlib ». La documentation détaillée de cette librairie se trouve ici : https://matplotlib.org/.

Copiez le code ci-dessous dans une nouvelle cellule :

#Afficher une image / Display a picture

# Importation de librairie matplotlib / Import the matplotlib libraries

import matplotlib.pyplot as plt

import matplotlib.image as im

 

img = im.imread('hardshell_jackets/10116634x1038116_zm.jpeg')

imgplot = plt.imshow(img)

 

Il se peut que lors de la première exécution, le message ci-dessous apparaît. Cela n'aura aucune incidence sur la suite des résultats.

Récupérer des informations de l'image

Une image est intrinsèquement un tableau de valeurs de pixels (picture element) et il est important de pouvoir récupérer certaines informations concernant une image, afin de pouvoir les utiliser avec des algorithmes de reconnaissance d'objet. Ci-dessous, un exemple de code permettant de récupérer certaines informations.

#Information sur l'image / Picture's information

print ("Picture Shape: ")

print(img.shape)

 

#Total number of pixels is accessed by img.size:

print ("Number of pixels: ")

print (img.size)

 

#Image datatype is obtained by img.dtype:

print("Picture data type:")

print(img.dtype)

 

 

Intégration avec le service cognitif « Custom Vision »

Microsoft propose de nombreux services cognitifs dont la liste complète est disponible via le lien suivant : https://azure.microsoft.com/en-us/services/cognitive-services/directory/

De plus, ces services peuvent être appelés en tant que service web afin de retourner les résultats d'une prédiction.

Dans cet exemple, nous allons utiliser le service « Custom Vision ». Ce service est disponible via le lien suivant : https://customvision.ai/.

Mais avant, il nous reste des petites préparations à faire au niveau de notre Notebook.

Installation du SDK Custom Vision

Dans un premier temps nous allons vérifier la présence de « pip » et de sa mise à jour. « pip » est un outil permettant l'installation de packages Python. Dans une nouvelle cellule du Notebook, copiez le code suivant :

#installation de pip / pip installation

import sys

! {sys.executable} -m pip freeze

! {sys.executable} -m pip --version

! {sys.executable} -m pip install --upgrade pip

 

 

Depuis votre notebook, entrez la commande suivante : (nous utilisons donc « pip » pour installer le package du service cognitif « Custom vision ») :

#Installation du SDK Custom Vision / Install the Custom Vision SDK

! {sys.executable} -m pip install azure-cognitiveservices-vision-customvision

 

 

 

Configuration du service cognitif « Custom Vision »

Nous allons maintenant créer un service « Custom vision » en suivant le lien suivant :

https://customvision.ai

Une fois sur la page d'accueil, cliquez sur « Sign in »

 

Vous avez la possibilité de tester gratuitement nos services cognitifs. Vous pouvez choisir de cliquer sur « Continue with trial » ou cliquez sur « Sign up for Azure ». Pour notre exemple, nous allons choisir « Continue with trial » :

Une fois le service créé, récupérez les informations de votre service en cliquant sur l'engrenage en haut à droite de la fenêtre

Puis récupérez les valeurs de vos clefs

Revenez dans votre Notebook Jupyter pour y assigner les valeurs de vos clefs dans les 2 variables ci-dessous et exécutez le code :

# Assignez les clefs de votre service "Custom Vision" aux variables / Assign your Custom service keys to variables

training_key = 'c5926d0852854f459c85facff519c759'

prediction_key = '32446a7de71b496798d38fded67fc2da'

 

 

Création d'un projet Custom Vision

A partir du Notebook, nous allons créer un projet dans le service cognitif « Custom Vision ». Dans une nouvelle cellule, copiez le code ci-dessous et exécutez-le :

from azure.cognitiveservices.vision.customvision.training import training_api

from azure.cognitiveservices.vision.customvision.training.models import ImageUrlCreateEntry

 

trainer = training_api.TrainingApi(training_key)

 

# Create a new project

print ("Creating project...")

project = trainer.create_project("MyProject")

 

 

Si vous retournez sur l'interface web du « Custom Vison » service, vous devez y trouver un nouveau projet :

 

Création des labels

Avant d'ajouter des images dans le service, nous allons créer nos premiers labels afin d'identifier les images.

Ajoutez le code suivant dans une nouvelle cellule et exécutez le code :

# Création des labels les images / Add tags for pictures

 

print("Creating tags")

hardshell_tag = trainer.create_tag(project.id,"Hardshell")

insulated_tag = trainer.create_tag(project.id,"Insulated")

print("Tags created")

 

 

Chargement des images

Maintenant nous allons importer les images dans notre projet « Custom Vision » et ajouter les labels en même temps. Copiez et exécutez le code ci-dessous dans une nouvelle cellule :

# Téléchargez les images / Upload pictures

import os

 

print("Adding hardshell images...")

hardshell_folder = "jacket_images/hardshell_jackets"

for file in os.listdir(os.fsencode("jacket_images/hardshell_jackets")):

with open(hardshell_folder + "/" + os.fsdecode(file),mode="rb") as Hardshell_img_data:

trainer.create_images_from_data(project.id,Hardshell_img_data,[hardshell_tag.id])

 

print("Adding insulated images...")

insulated_folder = "jacket_images/insulated_jackets"

for file2 in os.listdir(os.fsencode("jacket_images/insulated_jackets")):

with open(insulated_folder + "/" + os.fsdecode(file2),mode="rb") as insulated_img_data:

trainer.create_images_from_data(project.id,insulated_img_data,[insulated_tag.id])

 

print("Done !")

 

 

 

Vérifier la présence des images dans l'interface web du service cognitif et que les images possèdent le bon label.

 

 

 

 

 

 

Entrainement du projet

Après avoir ajouté les images et défini les différents labels, nous pouvons maintenant entrainer un model permettant d'identifier nos images.

Dans une nouvelle cellule, copiez et exécutez le code ci-dessous :

#Entrainement du projet / Train the project

import time

 

print("Training....")

iteration = trainer.train_project(project.id)

print (iteration.status)

while (iteration.status != "Completed"):

iteration = trainer.get_iteration(project.id,iteration.id)

print("Training status: " + iteration.status)

time.sleep(1)

 

# Set this iteration of the project as the default.

trainer.update_iteration(project.id,iteration.id,is_default=True)

print("Done!")

 

 

 

Si on vérifie dans l'interface web du service cognitif, une première itération de notre model a été créée.

 

 

Test du model

Maintenant que le modèle a été entrainé, nous allons le tester avec un autre set d'images

Dans un premier temps, nous allons créer une fonction pour convertir les images et envoyer une valeur de données au point de terminaison du service cognitif.

Pour faire cette conversion, nous allons créer une fonction. Copiez le code ci-dessous dans une nouvelle cellule :

 

def read_image_data(img_path):

import numpy as np

from io import BytesIO

import matplotlib.pyplot as plt

 

# Load the numpy array

#imgArray = np.load(img_path)

imgArray = im.imread(img_path)

# Write the array data to a stream

imageStream = BytesIO()

plt.imsave(imageStream, imgArray)

# Read the stream from the beginning

imageStream.seek(0)

return imageStream.read()

 

print ('read_image_data function created!')

 

 

 

Nous allons utiliser le modèle que nous avons entrainer pour réaliser des prédictions sur des images de tests. Nous allons aussi utiliser la fonction créée précédemment pour convertir les images avant de les envoyer au modèle.

Dans une nouvelle cellule de votre Notebook, copiez le code ci-dessous :

import os

import time

import numpy as np

 

#Importation du point de terminaison de prédiction / Import the prediction endpoint

from azure.cognitiveservices.vision.customvision.prediction import prediction_endpoint

from azure.cognitiveservices.vision.customvision.prediction.prediction_endpoint import models

 

#Création d'une instance du point de terminaison de prédiction

#Create an instance of the prediction endpoint

predictor = prediction_endpoint.PredictionEndpoint(prediction_key)

 

#Boucle sur l'ensemble des images / Loop through the test images

folder = 'Test'

files = os.listdir(folder)

i=1

x = np.linspace(0,10)

y = np.sin(x)

 

for file in sorted(files):

 

#Les images sont traitées dans l'ordre / process files in order

#Récupération du chemin de l'image et lecture des données / Get the file path and read the image data

 

img_path = os.path.join(folder,file) #Test pour savoir si c'est un fichier ou un dossier

if os.path.isfile(img_path):

print("File name: " + file)

img = im.imread(img_path)

plt.imshow(img)

plt.show()

#plt.plot(x,y)

#plt.figure(i+1)

 

img_data = read_image_data(img_path)

#Récupération des prédictions pour les images / Get the predicted tags for the image

results = predictor.predict_image(project.id, img_data, iteration.id)

fig = plt.figure()

#Affichage des labels et des probabilités / Display the tag name and probability for each prediction

for prediction in results.predictions:

print ("\t" + prediction.tag_name + ": {0:.2f}%".format(prediction.probability * 100))

 

print('\n')

#Pause technique :) / Technical Delay

time.sleep(0.25)

i=i+1

 

 

Notre model nous retourne donc des prédictions sur les images afin de tenter d'identifier si les images analysées sont des manteaux ou non, et si oui, quel type de manteau. Ci-dessous des exemples avec des images de tests

     

 

Utilisation du service cognitif avec Visual Studio

 

Maintenant que notre modèle fonction, il est peut-être aussi intéressant d'utiliser l'API du service cognitif afin d'intégrer les prédictions dans une application. Ci-dessous, une illustration rapide d'intégration du service cognitif dans une application.

 

Démarrez Visual Studio 2017 et créez un projet de type « Console App ».

 

Une fois le projet créé, dans le menu « Tools / NuGet Package Manager / Manage NuGet Packages for solution… » de Visual studio, et ajoutez les packages du Custom Vision comme illustré ci-dessous :

 

 

 

Rajoutez les 2 packages suivants :

 

 

Puis dans le fichier program.cs rajoutez le code ci-dessous. Remplacez les clefs par celles de votre projet du service cognitif

 

using Microsoft.Cognitive.CustomVision.Prediction;

using Microsoft.Cognitive.CustomVision.Training;

using Microsoft.Cognitive.CustomVision.Training.Models;

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Threading;

 

 

namespace myTutorialCustomVision

{

class
Program

{

//private static MemoryStream testImage;

static
void Main(string[] args)

{

var projectID = "<YourProjectID>";

var trainingKey = "<YourTrainingKey>";

var predictionKey = "<YourPredictionKey>";

string imagesPath = @"..\..\..\myTutorialCustomVision\Images";

string[] imageFiles = Directory.GetFiles(imagesPath, "*.jpg");

 

TrainingApi trainingApi = new TrainingApi() { ApiKey = trainingKey };

var project = trainingApi.GetProjects();

Guid myGuid = project[0].Id;

 

var iterations = trainingApi.GetIterations(Guid.Parse(projectID));

var validIterations = iterations.Where(iter => iter.Status == "Completed");

var lastIterationTrained = validIterations.OrderBy(iter => iter.LastModified).Last();

 

 

Iteration lastIteration = trainingApi.GetIteration(myGuid, lastIterationTrained.Id);

lastIteration.IsDefault = true;

trainingApi.UpdateIteration(myGuid, lastIteration.Id, lastIteration);

 

 

foreach (var image in imageFiles)

{

FileStream fileStream = new FileStream(image, FileMode.Open, FileAccess.Read);

PredictionEndpoint endpoint = new PredictionEndpoint() { ApiKey = predictionKey };

Console.WriteLine("Making a prediction for picture: " + Path.GetFileName(image));

var result = endpoint.PredictImage(myGuid, fileStream);

foreach (var c in result.Predictions)

{

Console.WriteLine($"\t{c.Tag}: {c.Probability:P1}");

}

 

}

Console.ReadKey();

 

}

}

}

 

 

Test de l'application

Pour tester l'application et les prédictions, j'ai rajouté un dossier Images dans le « Solution Explorer » et j'ai copié 2 images dans ce dossier

 

 

 

Résultat

L'application va retourner, pour chacune des images, une prédiction pour chacun des labels.

 

Il se peut que vous obteniez l'erreur « Operation returned an invalid status code '429' » si vous réalisez le test avec une grande quantité d'images. Souvent cette erreur vient du fait que votre service est soit en version d'essai soit sous-dimensionné. Pour corriger le problème, il suffit juste de changer le « Pricing tier » dans la page web du service custom vision, dans la partie « Account »,