Rileva le pose con ML Kit su iOS

ML Kit fornisce due SDK ottimizzati per il rilevamento delle posizioni.

Nome SDKPoseDetectionPoseDetectionAccurate
ImplementazioneGli asset per il rilevatore di base vengono collegati in modo statico alla tua app al momento della creazione.Gli asset per un rilevatore preciso vengono collegati in modo statico alla tua app al momento della creazione.
Dimensioni appFino a 29,6 MBFino a 33,2 MB
RendimentoiPhone X: ~45 f/siPhone X: ~29 f/s

Provalo

Prima di iniziare

  1. Includi i seguenti pod ML Kit nel 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. Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando xcworkspace. ML Kit è supportato in Xcode versione 13.2.1 o successiva.

1. Crea un'istanza di PoseDetector

Per rilevare una posa in un'immagine, crea prima un'istanza di PoseDetector e facoltativamente specifica le impostazioni del rilevatore.

PoseDetector opzioni

Modalità di rilevamento

Il PoseDetector funziona in due modalità di rilevamento. Assicurati di scegliere quello adatto al tuo caso d'uso.

stream (valore predefinito)
Il rilevatore della posa rileva prima la persona più in evidenza nell'immagine e poi esegue il rilevamento della posa. Nei frame successivi, la fase di rilevamento della persona non verrà eseguita, a meno che la persona non venga oscurata o non venga più rilevata con un grado di confidenza elevato. Il rilevatore della posa tenterà di tenere traccia della persona più in evidenza e riprenderà la sua posa in ogni inferenza. In questo modo si riduce la latenza e il rilevamento è più fluido. Utilizza questa modalità quando vuoi rilevare la posa in un video stream.
singleImage
Il rilevatore della posa rileva una persona e poi esegue il rilevamento della posa. Il passaggio di rilevamento persona viene eseguito per ogni immagine, quindi la latenza sarà più elevata e non è previsto il monitoraggio delle persone. Usa questa modalità quando usi il rilevamento della posa in immagini statiche o dove il tracciamento non è desiderato.

Specifica le opzioni del rilevatore della posa:

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;

Infine, ottieni un'istanza di PoseDetector. Trasmetti le opzioni che hai specificato:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. Prepara l'immagine di input

Per rilevare le posizioni, procedi nel seguente modo per ogni immagine o fotogramma del video. Se hai abilitato la modalità flusso di dati, devi creare VisionImage oggetti da CMSampleBuffer.

Crea un oggetto VisionImage utilizzando un elemento UIImage o CMSampleBuffer.

Se usi un UIImage, segui questi passaggi:

  • Crea un oggetto VisionImage con UIImage. Assicurati di specificare il valore .orientation corretto.

    Swift

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

    Objective-C

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

Se usi un CMSampleBuffer, segui questi passaggi:

  • Specifica l'orientamento dei dati dell'immagine contenuti in CMSampleBuffer.

    Per ottenere l'orientamento dell'immagine:

    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;
      }
    }
          
  • Crea un oggetto VisionImage utilizzando l'oggetto e l'orientamento CMSampleBuffer:

    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. Elabora l'immagine

Passa il VisionImage a uno dei metodi di elaborazione delle immagini del rilevatore della posa. Puoi utilizzare il metodo process(image:) asincrono o il metodo sincrono results().

Per rilevare gli oggetti in modo sincrono:

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.

Per rilevare gli oggetti in modo asincrono:

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. Ricevere informazioni sulla posa rilevata

Se viene rilevata una persona nell'immagine, l'API pose detection passa un array di oggetti Pose al gestore del completamento o restituisce l'array, a seconda che tu abbia chiamato il metodo asincrono o sincrono.

Se la persona non è completamente all'interno dell'immagine, il modello assegna le coordinate dei punti di riferimento mancanti al di fuori dell'inquadratura e assegna loro valori InFrameConfidence bassi.

Se non viene rilevata alcuna persona, l'array è vuoto.

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;
  }
}

Suggerimenti per migliorare il rendimento

La qualità dei risultati dipende dalla qualità dell'immagine di input:

  • Affinché il kit ML possa rilevare con precisione la posa, la persona nell'immagine deve essere rappresentata da un numero sufficiente di dati di pixel; per prestazioni ottimali, il soggetto deve essere di almeno 256 x 256 pixel.
  • Se rilevi la posa in un'applicazione in tempo reale, potresti considerare anche le dimensioni complessive delle immagini di input. Le immagini più piccole possono essere elaborate più rapidamente, quindi per ridurre la latenza, acquisisci immagini a risoluzioni più basse, ma tieni presenti i requisiti di risoluzione di cui sopra e assicurati che il soggetto occupi il più possibile l'immagine.
  • Anche una scarsa messa a fuoco dell'immagine può influire sulla precisione. Se non ottieni risultati accettabili, chiedi all'utente di recuperare l'immagine.

Se vuoi utilizzare il rilevamento della posa in un'applicazione in tempo reale, segui queste linee guida per ottenere le migliori frequenze di fotogrammi:

  • Utilizza l'SDK PoseDetection di base e la modalità di rilevamento stream.
  • Prova ad acquisire immagini a una risoluzione inferiore. Tuttavia, tieni presente anche i requisiti per le dimensioni immagine di questa API.
  • Per elaborare i fotogrammi video, utilizza l'API sincrona results(in:) del rilevatore. Richiama questo metodo dalla funzione captureOutput(_, didOutput:from:) di AVCaptureVideoDataOutputSampleBufferDelegate per ottenere in modo sincrono i risultati dal frame video specificato. Mantieni l'impostazione alwaysDiscardsLateVideoFrames di AVCaptureVideoDataOutput per limitare le chiamate al rilevatore. Se diventa disponibile un nuovo fotogramma video mentre il rilevatore è in esecuzione, verrà eliminato.
  • Se utilizzi l'output del rilevatore per sovrapporre elementi grafici all'immagine di input, ottieni il risultato da ML Kit, quindi esegui il rendering dell'immagine e della sovrapposizione in un unico passaggio. In questo modo, il rendering sulla superficie di visualizzazione viene mostrato una sola volta per ogni frame di input elaborato. Vedi le classi previewOverlayView e MLKDetectionOverlayView nell'app di esempio Showcase per un esempio.

Passaggi successivi