تشخیص دادن ژست‌ها با 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. پس‌از نصب یا به‌روزرسانی پادهای پروژه‌تان، پروژه Xcode را بااستفاده از xcworkspace آن باز کنید. ‫ML Kit در 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 استفاده می‌کنید، این مراحل را دنبال کنید:

  • با UIImage، شیء VisionImage ایجاد کنید. حتماً .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];

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

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

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

اگر فردی در تصویر تشخیص داده شود، API تشخیص ژست یا آرایه‌ای از 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:) آشکارساز استفاده کنید. این روش را از تابع AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) فراخوانی کنید تا نتایج را به‌صورت هم‌زمان از قاب ویدیو داده‌شده دریافت کنید. AVCaptureVideoDataOutput را با alwaysDiscardsLateVideoFrames روی درست تنظیم کنید تا تماس‌های برقرارشده با آشکارساز را محدود کنید. اگر قاب ویدیو جدیدی درحین اجرای آشکارساز دردسترس قرار گیرد، حذف خواهد شد.
  • اگر از برونداد آشکارساز برای رونهادن گرافیک روی تصویر ورودی استفاده می‌کنید، ابتدا نتیجه را از ML Kit دریافت کنید، سپس تصویر و رونهاد را در یک مرحله پردازش کنید. با انجام این کار، برای هر قاب ورودی پردازش‌شده، فقط یک‌بار به سطح نمایشگر رندر می‌کنید. برای دیدن نمونه، کلاس‌های previewOverlayView و MLKDetectionOverlayView را در برنامه نمونه ویترین مشاهده کنید.

مراحل بعدی