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

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

قبل از اینکه شروع کنی

  1. اگر قبلاً Firebase را به برنامه خود اضافه نکرده اید، این کار را با دنبال کردن مراحل راهنمای شروع کار انجام دهید.
  2. کتابخانه‌های ML Kit را در فایل پادفایل خود قرار دهید:
    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'
    
    پس از نصب یا به‌روزرسانی Pods پروژه، حتماً پروژه Xcode خود را با استفاده از .xcworkspace آن باز کنید.
  3. در برنامه خود، Firebase را وارد کنید:

    سریع

    import Firebase

    هدف-C

    @import Firebase;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

حداقل اندازه، نسبت به تصویر، برای تشخیص چهره ها.

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

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

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

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

سریع

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

هدف-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. آشکارساز چهره را اجرا کنید

برای تشخیص چهره در یک تصویر، تصویر را به عنوان UIImage یا CMSampleBufferRef به روش detect(in:) VisionFaceDetector ارسال کنید:

  1. یک نمونه از VisionFaceDetector را دریافت کنید:

    سریع

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

    هدف-C

    FIRVision *vision = [FIRVision vision];
    FIRVisionFaceDetector *faceDetector = [vision faceDetector];
    // Or, to change the default settings:
    // FIRVisionFaceDetector *faceDetector =
    //     [vision faceDetectorWithOptions:options];
    
  2. یک شی VisionImage با استفاده از UIImage یا CMSampleBufferRef ایجاد کنید.

    برای استفاده از UIImage :

    1. در صورت لزوم، تصویر را بچرخانید تا ویژگی imageOrientation آن .up باشد.
    2. یک شی VisionImage با استفاده از UIImage با چرخش صحیح ایجاد کنید. هیچ ابرداده چرخشی را مشخص نکنید—مقدار پیش‌فرض، .topLeft . باید استفاده شود.

      سریع

      let image = VisionImage(image: uiImage)

      هدف-C

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

    برای استفاده از CMSampleBufferRef :

    1. یک شی VisionImageMetadata ایجاد کنید که جهت داده های تصویر موجود در بافر CMSampleBufferRef را مشخص می کند.

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

      سریع

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

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

      سپس، شی فوق داده را ایجاد کنید:

      سریع

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

      هدف-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. یک شی VisionImage با استفاده از شی CMSampleBufferRef و ابرداده چرخش ایجاد کنید:

      سریع

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

      هدف-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. سپس تصویر را به متد detect(in:) منتقل کنید:

    سریع

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

    هدف-C

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

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

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

سریع

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

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

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

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

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

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

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

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

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

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

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

  • دریچه گاز به آشکارساز زنگ می زند. اگر یک قاب ویدیویی جدید در حین کار کردن آشکارساز در دسترس قرار گرفت، قاب را رها کنید.
  • اگر از خروجی آشکارساز برای همپوشانی گرافیک روی تصویر ورودی استفاده می‌کنید، ابتدا نتیجه را از کیت ML دریافت کنید، سپس تصویر را رندر کنید و در یک مرحله همپوشانی کنید. با انجام این کار، برای هر فریم ورودی فقط یک بار به سطح نمایشگر رندر می دهید. به عنوان مثال، کلاس‌های previewOverlayView و FIRDetectionOverlayView را در برنامه نمونه ویترینی ببینید.