Locomotive

Agence digitale

Le fun Retour au travail

Le fun

Retour aux articles

Analyse d'image et machine learning avec Google Vision API

La technologie et la recherche sont au coeur des projets Pilot® développés à l'interne chez Locomotive. Au printemps 2019, on a entamé les discussions sur un nouveau concept à développer pour succéder à Moment Zero, un projet d'expérimentation dans le cadre de Pilot® utilisant des données ouvertes et la réalité augmentée.

Validation du concept

Cette fois-ci, on s’organise différemment. On pose d’abord notre base de concept et une première équipe est sélectionnée pour délimiter le périmètre des premières fonctionnalités à tester. Comme le but de Pilot® est d'apprendre et repousser nos limites techniques, on débute par un prototype (MVP) de chaque fonctionnalité, pour ensuite travailler sur le user-flow, l’expérience utilisateur, le scénario et la direction artistique.

Analyse d’image et machine learning

La première fonctionnalité que l'on voulait tester concernait l’analyse d’image. L’idée d'un produit final sera de demander à l’utilisateur de prendre en photo un objet donné (par exemple: une tasse) et de valider l'objet en question.

Le premier prototype est simple. Il s'agit d'une interface de base demandant à l'utilisateur de prendre une photo d'un objet. Le résultat retourne tous les mots-clés que l'API d'analyse d’image a identifié par pourcentage de probabilité.

On a d’abord testé une solution avec Tensorflow.js. Le résultat était satisfaisant mais l’essai en ligne de Google Vision API nous donnait davantage d’informations. Cette première méthode est toutefois plus pratique pour détecter des objets en temps réel, avec une webcam par exemple.

On décide donc de commencer à tester Google Vision API et d'utiliser Node.js comme serveur pour communiquer.

Initialisation de Google Vision API

Avant tout, il faut paramétrer votre compte Google Cloud Platform et suivre les 4 premières étapes ici : https://cloud.google.com/vision/docs/quickstart-client-libraries

Pour l’étape 5, vous pouvez récupérer le fichier json et le mettre à la racine de votre projet. Dans votre terminal, il faudra exporter la variable d’environnement.

            export GOOGLE_APPLICATION_CREDENTIALS=”url/de/votre/fichier/json”
        

Mise en place du serveur Nodejs avec express et socket.io

Pour faciliter la gestion du serveur node, on utilise nodemon. Il faudra aussi installer expressjs et socketIO pour créer une communication entre le côté client (l'application) et le serveur node qui communiquera avec la Google Vision API.

            npm install nodemon -g
npm install express --save
npm install socket.io --save
        

Serveur index.js

À la racine du projet, vous pouvez créer un fichier index.js qui sera le fichier exécuté pour le lancement du serveur nodejs.

            // Express server setup
const express = require('express')
var app = express();
var http = require('http').createServer(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
});

http.listen(2222, function(){
    console.log('listening on *:2222');
});

io.on('connection', function (socket) {
    console.log(‘User connected’);
});

        

Lancement du serveur

On peut maintenant lancer le serveur dans le terminal via localhost:2222 et la console devrait vous indiquer qu'un utilisateur est connecté.

            nodemon index.js
        

Communication côté client

Pour la partie client, nous utilisons locomotive-boilerplate.

Dans le fichier index.html, on peut ajouter notre markup et le lier à notre module. Ensuite, on pourra créer notre fichier Detection.js dans assets/scripts/modules/ puis l'ajouter à la liste de modules dans modules.js

             <div data-module-detection class="c-detection">
<input type="file" data-detection="input">
</div>

        
            export {default as Detection} from './modules/Detection';
        

Gestion de fichier

Pour la gestion du fichier et du champs, on utilise filepond. Cette librairie flexible permet de gérer des uploads temporaires, ainsi que l’upload de plusieurs fichiers à la suite. Elle propose des plugins utiles pour crop/resize une image, pour corriger l’orientation lors d’une prise de photo depuis un smartphone, ou encore valider et gérer les différents types et tailles de fichiers avant le chargement sur le serveur. Filepond nous sera aussi utile dans la projection future du projet.

Pour les plugins on aura besoin du plugin de preview et le plugin d’orientation.

Côté client il faudra installer les packages suivant, puis initialiser filepond dans notre fichier Detection.js

            npm install filepond  --save
npm install filepond-plugin-image-preview --save
npm install filepond-plugin-image-exif-orientation --save

        
            import { module } from 'modujs';
import * as FilePond from 'filepond';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import FilePondPluginImageExifOrientation from 'filepond-plugin-image-exif-orientation';

export default class extends module {
    constructor(m) {
        super(m);
    }

    init() {
        this.$input = this.$('input')[0];

        this.socket = io();
        
        // Add plugins to Filepond
        FilePond.registerPlugin(FilePondPluginImagePreview);
        FilePond.registerPlugin(FilePondPluginImageExifOrientation);
	  
        const pond = FilePond.create(this.$input,{
            multiple: false,
            name: 'filepond',
            allowImageExifOrientation: true,
            labelIdle: 'Take a picture'
        });
    }
}

        

Socket.IO

Maintenant, on va ajouter Socket.IO côté client. Il est possible de placer le fichier source dans notre dossier assets/scripts/vendors ou l'installer avec un gestionnaire de package.

À la fin de notre fonction init() nous allons créer notre socket.

            this.socket = io();
        

Récupération et envoi de l'image à Google Vision API

Côté serveur on peut maintenant installer le package de Google Vision API.

Ensuite, dans le fichier serveur index.js on peut créer une fonction fetch pour l'appel à Google Vision API qui prendra en paramètre l’url d’une image. Puis on va simplement suivre les informations de la documentation.

On va aussi créer un écouteur de changement d’image pour socket.IO, qui va récupérer l’url d’une image et l’envoyer. À la fin de cette fonction fetch, on enverra à notre module un tableau des labels que la détection nous aura retourné grâce à un .emit() sur le socket.

            npm install --save @google-cloud/vision
        
            io.on('connection', function(socket){
    async function fetch(imageUrl) {

        // Imports the Google Cloud client library
        const vision = require('@google-cloud/vision');

        // Creates a client
        const client = new vision.ImageAnnotatorClient();

        // Performs label detection on the image file
        const [result] = await client.labelDetection({
            "image" : {
                "content" : imageUrl
            }
        });
        const labels = result.labelAnnotations;

        // Send all labels to my Detection module
        socket.emit('updatePredictions', labels);
    }

    socket.on('updateImage', function(imageUrl){
        fetch(imageUrl).catch(console.error);
    });

});

        

Note: l’envoi d’un base64 à Google Vision API fonctionne, mais il faudra retirer le préfixe et l’envoyer comme un objet “image” comme ci-dessus.

Récupération de la liste des labels côté client

De retour dans le module Detection.js, il est maintenant temps de gérer l’envoi de l’url de notre image à notre serveur node, et la réception de la liste des labels.

À la fin de notre fonction init() on va donc avoir: l’écoute de l’ajout d’un fichier à filepond avec un FileReader pour avoir un base64 de notre image, qui sera notre url envoyé à notre serveur.

            this.reader = new FileReader();

pond.on('addfile',(error, file) => {
     // get a base64 and remove the prefix
     this.reader.onload = (e) => {
          this.socket.emit('updateImage', e.target.result.split(',')[1]);
     }
     //read file to get a base64
     this.reader.readAsDataURL(file.source);
});

       
this.socket.on('updatePredictions',(labels) => {
	// Enjoy
	console.log(labels)
})

        

Conclusion

Voilà, le prototype fonctionne et notre première capsule pour notre second projet Pilot® est prête. On réfléchira sans doute à gérer l’API de Google Vision avec PHP grâce à notre CMS Charcoal pour le projet final, mais pour l'instant, on passe à la prochaine étape avec l'assurance que Google Vision pourra répondre à nos besoins pour ce projet.

Retour aux articles
Analyse d'image et machine learning avec Google Vision API Locomotive Scroll, le bon outil pour mon projet? C'est hot, 2ieme édition 500 jours plus tard, My Better Normal 6 piliers de la culture de travail chez Locomotive Pourquoi nous n’utilisons pas de frameworks front-end à Locomotive? 7 façons d'améliorer la communication avec le client C'est hot, 1re édition 3 choses que votre concepteur UX peut apprendre de votre psy, style Locomotive Trois fois de suite, Locomotive est couronnée l'agence de l'année Locomotive prend d'assaut le stade IGA et remporte les honneurs au concours Idéa La révolution de l'espace de travail tel que nous le connaissons Puis-je te dire bravo? Locomotive couronnée Agence de l'année pour une deuxième année consécutive Réalité augmentée sur le web, wut? L’évolution du scroll chez Locomotive Revivez le Parté of the Year de Locomotive Les p'tits déjs Loco La zoothérapie au bureau Locomotive remporte le prix Agence de l'année Journée tempête et ski de fond Locomotive en mode avion Comment bâtir une équipe de rêve et la garder? Un bureau haut en couleurs saisonnières Les vendredis sous le soleil d'été Une équipe de rêve pour Locomotive
À propos de Locomotive À propos de Locomotive
C H O O C H O O