Guide de détection d'objets pour Android

La tâche "Détecteur d'objets" vous permet de détecter la présence et l'emplacement de plusieurs classes d'objets. Par exemple, un détecteur d'objets peut localiser des chiens dans une image. Ces instructions vous expliquent comment utiliser la tâche "Détecteur d'objets" sur Android. L'exemple de code décrit dans ces instructions est disponible sur GitHub. Pour voir concrètement cette tâche, consultez cette démonstration Web. Pour en savoir plus sur les fonctionnalités, les modèles et les options de configuration de cette tâche, consultez la présentation.

Exemple de code

L'exemple de code MediaPipe Tasks est une implémentation simple d'une application de détection d'objets pour Android. L'exemple utilise l'appareil photo d'un appareil Android physique pour détecter en continu des objets, ainsi que des images et des vidéos de la galerie de l'appareil pour détecter des objets de manière statique.

Vous pouvez utiliser l'application comme point de départ pour votre propre application Android ou vous y référer lorsque vous modifiez une application existante. L'exemple de code du détecteur d'objets est hébergé sur GitHub.

Télécharger le code

Les instructions suivantes vous expliquent comment créer une copie locale de l'exemple de code à l'aide de l'outil de ligne de commande git.

Pour télécharger l'exemple de code, procédez comme suit:

  1. Clonez le dépôt git à l'aide de la commande suivante :
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Vous pouvez éventuellement configurer votre instance Git pour utiliser le paiement creux afin de n'avoir que les fichiers de l'application exemple de détecteur d'objets :
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/object_detection/android
    

Après avoir créé une version locale de l'exemple de code, vous pouvez importer le projet dans Android Studio et exécuter l'application. Pour obtenir des instructions, consultez le guide de configuration pour Android.

Composants clés

Les fichiers suivants contiennent le code crucial de l'exemple d'application de détecteur d'objets:

  • ObjectDetectorHelper.kt : initialise le détecteur d'objets, et gère le modèle et la sélection des délégués.
  • MainActivity.kt : implémente l'application et assemble les composants de l'interface utilisateur.
  • OverlayView.kt afin de gérer et d'afficher les résultats ;

Préparation

Cette section décrit les étapes clés de la configuration de votre environnement de développement et de vos projets de code afin d'utiliser le détecteur d'objets. Pour obtenir des informations générales sur la configuration de votre environnement de développement pour l'utilisation des tâches MediaPipe, y compris sur les exigences de version de la plate-forme, consultez le guide de configuration pour Android.

Dépendances

Le détecteur d'objets utilise la bibliothèque com.google.mediapipe:tasks-vision. Ajoutez cette dépendance au fichier build.gradle de votre projet de développement d'application Android. Importez les dépendances requises à l'aide du code suivant:

dependencies {
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

Modèle

La tâche de détecteur d'objets MediaPipe nécessite un modèle entraîné compatible avec cette tâche. Pour en savoir plus sur les modèles entraînés disponibles pour les détecteurs d'objets, consultez la section Modèles de la présentation des tâches.

Sélectionnez et téléchargez le modèle, puis stockez-le dans le répertoire de votre projet:

<dev-project-root>/src/main/assets

Utilisez la méthode BaseOptions.Builder.setModelAssetPath() pour spécifier le chemin d'accès utilisé par le modèle. Pour obtenir un exemple de code, consultez la section suivante.

Créer la tâche

Vous pouvez utiliser la fonction createFromOptions pour créer la tâche. La fonction createFromOptions accepte des options de configuration telles que le mode d'exécution, les paramètres régionaux des noms à afficher, le nombre maximal de résultats, le seuil de confiance, la liste d'autorisation de catégories et la liste de blocage. Si aucune option de configuration n'est spécifiée, la valeur par défaut est utilisée. Pour en savoir plus sur les options de configuration, consultez la section Présentation de la configuration.

La tâche "Détecteur d'objets" accepte trois types de données d'entrée: les images fixes, les fichiers vidéo et les flux vidéo en direct. Vous devez spécifier le mode d'exécution correspondant à votre type de données d'entrée lors de la création de la tâche. Choisissez l'onglet correspondant à votre type de données d'entrée pour voir comment créer la tâche et exécuter l'inférence.

Images

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Vidéo

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Diffusion en direct

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
      // Process the detection result here.
    })
    .setErrorListener((result, inputImage) -> {
      // Process the classification errors here.
    })
   .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

L'exemple de code du détecteur d'objets permet à l'utilisateur de basculer entre les modes de traitement. Cette approche complique le code de création de la tâche et peut ne pas être adaptée à votre cas d'utilisation. Vous pouvez voir ce code dans la fonction setupObjectDetector() de la classe ObjectDetectorHelper.

Options de configuration

Cette tâche dispose des options de configuration suivantes pour les applications Android:

Nom de l'option Description Plage de valeurs Valeur par défaut
runningMode Définit le mode d'exécution de la tâche. Il existe trois modes:

IMAGE: mode pour les entrées d'une seule image.

VIDEO: mode pour les images décodées d'une vidéo.

LIVE_STREAM: mode de diffusion en direct de données d'entrée, issues par exemple d'une caméra. Dans ce mode, resultListener doit être appelé pour configurer un écouteur afin de recevoir les résultats de manière asynchrone.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocales Définit la langue des libellés à utiliser pour les noms à afficher fournis dans les métadonnées du modèle de la tâche, le cas échéant. La valeur par défaut est en pour l'anglais. Vous pouvez ajouter des thèmes localisés aux métadonnées d'un modèle personnalisé à l'aide de l'API TensorFlow Lite Metadata Writer. Code des paramètres régionaux en
maxResults Définit le nombre maximal (facultatif) de résultats de détection les mieux notés à renvoyer. Tout nombre positif -1 (tous les résultats sont renvoyés)
scoreThreshold Définit le seuil de score de prédiction qui remplace celui fourni dans les métadonnées du modèle (le cas échéant). Les résultats inférieurs à cette valeur sont refusés. N'importe quelle valeur flottante Non définie
categoryAllowlist Définit la liste facultative des noms de catégories autorisés. S'ils ne sont pas vides, les résultats de détection dont le nom de catégorie ne figure pas dans cet ensemble seront filtrés. Les noms de catégorie en double ou inconnus sont ignorés. Cette option s'exclut mutuellement avec categoryDenylist. L'utilisation des deux résultats génère une erreur. N'importe quelle chaîne Non définie
categoryDenylist Définit la liste facultative des noms de catégorie qui ne sont pas autorisés. S'ils ne sont pas vides, les résultats de détection dont le nom de catégorie figure dans cet ensemble seront filtrés. Les noms de catégorie en double ou inconnus sont ignorés. Cette option s'exclut mutuellement avec categoryAllowlist. L'utilisation des deux entraîne une erreur. N'importe quelle chaîne Non définie
resultListener Définit l'écouteur de résultats pour qu'il reçoive les résultats de la détection de manière asynchrone lorsque le détecteur d'objets est en mode flux en direct. Vous ne pouvez utiliser cette option que lorsque vous définissez runningMode sur LIVE_STREAM. Non applicable Non définie

Préparation des données

Vous devez convertir l'image ou l'image d'entrée en objet com.google.mediapipe.framework.image.MPImage avant de la transmettre au détecteur d'objets.

Les exemples suivants expliquent et montrent comment préparer les données à traiter pour chacun des types de données disponibles:

Images

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the user’s device as a Bitmap object using BitmapFactory.

// Convert an Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

Vidéo

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load a video file on the user's device using MediaMetadataRetriever

// From the video’s metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT values. Use these values
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

Diffusion en direct

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraX’s ImageAnalysis to continuously receive frames
// from the device’s camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Android’s ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Android’s Image object and convert it to
// a MediaPipe’s Image object.
android.media.Image mediaImage = imageProxy.getImage()
MPImage mpImage = new MediaImageBuilder(mediaImage).build();
    

Dans l'exemple de code du détecteur d'objets, la préparation des données est gérée dans la classe ObjectDetectorHelper au sein des fonctions detectImage(), detectVideoFile() et detectLivestreamFrame().

Exécuter la tâche

Selon le type de données que vous utilisez, utilisez la méthode ObjectDetector.detect...() spécifique à ce type de données. Utilisez detect() pour les images individuelles, detectForVideo() pour les images des fichiers vidéo et detectAsync() pour les flux vidéo. Lorsque vous effectuez des détections sur un flux vidéo, veillez à les exécuter sur un thread distinct pour éviter de bloquer le thread de l'interface utilisateur.

Les exemples de code suivants montrent comment exécuter le détecteur d'objets dans ces différents modes de données:

Images

ObjectDetectorResult detectionResult = objectDetector.detect(image);
    

Vidéo

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ObjectDetectorResult detectionResult =
    objectDetector.detectForVideo(image, frameTimestampMs);
    

Diffusion en direct

// Run inference on the frame. The detection results will be available
// via the `resultListener` provided in the `ObjectDetectorOptions` when
// the object detector was created.
objectDetector.detectAsync(image, frameTimestampMs);
    

L'exemple de code du détecteur d'objets présente les implémentations de chacun de ces modes plus en détail : detect(), detectVideoFile() et detectAsync(). L'exemple de code permet à l'utilisateur de basculer entre les modes de traitement, ce qui n'est peut-être pas nécessaire pour votre cas d'utilisation.

Veuillez noter les points suivants :

  • Lors de l'exécution en mode vidéo ou en mode flux en direct, vous devez également fournir l'horodatage de l'image d'entrée à la tâche du détecteur d'objets.
  • Lors de l'exécution en mode image ou vidéo, la tâche du détecteur d'objets bloque le thread actuel jusqu'à ce qu'il ait fini de traiter l'image ou le cadre d'entrée. Pour éviter de bloquer le thread actuel, exécutez le traitement dans un thread d'arrière-plan.
  • Lors de l'exécution en mode flux en direct, la tâche du détecteur d'objets ne bloque pas le thread actuel, mais est renvoyée immédiatement. Il appelle son écouteur de résultat avec le résultat de la détection chaque fois qu'il a fini de traiter une trame d'entrée. Si la fonction de détection est appelée lorsque la tâche de détecteur d'objets est occupée à traiter une autre trame, la nouvelle trame d'entrée est ignorée.

Gérer et afficher les résultats

Lors de l'exécution de l'inférence, la tâche du détecteur d'objets renvoie un objet ObjectDetectorResult qui décrit les objets qu'elle a trouvés dans l'image d'entrée.

Voici un exemple des données de sortie de cette tâche:

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

L'image suivante montre une visualisation du résultat de la tâche:

L'exemple de code du détecteur d'objets montre comment afficher les résultats de détection renvoyés par la tâche. Pour en savoir plus, consultez la classe OverlayView.