Détecter des postures avec ML Kit sur iOS

ML Kit fournit deux SDK optimisés pour la détection des postures.

Nom du SDKPoseDetectionPoseDetectionAccurate
ImplémentationLes éléments du détecteur de base sont associés de manière statique à votre application au moment de la compilation.Pour un détecteur précis, les éléments sont associés de manière statique à votre application au moment de la compilation.
Taille de l'applicationJusqu'à 29,6 MoJusqu'à 33,2 Mo
PerformancesiPhone X: ~45FPSiPhone X: ~29FPS

Essayer

Avant de commencer

  1. Incluez les pods ML Kit suivants dans votre Podfile:

    # If you want to use the base implementation:
    pod 'GoogleMLKit/PoseDetection', '3.2.0'
    
    # If you want to use the accurate implementation:
    pod 'GoogleMLKit/PoseDetectionAccurate', '3.2.0'
    
  2. Après avoir installé ou mis à jour les pods de votre projet, ouvrez votre projet Xcode à l'aide de son xcworkspace. ML Kit est compatible avec Xcode 13.2.1 ou version ultérieure.

1. Créer une instance de PoseDetector

Pour détecter une posture dans une image, créez d'abord une instance de PoseDetector, puis et éventuellement spécifier les paramètres du détecteur.

Options PoseDetector

Mode Détection

Le PoseDetector fonctionne dans deux modes de détection. Veillez à choisir celui qui correspond votre cas d'utilisation.

stream (par défaut)
Le détecteur de poses détecte d'abord une personne proéminente sur l'image, puis lancer la détection des postures. Dans les frames suivants, l'étape de détection de personnes ne sera pas menée à moins que la personne ou si elles ne sont plus détectées avec un niveau de confiance élevé. Le détecteur de pose essayez de suivre la personne la plus visible et de retrouver sa pose dans chaque l'inférence. Cela réduit la latence et facilite la détection. Utilisez ce mode lorsque vous qui veulent détecter une posture dans un flux vidéo.
singleImage
Le détecteur de poses détecte une personne, puis exécute la posture la détection automatique. L'étape de détection de personnes est exécutée pour chaque image, ce qui réduit être plus élevée, et il n'y a pas de suivi de personnes. Utilisez ce mode lorsque vous utilisez la position sur les images statiques ou lorsque le suivi n'est pas souhaité.

Spécifiez les options du détecteur de poses:

Swift

// Base pose detector with streaming, when depending on the PoseDetection SDK
let options = PoseDetectorOptions()
options.detectorMode = .stream

// Accurate pose detector on static images, when depending on the
// PoseDetectionAccurate SDK
let options = AccuratePoseDetectorOptions()
options.detectorMode = .singleImage

Objective-C

// Base pose detector with streaming, when depending on the PoseDetection SDK
MLKPoseDetectorOptions *options = [[MLKPoseDetectorOptions alloc] init];
options.detectorMode = MLKPoseDetectorModeStream;

// Accurate pose detector on static images, when depending on the
// PoseDetectionAccurate SDK
MLKAccuratePoseDetectorOptions *options =
    [[MLKAccuratePoseDetectorOptions alloc] init];
options.detectorMode = MLKPoseDetectorModeSingleImage;

Enfin, récupérez une instance de PoseDetector. Transmettez les options que vous avez spécifiées:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. Préparer l'image d'entrée

Pour détecter les postures, procédez comme suit pour chaque image ou frame de la vidéo. Si vous avez activé le mode de traitement par flux, vous devez créer des objets VisionImage à partir de CMSampleBuffer.

Créez un objet VisionImage à l'aide d'un UIImage ou d'un CMSampleBuffer

Si vous utilisez un UIImage, procédez comme suit:

  • Créez un objet VisionImage avec UIImage. Veillez à spécifier le bon .orientation.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Si vous utilisez un CMSampleBuffer, procédez comme suit:

  • Spécifiez l'orientation des données d'image contenues dans le CMSampleBuffer

    Pour obtenir l'orientation de l'image:

    Swift

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • Créez un objet VisionImage à l'aide de la classe Objet CMSampleBuffer et orientation:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. Traiter l'image

Transmettez VisionImage à l'une des méthodes de traitement d'image du détecteur de poses. Vous pouvez utiliser la méthode process(image:) asynchrone ou la méthode results() synchrone.

Pour détecter des objets de manière synchrone, procédez comme suit:

Swift

var results: [Pose]
do {
  results = try poseDetector.results(in: image)
} catch let error {
  print("Failed to detect pose with error: \(error.localizedDescription).")
  return
}
guard let detectedPoses = results, !detectedPoses.isEmpty else {
  print("Pose detector returned no results.")
  return
}

// Success. Get pose landmarks here.

Objective-C

NSError *error;
NSArray *poses = [poseDetector resultsInImage:image error:&error];
if (error != nil) {
  // Error.
  return;
}
if (poses.count == 0) {
  // No pose detected.
  return;
}

// Success. Get pose landmarks here.

Pour détecter des objets de manière asynchrone:

Swift

poseDetector.process(image) { detectedPoses, error in
  guard error == nil else {
    // Error.
    return
  }
  guard !detectedPoses.isEmpty else {
    // No pose detected.
    return
  }

  // Success. Get pose landmarks here.
}

Objective-C

[poseDetector processImage:image
                completion:^(NSArray * _Nullable poses,
                             NSError * _Nullable error) {
                    if (error != nil) {
                      // Error.
                      return;
                    }
                    if (poses.count == 0) {
                      // No pose detected.
                      return;
                    }

                    // Success. Get pose landmarks here.
                  }];

4. Obtenir des informations sur la posture détectée

Si une personne est détectée sur l'image, l'API de détection des postures transmet un résultat d'objets Pose au gestionnaire d'achèvement ou renvoie le tableau, selon que vous avez appelé la méthode asynchrone ou synchrone.

Si la personne n'est pas complètement à l'intérieur de l'image, le modèle attribue les coordonnées des points de repère manquants en dehors du cadre et leur donne InFrameConfidence.

Si aucune personne n'a été détectée, le tableau est vide.

Swift

for pose in detectedPoses {
  let leftAnkleLandmark = pose.landmark(ofType: .leftAnkle)
  if leftAnkleLandmark.inFrameLikelihood > 0.5 {
    let position = leftAnkleLandmark.position
  }
}

Objective-C

for (MLKPose *pose in detectedPoses) {
  MLKPoseLandmark *leftAnkleLandmark =
      [pose landmarkOfType:MLKPoseLandmarkTypeLeftAnkle];
  if (leftAnkleLandmark.inFrameLikelihood > 0.5) {
    MLKVision3DPoint *position = leftAnkleLandmark.position;
  }
}

Conseils pour améliorer les performances

La qualité des résultats dépend de la qualité de l'image d'entrée:

  • Pour que ML Kit détecte avec précision la posture, la personne sur l'image doit être représentées par des données de pixels suffisantes ; pour obtenir des performances optimales, le sujet doit mesurer au moins 256 x 256 pixels.
  • Si vous détectez une posture dans une application en temps réel, vous pouvez également les dimensions globales des images d'entrée. Les images plus petites peuvent être traitées pour réduire la latence, prendre des photos à des résolutions inférieures, tout en conservant tenez compte des exigences de résolution ci-dessus et veillez à ce que le sujet occupe la plus grande partie possible de l'image.
  • Une mauvaise mise au point de l'image peut également nuire à sa précision. Si vous n'obtenez pas de résultats acceptables, demandez à l'utilisateur de reprendre l'image.

Si vous souhaitez utiliser la détection des postures dans une application en temps réel, suivez ces consignes pour obtenir une fréquence d'images optimale:

  • Utilisez le SDK PoseDetection de base et le mode de détection stream.
  • Envisagez de capturer des images à une résolution plus faible. Cependant, gardez également à l'esprit les exigences de cette API concernant les dimensions de l'image.
  • Pour traiter les images vidéo, utilisez l'API synchrone results(in:) du détecteur. Appelez cette méthode à partir de la classe AVCaptureVideoDataOutputSampleBufferDelegate de captureOutput(_, didOutput:from:) pour obtenir de manière synchrone les résultats à partir d'une image vidéo donnée. Laissez la valeur alwaysDiscardsLateVideoFrames de AVCaptureVideoDataOutput définie sur "true" pour limiter les appels au détecteur. Si une nouvelle image vidéo devient disponible alors que le détecteur est en cours d'exécution, elle est supprimée.
  • Si vous utilisez la sortie du détecteur pour superposer des graphiques sur l'image d'entrée, obtenez d'abord le résultat de ML Kit, puis effectuez le rendu de l'image et de la superposition en une seule étape. Ainsi, vous n'effectuez le rendu sur la surface d'affichage qu'une seule fois pour chaque image d'entrée traitée. Consultez le previewOverlayView et MLKDetectionOverlayView dans l'application exemple Showcase.

Étapes suivantes