Détecter des objets dans des images avec ML Kit: Android

1. Avant de commencer

ML Kit est un SDK mobile qui intègre l'expertise de Google en matière de machine learning sur l'appareil dans les applications Android et iOS. Vous pouvez utiliser les API Vision et Natural Language, à la fois puissantes et simples d'utilisation, pour résoudre les problèmes courants dans vos applications ou créer de toutes nouvelles expériences utilisateur. Tous sont optimisés par les modèles de ML de pointe de Google et sont disponibles sans frais.

Les API de ML Kit s'exécutent toutes sur l'appareil, ce qui permet des cas d'utilisation en temps réel où vous souhaitez traiter un flux de caméra en direct, par exemple. Cela signifie également que la fonctionnalité est disponible hors connexion.

Cet atelier de programmation vous guidera à travers des étapes simples pour ajouter la détection et le suivi d'objets (ODT) pour une image donnée dans votre application Android existante. Veuillez noter que cet atelier de programmation prend quelques raccourcis pour mettre en évidence l'utilisation de ML Kit ODT.

Objectifs de l'atelier

Dans cet atelier de programmation, vous allez créer une application Android avec ML Kit. Votre application utilisera l'API ML Kit Object Detection and Tracking pour détecter des objets dans une image donnée.Au final, vous devriez obtenir un résultat semblable à l'image de droite.

Points abordés

  • Intégrer le SDK ML Kit à votre application Android
  • API ML Kit Object Detection and Tracking

Prérequis

  • Une version récente d'Android Studio (version 4.1.2 ou ultérieure)
  • Émulateur Android Studio ou appareil Android physique
  • L'exemple de code
  • Connaissances de base du développement Android en Kotlin

Cet atelier de programmation est consacré à ML Kit. Les concepts et les blocs de codes non pertinents ne sont pas abordés, et vous sont fournis afin que vous puissiez simplement les copier et les coller.

2. Configuration

Télécharger le code

Cliquez sur le lien ci-dessous pour télécharger l'ensemble du code de cet atelier de programmation :

Décompressez le fichier ZIP téléchargé. Cela a pour effet de décompresser un dossier racine (mlkit-android-main) contenant toutes les ressources dont vous aurez besoin. Pour cet atelier de programmation, vous n'aurez besoin que des sources du sous-répertoire object-detection.

Le sous-répertoire object-detection du dépôt mlkit-android contient deux répertoires :

  • android_studio_folder.pngstarter : code de démarrage sur lequel s'appuie cet atelier de programmation.
  • android_studio_folder.pngfinal : code complet de l'exemple d'application finalisée.

3. Ajouter l'API ML Kit Object Detection and Tracking au projet

Importer l'application dans Android Studio

Commençons par importer l'application de démarrage dans Android Studio.

Ouvrez Android Studio, sélectionnez Import Project (Gradle, Eclipse ADT, etc.) (Importer un projet (Gradle, Eclipse ADT, etc.)), puis choisissez le dossier starter dans le code source que vous avez téléchargé précédemment.

7c0f27882a2698ac.png

Ajouter les dépendances pour la détection et le suivi d'objets ML Kit

Les dépendances ML Kit vous permettent d'intégrer le SDK ML Kit ODT dans votre application. Ajoutez les lignes suivantes à la fin du fichier app/build.gradle de votre projet :

build.gradle

dependencies {
  // ...
  implementation 'com.google.mlkit:object-detection:16.2.4'
}

Synchroniser votre projet avec les fichiers Gradle

Pour vous assurer que toutes les dépendances sont disponibles pour votre application, vous devez synchroniser votre projet avec les fichiers Gradle à ce stade.

Sélectionnez Sync Project with Gradle Files ( Synchroniser le projet avec les fichiers Gradle) b451ab2d04d835f9.png dans la barre d'outils Android Studio.

(Si ce bouton est désactivé, assurez-vous d'importer uniquement starter/app/build.gradle , et non l'intégralité du dépôt.)

4. Exécuter l'application de démarrage

Maintenant que vous avez importé le projet dans Android Studio et ajouté les dépendances pour la détection et le suivi d'objets ML Kit, vous êtes prêt à exécuter l'application pour la première fois.

Connectez votre appareil Android à votre hôte via USB ou démarrez l'émulateur Android Studio, puis cliquez sur Run ( Exécuter) execute.png dans la barre d'outils Android Studio.

Exécuter et explorer l'application

L'application doit se lancer sur votre appareil Android. Il contient du code récurrent qui vous permet de prendre une photo ou de sélectionner une image prédéfinie, puis de l'envoyer à un pipeline de détection et de suivi d'objets que vous allez créer dans cet atelier de programmation. Explorons un peu l'application avant d'écrire du code.

Tout d'abord, un bouton ( c6d965d639c3646.png) en bas permet de :

  • ouvrir l'application Appareil photo intégrée à votre appareil/émulateur ;
  • prendre une photo dans votre application Appareil photo ;
  • recevoir l'image capturée dans l'application de départ ;
  • afficher l'image

Essayez le bouton Prendre une photo, suivez les instructions pour prendre une photo, acceptez la photo et regardez-la s'afficher dans l'application de démarrage.

Répétez ces étapes plusieurs fois pour voir comment cela fonctionne :

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

Ensuite, vous pouvez choisir parmi trois images prédéfinies. Vous pourrez utiliser ces images ultérieurement pour tester le code de détection d'objets si vous exécutez un émulateur Android.

Sélectionnez une image parmi les trois images prédéfinies. Vérifiez que l'image s'affiche dans la vue agrandie :

1dd41b3ec978f1d9.png

5. Ajouter la détection d'objets sur l'appareil

Au cours de cette étape, vous allez ajouter la fonctionnalité de détection d'objets dans les images à l'application de démarrage. Comme vous l'avez vu à l'étape précédente, l'application de démarrage contient du code passe-partout permettant de prendre des photos avec l'application Appareil photo de l'appareil. L'application contient également trois images prédéfinies sur lesquelles vous pouvez essayer la détection d'objets si vous exécutez l'atelier de programmation sur un émulateur Android.

Lorsque vous avez sélectionné une image, soit parmi les images prédéfinies, soit en prenant une photo avec l'application Appareil photo, le code standard décode cette image en instance Bitmap, l'affiche à l'écran et appelle la méthode runObjectDetection avec l'image.

Au cours de cette étape, vous allez ajouter du code à la méthode runObjectDetection pour effectuer la détection d'objets.

Configurer et exécuter la détection d'objets sur l'appareil dans une image

Pour configurer ML Kit ODT, il vous suffit de suivre trois étapes simples avec trois API :

  • préparer une image : InputImage
  • créer un objet détecteur : ObjectDetection.getClient(options)
  • connect the 2 objects above: process(image)

Vous allez les implémenter dans la fonction runObjectDetection(bitmap: Bitmap) du fichier MainActivity.kt.

/**
 * ML Kit Object Detection Function
 */
private fun runObjectDetection(bitmap: Bitmap) {
}

Pour le moment, la fonction est vide. Passez aux étapes suivantes pour implémenter ML Kit ODT. Android Studio vous invitera à ajouter les importations nécessaires :

  • com.google.mlkit.vision.common.InputImage
  • com.google.mlkit.vision.objects.ObjectDetection
  • com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions

Étape 1 : Créez un InputImage

ML Kit fournit une API simple pour créer un InputImage à partir d'un Bitmap. Vous pouvez ensuite transmettre un InputImage aux API ML Kit.

// Step 1: create ML Kit's InputImage object
val image = InputImage.fromBitmap(bitmap, 0)

Ajoutez le code ci-dessus en haut de runObjectDetection(bitmap:Bitmap).

Étape 2 : Créez une instance de détecteur

ML Kit suit le schéma de conception Builder. Vous transmettez la configuration au compilateur, puis vous obtenez un détecteur à partir de celui-ci. Trois options de configuration sont disponibles (celles en gras sont utilisées dans cet atelier de programmation) :

  • mode détecteur (image unique ou flux)
  • mode de détection (détection d'un seul ou plusieurs objets)
  • mode de classification (activé ou désactivé)

Cet atelier de programmation concerne la détection et la classification de plusieurs objets dans une seule image. Ajoutez-le maintenant :

// Step 2: acquire detector object
val options = ObjectDetectorOptions.Builder()
   .setDetectorMode(ObjectDetectorOptions.SINGLE_IMAGE_MODE)
   .enableMultipleObjects()
   .enableClassification()
   .build()
val objectDetector = ObjectDetection.getClient(options)

Étape 3 : Fournissez une ou plusieurs images au détecteur

La détection et la classification d'objets sont des processus asynchrones :

  • Vous envoyez une image au détecteur (via process()).
  • Le détecteur travaille dur pour cela.
  • Le détecteur vous renvoie le résultat via un rappel.

Le code suivant effectue cette opération (copiez-le et ajoutez-le au code existant dans fun runObjectDetection(bitmap:Bitmap)):).

// Step 3: feed given image to detector and setup callback
objectDetector.process(image)
   .addOnSuccessListener {
       // Task completed successfully
        debugPrint(it)
   }
   .addOnFailureListener {
       // Task failed with an exception
       Log.e(TAG, it.message.toString())
   }

Une fois l'opération terminée, le détecteur vous envoie une notification contenant les informations suivantes :

  • Nombre total d'objets détectés. Chaque objet détecté est décrit avec les informations suivantes :
  • trackingId : entier que vous utilisez pour le suivre dans les différents cadres (NON utilisé dans cet atelier de programmation).
  • boundingBox : cadre de délimitation de l'objet.
  • labels: : liste des libellés de l'objet détecté (uniquement lorsque la classification est activée) :
  • index (obtenir l'index de ce libellé)
  • text (Obtenez le texte de ce libellé, y compris "Articles de mode", "Aliments", "Articles pour la maison", "Lieu", "Plante")
  • confidence ( nombre à virgule flottante compris entre 0,0 et 1,0, où 1,0 correspond à 100 %)

Vous avez probablement remarqué que le code effectue un traitement de type printf pour le résultat détecté avec debugPrint().

Ajoutez-le à la classe MainActivity :

private fun debugPrint(detectedObjects: List<DetectedObject>) {
   detectedObjects.forEachIndexed { index, detectedObject ->
       val box = detectedObject.boundingBox

       Log.d(TAG, "Detected object: $index")
       Log.d(TAG, " trackingId: ${detectedObject.trackingId}")
       Log.d(TAG, " boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")
       detectedObject.labels.forEach {
           Log.d(TAG, " categories: ${it.text}")
           Log.d(TAG, " confidence: ${it.confidence}")
       }
   }
}

Vous êtes maintenant prêt à accepter des images pour la détection.

Exécutons l'atelier de programmation en cliquant sur Run ( Exécuter) execute.png dans la barre d'outils Android Studio. Essayez de sélectionner une image prédéfinie ou de prendre une photo, puis examinez la fenêtre Logcat16bd6ea224cf8cf1.png) dans l'IDE.

Le résultat doit ressembler à ceci :

D/MLKit Object Detection: Detected object: 0
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (481, 2021) - (2426,3376)
D/MLKit Object Detection:  categories: Food
D/MLKit Object Detection:  confidence: 0.90234375
D/MLKit Object Detection: Detected object: 1
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (2639, 2633) - (3058,3577)
D/MLKit Object Detection: Detected object: 2
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (3, 1816) - (615,2597)
D/MLKit Object Detection:  categories: Home good
D/MLKit Object Detection:  confidence: 0.75390625

… ce qui signifie que le détecteur a vu trois objets :

  • Les catégories sont Aliments et Articles pour la maison.
  • Aucune catégorie n'est renvoyée pour la deuxième, car il s'agit d'une classe inconnue.
  • Non, car il s'agit du mode de détection d'une seule image.trackingId
  • Position à l'intérieur du rectangle boundingBox (par exemple, (481, 2021) – (2426, 3376))
  • Le détecteur est presque certain que le premier est un aliment (90 % de confiance : c'était une salade).

Techniquement, c'est tout ce dont vous avez besoin pour que la détection d'objets ML Kit fonctionne. Vous avez tout ce qu'il faut pour le moment ! Félicitations !

Du côté de l'UI, vous en êtes toujours au même point qu'au début, mais vous pouvez utiliser les résultats détectés dans l'UI, par exemple en dessinant le cadre de sélection pour créer une meilleure expérience. Passons à l'étape suivante : le post-traitement des résultats détectés.

6. Post-traitement des résultats de détection

Dans les étapes précédentes, vous avez imprimé le résultat détecté dans logcat, ce qui est simple et rapide.

Dans cette section, vous allez utiliser le résultat dans l'image :

  • dessiner le cadre de délimitation sur l'image
  • dessine le nom de la catégorie et la confiance à l'intérieur du cadre de délimitation

Comprendre les utilitaires de visualisation

L'atelier de programmation contient du code récurrent pour vous aider à visualiser le résultat de la détection. Utilisez ces utilitaires pour simplifier notre code de visualisation :

  • data class BoxWithText(val box: Rect, val text: String) : il s'agit d'une classe de données permettant de stocker un résultat de détection d'objet pour la visualisation. box correspond au cadre de délimitation où se trouve l'objet, et text est la chaîne de résultat de la détection à afficher avec le cadre de délimitation de l'objet.
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<BoxWithText>): Bitmap : cette méthode dessine les résultats de la détection d'objets dans detectionResults sur l'bitmap d'entrée et renvoie la copie modifiée.

Voici un exemple de résultat de la méthode utilitaire drawDetectionResult :

58c6f1d4ddb00dfa.png

Visualiser le résultat de la détection ML Kit

Utilisez les utilitaires de visualisation pour dessiner le résultat de la détection d'objets ML Kit au-dessus de l'image d'entrée.

Accédez à l'endroit où vous appelez debugPrint() et ajoutez l'extrait de code suivant en dessous :

// Parse ML Kit's DetectedObject and create corresponding visualization data
val detectedObjects = it.map { obj ->
    var text = "Unknown"

    // We will show the top confident detection result if it exist
    if (obj.labels.isNotEmpty()) {
        val firstLabel = obj.labels.first()
        text = "${firstLabel.text}, ${firstLabel.confidence.times(100).toInt()}%"
    }
    BoxWithText(obj.boundingBox, text)
}

// Draw the detection result on the input bitmap
val visualizedResult = drawDetectionResult(bitmap, detectedObjects)

// Show the detection result on the app screen
runOnUiThread {
    inputImageView.setImageBitmap(visualizedResult)
}
  • Vous commencez par analyser le DetectedObject de ML Kit et à créer une liste d'objets BoxWithText pour afficher le résultat de la visualisation.
  • Vous dessinez ensuite le résultat de la détection sur l'image d'entrée à l'aide de la méthode utilitaire drawDetectionResult et l'affichez à l'écran.

Exécuter le code

Cliquez ensuite sur Run ( Exécuter) execute.png dans la barre d'outils Android Studio.

Une fois l'application chargée, appuyez sur le bouton avec l'icône de l'appareil photo, pointez l'appareil photo sur un objet, prenez une photo, acceptez la photo (dans l'application Appareil photo) ou appuyez simplement sur l'une des images prédéfinies. Les résultats de la détection devraient s'afficher. Appuyez à nouveau sur le bouton ou sélectionnez une autre image pour répéter l'opération plusieurs fois et découvrir la dernière version de ML Kit ODT.

a03109cb30d5014d.png

7. Félicitations !

Vous avez utilisé ML Kit pour ajouter des fonctionnalités de détection d'objets à votre application :

  • Trois étapes avec trois API
  • Créer une image d'entrée
  • Créer un détecteur
  • Envoyer une image au détecteur

Et voilà !

Au fur et à mesure, vous pouvez améliorer le modèle. Comme vous pouvez le voir, le modèle par défaut ne peut reconnaître que cinq catégories. Il ne connaît même pas le couteau, la fourchette et la bouteille. Consultez l'autre atelier de programmation de notre parcours de formation sur le machine learning sur l'appareil : détection d'objets pour découvrir comment entraîner un modèle personnalisé.

Points abordés

  • Ajouter la détection et le suivi d'objets ML Kit à votre application Android
  • Utiliser la détection et le suivi d'objets sur l'appareil dans ML Kit pour détecter des objets dans des images

Étapes suivantes

En savoir plus