Rileva le pose con ML Kit su iOS

ML Kit fornisce due SDK ottimizzati per il rilevamento della posa.

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

Prova

  • Prova l'app di esempio per vedere un utilizzo di esempio di questa API.

Prima di iniziare

  1. Includi i seguenti pod ML Kit nel tuo 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 il relativo xcworkspace. ML Kit è supportato in Xcode versione 13.2.1 o successive.

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

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

stream (valore predefinito)
Il rilevatore di posizioni rileva prima la persona più in evidenza nell'immagine, poi esegue il rilevamento. Nei frame successivi, la fase di rilevamento di persone non verrà eseguita, a meno che la persona non sia oscurata o non sia più rilevata con un'affidabilità elevata. Il rilevatore della posa tenterà di tracciare la persona più in evidenza e tornerà alla posa in ogni inferenza. Questo riduce la latenza e semplifica il rilevamento. Utilizza questa modalità per rilevare la posa in uno stream video.
singleImage
Il rilevatore di posa rileva una persona ed esegue il rilevamento. Il passaggio di rilevamento persone verrà eseguito per ogni immagine, quindi la latenza sarà maggiore e il monitoraggio persone non sarà disponibile. Usa questa modalità se usi il rilevamento della posa su immagini statiche o per cui il tracciamento non è desiderato.

Specifica le opzioni del rilevatore di 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, recupera un'istanza di PoseDetector. Passa le opzioni specificate:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. Prepara l'immagine di input

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

Crea un oggetto VisionImage utilizzando un UIImage o un 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 CMSampleBuffer e l'orientamento:

    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 VisionImage a uno dei metodi di elaborazione dell'immagine del rilevatore di posizioni. 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 di rilevamento delle posizioni passa un array di oggetti Pose al gestore di completamento o restituisce l'array, a seconda che tu abbia chiamato il metodo asincrono o sincrono.

Se la persona non si trovava completamente nell'immagine, il modello assegna le coordinate dei punti di riferimento mancanti al di fuori del frame e restituisce 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é ML Kit possa rilevare accuratamente la posa, la persona nell'immagine deve essere rappresentata da sufficienti dati di pixel; per ottenere le migliori prestazioni, il soggetto deve essere di almeno 256 x 256 pixel.
  • Se rilevi la posa in un'applicazione in tempo reale, puoi 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 a mente i requisiti di risoluzione sopra indicati e assicurati che il soggetto occupi la maggior parte dell'immagine possibile.
  • Anche una scarsa messa a fuoco delle immagini 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 fotogrammi:

  • Utilizza l'SDK PoseDetection di base e la modalità di rilevamento stream.
  • Valuta la possibilità di acquisire immagini a una risoluzione più bassa. Tuttavia, tieni presente anche i requisiti di dimensione delle immagini di questa API.
  • Per elaborare i frame 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 il valore alwaysDiscardsLateVideoFrames di AVCaptureVideoDataOutput per limitare le chiamate al rilevatore. Se un nuovo fotogramma video diventa disponibile mentre il rilevatore è in esecuzione, questo verrà eliminato.
  • Se utilizzi l'output del rilevatore per sovrapporre i grafici all'immagine di input, ottieni il risultato da ML Kit, quindi esegui il rendering dell'immagine e dell'overlay in un unico passaggio. In questo modo, esegui il rendering sulla superficie del display solo una volta per ogni frame di input elaborato. Per un esempio, consulta le classi previewOverlayView e MLKDetectionOverlayView nell'app di esempio Showcase.

Passaggi successivi