Gesichter mit ML Kit unter iOS erkennen

Mit dem ML Kit können Sie Gesichter in Bildern und Videos erkennen.

Testen

  • Probieren Sie die Beispiel-App aus, um sich ein Anwendungsbeispiel dieser API anzusehen.
  • Probiere den Code selbst mit dem Codelab aus.

Hinweis

  1. Fügen Sie die folgenden ML Kit-Pods in Ihre Podfile ein:
    pod 'GoogleMLKit/FaceDetection', '3.2.0'
    
  2. Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie das Xcode-Projekt mit dessen .xcworkspace. ML Kit wird ab Xcode Version 12.4 unterstützt.

Richtlinien für Eingabebilder

Für die Gesichtserkennung sollten Sie ein Bild mit einer Größe von mindestens 480 x 360 Pixeln verwenden. Damit ML Kit Gesichter richtig erkennen kann, müssen Eingabebilder Gesichter enthalten, die durch genügend Pixeldaten dargestellt werden. Im Allgemeinen sollte jedes Gesicht, das Sie in einem Bild erkennen möchten, mindestens 100 × 100 Pixel haben. Wenn die Konturen von Gesichtern erkannt werden sollen, ist für ML Kit eine hochauflösendere Eingabe erforderlich: Jedes Gesicht sollte mindestens 200 x 200 Pixel groß sein.

Wenn Sie Gesichter in einer Echtzeitanwendung erkennen, sollten Sie auch die Gesamtabmessungen der Eingabebilder berücksichtigen. Kleinere Bilder lassen sich schneller verarbeiten. So können Sie die Latenz reduzieren, indem Sie Bilder mit niedrigerer Auflösung aufnehmen. Beachten Sie jedoch die oben genannten Anforderungen an die Genauigkeit und achten Sie darauf, dass das Gesicht des Objekts so viel wie möglich einnimmt. Weitere Informationen finden Sie unter Tipps zur Verbesserung der Echtzeitleistung.

Ein schlechter Bildfokus kann sich auch auf die Genauigkeit auswirken. Wenn du keine akzeptablen Ergebnisse erhältst, bitte den Nutzer, das Bild noch einmal aufzunehmen.

Die Ausrichtung eines Gesichts relativ zur Kamera kann sich auch darauf auswirken, welche Gesichtsmerkmale ML Kit erkennt. Siehe Konzepte der Gesichtserkennung.

1. Gesichtserkennung konfigurieren

Bevor Sie die Gesichtserkennung auf ein Bild anwenden, müssen Sie diese mit einem FaceDetectorOptions-Objekt festlegen, wenn Sie eine der Standardeinstellungen des Gesichtserkennungssystems ändern möchten. Sie können die folgenden Einstellungen ändern:

Einstellungen
performanceMode fast (Standard) | accurate

Bevorzugen Sie Geschwindigkeit oder Genauigkeit bei der Gesichtserkennung.

landmarkMode none (Standard) | all

Gibt an, ob versucht wird, alle erkannten Gesichtsmerkmale wie Augen, Ohren, Nase, Wangen oder Mund zu erkennen.

contourMode none (Standard) | all

Gibt an, ob die Konturen der Gesichtszüge erkannt werden sollen. Konturen werden nur für das auffälligste Gesicht in einem Bild erkannt.

classificationMode none (Standard) | all

Gibt an, ob Gesichter in Kategorien klassifiziert werden sollen, z. B. „Lächeln“ oder „Augen geöffnet“.

minFaceSize CGFloat (Standard: 0.1)

Legt die kleinste gewünschte Gesichtsgröße fest, ausgedrückt als Verhältnis der Breite des Kopfes zur Breite des Bildes.

isTrackingEnabled false (Standard) | true

Gibt an, ob Gesichter einer ID zugewiesen werden sollen, mit der Gesichter über Bilder hinweg verfolgt werden kann.

Beachten Sie, dass bei aktivierter Konturerkennung nur ein Gesicht erkannt wird. Die Gesichtserkennung liefert also keine nützlichen Ergebnisse. Aus diesem Grund und zur Verbesserung der Erkennungsgeschwindigkeit sollten Sie nicht sowohl die Konturerkennung als auch die Gesichtsverfolgung aktivieren.

Erstellen Sie beispielsweise ein FaceDetectorOptions-Objekt wie eines der folgenden:

Swift

// High-accuracy landmark detection and face classification
let options = FaceDetectorOptions()
options.performanceMode = .accurate
options.landmarkMode = .all
options.classificationMode = .all

// Real-time contour detection of multiple faces
// options.contourMode = .all

Objective-C

// High-accuracy landmark detection and face classification
MLKFaceDetectorOptions *options = [[MLKFaceDetectorOptions alloc] init];
options.performanceMode = MLKFaceDetectorPerformanceModeAccurate;
options.landmarkMode = MLKFaceDetectorLandmarkModeAll;
options.classificationMode = MLKFaceDetectorClassificationModeAll;

// Real-time contour detection of multiple faces
// options.contourMode = MLKFaceDetectorContourModeAll;

2. Eingabebild vorbereiten

Um Gesichter in einem Bild zu erkennen, übergeben Sie das Bild als UIImage oder CMSampleBufferRef mit der Methode process(_:completion:) oder results(in:) an FaceDetector:

Erstellen Sie ein VisionImage-Objekt mit einem UIImage oder einem CMSampleBuffer.

Wenn Sie UIImage verwenden, gehen Sie so vor:

  • Erstellen Sie ein VisionImage-Objekt mit UIImage. Achten Sie darauf, die richtige .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 Sie CMSampleBuffer verwenden, gehen Sie so vor:

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

    So erhalten 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;
      }
    }
          
  • Erstellen Sie ein VisionImage-Objekt mit dem Objekt CMSampleBuffer 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. Instanz von FaceDetector abrufen

Rufen Sie eine Instanz von FaceDetector ab:

Swift

let faceDetector = FaceDetector.faceDetector(options: options)

Objective-C

MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
      

4. Bild verarbeiten

Übergeben Sie dann das Bild an die Methode process():

Swift

weak var weakSelf = self
faceDetector.process(visionImage) { faces, error in
  guard let strongSelf = weakSelf else {
    print("Self is nil!")
    return
  }
  guard error == nil, let faces = faces, !faces.isEmpty else {
    // ...
    return
  }

  // Faces detected
  // ...
}

Objective-C

[faceDetector processImage:image
                completion:^(NSArray<MLKFace *> *faces,
                             NSError *error) {
  if (error != nil) {
    return;
  }
  if (faces.count > 0) {
    // Recognized faces
  }
}];

5. Informationen zu erkannten Gesichtern abrufen

Wenn die Gesichtserkennung erfolgreich ist, übergibt der Gesichtserkennungsassistent ein Array von Face-Objekten an den Abschluss-Handler. Jedes Face-Objekt stellt ein Gesicht dar, das im Bild erkannt wurde. Für jedes Gesicht können Sie die Begrenzungskoordinaten im Eingabebild sowie alle anderen Informationen abrufen, die Sie anhand des Gesichtsdetektors ermittelt haben. Beispiel:

Swift

for face in faces {
  let frame = face.frame
  if face.hasHeadEulerAngleX {
    let rotX = face.headEulerAngleX  // Head is rotated to the uptoward rotX degrees
  }
  if face.hasHeadEulerAngleY {
    let rotY = face.headEulerAngleY  // Head is rotated to the right rotY degrees
  }
  if face.hasHeadEulerAngleZ {
    let rotZ = face.headEulerAngleZ  // Head is tilted sideways rotZ degrees
  }

  // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
  // nose available):
  if let leftEye = face.landmark(ofType: .leftEye) {
    let leftEyePosition = leftEye.position
  }

  // If contour detection was enabled:
  if let leftEyeContour = face.contour(ofType: .leftEye) {
    let leftEyePoints = leftEyeContour.points
  }
  if let upperLipBottomContour = face.contour(ofType: .upperLipBottom) {
    let upperLipBottomPoints = upperLipBottomContour.points
  }

  // If classification was enabled:
  if face.hasSmilingProbability {
    let smileProb = face.smilingProbability
  }
  if face.hasRightEyeOpenProbability {
    let rightEyeOpenProb = face.rightEyeOpenProbability
  }

  // If face tracking was enabled:
  if face.hasTrackingID {
    let trackingId = face.trackingID
  }
}

Objective-C

for (MLKFace *face in faces) {
  // Boundaries of face in image
  CGRect frame = face.frame;
  if (face.hasHeadEulerAngleX) {
    CGFloat rotX = face.headEulerAngleX;  // Head is rotated to the upward rotX degrees
  }
  if (face.hasHeadEulerAngleY) {
    CGFloat rotY = face.headEulerAngleY;  // Head is rotated to the right rotY degrees
  }
  if (face.hasHeadEulerAngleZ) {
    CGFloat rotZ = face.headEulerAngleZ;  // Head is tilted sideways rotZ degrees
  }

  // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
  // nose available):
  MLKFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar];
  if (leftEar != nil) {
    MLKVisionPoint *leftEarPosition = leftEar.position;
  }

  // If contour detection was enabled:
  MLKFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom];
  if (upperLipBottomContour != nil) {
    NSArray<MLKVisionPoint *> *upperLipBottomPoints = upperLipBottomContour.points;
    if (upperLipBottomPoints.count > 0) {
      NSLog("Detected the bottom contour of the subject's upper lip.")
    }
  }

  // If classification was enabled:
  if (face.hasSmilingProbability) {
    CGFloat smileProb = face.smilingProbability;
  }
  if (face.hasRightEyeOpenProbability) {
    CGFloat rightEyeOpenProb = face.rightEyeOpenProbability;
  }

  // If face tracking was enabled:
  if (face.hasTrackingID) {
    NSInteger trackingID = face.trackingID;
  }
}

Beispiel für Gesichtskonturen

Wenn die Gesichtskonturerkennung aktiviert ist, wird für jedes erkannte Gesicht eine Liste mit Punkten angezeigt. Diese Punkte stellen die Form des Features dar. Weitere Informationen zur Darstellung von Konturen finden Sie unter Konzepte für die Gesichtserkennung.

In der folgenden Abbildung ist zu sehen, wie diese Punkte einem Gesicht zugeordnet sind. Klicken Sie auf das Bild, um es zu vergrößern:

Beispiel für erkanntes konturiertes Mesh-Netzwerk

Gesichtserkennung in Echtzeit

Wenn Sie die Gesichtserkennung in einer Echtzeitanwendung verwenden möchten, beachten Sie die folgenden Best Practices, um die besten Framerates zu erzielen:

  • Konfigurieren Sie den Gesichtserkennung so, dass entweder die Gesichtserkennung oder die Klassifizierung und die Erkennung von Sehenswürdigkeiten verwendet werden, aber nicht beides:

    Konturerkennung
    Erkennung von Sehenswürdigkeiten
    Klassifizierung
    Erkennung und Klassifizierung von Sehenswürdigkeiten
    Konturerkennung und Sehenswürdigkeitenerkennung
    Konturerkennung und -klassifizierung
    Konturerkennung, Sehenswürdigkeiten und Klassifizierung

  • Modus „fast“ aktivieren (standardmäßig aktiviert).

  • Bilder mit einer geringeren Auflösung aufnehmen Beachten Sie jedoch die Anforderungen an die Bildabmessungen dieser API.

  • Verwenden Sie zur Verarbeitung von Videoframes die synchrone API des Detektors results(in:). Rufen Sie diese Methode über die captureOutput(_, didOutput:from:)-Funktion der AVCaptureVideoDataOutputSampleBufferDelegate auf, um synchron Ergebnisse aus dem angegebenen Videoframe zu erhalten. Behalten Sie alwaysDiscardsLateVideoFrames von AVCaptureVideoDataOutput als true bei, um Aufrufe an den Detektor zu drosseln. Wenn während der Ausführung des Detektors ein neuer Videoframe verfügbar ist, wird er verworfen.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf dem Eingabebild einzublenden, rufen Sie zuerst das Ergebnis aus ML Kit ab und rendern dann das Bild und das Overlay in einem einzigen Schritt. Dadurch wird die Anzeige für jeden verarbeiteten Eingabeframe nur einmal auf der Anzeigeoberfläche gerendert. Ein Beispiel findest du in der Kurzanleitung zu updatePreviewOverlayViewWithLastFrame.