Rilevare le posizioni con il ML Kit su iOS

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

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

Nome SDKRilevamento posizioneRileva posizione
ImplementazioneGli asset per il rilevatore di base vengono collegati in modo statico alla tua app al momento della build.Gli asset per il rilevatore accurato vengono collegati in modo statico alla tua app al momento della build.
Dimensioni appFino a 29,6 MBFino a 33,2 MB
PrestazioniiPhone X: ~45 f/siPhone X: ~29 f/s

Prima di iniziare

  1. Nel podfile includi i seguenti pod ML Kit:

    # 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 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.

Opzioni PoseDetector

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 posa rileva innanzitutto la persona più in evidenza nell'immagine, quindi esegue il rilevamento. Nei frame successivi, il passaggio di rilevamento di una persona non verrà eseguito a meno che la persona non venga oscurata o non venga più rilevata con un'elevata affidabilità. Il rilevatore di posizioni proverà a tenere traccia della persona più in evidenza e a restituire la sua posa a ogni inferenza. Questo riduce la latenza e agevola il rilevamento. Utilizza questa modalità se vuoi rilevare la posa in un video stream.
singleImage
Il rilevatore di posa rileva la persona e poi esegue il rilevamento della posa. Il passaggio di rilevamento persone viene eseguito per ogni immagine, quindi la latenza è superiore e non è previsto il monitoraggio delle persone. Usa questa modalità quando utilizzi il rilevamento della posa su immagini statiche o dove non vuoi il monitoraggio.

Specifica le opzioni del rilevatore di posizioni:

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 posizioni, procedi nel seguente modo per ogni immagine o frame del video. Se hai abilitato la modalità flusso, devi creare VisionImage oggetti da CMSampleBuffer s.

Crea un oggetto VisionImage utilizzando un UIImage o un CMSampleBuffer.

Se utilizzi una UIImage, segui questi passaggi:

  • Crea un oggetto VisionImage con il UIImage. Assicurati di specificare il .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 una CMSampleBuffer, segui questi passaggi:

  • Specifica l'orientamento dei dati immagine contenuti nel documento 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 VisionImage a uno dei metodi di elaborazione delle immagini del rilevatore di posizioni. Puoi utilizzare il metodo process(image:) asincrono o il metodo results() sincrono.

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 della posa 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 all'interno dell'immagine, il modello assegna le coordinate mancanti dei punti di riferimento al di fuori del frame e assegna valori bassi di InFrameConfidence.

Se non è stata 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 con precisione la posizione, la persona nell'immagine deve essere rappresentata da dati pixel sufficienti; per prestazioni ottimali, il soggetto deve essere di almeno 256 x 256 pixel.
  • Se rilevi la posa in un'applicazione in tempo reale, puoi anche valutare le dimensioni complessive delle immagini di input. Le immagini più piccole possono essere elaborate più velocemente, quindi per ridurre la latenza, acquisisci immagini a risoluzioni più basse, ma tieni presenti i requisiti di risoluzione precedenti e assicurati che il soggetto occupi il maggior numero possibile di immagini.
  • Una scarsa messa a fuoco dell'immagine può anche influire sulla precisione. Se non ottieni risultati accettabili, chiedi all'utente di riottenere 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:

  • Usa l'SDK PoseDetection di base e la modalità di rilevamento stream.
  • Potresti acquisire 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. Richiama questo metodo dalla funzione AV CaptureVideoDataOutputSampleBufferDelegate's captureOutput(_, DidOutput:from:) per ottenere in modo sincrono i risultati dal frame video specificato. Mantieni AV CaptureVideoDataOutput trueIgnorasLateVideoFrames su true per limitare le chiamate al rilevatore. Se un nuovo video diventa disponibile mentre il rilevatore è in esecuzione, verrà ignorato.
  • Se utilizzi l'output del rilevatore per sovrapporre la grafica sull'immagine di input, ottieni prima il risultato dal ML Kit, quindi visualizza l'immagine e l'overlay in un solo passaggio. In questo modo, il pannello viene visualizzato una sola volta per ogni frame di input elaborato. Consulta le classi previewAnteprimaView e MLKDetectionOverlayView nell'applicazione di esempio di Showcase per un esempio.

Passaggi successivi