Wykrywanie twarzy za pomocą ML Kit na iOS

Za pomocą pakietu ML Kit możesz wykrywać twarze na obrazach i w filmach.

Wypróbuj

  • Wypróbuj przykładową aplikację, aby: zobaczysz przykład użycia tego interfejsu API.
  • Wypróbuj kod samodzielnie za pomocą

Zanim zaczniesz

  1. W pliku Podfile umieść te pody ML Kit:
    pod 'GoogleMLKit/FaceDetection', '3.2.0'
    
  2. Po zainstalowaniu lub zaktualizowaniu podów projektu otwórz projekt Xcode za pomocą .xcworkspace ML Kit jest obsługiwany w Xcode w wersji 12.4 lub nowszej.

Wytyczne dotyczące obrazu wejściowego

Do rozpoznawania twarzy należy użyć obrazu o wymiarach co najmniej 480 x 360 pikseli. Aby ML Kit mógł precyzyjnie wykrywać twarze, obrazy wejściowe muszą zawierać twarze które są reprezentowane przez wystarczającą ilość danych pikseli. Ogólnie rzecz biorąc, każda twarz, którą chcesz pokazać, powinna mieć rozmiar co najmniej 100 x 100 pikseli. Jeśli chcesz wykrywać aby określić kontury twarzy, ML Kit wymaga wyższej rozdzielczości: powinien wynosić co najmniej 200 x 200 pikseli.

Jeśli wykrywasz twarze w aplikacji działającej w czasie rzeczywistym, możesz też aby wziąć pod uwagę ogólne wymiary obrazów wejściowych. Mniejsze obrazy szybsze przetwarzanie. Aby zmniejszyć opóźnienia, rób zdjęcia w niższej rozdzielczości, pamiętaj o powyższych wymaganiach dotyczących dokładności i upewnij się, twarz obiektu zajmuje jak najwięcej miejsca na obrazie. Zobacz też wskazówkami na temat poprawy skuteczności w czasie rzeczywistym.

Słaba ostrość obrazu również może mieć wpływ na dokładność. Jeśli nie otrzymasz akceptacji poproś użytkownika o powtórzenie zdjęcia.

Położenie twarzy w odniesieniu do aparatu może też wpływać na jej wygląd. wykrywanych przez ML Kit. Zobacz Pojęcia związane z wykrywaniem twarzy.

1. Konfigurowanie wykrywania twarzy

Zanim zastosujesz wykrywanie twarzy na zdjęciu, możesz zmienić domyślnych ustawień wykrywania twarzy, określ je za pomocą FaceDetectorOptions. Możesz zmienić te ustawienia:

Ustawienia
performanceMode fast (domyślna) | accurate

Większa szybkość lub dokładność podczas wykrywania twarzy.

landmarkMode none (domyślna) | all

Czy próbować wykryć „punkty orientacyjne” — oczy, uszu, nosa, policzków, ust – wszystkich wykrytych twarzy.

contourMode none (domyślna) | all

Określa, czy wykrywać kontury rysów twarzy. Kontury są tylko dla najbardziej widocznej twarzy na zdjęciu.

classificationMode none (domyślna) | all

Określa, czy twarze mają być klasyfikowane w kategoriach takich jak „uśmiech” i „oczy otwarte”.

minFaceSize CGFloat (domyślnie: 0.1)

Ustawia najmniejszy wymagany rozmiar twarzy, wyrażony jako współczynnik od szerokości głowy do szerokości obrazu.

isTrackingEnabled false (domyślna) | true

Określa, czy przypisywać twarzom identyfikator, który może służyć do śledzenia i twarze na zdjęciach.

Pamiętaj, że przy włączonym wykrywaniu kontur tylko jedna twarz więc śledzenie twarzy nie da żadnych przydatnych wyników. Do tego celu i aby zwiększyć szybkość wykrywania, nie włączaj obu konturów wykrywaniem oraz śledzeniem twarzy.

Na przykład utwórz FaceDetectorOptions. jak jeden z następujących przykładów:

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. Przygotowywanie obrazu wejściowego

Aby wykrywać twarze na zdjęciu, przekaż je jako UIImage lub CMSampleBufferRef do FaceDetector przy użyciu Metoda process(_:completion:) lub results(in:):

Utwórz obiekt VisionImage za pomocą UIImage lub CMSampleBuffer.

Jeśli używasz UIImage, wykonaj te czynności:

  • Utwórz obiekt VisionImage za pomocą UIImage. Pamiętaj, by określić prawidłowy .orientation.

    Swift

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

    Objective-C

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

Jeśli używasz CMSampleBuffer, wykonaj te czynności:

  • Określ orientację danych zdjęć zawartych w pliku CMSampleBuffer

    Aby sprawdzić orientację obrazu:

    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;
      }
    }
          
  • Utwórz obiekt VisionImage za pomocą CMSampleBuffer obiekt i orientacja:

    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. Pobieranie instancji FaceDetector

Pobierz instancję FaceDetector:

Swift

let faceDetector = FaceDetector.faceDetector(options: options)

Objective-C

MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
      

4. Przetwarzanie zdjęcia

Następnie przekaż obraz do metody 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. Uzyskiwanie informacji o wykrytych twarzy

Jeśli operacja wykrywania twarzy się powiedzie, czujnik twarzy przekaże tablicę z Face obiektów do modułu obsługi uzupełniania. Każdy Face obiekt reprezentuje twarz wykrytą na obrazie. Dla: można sprawdzić współrzędne ograniczające na obrazie wejściowym, wszelkie inne informacje skonfigurowane przez Ciebie w celu wykrywania twarzy. Na przykład:

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

Przykład konturu twarzy

Gdy włączysz wykrywanie konturu twarzy, zobaczysz listę punktów za wszystkie wykryte cechy twarzy. Te punkty odpowiadają kształtowi funkcji. Zobacz Twarz Pojęcia związane z wykrywaniem, aby uzyskać szczegółowe informacje o konturach reprezentowanych.

Poniższy obraz przedstawia sposób, w jaki punkty są odwzorowywane na twarz, kliknij obraz, aby go powiększyć:

przykład wykrytej siatki konturowej twarzy

Wykrywanie twarzy w czasie rzeczywistym

Jeśli chcesz używać wykrywania twarzy w aplikacjach działających w czasie rzeczywistym, postępuj zgodnie z tymi instrukcjami wytycznych dotyczących uzyskiwania najlepszej liczby klatek na sekundę:

  • Skonfiguruj wykrywacz twarzy, aby używał jednego wykrywanie kontur lub klasyfikacja twarzy i wykrywanie punktów orientacyjnych, ale nie oba te rodzaje naraz:

    Wykrywanie konturów
    Wykrywanie punktów orientacyjnych
    Klasyfikacja
    Wykrywanie i klasyfikacja punktów orientacyjnych
    Wykrywanie konturów i wykrywanie punktów orientacyjnych
    Wykrywanie i klasyfikacja kontur
    Wykrywanie konturów, wykrywanie punktów orientacyjnych i klasyfikacja

  • Włącz tryb fast (domyślnie włączony).

  • Rozważ robienie zdjęć w niższej rozdzielczości. Pamiętaj jednak, wymagania dotyczące wymiarów obrazów w tym interfejsie API.

  • Do przetwarzania klatek wideo używaj synchronicznego interfejsu API results(in:) detektora. Zadzwoń do nas tę metodę z AVCaptureVideoDataOutputSampleBufferDelegate . captureOutput(_, didOutput:from:), aby synchronicznie pobierać wyniki dotyczące danego filmu ramki. Zachowaj AVCaptureVideoDataOutput: alwaysDiscardsLateVideoFrames jako true, aby ograniczyć wywołania detektora. Jeśli nowy gdy klatka wideo jest dostępna, gdy jest uruchomiony detektor, zostanie usunięta.
  • Jeśli użyjesz danych wyjściowych detektora do nakładania grafiki na obrazu wejściowego, najpierw pobierz wynik z ML Kit, a następnie wyrenderuj obraz i nakładanie nakładek w jednym kroku. W ten sposób renderowanie na powierzchni tylko raz na każdą przetworzoną ramkę wejściową. Zobacz updatePreviewOverlayViewWithLastFrame. znajdziesz na przykład w krótkim wprowadzeniu do korzystania z ML Kit.