Posen mit ML Kit für iOS erkennen

ML Kit bietet zwei optimierte SDKs für die Posenerkennung.

SDK-NamePoseDetectionPoseDetectionAccurate
ImplementierungAssets für den Basisdetektor werden bei der Build-Erstellung statisch mit Ihrer App verknüpft.Assets für einen genauen Detektor sind bei der Build-Erstellung statisch mit Ihrer App verknüpft.
App-GrößeBis zu 29,6 MBBis zu 33,2 MB
LeistungiPhone X: ~45 fpsiPhone X: ~29 fps

Ausprobieren

  • Probieren Sie die Beispiel-App aus, um sich ein Anwendungsbeispiel für diese API anzusehen.

Hinweis

  1. Fügen Sie die folgenden ML Kit-Pods in Ihre Podfile-Datei ein:

    # 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. Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie das Xcode-Projekt mit der xcworkspace. ML Kit wird ab Xcode-Version 13.2.1 unterstützt.

1. Instanz von PoseDetector erstellen

Wenn Sie eine Pose in einem Bild erkennen möchten, erstellen Sie zuerst eine Instanz von PoseDetector und geben Sie optional die Detektoreinstellungen an.

PoseDetector Optionen

Erkennungsmodus

PoseDetector wird in zwei Erkennungsmodi ausgeführt. Achten Sie darauf, dass Sie die Option auswählen, die zu Ihrem Anwendungsfall passt.

stream (Standard)
Die Posenerkennung erkennt zuerst die Person, die im Bild am wichtigsten ist, und führt dann die Posenerkennung aus. In nachfolgenden Frames wird der Schritt zur Personenerkennung nur dann ausgeführt, wenn die Person verdeckt wird oder nicht mehr mit hoher Zuverlässigkeit erkannt wird. Der Posendetektor versucht, die auffälligste Person zu verfolgen und ihre Position in jeder Rückleitung zurückzugeben. Dadurch wird die Latenz verringert und die Erkennung optimiert. Verwenden Sie diesen Modus, wenn Sie in einem Videostream eine Pose erkennen möchten.
singleImage
Die Posenerkennung erkennt eine Person und führt dann die Posenerkennung aus. Der Schritt zur Personenerkennung wird für jedes Bild ausgeführt, sodass die Latenz höher ist und keine Personenverfolgung stattfindet. Verwenden Sie diesen Modus, wenn Sie die Posenerkennung bei statischen Bildern verwenden oder das Tracking nicht gewünscht wird.

Legen Sie die Optionen für die Positionserkennung fest:

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;

Schließlich rufen Sie eine Instanz von PoseDetector ab. Übergeben Sie die angegebenen Optionen:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. Eingabebild vorbereiten

Um Posen zu erkennen, gehen Sie für jedes Bild oder jeden Frame des Videos folgendermaßen vor: Wenn Sie den Streammodus aktiviert haben, müssen Sie VisionImage-Objekte aus CMSampleBuffers erstellen.

Erstellen Sie ein VisionImage-Objekt mithilfe von UIImage oder CMSampleBuffer.

Wenn du ein UIImage verwendest, gehe so vor:

  • Erstellen Sie ein VisionImage-Objekt mit der UIImage. Geben Sie die richtige .orientation an.

    Swift

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

    Objective-C

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

Wenn du ein CMSampleBuffer verwendest, gehe so vor:

  • Geben Sie die Ausrichtung der Bilddaten an, die in CMSampleBuffer enthalten sind.

    So ermitteln Sie die Bildausrichtung:

    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;
      }
    }
          
  • Erstelle ein VisionImage-Objekt mit dem CMSampleBuffer-Objekt und der Ausrichtung:

    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. Bild verarbeiten

Übergib VisionImage an eine der Bildverarbeitungsmethoden des Posendetektors. Sie können entweder die asynchrone Methode process(image:) oder die synchrone Methode results() verwenden.

So erkennen Sie Objekte synchron:

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.

So erkennen Sie Objekte asynchron:

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. Informationen zur erkannten Pose abrufen

Wenn im Bild eine Person erkannt wird, übergibt die Posenerkennungs-API entweder ein Array von Pose-Objekten an den Abschluss-Handler oder gibt das Array zurück, je nachdem, ob Sie die asynchrone oder synchrone Methode aufgerufen haben.

Wenn sich die Person nicht vollständig innerhalb des Bildes befand, weist das Modell die fehlenden Orientierungspunkte außerhalb des Frames zu und gibt ihr niedrige InFrameConfidence-Werte zu.

Wenn keine Person erkannt wurde, ist das Array leer.

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

Tipps zur Verbesserung der Leistung

Die Qualität Ihrer Ergebnisse hängt von der Qualität des Eingabebildes ab:

  • Damit ML Kit die Pose genau erkennen kann, sollte die Person im Bild durch genügend Pixeldaten repräsentiert werden. Für eine optimale Leistung sollte das Objekt mindestens 256 × 256 Pixel groß sein.
  • Wenn Sie in einer Echtzeitanwendung eine Pose erkennen, sollten Sie auch die Gesamtabmessungen der Eingabebilder berücksichtigen. Kleinere Bilder können schneller verarbeitet werden. Um die Latenz zu verringern, sollten Sie Bilder mit niedrigeren Auflösungen erfassen. Beachten Sie jedoch die oben genannten Anforderungen an die Auflösung und achten Sie darauf, dass die Person einen möglichst großen Teil des Bildes einnimmt.
  • Ein schlechter Bildfokus kann auch die Genauigkeit beeinträchtigen. Sollten die Ergebnisse nicht akzeptabel sein, bitten Sie den Nutzer, das Bild erneut zu erfassen.

Wenn du die Posenerkennung in einer Echtzeitanwendung verwenden möchtest, solltest du die folgenden Richtlinien beachten, um die besten Framerates zu erzielen:

  • Verwenden Sie das Basis-PoseDetection SDK und den stream-Erkennungsmodus.
  • Nehmen Sie Bilder mit einer niedrigeren Auflösung auf. Beachten Sie jedoch auch die Anforderungen dieser API an die Bildabmessungen.
  • Verwende zum Verarbeiten von Videoframes die synchrone results(in:) API des Detektors. Rufen Sie diese Methode aus der Funktion captureOutput(_, didOutput:from:) von AVCaptureVideoDataOutputSampleBufferDelegate auf, um synchron Ergebnisse aus dem angegebenen Videoframe abzurufen. Belassen Sie alwaysDiscardsLateVideoFrames von AVCaptureVideoDataOutput auf „true“, um Aufrufe an den Detektor zu drosseln. Wenn ein neuer Videoframe verfügbar wird, während der Detektor ausgeführt wird, wird er entfernt.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken über das Eingabebild zu blenden, rufen Sie zuerst das Ergebnis aus ML Kit ab und rendern Sie dann das Bild und das Overlay in einem Schritt. Auf diese Weise rendern Sie auf der Anzeigeoberfläche nur einmal für jeden verarbeiteten Eingabe-Frame. Ein Beispiel finden Sie in den Klassen previewOverlayView und MLKDetectionOverlayView in der Showcase-Beispiel-App.

Nächste Schritte