Guide de détection des points de repère pour les postures sur iOS

La tâche Pose Markerer vous permet de détecter des repères de corps humain dans une image ou vidéo. Vous pouvez utiliser cette tâche pour identifier les emplacements clés du corps, analyser la posture, et catégoriser les mouvements. Cette tâche utilise des modèles de machine learning (ML) qui fonctionnent avec des images ou des vidéos uniques. La tâche génère des points de repère concernant les postures du corps dans une image en 3D et en 3D.

Ces instructions vous expliquent comment utiliser le jalon de postures avec les applications iOS. Le code décrit dans ces instructions est disponible sur GitHub

Pour voir une démonstration de cette tâche, consultez cette page Web une démonstration. Pour en savoir plus sur les fonctionnalités, les modèles et les options de configuration de cette tâche, consultez les Aperçu.

Exemple de code

L'exemple de code MediaPipe Tasks est une implémentation de base d'un repère de postures pour iOS. L'exemple utilise l'appareil photo d'un appareil iOS physique pour détecter détecter des postures dans un flux vidéo continu. L'application peut également détecter les postures des images et des vidéos de la galerie de l'appareil.

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

Télécharger le code

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

<ph type="x-smartling-placeholder">

Pour télécharger l'exemple de code:

  1. Clonez le dépôt Git à l'aide de la commande suivante:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Si vous le souhaitez, vous pouvez configurer votre instance Git pour utiliser le paiement creuse. Seuls les fichiers de l'application exemple Pose Markerer:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/pose_landmarker/ios/
    

Après avoir créé une version locale de l'exemple de code, vous pouvez installer bibliothèque de tâches MediaPipe, ouvrez le projet avec Xcode et exécutez l'application. Pour instructions, consultez le Guide de configuration pour iOS.

Composants clés

Les fichiers suivants contiennent le code crucial pour l'exemple de jalon de postures application:

  • PoseLandmarkerService.swift: Initialise le point de repère, gère la sélection du modèle et exécute l'inférence sur les données d'entrée.
  • CameraViewController: Implémente l'interface utilisateur pour le mode de saisie du flux de la caméra en direct et permet de visualiser les de points de repère.
  • MediaLibraryViewController.swift: Elle implémente l'interface utilisateur pour le mode d'entrée de fichiers d'images fixes et de fichiers vidéo, et visualise les points de repère.

Configuration

Cette section décrit les étapes clés à suivre pour configurer votre environnement de développement projets de code pour utiliser Pose Markerer. Pour obtenir des informations générales sur la configuration environnement de développement permettant d'utiliser des tâches MediaPipe, y compris la version de la plate-forme consultez le Guide de configuration pour iOS.

<ph type="x-smartling-placeholder">

Dépendances

La fonction Pose Markerer utilise la bibliothèque MediaPipeTasksVision, qui doit être installée. à l'aide de CocoaPods. La bibliothèque est compatible avec les applications Swift et Objective-C et ne nécessite aucune configuration de langue supplémentaire.

Pour obtenir des instructions sur l'installation de CocoaPods sous macOS, reportez-vous au document CocoaPods guide d'installation. Pour savoir comment créer un Podfile avec les pods nécessaires pour votre consultez la section Utilisation CocoaPods

Ajoutez le pod MediaPipeTasksVision dans le fichier Podfile à l'aide du code suivant:

target 'MyPoseLandmarkerApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

Si votre application inclut des cibles de tests unitaires, reportez-vous au Guide de configuration iOS. votre Podfile.

Modèle

La tâche MediaPipe Pose Repèreer nécessite un bundle entraîné et compatible pour cette tâche. Pour en savoir plus sur les modèles entraînés disponibles pour Pose Benchmarker, consultez la présentation des tâches Modèles .

Utilisez le download_models.sh à l'aide du script pour télécharger les modèles et les ajouter au répertoire de votre projet à l'aide de Xcode. Pour pour savoir comment ajouter des fichiers à votre projet Xcode, reportez-vous à la section Gérer les fichiers et dossiers dans votre Xcode projet.

Utilisez la propriété BaseOptions.modelAssetPath pour spécifier le chemin d'accès au modèle. dans votre app bundle. Pour obtenir un exemple de code, consultez la section suivante.

Créer la tâche

Vous pouvez créer la tâche Pose Markerer en appelant l'un de ses initialiseurs. La L'initialiseur PoseLandmarker(options:) accepte les valeurs pour la configuration options.

Si vous n'avez pas besoin d'un repère de posture initialisé avec une configuration personnalisée vous pouvez utiliser l'initialiseur PoseLandmarker(modelPath:) pour créer Utilisez les options par défaut pour la position de l'application Repère. Pour en savoir plus sur la configuration consultez la page Présentation de la configuration.

La tâche Pose Markerer prend en charge trois types de données d'entrée: images fixes et fichiers vidéo. et les flux vidéo en direct. Par défaut, PoseLandmarker(modelPath:) initialise un pour les images fixes. Si vous souhaitez que votre tâche soit initialisée pour traiter des vidéos ou de flux vidéo en direct, utilisez PoseLandmarker(options:) pour spécifier la vidéo ou diffusion en direct. Le mode "Diffusion en direct" nécessite également l'option de configuration poseLandmarkerLiveStreamDelegate, qui active Utilisez le jalon pour transmettre au délégué les résultats de la détection du point de repère de posture. de manière asynchrone.

Choisissez l'onglet correspondant à votre mode d'exécution pour découvrir comment créer la tâche. et exécuter des inférences.

Swift

Image

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "pose_landmarker",
                                      ofType: "task")

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

let poseLandmarker = try PoseLandmarker(options: options)
    

Vidéo

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "pose_landmarker",
                                      ofType: "task")

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

let poseLandmarker = try PoseLandmarker(options: options)
    

Diffusion en direct

import MediaPipeTasksVision

// Class that conforms to the `PoseLandmarkerLiveStreamDelegate` protocol and
// implements the method that the pose landmarker calls once it finishes
// performing pose landmark detection in each input frame.
class PoseLandmarkerResultProcessor: NSObject, PoseLandmarkerLiveStreamDelegate {

  func poseLandmarker(
    _ poseLandmarker: PoseLandmarker,
    didFinishDetection result: PoseLandmarkerResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the pose landmarker result or errors here.

  }
}

let modelPath = Bundle.main.path(forResource: "pose_landmarker",
                                      ofType: "task")

let options = PoseLandmarkerOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.minPoseDetectionConfidence = minPoseDetectionConfidence
options.minPosePresenceConfidence = minPosePresenceConfidence
options.minTrackingConfidence = minTrackingConfidence
options.numPoses = numPoses

// Assign an object of the class to the `poseLandmarkerLiveStreamDelegate`
// property.
let processor = PoseLandmarkerResultProcessor()
options.poseLandmarkerLiveStreamDelegate = processor

let poseLandmarker = try PoseLandmarker(options: options)
    

Objective-C

Image

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker"
                                                      ofType:@"task"];

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Vidéo

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker"
                                                      ofType:@"task"];

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Diffusion en direct

@import MediaPipeTasksVision;

// Class that conforms to the `MPPPoseLandmarkerLiveStreamDelegate` protocol
// and implements the method that the pose landmarker calls once it finishes
// performing pose landmarks= detection in each input frame.

@interface APPPoseLandmarkerResultProcessor : NSObject 

@end

@implementation APPPoseLandmarkerResultProcessor

-   (void)poseLandmarker:(MPPPoseLandmarker *)poseLandmarker
    didFinishDetectionWithResult:(MPPPoseLandmarkerResult *)poseLandmarkerResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the pose landmarker result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"pose_landmarker"
                                                      ofType:@"task"];

MPPPoseLandmarkerOptions *options = [[MPPPoseLandmarkerOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.minPoseDetectionConfidence = minPoseDetectionConfidence;
options.minPosePresenceConfidence = minPosePresenceConfidence;
options.minTrackingConfidence = minTrackingConfidence;
options.numPoses = numPoses;

// Assign an object of the class to the `poseLandmarkerLiveStreamDelegate`
// property.
APPPoseLandmarkerResultProcessor *processor =
  [APPPoseLandmarkerResultProcessor new];
options.poseLandmarkerLiveStreamDelegate = processor;

MPPPoseLandmarker *poseLandmarker =
  [[MPPPoseLandmarker alloc] initWithOptions:options error:nil];
    

Remarque:Si vous utilisez le mode vidéo ou le mode diffusion en direct, Pose Markerer utilise pour éviter de déclencher le modèle de détection de la paume de la main à chaque image, ce qui permet réduire la latence.

Options de configuration

Cette tâche comporte les options de configuration suivantes pour les applications iOS:

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

IMAGE: mode utilisé pour la saisie d'une seule image.

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

LIVE_STREAM: mode d'une diffusion en direct des entrées provenant d'un appareil photo, par exemple. Dans ce mode, poseLandmarkerLiveStreamDelegate doit être défini sur Une instance d'une classe qui implémente le PoseLandmarkerLiveStreamDelegate pour recevoir les résultats de en effectuant une détection asynchrone des points de repère.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
num_poses Nombre maximal de postures pouvant être détectées par le Repère de position. Integer > 0 1
min_pose_detection_confidence Score de confiance minimal pour que la détection de postures soit considéré comme réussi. Float [0.0,1.0] 0.5
min_pose_presence_confidence Score de confiance minimal de la présence de la pose dans la détection des points de repère de pose. Float [0.0,1.0] 0.5
min_tracking_confidence Score de confiance minimal pour le suivi des postures pour être considéré réussi. Float [0.0,1.0] 0.5
output_segmentation_masks Permet d'afficher ou non un masque de segmentation pour le repère de posture . Boolean False
result_callback Définit l'écouteur des résultats pour qu'il reçoive les résultats du point de repère. de manière asynchrone lorsque Pose Markerer est en mode diffusion en direct. Ne peut être utilisé que lorsque le mode d'exécution est défini sur LIVE_STREAM ResultListener N/A

Configuration de la diffusion en direct

Lorsque le mode de course est configuré pour une diffusion en direct, le repère de posture nécessite l'option de configuration poseLandmarkerLiveStreamDelegate supplémentaire, qui permet au Pose Markerer de fournir des résultats de détection des points de repère de postures. de manière asynchrone. Le délégué doit implémenter poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:), que le traceur de postures appelle après le traitement des résultats de la pose la détection de points de repère sur chaque image.

Nom de l'option Description Plage de valeurs Valeur par défaut
poseLandmarkerLiveStreamDelegate Active le repère de postures afin de recevoir les résultats de la posture la détection de points de repère de manière asynchrone en mode diffusion en direct. La classe dont est définie sur cette propriété doit implémenter poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) . Non applicable Non défini

Préparer les données

Vous devez convertir l'image ou le cadre d'entrée en objet MPImage avant en la transmettant au jalon de postures. MPImage est compatible avec différents types d'images iOS et peuvent les utiliser dans n'importe quel mode d'exécution pour l'inférence. Pour plus plus d'informations sur MPImage, consultez API MPImage

Choisissez un format d'image iOS en fonction de votre cas d'utilisation et du mode de course que vous requise par l'application.MPImage accepte les règles de confidentialité UIImage, CVPixelBuffer et CMSampleBuffer formats d'image iOS.

UIImage

Le format UIImage convient bien aux modes d'exécution suivants:

  • Images : images d'un app bundle, d'une galerie d'utilisateur ou d'un système de fichiers au format suivant : Les images UIImage peuvent être converties en objet MPImage.

  • Vidéos: utilisez AVAssetImageGenerator. pour extraire des images vidéo CGImage le format d'image, puis les convertir en UIImage images.

Swift

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    

Objective-C

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

L'exemple initialise un MPImage avec les valeurs par défaut UIImage.Orientation.Up l'orientation. Vous pouvez initialiser un MPImage avec n'importe laquelle des UIImage.Orientation valeurs. La fonction Pose Markerer n'est pas compatible avec les orientations en miroir comme .upMirrored. .downMirrored, .leftMirrored et .rightMirrored.

Pour plus d'informations sur UIImage, reportez-vous à UIImage Apple Developer documentation.

CVPixelBuffer

Le format CVPixelBuffer convient bien aux applications qui génèrent des frames et utiliser la classe iOS CoreImage pour le traitement.

Le format CVPixelBuffer convient bien aux modes d'exécution suivants:

  • Images: applications qui génèrent CVPixelBuffer images après un traitement utilisant le framework CoreImage d'iOS peut être envoyé au repère de postures dans le d'exécution de l'image.

  • Vidéos: les images vidéo peuvent être converties au format CVPixelBuffer pour avant d'être envoyées au repère de postures en mode vidéo.

  • Diffusion en direct: les applications utilisant un appareil photo iOS pour générer des images peuvent être converties au format CVPixelBuffer pour être traité avant d'être envoyé au Posez jalonner le jalon en mode diffusion en direct.

Swift

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    

Objective-C

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

Pour plus d'informations sur CVPixelBuffer, reportez-vous au fichier CVPixelBuffer Développeur documentation.

CMSampleBuffer

Le format CMSampleBuffer stocke des échantillons multimédias d'un type uniforme et est bien adapté au streaming en direct. Les images en direct des appareils photo iOS sont envoyé de manière asynchrone au format CMSampleBuffer par iOS AVCaptureVideoDataOutput.

Swift

// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    

Objective-C

// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

Pour plus d'informations sur CMSampleBuffer, reportez-vous au fichier CMSampleBuffer Développeur documentation.

Exécuter la tâche

Pour exécuter le repère de postures, utilisez la méthode detect() spécifique à la en cours d'exécution:

  • Image fixe: detect(image:)
  • Vidéo : detect(videoFrame:timestampInMilliseconds:)
  • Diffusion en direct : detectAsync(image:timestampInMilliseconds:)

Les exemples de code suivants illustrent des exemples simples d'exécution de Pose Markerer dans ces différents modes de fonctionnement:

Swift

Image

let result = try poseLandmarker.detect(image: image)
    

Vidéo

let result = try poseLandmarker.detect(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

Diffusion en direct

try poseLandmarker.detectAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objective-C

Image

MPPPoseLandmarkerResult *result =
  [poseLandmarker detectImage:image error:nil];
    

Vidéo

MPPPoseLandmarkerResult *result =
  [poseLandmarker detectVideoFrame:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

Diffusion en direct

BOOL success =
  [poseLandmarker detectAsyncImage:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

L'exemple de code Pose Markerer montre les implémentations de chacun de ces modes. detect(image:), detect(videoFrame:timestampInMilliseconds:), et detectAsync(image:timestampInMilliseconds:). L'exemple de code autorise à l'utilisateur de passer d'un mode de traitement à un autre, ce qui n'est peut-être pas nécessaire .

Veuillez noter les points suivants :

  • Lorsque vous utilisez le mode vidéo ou le mode direct, vous devez également fournir le code temporel de la trame d'entrée à la tâche Pose Markerer.

  • Lors de l'exécution en mode image ou vidéo, la tâche "Repère de posture" bloque thread actuel jusqu'à ce qu'il ait fini de traiter l'image ou le frame d'entrée. À éviter de bloquer le thread actuel, exécuter le traitement en arrière-plan thread utilisant iOS Dispatch ou NSOperation cadres réglementaires.

  • En mode diffusion en direct, la tâche Pose Markerer est immédiatement renvoyée. et ne bloque pas le thread actuel. Elle appelle poseLandmarker(_:didFinishDetection:timestampInMilliseconds:error:) méthode avec le résultat du point de repère "pose" après le traitement de chaque trame d'entrée. La Pose Markerer invoque cette méthode de manière asynchrone sur une série dédiée la file d'attente de distribution. Pour afficher les résultats dans l'interface utilisateur, envoyez la dans la file d'attente principale après leur traitement. Si le detectAsync est appelée lorsque la tâche Pose Markerer est en train de traiter une autre image, le repère de postures ignore la nouvelle image d'entrée.

Gérer et afficher les résultats

Lors de l'exécution de l'inférence, la tâche Pose Markerer renvoie un PoseLandmarkerResult qui contient les coordonnées de chaque point de repère de la position.

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

PoseLandmarkerResult:
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : 0.129959
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
      visibility   : 0.999909
      presence     : 0.999958
    ... (33 landmarks per pose)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
      visibility   : 0.999976
      presence     : 0.999998
    ... (33 world landmarks per pose)
  SegmentationMasks:
    ... (pictured below)

La sortie contient à la fois les coordonnées normalisées (Landmarks) et le monde coordonnées (WorldLandmarks) de chaque point de repère.

La sortie contient les coordonnées normalisées suivantes (Landmarks):

  • x et y: coordonnées des points de repère normalisées entre 0,0 et 1,0 par le la largeur (x) et la hauteur (y) de l'image.

  • z: profondeur du point de repère, la profondeur au milieu des hanches origine. Plus la valeur est faible, plus le point de repère est proche de la caméra. La la magnitude de z utilise à peu près la même échelle que x.

  • visibility: probabilité que le point de repère soit visible dans l'image.

La sortie contient les coordonnées mondiales suivantes (WorldLandmarks):

  • x, y et z: coordonnées tridimensionnelles du monde réel en mètres, avec l'attribut le milieu des hanches comme origine.

  • visibility: probabilité que le point de repère soit visible dans l'image.

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

Le masque de segmentation facultatif représente la probabilité que chaque pixel appartienne à une personne détectée. L'image suivante montre un masque de segmentation résultat de la tâche:

L'exemple de code Pose Markerer montre comment afficher le Pose Markerer. résultats.