Mendeteksi wajah dengan ML Kit di iOS

Anda dapat menggunakan ML Kit untuk mendeteksi wajah dalam gambar dan video.

Cobalah

Sebelum memulai

  1. Sertakan pod ML Kit berikut di Podfile Anda:
    pod 'GoogleMLKit/FaceDetection', '3.2.0'
    
  2. Setelah Anda menginstal atau mengupdate Pod project, buka project Xcode menggunakan .xcworkspace. ML Kit didukung di Xcode versi 12.4 atau yang lebih baru.

Panduan gambar input

Untuk pengenalan wajah, Anda harus menggunakan gambar dengan dimensi minimal 480x360 piksel. Agar ML Kit dapat mendeteksi wajah secara akurat, gambar input harus berisi wajah yang diwakili oleh data piksel yang memadai. Secara umum, setiap wajah yang Anda inginkan untuk dideteksi dalam gambar harus berukuran minimal 100x100 piksel. Jika Anda ingin mendeteksi kontur wajah, ML Kit membutuhkan input resolusi yang lebih tinggi: setiap wajah harus berukuran minimal 200x200 piksel.

Jika Anda mendeteksi wajah dalam aplikasi {i>real-time<i}, Anda mungkin juga ingin untuk mempertimbangkan dimensi keseluruhan gambar input. Gambar yang lebih kecil bisa diproses lebih cepat, sehingga untuk mengurangi latensi, ambil gambar pada resolusi lebih rendah, tetapi pertahankan memenuhi persyaratan akurasi di atas dan memastikan bahwa wajah subjek menempati sebanyak mungkin gambar. Lihat juga tips untuk meningkatkan performa real-time.

Fokus gambar yang buruk juga dapat memengaruhi akurasi. Jika Anda tidak dapat diterima meminta pengguna untuk mengambil ulang gambar.

Orientasi wajah terhadap arah kamera juga dapat memengaruhi karakteristik wajah yang terdeteksi oleh ML Kit. Lihat Konsep Deteksi Wajah.

1. Mengonfigurasi detektor wajah

Jika Anda ingin mengubah setelan sebelum menerapkan deteksi wajah ke suatu gambar di setelan default detektor wajah, tentukan setelan tersebut dengan Objek FaceDetectorOptions. Anda dapat mengubah setelan berikut:

Setelan
performanceMode fast (default) | accurate

Mendukung kecepatan atau akurasi saat mendeteksi wajah.

landmarkMode none (default) | all

Apakah untuk mencoba mendeteksi "landmark" wajah—mata, telinga, hidung, pipi, mulut—dari semua wajah yang terdeteksi.

contourMode none (default) | all

Apakah mendeteksi kontur fitur wajah. Kontur adalah terdeteksi hanya untuk wajah yang paling terlihat dalam gambar.

classificationMode none (default) | all

Mengklasifikasikan wajah ke dalam kategori atau tidak, seperti "tersenyum" dan "mata terbuka".

minFaceSize CGFloat (default: 0.1)

Menetapkan ukuran wajah terkecil yang diinginkan, yang dinyatakan sebagai rasio lebar kepala selebar gambar.

isTrackingEnabled false (default) | true

Menetapkan ID pada wajah atau tidak, yang dapat digunakan untuk melacak wajah di seluruh gambar.

Perhatikan bahwa saat deteksi kontur diaktifkan, hanya satu wajah yang terdeteksi, sehingga pelacakan wajah tidak memberikan hasil yang berguna. Untuk ini alasan, dan untuk meningkatkan kecepatan deteksi, jangan aktifkan kedua deteksi dan pelacakan wajah.

Misalnya, membuat FaceDetectorOptions seperti salah satu contoh berikut:

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. Menyiapkan gambar input

Untuk mendeteksi wajah dalam gambar, teruskan gambar sebagai UIImage atau CMSampleBufferRef ke FaceDetector menggunakan Metode process(_:completion:) atau results(in:):

Buat objek VisionImage menggunakan UIImage atau objek CMSampleBuffer.

Jika Anda menggunakan UIImage, ikuti langkah-langkah berikut:

  • Buat objek VisionImage dengan UIImage. Pastikan untuk menentukan .orientation yang benar.

    Swift

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

    Objective-C

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

Jika Anda menggunakan CMSampleBuffer, ikuti langkah-langkah berikut:

  • Tentukan orientasi data gambar yang terdapat dalam CMSampleBuffer.

    Untuk mendapatkan orientasi gambar:

    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;
      }
    }
          
  • Buat objek VisionImage menggunakan Objek dan orientasi CMSampleBuffer:

    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. Mendapatkan instance FaceDetector

Dapatkan instance FaceDetector:

Swift

let faceDetector = FaceDetector.faceDetector(options: options)

Objective-C

MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
      

4. Memproses gambar

Lalu, teruskan gambar ke metode 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. Mendapatkan informasi tentang wajah yang terdeteksi

Jika operasi deteksi wajah berhasil, detektor wajah akan meneruskan array objek Face ke pengendali penyelesaian. Masing-masing Objek Face mewakili wajah yang terdeteksi dalam gambar. Sebagai setiap wajah, Anda bisa mendapatkan koordinat pembatasnya di gambar input, serta informasi lain yang telah Anda konfigurasikan untuk ditemukan oleh detektor wajah. Contoh:

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

Contoh kontur wajah

Ketika Anda mengaktifkan deteksi kontur wajah, Anda akan mendapatkan daftar titik untuk setiap fitur wajah yang terdeteksi. Titik-titik ini menggambarkan bentuk aplikasi baru. Lihat Wajah Konsep Deteksi untuk mengetahui detail tentang bagaimana kontur terwakili.

Gambar berikut mengilustrasikan bagaimana titik-titik ini dipetakan ke wajah, klik untuk memperbesarnya:

contoh mesh kontur wajah yang terdeteksi

Deteksi wajah real-time

Jika Anda ingin menggunakan deteksi wajah dalam aplikasi real-time, ikuti langkah-langkah berikut panduan untuk mencapai kecepatan frame terbaik:

  • Konfigurasi detektor wajah untuk menggunakan deteksi kontur wajah atau klasifikasi dan deteksi struktur, tetapi tidak keduanya:

    Deteksi kontur
    Deteksi tempat terkenal
    Klasifikasi
    Deteksi dan klasifikasi tempat terkenal
    Deteksi kontur dan deteksi tempat terkenal
    Deteksi dan klasifikasi kontur
    Deteksi kontur, deteksi tempat terkenal, dan klasifikasi

  • Aktifkan mode fast (diaktifkan secara default).

  • Sebaiknya ambil gambar dengan resolusi yang lebih rendah. Namun, perlu diingat persyaratan dimensi gambar API ini.

  • Untuk memproses frame video, gunakan API sinkron results(in:) dari detektor. Telepon metode ini dari class AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) untuk mendapatkan hasil dari video yang diberikan secara sinkron {i>frame<i}. Simpan AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames sebagai true untuk men-throttle panggilan ke detektor. Jika frame video tersedia saat detektor sedang berjalan, dan frame tersebut akan dihapus.
  • Jika Anda menggunakan output detektor untuk menempatkan grafik gambar input, pertama-tama dapatkan hasilnya dari ML Kit, lalu render gambar dan overlay dalam satu langkah. Dengan demikian, Anda merender ke permukaan tampilan hanya sekali untuk setiap {i> frame<i} input yang diproses. Lihat updatePreviewOverlayViewWithLastFrame dalam contoh panduan memulai ML Kit sebagai contoh.