Gesichter mit ML Kit auf iOS erkennen

Sie können ML Kit verwenden, um Gesichter in Bildern und Videos zu erkennen.

Bevor Sie beginnen

  1. Wenn Sie nicht bereits Firebase zu Ihrer App, tun Sie dies , indem Sie die Schritte im Leitfaden zur Inbetriebnahme .
  2. Fügen Sie die ML - Kit - Bibliotheken in Ihrem Podfile:
    pod 'Firebase/MLVision', '6.25.0'
    # If you want to detect face contours (landmark detection and classification
    # don't require this additional model):
    pod 'Firebase/MLVisionFaceModel', '6.25.0'
    
    Nachdem Sie Ihr Projekt Pods installieren oder aktualisieren, sollten Sie Ihre Xcode - Projekt zu öffnen , seine Verwendung .xcworkspace .
  3. Importieren Sie Firebase in Ihre App:

    Schnell

    import Firebase

    Ziel c

    @import Firebase;

Richtlinien für die Eingabe von Bildern

Damit ML Kit Gesichter genau erkennen kann, müssen die eingegebenen Bilder Gesichter enthalten, die durch ausreichende Pixeldaten dargestellt werden. Im Allgemeinen sollte jedes Gesicht, das Sie in einem Bild erkennen möchten, mindestens 100 x 100 Pixel groß sein. Wenn Sie die Konturen von Gesichtern erkennen möchten, erfordert ML Kit eine Eingabe mit höherer Auflösung: Jedes Gesicht sollte mindestens 200 x 200 Pixel groß sein.

Wenn Sie Gesichter in einer Echtzeitanwendung erkennen, sollten Sie auch die Gesamtabmessungen der eingegebenen Bilder berücksichtigen. Kleinere Bilder können schneller verarbeitet werden. Um die Latenz zu reduzieren, nehmen Sie Bilder mit niedrigeren Auflösungen auf (beachten Sie die oben genannten Genauigkeitsanforderungen) und stellen Sie sicher, dass das Gesicht des Motivs so viel wie möglich vom Bild einnimmt. Siehe auch Tipps Echtzeit - Performance zu verbessern .

Ein schlechter Bildfokus kann die Genauigkeit beeinträchtigen. Wenn Sie keine akzeptablen Ergebnisse erhalten, bitten Sie den Benutzer, das Bild erneut aufzunehmen.

Die Ausrichtung eines Gesichts relativ zur Kamera kann sich auch auf die von ML Kit erkannten Gesichtsmerkmale auswirken. Siehe Gesichtserkennung Konzepte .

1. Konfigurieren Sie den Gesichtsdetektor

Bevor Sie die Gesichtserkennung auf ein Bild anwenden, wenn Sie eines der Gesichtsdetektor Standardeinstellungen ändern möchten, geben Sie diese Einstellungen mit einem VisionFaceDetectorOptions Objekt. Sie können die folgenden Einstellungen ändern:

Einstellungen
performanceMode fast (default) | accurate

Bevorzugen Sie Geschwindigkeit oder Genauigkeit beim Erkennen von Gesichtern.

landmarkMode none (default) | all

Ob versucht werden soll, die Gesichts-„Wahrzeichen“ – Augen, Ohren, Nase, Wangen, Mund – aller erkannten Gesichter zu erkennen.

contourMode none (default) | all

Ob die Konturen der Gesichtszüge erkannt werden sollen. Konturen werden nur für das prominenteste Gesicht in einem Bild erkannt.

classificationMode none (default) | all

Ob Gesichter in Kategorien wie "Lächeln" und "Augen offen" eingeteilt werden sollen oder nicht.

minFaceSize CGFloat (Standard: 0.1 )

Die minimale Größe der zu erkennenden Gesichter im Verhältnis zum Bild.

isTrackingEnabled false (default) | true

Ob Gesichtern eine ID zugewiesen werden soll, mit der Gesichter über Bilder hinweg verfolgt werden können.

Beachten Sie, dass bei aktivierter Konturerkennung nur ein Gesicht erkannt wird, sodass die Gesichtsverfolgung keine nützlichen Ergebnisse liefert. Aus diesem Grund und um die Erkennungsgeschwindigkeit zu verbessern, aktivieren Sie nicht sowohl die Konturerkennung als auch die Gesichtsverfolgung.

Zum Beispiel baut ein VisionFaceDetectorOptions Objekt wie einer der folgenden Beispiele:

Schnell

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

// Real-time contour detection of multiple faces
let options = VisionFaceDetectorOptions()
options.contourMode = .all

Ziel c

// High-accuracy landmark detection and face classification
FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init];
options.performanceMode = FIRVisionFaceDetectorPerformanceModeAccurate;
options.landmarkMode = FIRVisionFaceDetectorLandmarkModeAll;
options.classificationMode = FIRVisionFaceDetectorClassificationModeAll;

// Real-time contour detection of multiple faces
FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init];
options.contourMode = FIRVisionFaceDetectorContourModeAll;

2. Führen Sie den Gesichtsdetektor aus

Zum Nachweis von Gesichtern in einem Bild, passieren das Bild als UIImage oder CMSampleBufferRef zum VisionFaceDetector ‚s detect(in:) Methode:

  1. Erhalten Sie eine Instanz von VisionFaceDetector :

    Schnell

    lazy var vision = Vision.vision()
    
    let faceDetector = vision.faceDetector(options: options)
    

    Ziel c

    FIRVision *vision = [FIRVision vision];
    FIRVisionFaceDetector *faceDetector = [vision faceDetector];
    // Or, to change the default settings:
    // FIRVisionFaceDetector *faceDetector =
    //     [vision faceDetectorWithOptions:options];
    
  2. Erstellen Sie ein VisionImage Objekt unter Verwendung eines UIImage oder eine CMSampleBufferRef .

    So verwenden Sie eine UIImage :

    1. Falls erforderlich, drehen Sie das Bild so , dass seine imageOrientation Eigenschaft ist .up .
    2. Erstellen Sie ein VisionImage Objekt die korrekt gedreht mit UIImage . Geben Sie nicht jede Drehung Metadaten den Standardwert, .topLeft , verwendet werden.

      Schnell

      let image = VisionImage(image: uiImage)

      Ziel c

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    So verwenden Sie eine CMSampleBufferRef :

    1. Erstellen eines VisionImageMetadata Objekt , das angibt , ist die Orientierung der Bilddaten in der enthaltenen CMSampleBufferRef Puffer.

      So erhalten Sie die Bildausrichtung:

      Schnell

      func imageOrientation(
          deviceOrientation: UIDeviceOrientation,
          cameraPosition: AVCaptureDevice.Position
          ) -> VisionDetectorImageOrientation {
          switch deviceOrientation {
          case .portrait:
              return cameraPosition == .front ? .leftTop : .rightTop
          case .landscapeLeft:
              return cameraPosition == .front ? .bottomLeft : .topLeft
          case .portraitUpsideDown:
              return cameraPosition == .front ? .rightBottom : .leftBottom
          case .landscapeRight:
              return cameraPosition == .front ? .topRight : .bottomRight
          case .faceDown, .faceUp, .unknown:
              return .leftTop
          }
      }

      Ziel c

      - (FIRVisionDetectorImageOrientation)
          imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                                 cameraPosition:(AVCaptureDevicePosition)cameraPosition {
        switch (deviceOrientation) {
          case UIDeviceOrientationPortrait:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationLeftTop;
            } else {
              return FIRVisionDetectorImageOrientationRightTop;
            }
          case UIDeviceOrientationLandscapeLeft:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationBottomLeft;
            } else {
              return FIRVisionDetectorImageOrientationTopLeft;
            }
          case UIDeviceOrientationPortraitUpsideDown:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationRightBottom;
            } else {
              return FIRVisionDetectorImageOrientationLeftBottom;
            }
          case UIDeviceOrientationLandscapeRight:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationTopRight;
            } else {
              return FIRVisionDetectorImageOrientationBottomRight;
            }
          default:
            return FIRVisionDetectorImageOrientationTopLeft;
        }
      }

      Erstellen Sie dann das Metadatenobjekt:

      Schnell

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      Ziel c

      FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
      AVCaptureDevicePosition cameraPosition =
          AVCaptureDevicePositionBack;  // Set to the capture device you used.
      metadata.orientation =
          [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                       cameraPosition:cameraPosition];
    2. Erstellen Sie ein VisionImage Objekt mit dem CMSampleBufferRef Objekt und die Rotation von Metadaten:

      Schnell

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      Ziel c

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Dann passieren die Bild auf die detect(in:) Methode:

    Schnell

    faceDetector.process(visionImage) { faces, error in
      guard error == nil, let faces = faces, !faces.isEmpty else {
        // ...
        return
      }
    
      // Faces detected
      // ...
    }
    

    Ziel c

    [faceDetector detectInImage:image
                     completion:^(NSArray<FIRVisionFace *> *faces,
                                  NSError *error) {
      if (error != nil) {
        return;
      } else if (faces != nil) {
        // Recognized faces
      }
    }];
    

3. Holen Sie sich Informationen über erkannte Gesichter

Wenn der Gesichtserfassungsvorgang erfolgreich ist , gelangt das Gesichtsdetektor ein Array von VisionFace zur Fertigstellung Handler - Objekte. Jedes VisionFace Objekt repräsentiert ein Gesicht , das in dem Bild festgestellt wurde. Für jedes Gesicht können Sie seine Begrenzungskoordinaten im Eingabebild sowie alle anderen Informationen abrufen, für die Sie den Gesichtsdetektor konfiguriert haben. Zum Beispiel:

Schnell

for face in faces {
  let frame = face.frame
  if face.hasHeadEulerAngleY {
    let rotY = face.headEulerAngleY  // Head is rotated to the right rotY degrees
  }
  if face.hasHeadEulerAngleZ {
    let rotZ = face.headEulerAngleZ  // Head is rotated upward 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
  }
}

Ziel c

for (FIRVisionFace *face in faces) {
  // Boundaries of face in image
  CGRect frame = face.frame;

  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):
  FIRVisionFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar];
  if (leftEar != nil) {
    FIRVisionPoint *leftEarPosition = leftEar.position;
  }

  // If contour detection was enabled:
  FIRVisionFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom];
  if (upperLipBottomContour != nil) {
    NSArray<FIRVisionPoint *> *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 Sie die Gesichtskonturerkennung aktiviert haben, erhalten Sie eine Liste von Punkten für jedes erkannte Gesichtsmerkmal. Diese Punkte repräsentieren die Form des Features. Siehe die Gesichtserkennung Konzepte Übersicht für Einzelheiten darüber , wie Konturen dargestellt werden.

Die folgende Abbildung zeigt, wie diese Punkte einem Gesicht zugeordnet werden (zum Vergrößern auf das Bild klicken):

Gesichtserkennung in Echtzeit

Wenn Sie die Gesichtserkennung in einer Echtzeitanwendung verwenden möchten, befolgen Sie diese Richtlinien, um die besten Frameraten zu erzielen:

  • Konfigurieren des Gesichtsdetektor entweder Gesichtskonturerkennung und Klassifizierung und Wahrzeichen Erkennung zu verwenden, aber nicht beides:

    Konturerkennung
    Erkennung von Wahrzeichen
    Einstufung
    Erkennung und Klassifizierung von Wahrzeichen
    Konturerkennung und Landmarkenerkennung
    Konturerkennung und -klassifizierung
    Konturerkennung, Erkennung von Orientierungspunkten und Klassifizierung

  • Aktivieren fast Modus (Standardeinstellung).

  • Ziehen Sie in Erwägung, Bilder mit einer niedrigeren Auflösung aufzunehmen. Beachten Sie jedoch auch die Anforderungen an die Bildabmessungen dieser API.

  • Throttle-Anrufe an den Detektor. Wenn ein neues Videobild verfügbar wird, während der Detektor läuft, lassen Sie das Bild fallen.
  • Wenn Sie die Ausgabe des Detektors verwenden, um das Eingabebild mit Grafiken zu überlagern, rufen Sie zuerst das Ergebnis von ML Kit ab und rendern dann das Bild und die Überlagerung in einem einzigen Schritt. Auf diese Weise rendern Sie für jeden Eingabeframe nur einmal auf der Anzeigeoberfläche. Siehe die previewOverlayView und FIRDetectionOverlayView Klassen in der Vitrine Beispielanwendung für ein Beispiel.