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

ML Kit دو SDK بهینه سازی شده برای تشخیص پوس ارائه می دهد.

نام SDK PoseDetection PoseDetectionAccurate
پیاده سازی دارایی‌های آشکارساز پایه به‌طور ایستا به برنامه شما در زمان ساخت مرتبط هستند. دارایی‌های ردیاب دقیق به صورت ایستا به برنامه شما در زمان ساخت مرتبط می‌شوند.
اندازه برنامه تا 29.6 مگابایت تا 33.2 مگابایت
عملکرد iPhone X: ~45FPS iPhone X: ~ 29FPS

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

قبل از شروع

  1. پادهای کیت ML زیر را در فایل پادفایل خود قرار دهید:

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

1. یک نمونه از PoseDetector ایجاد کنید

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

گزینه های PoseDetector

حالت تشخیص

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

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

گزینه های آشکارساز پوس را مشخص کنید:

سویفت

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

هدف-C

// 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 را دریافت کنید. گزینه هایی که مشخص کردید را پاس کنید:

سویفت

let poseDetector = PoseDetector.poseDetector(options: options)

هدف-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

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

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

با استفاده از 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. تصویر را پردازش کنید

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

برای تشخیص همزمان اشیا:

سویفت

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.

هدف-C

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.

برای تشخیص اشیاء به صورت ناهمزمان:

سویفت

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

هدف-C

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

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

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

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

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

سویفت

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

هدف-C

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

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

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

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

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

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

مراحل بعدی