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

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

آن را امتحان کنید

  • با برنامه نمونه بازی کنید تا نمونه استفاده از این API را ببینید.
  • کد را خودتان با Codelab امتحان کنید.

قبل از شروع

  1. پادهای کیت ML زیر را در فایل پادفایل خود قرار دهید:
    pod 'GoogleMLKit/FaceDetection', '3.2.0'
    
  2. پس از نصب یا به روز رسانی Pods پروژه خود، پروژه Xcode خود را با استفاده از .xcworkspace . آن باز کنید. کیت ML در Xcode نسخه 12.4 یا بالاتر پشتیبانی می شود.

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

برای تشخیص چهره، باید از تصویری با ابعاد حداقل 480x360 پیکسل استفاده کنید. برای اینکه کیت ML بتواند چهره‌ها را به‌طور دقیق تشخیص دهد، تصاویر ورودی باید دارای چهره‌هایی باشند که با داده‌های پیکسلی کافی نشان داده شوند. به طور کلی، هر چهره ای که می خواهید در یک تصویر تشخیص دهید باید حداقل 100x100 پیکسل باشد. اگر می‌خواهید خطوط چهره‌ها را تشخیص دهید، کیت ML به ورودی وضوح بالاتری نیاز دارد: هر چهره باید حداقل 200x200 پیکسل باشد.

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

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

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

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

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

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

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

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

آیا تلاش برای تشخیص "نقاط برجسته" صورت - چشم ها، گوش ها، بینی، گونه ها، دهان- همه چهره های شناسایی شده.

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

آیا برای تشخیص خطوط خطوط صورت. خطوط تنها برای برجسته ترین چهره در یک تصویر شناسایی می شوند.

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

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

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

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

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

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

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

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

سویفت

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

هدف-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. تصویر ورودی را آماده کنید

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

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

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

  • با UIImage یک شی VisionImage ایجاد کنید. مطمئن شوید که جهت .orientation را مشخص کرده اید.

    سویفت

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

    هدف-C

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

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

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

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

    سویفت

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

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

    سویفت

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

    هدف-C

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

3. یک نمونه از FaceDetector را دریافت کنید

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

سویفت

let faceDetector = FaceDetector.faceDetector(options: options)

هدف-C

MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
      

4. تصویر را پردازش کنید

سپس تصویر را به متد process() منتقل کنید:

سویفت

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

هدف-C

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

5. اطلاعاتی در مورد چهره های شناسایی شده دریافت کنید

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

سویفت

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

هدف-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;
  }
}

نمونه ای از خطوط صورت

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

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

به عنوان مثال مش کانتور صورت را شناسایی کرد

تشخیص چهره در زمان واقعی

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

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

    تشخیص کانتور
    تشخیص نقطه عطف
    طبقه بندی
    تشخیص و طبقه بندی نقاط عطف
    تشخیص کانتور و تشخیص نقطه عطف
    تشخیص و طبقه بندی کانتور
    تشخیص کانتور، تشخیص نقطه عطف و طبقه بندی

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

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

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