تشخیص چهره با ML Kit در iOS

می‌توانید از ML Kit برای تشخیص چهره در تصاویر و ویدیو استفاده کنید.

امتحان کنید

  • با برنامه نمونه بازی کنید تا نمونه‌ای از کاربرد این API را ببینید.
  • با codelab خودتان کد را امتحان کنید.

قبل‌از شروع

  1. پادهای ML Kit زیر را در Podfile خود اضافه کنید:
    pod 'GoogleMLKit/FaceDetection', '8.0.0'
    
  2. پس‌از نصب یا به‌روزرسانی Pods پروژه، پروژه Xcode خود را بااستفاده از .xcworkspace باز کنید. ‫ML Kit در Xcode نسخه ۱۲.۴ یا بالاتر پشتیبانی می‌شود.

دستورالعمل‌های تصویر ورودی

برای تشخیص چهره، باید از تصویری با ابعاد حداقل ۴۸۰x۳۶۰ پیکسل استفاده کنید. برای اینکه ML Kit بتواند چهره‌ها را به‌درستی تشخیص دهد، تصاویر ورودی باید حاوی چهره‌هایی باشند که با داده‌های پیکسلی کافی نمایش داده شده‌اند. به‌طورکلی، هر چهره‌ای که می‌خواهید در تصویر تشخیص داده شود باید حداقل ۱۰۰x۱۰۰ پیکسل باشد. اگر می‌خواهید خطوط چهره را تشخیص دهید، ML Kit به ورودی با وضوح بالاتر نیاز دارد: هر چهره باید حداقل ۲۰۰×۲۰۰ پیکسل باشد.

اگر چهره‌ها را در یک برنامه هم‌زمان تشخیص می‌دهید، ممکن است بخواهید ابعاد کلی تصاویر ورودی را نیز درنظر بگیرید. تصاویر کوچک‌تر را می‌توان سریع‌تر پردازش کرد، بنابراین برای کاهش تأخیر، تصاویر را با وضوح پایین‌تر ثبت کنید، اما الزامات دقت بالا را درنظر داشته باشید و مطمئن شوید که چهره سوژه تا حد امکان بخش بیشتری از تصویر را اشغال می‌کند. همچنین نکاتی برای بهبود عملکرد هم‌زمان را ببینید.

فوکوس ضعیف تصویر نیز می‌تواند بر دقت تأثیر بگذارد. اگر نتایج قابل‌قبول دریافت نکردید، از کاربر بخواهید تصویر را دوباره بگیرد.

جهت چهره نسبت‌به دوربین نیز می‌تواند بر ویژگی‌های چهره‌ای که ML Kit تشخیص می‌دهد تأثیر بگذارد. به مفاهیم تشخیص چهره مراجعه کنید.

۱. پیکربندی آشکارساز چهره

قبل‌از اعمال تشخیص چهره روی تصویر، اگر می‌خواهید هرکدام از تنظیمات پیش‌فرض تشخیص چهره را تغییر دهید، آن تنظیمات را با شیء FaceDetectorOptions مشخص کنید. می‌توانید تنظیمات زیر را تغییر دهید:

تنظیمات
performanceMode ‫fast (پیش‌فرض) | accurate

هنگام تشخیص چهره، سرعت یا دقت را ترجیح دهید.

landmarkMode ‫none (پیش‌فرض) | all

تلاش برای شناسایی «نشان‌های چهره» (چشم‌ها، گوش‌ها، بینی، گونه‌ها، دهان) همه چهره‌های شناسایی‌شده.

contourMode ‫none (پیش‌فرض) | all

آیا خطوط محیطی ویژگی‌های چهره تشخیص داده شود یا نه. خطوط محیطی فقط برای برجسته‌ترین چهره در تصویر تشخیص داده می‌شود.

classificationMode ‫none (پیش‌فرض) | all

اینکه چهره‌ها در دسته‌هایی مثل «لبخند» و «چشمان باز» طبقه‌بندی شوند یا نه.

minFaceSize ‫CGFloat (پیش‌فرض: 0.1)

کوچک‌ترین اندازه چهره موردنظر را تنظیم می‌کند که به‌صورت نسبت عرض سر به عرض تصویر بیان می‌شود.

isTrackingEnabled ‫false (پیش‌فرض) | true

آیا به چهره‌ها شناسه اختصاص داده شود یا نه، که می‌تواند برای ردیابی چهره‌ها در تصاویر استفاده شود.

توجه داشته باشید که وقتی تشخیص کانتور فعال است، فقط یک چهره شناسایی می‌شود، بنابراین ردگیری چهره نتایج مفیدی تولید نمی‌کند. به همین دلیل و برای بهبود سرعت تشخیص، هم تشخیص خطوط محیطی و هم ردیابی چهره را فعال نکنید.

برای مثال، FaceDetectorOptions شیئی مانند یکی از نمونه‌های زیر بسازید:

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

آبجکتیو-سی

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

۲. آماده کردن تصویر ورودی

برای تشخیص چهره‌ها در تصویر، تصویر را به‌عنوان UIImage یا CMSampleBufferRef به FaceDetector بااستفاده از روش process(_:completion:) یا results(in:) ارسال کنید:

بااستفاده از UIImage یا CMSampleBuffer، شیء VisionImage ایجاد کنید.

اگر از UIImage استفاده می‌کنید، این مراحل را دنبال کنید:

  • یک شیء VisionImage با UIImage ایجاد کن. حتماً .orientation صحیح را مشخص کنید.

    Swift

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

    آبجکتیو-سی

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

اگر از CMSampleBuffer استفاده می‌کنید، این مراحل را دنبال کنید:

  • جهت داده‌های تصویر موجود در CMSampleBuffer را مشخص کنید.

    برای دریافت جهت تصویر:

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

    آبجکتیو-سی

    - (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;
      }
    }
          
  • بااستفاده از شیء CMSampleBuffer و جهت‌گیری، شیء VisionImage ایجاد کنید:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    آبجکتیو-سی

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

۳. دریافت نمونه‌ای از FaceDetector

نمونه‌ای از FaceDetector را دریافت کنید:

Swift

let faceDetector = FaceDetector.faceDetector(options: options)

آبجکتیو-سی

MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
      

۴. پردازش تصویر

سپس، تصویر را به روش 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
  // ...
}

آبجکتیو-سی

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

۵. دریافت اطلاعات درباره چهره‌های شناسایی‌شده

اگر عملیات تشخیص چهره موفق باشد، تشخیص‌دهنده چهره آرایه‌ای از اشیاء Face را به مدیریت‌کننده تکمیل ارسال می‌کند. هر Face شیء نشان‌دهنده چهره‌ای است که در تصویر شناسایی شده است. برای هر چهره، می‌توانید مختصات محدودکننده آن را در تصویر ورودی، و همچنین هر اطلاعات دیگری را که آشکارساز چهره برای یافتن آن پیکربندی کرده‌اید دریافت کنید. برای مثال:

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

آبجکتیو-سی

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

مثالی از خطوط تراز چهره

وقتی تشخیص خطوط چهره را فعال می‌کنید، فهرستی از نقاط برای هر ویژگی چهره‌ای که تشخیص داده شده است دریافت می‌کنید. این نقطه‌ها نشان‌دهنده شکل عارضه است. برای جزئیات مربوط به نحوه نمایش خطوط محیطی، مفاهیم تشخیص چهره را ببینید.

تصویر زیر نشان می‌دهد که این نقاط چگونه روی چهره نگاشت می‌شوند، برای بزرگ کردن تصویر روی آن کلیک کنید:

نمونه‌ای از مش کانتور چهره شناسایی‌شده

تشخیص چهره هم‌زمان

اگر می‌خواهید از تشخیص چهره در یک برنامه درلحظه استفاده کنید، این دستورالعمل‌ها را برای دستیابی به بهترین نرخ‌های فریم دنبال کنید:

  • آشکارساز چهره را پیکربندی کنید تا از تشخیص یا طبقه‌بندی خطوط چهره و تشخیص نشانگر استفاده کند، اما از هر دو استفاده نکند:

    تشخیص خطوط محیطی
    تشخیص نشانگر مکانی
    طبقه‌بندی
    تشخیص و طبقه‌بندی نشانگر مکانی
    تشخیص خطوط محیطی و تشخیص نشانگر مکانی
    تشخیص خطوط محیطی و طبقه‌بندی
    تشخیص خطوط محیطی، تشخیص نشانگر مکانی، و طبقه‌بندی

  • حالت fast را فعال کنید (به‌طور پیش‌فرض فعال است).

  • تصاویر را با وضوح پایین‌تری بگیرید. بااین‌حال، الزامات ابعاد تصویر این API را نیز درنظر داشته باشید.

  • برای پردازش قاب‌های ویدیو، از results(in:) میانای برنامه‌سازی کاربردی هم‌زمان آشکارساز استفاده کنید. این روش را از تابع AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) فراخوانی کنید تا نتایج را به‌صورت هم‌زمان از قاب ویدیو داده‌شده دریافت کنید. AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames را به‌عنوان true نگه دارید تا تماس‌ها با آشکارساز را محدود کنید. اگر قاب ویدیو جدیدی درحین اجرای آشکارساز دردسترس قرار گیرد، حذف خواهد شد.
  • اگر از برونداد آشکارساز برای رونهادن گرافیک روی تصویر ورودی استفاده می‌کنید، ابتدا نتیجه را از ML Kit دریافت کنید، سپس تصویر را پرداز و در یک مرحله رونهاد کنید. با انجام این کار، برای هر قاب ورودی پردازش‌شده، فقط یک‌بار به سطح نمایشگر رندر می‌کنید. برای نمونه، updatePreviewOverlayViewWithLastFrame را در نمونه شروع سریع ML Kit ببینید.