تشخیص دادن ژست‌ها با ML Kit در iOS

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

نام کیت توسعه نرم‌افزارPoseDetectionPoseDetectionAccurate
پیاده‌سازیدارایی‌های آشکارساز پایه در زمان ساخت به‌صورت ایستا به برنامه‌تان پیوند داده می‌شوند.دارایی‌های مربوط به آشکارساز دقیق در زمان ساخت به‌طور ایستا به برنامه‌تان پیوند داده می‌شود.
حجم برنامهتا ۲۹٫۶ مگابایتتا ۳۳٫۲ مگابایت
عملکردiPhone X: ~45FPSiPhone X: ~29FPS

امتحان کنید

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

قبل‌از شروع

  1. پادهای ML Kit زیر را در Podfile خود اضافه کنید:

    # If you want to use the base implementation:
    pod 'GoogleMLKit/PoseDetection', '8.0.0'
    
    # If you want to use the accurate implementation:
    pod 'GoogleMLKit/PoseDetectionAccurate', '8.0.0'
    
  2. پس‌از نصب یا به‌روزرسانی podهای پروژه‌تان، پروژه Xcode را بااستفاده از xcworkspace آن باز کنید. «کیت یادگیری ماشین» در Xcode نسخه ۱۳.۲.۱ یا بالاتر پشتیبانی می‌شود.

۱. ایجاد نمونه‌ای از PoseDetector

برای تشخیص دادن ژست در تصویر، ابتدا نمونه‌ای از PoseDetector ایجاد کنید و به‌صورت اختیاری تنظیمات آشکارساز را مشخص کنید.

PoseDetector گزینه

حالت تشخیص

PoseDetector در دو حالت تشخیص کار می‌کند. حتماً موردی را انتخاب کنید که با مورد استفاده شما مطابقت دارد.

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

گزینه‌های تشخیص‌دهنده حالت را مشخص کنید:

Swift

// Base pose detector with streaming, when depending on the PoseDetection SDK
let options = PoseDetectorOptions()
options.detectorMode = .stream

// Accurate pose detector on static images, when depending on the
// PoseDetectionAccurate SDK
let options = AccuratePoseDetectorOptions()
options.detectorMode = .singleImage

آبجکتیو-سی

// Base pose detector with streaming, when depending on the PoseDetection SDK
MLKPoseDetectorOptions *options = [[MLKPoseDetectorOptions alloc] init];
options.detectorMode = MLKPoseDetectorModeStream;

// Accurate pose detector on static images, when depending on the
// PoseDetectionAccurate SDK
MLKAccuratePoseDetectorOptions *options =
    [[MLKAccuratePoseDetectorOptions alloc] init];
options.detectorMode = MLKPoseDetectorModeSingleImage;

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

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

آبجکتیو-سی

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

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

برای تشخیص ژست‌ها، مراحل زیر را برای هر تصویر یا فریم ویدیو انجام دهید. اگر حالت جاری‌سازی را فعال کرده‌اید، باید VisionImage شیء از CMSampleBuffer ایجاد کنید.

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

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

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

VisionImage را به یکی از روش‌های پردازش تصویر آشکارساز حالت ارسال کنید. می‌توانید از روش ناهمگام process(image:) یا روش همگام results() استفاده کنید.

برای شناسایی هم‌زمان اشیاء:

Swift

var results: [Pose]
do {
  results = try poseDetector.results(in: image)
} catch let error {
  print("Failed to detect pose with error: \(error.localizedDescription).")
  return
}
guard let detectedPoses = results, !detectedPoses.isEmpty else {
  print("Pose detector returned no results.")
  return
}

// Success. Get pose landmarks here.

آبجکتیو-سی

NSError *error;
NSArray *poses = [poseDetector resultsInImage:image error:&error];
if (error != nil) {
  // Error.
  return;
}
if (poses.count == 0) {
  // No pose detected.
  return;
}

// Success. Get pose landmarks here.

برای شناسایی اشیاء به‌صورت ناهمگام:

Swift

poseDetector.process(image) { detectedPoses, error in
  guard error == nil else {
    // Error.
    return
  }
  guard !detectedPoses.isEmpty else {
    // No pose detected.
    return
  }

  // Success. Get pose landmarks here.
}

آبجکتیو-سی

[poseDetector processImage:image
                completion:^(NSArray * _Nullable poses,
                             NSError * _Nullable error) {
                    if (error != nil) {
                      // Error.
                      return;
                    }
                    if (poses.count == 0) {
                      // No pose detected.
                      return;
                    }

                    // Success. Get pose landmarks here.
                  }];

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

اگر فردی در تصویر شناسایی شود، میانای برنامه‌سازی کاربردی تشخیص حالت یا آرایه‌ای از اشیای Pose را به گرداننده تکمیل ارسال می‌کند یا آرایه را برمی‌گرداند، بسته به اینکه روش ناهمگام یا همگام را فراخوانی کرده باشید.

اگر فرد کاملاً داخل تصویر نباشد، مدل مختصات نقاط عطف گم‌شده را خارج از قاب اختصاص می‌دهد و به آن‌ها مقادیر InFrameConfidence پایینی می‌دهد.

اگر هیچ فردی شناسایی نشود، آرایه خالی است.

Swift

for pose in detectedPoses {
  let leftAnkleLandmark = pose.landmark(ofType: .leftAnkle)
  if leftAnkleLandmark.inFrameLikelihood > 0.5 {
    let position = leftAnkleLandmark.position
  }
}

آبجکتیو-سی

for (MLKPose *pose in detectedPoses) {
  MLKPoseLandmark *leftAnkleLandmark =
      [pose landmarkOfType:MLKPoseLandmarkTypeLeftAnkle];
  if (leftAnkleLandmark.inFrameLikelihood > 0.5) {
    MLKVision3DPoint *position = leftAnkleLandmark.position;
  }
}

نکته‌هایی برای بهبود عملکرد

کیفیت نتایج شما به کیفیت تصویر ورودی بستگی دارد:

  • برای اینکه ML Kit بتواند حالت را به‌درستی تشخیص دهد، فرد موجود در تصویر باید با داده‌های پیکسلی کافی نشان داده شود؛ برای بهترین عملکرد، سوژه باید حداقل ۲۵۶×۲۵۶ پیکسل باشد.
  • اگر در برنامه‌ای هم‌زمان حالت را تشخیص می‌دهید، ممکن است بخواهید ابعاد کلی تصاویر ورودی را نیز درنظر بگیرید. تصاویر کوچک‌تر سریع‌تر پردازش می‌شوند، بنابراین برای کاهش تأخیر، تصاویر را با وضوح پایین‌تر ثبت کنید، اما الزامات وضوح بالا را درنظر داشته باشید و مطمئن شوید که سوژه تا حد امکان بخش بیشتری از تصویر را اشغال می‌کند.
  • تمرکز ضعیف تصویر نیز می‌تواند بر دقت تأثیر بگذارد. اگر نتایج قابل‌قبولی دریافت نکردید، از کاربر بخواهید تصویر را دوباره بگیرد.

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

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

مراحل بعدی