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 in fase di compilazione.Gli asset per il rilevamento accurato sono collegati in modo statico alla tua app in fase di compilazione.
Dimensioni appFino a 29,6 MBFino a 33,2 MB
PrestazioniiPhone X: circa 45 FPSiPhone X: circa 29 FPS

Prova

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

Prima di iniziare

  1. Includi i seguenti pod di ML Kit nel tuo Podfile:

    # If you want to use the base implementation:
    pod 'GoogleMLKit/PoseDetection', '8.0.0'
    
    # If you want to use the accurate implementation:
    pod 'GoogleMLKit/PoseDetectionAccurate', '8.0.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 opera in due modalità di rilevamento. Assicurati di scegliere quello che corrisponde al tuo caso d'uso.

stream (valore predefinito)
Il rilevatore di pose rileva prima la persona più prominente nell'immagine e poi esegue il rilevamento della posa. Nei fotogrammi successivi, la fase di rilevamento delle persone non verrà eseguita a meno che la persona non venga obscured o non venga più rilevata con un'elevata confidenza. Il rilevatore di pose tenterà di monitorare la persona più in evidenza e restituirà la sua posa in ogni deduzione. In questo modo si riduce la latenza e si semplifica il rilevamento. Utilizza questa modalità quando vuoi rilevare la posa in uno stream video.
singleImage
Il rilevatore di pose rileva una persona ed esegue il rilevamento della posa. Il passaggio di rilevamento delle persone verrà eseguito per ogni immagine, pertanto la latenza sarà più elevata e non è previsto il monitoraggio delle persone. Utilizza questa modalità quando utilizzi il rilevamento delle pose su immagini statiche o quando non è necessario il monitoraggio.

Specifica le opzioni del rilevatore di pose:

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. 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, svolgi i seguenti passaggi per ogni immagine o fotogramma del video. Se hai attivato la modalità di streaming, devi creare oggetti VisionImage da CMSampleBuffer.

Crea un oggetto VisionImage utilizzando un UIImage o un CMSampleBuffer.

Se utilizzi 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 utilizzi 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'orientamento e l'oggetto 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 VisionImage a uno dei metodi di elaborazione delle immagini del rilevatore di pose. Puoi utilizzare il metodo asincrono process(image:) 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. Visualizzare le informazioni sulla posa rilevata

Se nell'immagine viene rilevata una persona, l'API di rilevamento delle pose 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 era completamente all'interno dell'immagine, il modello assegna le coordinate dei punti di riferimento mancanti all'esterno dell'inquadratura e li assegna a valori bassi di InFrameConfidence.

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 rilevi con precisione la posa, la persona nell'immagine deve essere rappresentata da dati pixel sufficienti. Per il massimo rendimento, l'oggetto deve essere di almeno 256 x 256 pixel.
  • Se rilevi la posa in un'applicazione in tempo reale, ti consigliamo di prendere in considerazione anche le dimensioni complessive delle immagini di input. Le immagini più piccole possono essere elaborate più velocemente, quindi per ridurre la latenza, acquisisci le immagini a risoluzioni inferiori, ma tieni presente i requisiti di risoluzione sopra indicati e assicurati che l'oggetto occupi il più possibile l'immagine.
  • Anche la scarsa messa a fuoco delle immagini può influire sull'accuratezza. Se non ottieni risultati accettabili, invita l'utente a acquisire di nuovo l'immagine.

Se vuoi utilizzare il rilevamento delle pose in un'applicazione in tempo reale, segui queste linee guida per ottenere le frequenze frame migliori:

  • Utilizza l'SDK di base PoseDetection e la modalità di rilevamento stream.
  • Valuta la possibilità di acquisire le immagini a una risoluzione inferiore. Tuttavia, tieni presente anche i requisiti relativi alle dimensioni delle immagini di questa API.
  • Per l'elaborazione dei frame video, utilizza l'API sincrona results(in:) del rilevatore. Chiama questo metodo dalla funzione captureOutput(_, didOutput:from:) di AVCaptureVideoDataOutputSampleBufferDelegate per ottenere in modo sincrono i risultati dal frame video specificato. Mantieni alwaysDiscardsLateVideoFrames di AVCaptureVideoDataOutput impostato su true per limitare le chiamate al rilevatore. Se un nuovo frame video diventa disponibile mentre il rilevatore è in esecuzione, verrà eliminato.
  • Se utilizzi l'output del rilevatore per sovrapporre la grafica all'immagine di input, ottieni prima il risultato da ML Kit, quindi esegui il rendering dell'immagine e del overlay in un unico passaggio. In questo modo, esegui il rendering sulla superficie di visualizzazione una sola volta per ogni frame di input elaborato. Per un esempio, consulta le classi previewOverlayView e MLKDetectionOverlayView nell'app di esempio della vetrina.

Passaggi successivi