Aujourd’hui il n’est pas rare de tomber sur des articles traitant des sujets suivants : “Machine Learning“, “Deep Learning“. Mais qu’est-ce que ça signifie ? En quoi est-ce révolutionnaire ?

 

Selon notre ami Wikipédia, le Machine Learning, champ d’étude de l’intelligence artificielle, doit permettre à une machine d’effectuer des traitements complexes grâce à un processus systématique (classification). Le deep learning est en fait une composante du machine learning et nous vous conseillons cette très pédagogique vidéo de Yann LeCun chercheur en IA chez Facebook.

 

Le machine learning ( ML )  permet aujourd’hui d’effectuer du traitement d’image (circulation urbaine, médicales…), de la reconnaissance d’objet, de la reconnaissance faciale, etc… Google a même développé un programme se nommant AlphaGo permettant de battre le champion de monde au jeu de go, chose qu’on estimait impossible avant une bonne dizaine d’années…

Vous l’aurez compris les domaines et les possibilités sont vastes et laissent entrevoir de grandes transformations dans les années à venir.

Parmi l’ensemble des domaines possibles, nous avons décidé de tester “l’analyse faciale” par le biais d’un SDK embarqué dans notre application, ou encore par des solutions SaaS :

La reconnaissance faciale est-elle donc facilement à notre portée ?

Imaginons ensemble le scénario suivant :

Il est lundi, j’ai une réunion planifiée à 9h. J’entre dans la salle de réunion quand tout à coup un écran se débloque et énonce les mots suivants : “Bonjour Mehdi, votre réunion va démarrer dans 5 minutes, voulez-vous envoyer un messages aux autres participants ?”.

Un objet capable de reconnaitre des personnes dans un environnement restreint, avec un excellent compromis coût / performance (coût du hardware, de la solution software, latence raisonnable, bonne efficacité…) !

 

Plusieurs idées peuvent alors découler de ce scénario !

Nous décidâmes de partir sur une solution SaaS de reconnaissance faciale : AWS Rekognition. Une occasion de plus pour Ineat Group “AWS Partner” de continuer à explorer le catalogue de services d’Amazon.

AWS rekognition permet d’analyser différentes informations d’une photo ou d’un flux vidéo. Voici un bref aperçu des résultats avec quelques photographies :

 

Reconnaissance d’objets

Détection d’objet, de matériaux, paysage

 

Analyse faciale

Récupération des informations du visage, genre, yeux, expression, etc…

 

Reconnaissance de texte

 

Reconnaissance faciale

 

La personne au centre est identifiée dans différentes positions et situations parmi un ensemble de personnes. Malgré des expressions, coiffures, angles de prises de vues différentes l’algorithme arrive à l’identifier.

Comment intégrer ces fonctionnalités facilement / rapidement ?

Voici les quelques procédures à suivre depuis la console AWS

Premièrement, se rendre sur la console AWS et sélectionner le service Mobile Hub :

Mobile Hub permet de déclarer des applications mobiles pour les différents services AWS ( Amazon Cognito, AWS Lambda, Amazon S3, Amazon Kinesis, Amazon DynamoDB, Amazon Pinpoint et bien plus encore ). Dans notre cas pour utiliser le service AWS Rekognition.

 

Créer un projet mobile et y ajouter vos informations :

 

Choisir la plateforme de développement, pour cet article nous avons choisi Android :

 

Télécharger le fichier awsconfiguration.json et le placer dans le répertoire /app/src/res/raw/. Ce fichier contient l’ensemble des informations nécessaires à l’utilisation des APIs AWS avec vos informations de projet.

 

Continuer en cliquant sur “done”

Dorénavant votre application est créée ! Prochaine étape : configurer le manager d’accès IAM.

Lorsqu’on créée une application, un rôle se nommant [nom_app]_auth_MOBILEHUB_[date] lui est associé ( créé automatiquement par Mobile HUB). Celui-ci doit être configuré pour pouvoir être utilisé par les services AWS Rekognition.

 

Depuis l’écran de détail du rôle cliquer sur “Attacher une stratégie” :

 

Filtrer avec le mot clé “Rekognition” afin de retrouver les différentes stratégies associées à AWS rekognition. Sélectionner AmazonRekognitionFullAccess et cliquer sur “Attacher une stratégie“.

 

Votre application a maintenant les permissions pour utiliser les services Rekognition. Place à la configuration du projet.

Afin d’avoir accès aux services, il faut ajouter les credentials de l’application que vous venez de créer dans Mobile Hub. Pour cela, télécharger le fichier awsconfiguration.json associé à votre projet depuis Mobile Hub. (le fichier est disponible en cliquant sur le bouton menu de votre app)

 

Placer le fichier dans le répertoire /res/raw de votre projet. Vérifier qu’il a bien la structure suivante :

{
  "UserAgent": "MobileHub/1.0",
  "Version": "1.0",
  "CredentialsProvider": {
    "CognitoIdentity": {
      "Default": {
        "PoolId": "eu-west-1:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "Region": "eu-west-1"
      }
    }
  },
  "IdentityManager": {
    "Default": {}
  },
  "CognitoUserPool": {
    "Default": {
      "PoolId": "eu-west-1_XXXXXXX",
      "AppClientId": "XXXXXXXXXXXXXXXXXXXXX",
      "AppClientSecret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
      "Region": "eu-west-1"
    }
  },
  "PinpointAnalytics": {
    "Default": {
      "AppId": "XXXXXXXXXXXXXXXXXXXXX",
      "Region": "us-east-1"
    }
  },
  "PinpointTargeting": {
    "Default": {
      "Region": "us-east-1"
    }
  }
}

 

Ajouter les dépendances gradle :

dependencies {
    implementation (‘com.amazonaws:aws-android-sdk-mobile-client:2.6.+@aar’) { transitive = true }

    // AWS SDK auth
    implementation('com.amazonaws:aws-android-sdk-auth-ui:2.6.+@aar') { transitive = true }
    implementation('com.amazonaws:aws-android-sdk-auth-userpools:2.6.+@aar') { transitive = true }

    // MultiDex si votre projet contient plusieurs dépendances
    implementation 'com.android.support:multidex:1.0.3'
    
    // kotlin JRE
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}

Ces dépendances permettent d’intégrer le jar Rekognition, ainsi que l’authentification aux services AWS.

 

Maintenant il faut sécuriser l’application, pour cela ajouter le provider Cognito dans une classe Application :

import android.support.multidex.MultiDexApplication
import com.amazonaws.mobile.auth.core.IdentityManager
import com.amazonaws.mobile.auth.userpools.CognitoUserPoolsSignInProvider
import com.amazonaws.mobile.config.AWSConfiguration
import java.util.logging.Level
import java.util.logging.Logger


class App : MultiDexApplication() {

    override fun onCreate() {
        super.onCreate()

        // Init logger aws
        Logger.getLogger("org.apache.http").level = Level.FINEST
        Logger.getLogger("com.amazonaws").level = Level.FINEST

        // Ajouter le provider d'authentification cognito
        if (IdentityManager.getDefaultIdentityManager() == null) {
            val identityManager = IdentityManager(applicationContext, AWSConfiguration(this))
            IdentityManager.setDefaultIdentityManager(identityManager)
            IdentityManager.getDefaultIdentityManager().addSignInProvider(CognitoUserPoolsSignInProvider::class.java)
        }

    }

}

N’oubliez-pas de charger cette classe dans le fichier AndroidManifest.xml :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ineat.rekognizer">

    <uses-feature android:name="android.hardware.camera2" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        
        <!-- ... -->    
 
    </application>

</manifest>

N’hésitez-pas à consulter la documentation technique afin de déterminer le type de connexion qui vous convient.

Maintenant que le provider de connexion est mis en place, écrire un écran de connexion utilisant la classe IdentityManager. En voici un exemple :

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.amazonaws.mobile.auth.core.DefaultSignInResultHandler
import com.amazonaws.mobile.auth.core.IdentityManager
import com.amazonaws.mobile.auth.core.IdentityProvider
import com.amazonaws.mobile.auth.ui.AuthUIConfiguration
import com.amazonaws.mobile.auth.ui.SignInActivity
import com.ineat.rekognizer.MainActivity


class LoginActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Vérifier si l'utilisateur est connecté
        IdentityManager.getDefaultIdentityManager().resumeSession(this, {
            if (it.isUserSignedIn) {
                startActivity(Intent(this, MainActivity::class.java))
                finish()
            } else {
                performConnection()
            }
        })
    }

    /**
     * Afficher la page de connexion AWS
     */
    private fun performConnection() {
        IdentityManager.getDefaultIdentityManager().login(this, object : DefaultSignInResultHandler() {
            override fun onSuccess(callingActivity: Activity, provider: IdentityProvider) {
                startActivity(Intent(this@LoginActivity, MainActivity::class.java))
                finish()
            }

            override fun onCancel(callingActivity: Activity): Boolean {
                return false
            }

        })

        SignInActivity.startSignInActivity(this, AuthUIConfiguration.Builder().userPools(true).build())
    }
}

 

Mon application parvient maintenant à s’identifier, mais comment retrouver un visage sur une photographie ?

Avant d’intégrer la reconnaissance de visage expliquons comment cela fonctionne. AWS Rekognition permet d’identifier des personnes par un mécanisme d’apprentissage profond. Et pour cela il a besoin de données afin de lancer ce mécanisme.

face POI

Les données sont stockés dans des collections qu’il faudra créer au besoin. Lorsqu’une image est ajoutée dans une collection, un processus d’apprentissage est lancé : c’est ce qu’on nomme la phase d’indexation.

Cela permet d’extraire un ensemble de caractéristiques du visage de la personne. De ce fait, plus il y aura d’images indexées plus l’algorithme sera capable d’identifier la personne.

Premièrement il faut créer une collection dans laquelle sera stockée toutes les images :

val collectionId = "..."
val result = client.listCollections(ListCollectionsRequest().withMaxResults(100))
val containCollection = result.collectionIds.contains(collectionId)
var createCollectionResult: CreateCollectionResult? = null
if (containCollection.not()) {
    createCollectionResult =  client.createCollection(CreateCollectionRequest().withCollectionId(COLLECTION_ID))
}
val exist = containCollection.or(createCollectionResult != null)

 

Indexation d’un visage dans une collection :

val collectionId = "..."
val client = AmazonRekognitionClient(App.getCredentialsProvider())
val imageByteBuffer = ByteBuffer.wrap(pictureByteArray)
val personName = "" // nom de la personne qu'on souhaite sauvegarder
val request = IndexFacesRequest()
                .withCollectionId(collectionId)
                .withExternalImageId(personName)
                .withImage(Image().withBytes(ByteBuffer.wrap(pictureByteArray)))
val result = client.indexFaces(request)
val recorded = result.faceRecords.isEmpty().not()

Il est possible d’ajouter un identifiant à une photo, c’est ce qu’on utilisera pour stocker le nom de la personne.

Cette propriété se nomme “externalImageId“.

 

Rappel: Cette étape est importante ! Elle permet de lancer une phrase d’apprentissage afin d’extraire les caractéristiques faciale d’une personne.

 

 

Rechercher un visage :

val client = AmazonRekognitionClient(App.getCredentialsProvider())
val pictureByteArray // = bitmap photo to Byte Array

// ...

val imageByteBuffer = ByteBuffer.wrap(pictureByteArray)
val image = Image().withBytes(imageByteBuffer)
val request = SearchFacesByImageRequest()
                .withImage(image)
                .withMaxFaces(MAX_FACES)
                .withCollectionId(COLLECTION_ID)
                .withFaceMatchThreshold(FACE_MATCH_THRESHOLD)

val result = client.searchFacesByImage(request)

val hasFaces = result.faceMatches.isEmpty().not()

// ...
        
val faceMatch = result.faceMatches[0]
val similarity = faceMatch.similarity
val face = faceMatch.face
// face.faceId
// face.imageId
// face.externalImageId
// ...

 

Avec ces trois snippets vous êtes dorénavant capable d’indexer et retrouver une personne sur une image. Si vous souhaitez détecter des visages depuis une source vidéo en temps réel je vous invite à consulter la documentation des processeurs Kinesis.

Si vous êtes intéressés par le code d’une application Android réalisant l’identification depuis la caméra en temps réel, contactez-nous sur Twitter 😉 .

AWS Deeplens

Il y a quelques mois Amazon a annoncé la première camera vidéo compatible avec l’apprentissage profond : AWS Deeplens. Celle-ci est disponible à l’achat aux Etats-Unis et nous reviendrons dans un prochain article sur nos premiers pas avec celle-ci.