Posen mit ML Kit für iOS erkennen

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

SDK-NamePoseDetectionPoseDetectionAccurate
ImplementierungAssets für Basisdetektoren sind beim Build statisch mit Ihrer Anwendung verknüpft.Assets für genaue Detektoren sind beim Build 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 ein Beispiel für die Verwendung dieser API zu sehen.

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 Ihr Xcode-Projekt mit der xcworkspace. ML Kit wird in Xcode ab Version 13.2.1 unterstützt.

1. Instanz von PoseDetector erstellen

Erstellen Sie zuerst eine Instanz von PoseDetector und geben Sie optional die Detektoreinstellungen an, um eine Pose in einem Bild zu erkennen.

PoseDetector Optionen

Erkennungsmodus

Das PoseDetector funktioniert in zwei Erkennungsmodi. Wählen Sie unbedingt die Option aus, die zu Ihrem Anwendungsfall passt.

stream (Standard)
Der Posendetektor erkennt zuerst die bekannteste Person auf dem Bild und führt dann die Posenerkennung durch. In nachfolgenden Frames wird die Personenerkennung nur dann ausgeführt, wenn die Person verdeckt wird oder nicht mehr mit hoher Zuverlässigkeit erkannt wird. Der Posendetektor versucht, die bekannteste Person zu verfolgen und ihre Pose in jeder Ableitung zurückzugeben. Dies reduziert die Latenz und sorgt für eine reibungslose Erkennung. Verwenden Sie diesen Modus, wenn Sie eine Pose in einem Videostream erkennen möchten.
singleImage
Der Posendetektor erkennt eine Person und führt dann die Posenerkennung durch. Die Personenerkennung wird für jedes Bild ausgeführt, sodass die Latenz höher ist und es keine Personennachverfolgung gibt. Verwenden Sie diesen Modus, wenn Sie die Posenerkennung auf statischen Bildern verwenden oder wenn eine Nachverfolgung nicht erwünscht ist.

Geben Sie die Optionen für die Positionserkennung an:

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;

Rufen Sie abschließend 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 eines Videos wie folgt vor: Wenn Sie den Streammodus aktiviert haben, müssen Sie VisionImage-Objekte aus CMSampleBuffers erstellen.

Erstellen Sie mit UIImage oder CMSampleBuffer ein VisionImage-Objekt.

Wenn du UIImage verwendest, gehe so vor:

  • Erstellen Sie mit der UIImage ein VisionImage-Objekt. Achte darauf, den richtigen .orientation anzugeben.

    Swift

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

    Objective-C

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

Wenn du CMSampleBuffer verwendest, gehe so vor:

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

    So rufen Sie die Bildausrichtung ab:

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

    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

Übergeben Sie die VisionImage an eine der Bildverarbeitungsmethoden des Pose-Detektors. Sie können entweder die asynchrone process(image:)-Methode oder die synchrone results()-Methode 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 auf dem 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 im Bild befand, weist das Modell die fehlenden Markierungskoordinaten außerhalb des Frames zu und weist ihr niedrige InFrameConfidence-Werte zu.

Wenn keine Person gefunden 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 Leistungsverbesserung

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

  • Damit das ML Kit die Pose genau erkennen kann, sollte die Person auf dem Bild durch genügend Pixeldaten repräsentiert sein. Für eine optimale Leistung sollte die Person mindestens 256 × 256 Pixel groß sein.
  • Wenn Sie Posen in einer Echtzeitanwendung 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 geringerer Auflösung erfassen. Beachten Sie dabei jedoch die oben genannten Auflösungsanforderungen und achten Sie darauf, dass das Motiv so viel wie möglich auf dem Bild einnimmt.
  • Ein schlechter Bildfokus kann sich auch auf die Genauigkeit auswirken. Wenn Sie keine akzeptablen Ergebnisse erhalten, bitten Sie den Nutzer, das Bild neu aufzunehmen.

Wenn Sie die Posenerkennung in einer Echtzeitanwendung verwenden möchten, beachten Sie die folgenden Richtlinien, um die besten Framerates zu erzielen:

  • Verwende das 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 Bildabmessung.
  • Verwenden Sie 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 das Feld 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 dieser gelöscht.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf dem Eingabebild einzublenden, rufen Sie zuerst das Ergebnis aus dem ML Kit ab und rendern Sie dann das Bild und das Overlay in einem einzigen Schritt. Auf diese Weise rendern Sie für jeden verarbeiteten Eingabeframe nur einmal auf der Anzeigeoberfläche. Ein Beispiel hierfür finden Sie in der Showcase-Beispiel-App den Klassen previewOverlayView und MLKDetectionOverlayView.

Nächste Schritte