رصد الأوضاع باستخدام أدوات تعلّم الآلة على نظام التشغيل iOS

توفّر حزمة تعلّم الآلة حزمتَي تطوير برامج (SDK) محسّنتَين لرصد الوضعيات.

اسم حزمة تطوير البرامج (SDK)PoseDetectionPoseDetectionAccurate
التنفيذيتم ربط مواد العرض الخاصة بأداة رصد الأخطاء الأساسية بتطبيقك بشكل ثابت في مدّة التصميم.يتم ربط مواد العرض الخاصة بأداة الرصد الدقيقة بتطبيقك بشكل ثابت في مدّة التصميم.
حجم التطبيقحتى 29.6 ميغابايتحتى 33.2 ميغابايت
الأداءiPhone X: ~45FPSiPhone X: ~29FPS

للتجربة:

  • يمكنك تجربة التطبيق النموذجي للاطّلاع على مثال على كيفية استخدام واجهة برمجة التطبيقات هذه.

قبل البدء

  1. أدرِج مجموعات حزمة تعلّم الآلة التالية في ملف 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 مع الإصدار 13.2.1 من Xcode أو الإصدارات الأحدث.

1. إنشاء مثيل من 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

Objective-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. مرِّر الخيارات التي حدّدتها:

Swift

let poseDetector = PoseDetector.poseDetector(options: options)

Objective-C

MLKPoseDetector *poseDetector =
    [MLKPoseDetector poseDetectorWithOptions:options];

2. إعداد الصورة المصدر

لاكتشاف الوضعيات، اتّبِع الخطوات التالية لكل صورة أو إطار فيديو. إذا فعّلت وضع البث، عليك إنشاء عناصر VisionImage من CMSampleBuffer.

أنشئ عنصر VisionImage باستخدام UIImage أو CMSampleBuffer.

إذا كنت تستخدم UIImage، اتّبِع الخطوات التالية:

  • أنشئ عنصر VisionImage باستخدام UIImage. احرص على تحديد .orientation الصحيح.

    Swift

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

    Objective-C

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

    Objective-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 والاتجاه:

    Swift

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

    Objective-C

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

3- معالجة الصورة

مرِّر 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.

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

لرصد العناصر بشكل غير متزامن، اتّبِع الخطوات التالية:

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

Objective-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. الحصول على معلومات حول الوضعية التي تم رصدها

في حال رصد شخص في الصورة، ستمرِّر واجهة برمجة التطبيقات الخاصة برصد الوضعية مصفوفة من عناصر Pose إلى معالج الإكمال أو ستعرض المصفوفة، وذلك حسب ما إذا كنت قد استدعيت الطريقة غير المتزامنة أو المتزامنة.

إذا لم يكن الشخص بالكامل داخل الصورة، يحدّد النموذج إحداثيات المعالم غير الظاهرة خارج الإطار ويمنحها قيم InFrameConfidence منخفضة.

إذا لم يتم رصد أي شخص، ستكون المصفوفة فارغة.

Swift

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

Objective-C

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

نصائح لتحسين الأداء

تعتمد جودة النتائج على جودة الصورة المُدخَلة:

  • لكي ترصد حزمة تعلّم الآلة الوضعية بدقة، يجب أن تتضمّن الصورة بيانات بكسل كافية للشخص، ولتحقيق أفضل أداء، يجب أن يكون حجم العنصر 256x256 بكسل على الأقل.
  • إذا كنت ترصد الوضعيات في تطبيق يعمل في الوقت الفعلي، قد تحتاج أيضًا إلى مراعاة الأبعاد الإجمالية لصور الإدخال. يمكن معالجة الصور الأصغر حجمًا بشكل أسرع، لذا لتقليل وقت الاستجابة، التقط صورًا بدقة أقل، ولكن ضع في اعتبارك متطلبات الدقة المذكورة أعلاه وتأكَّد من أنّ العنصر يملأ أكبر قدر ممكن من الصورة.
  • يمكن أن يؤثر عدم وضوح الصورة أيضًا في الدقة. إذا لم تحصل على نتائج مقبولة، اطلب من المستخدم إعادة التقاط الصورة.

إذا كنت تريد استخدام ميزة "رصد الوضعيات" في تطبيق يعمل في الوقت الفعلي، اتّبِع الإرشادات التالية للحصول على أفضل معدّلات عرض اللقطات:

  • استخدِم حزمة تطوير البرامج (SDK) الأساسية الخاصة بخدمة PoseDetection ووضع الرصد stream.
  • ننصحك بالتقاط الصور بدقة أقل. ومع ذلك، ضَع في اعتبارك أيضًا متطلبات أبعاد الصورة في واجهة برمجة التطبيقات هذه.
  • لمعالجة لقطات الفيديو، استخدِم واجهة برمجة التطبيقات المتزامنة results(in:) الخاصة بأداة الكشف. استدعِ هذه الطريقة من الدالة captureOutput(_, didOutput:from:) الخاصة بـ AVCaptureVideoDataOutputSampleBufferDelegate للحصول على النتائج بشكل متزامن من إطار الفيديو المحدّد. اضبط قيمة alwaysDiscardsLateVideoFrames في AVCaptureVideoDataOutput على true للحدّ من عدد طلبات البيانات إلى أداة الرصد. إذا أصبح إطار فيديو جديد متاحًا أثناء تشغيل أداة الرصد، سيتم تجاهله.
  • إذا كنت تستخدم ناتج أداة رصد الوجوه لتراكب الرسومات على صورة الإدخال، احصل أولاً على النتيجة من حزمة تعلّم الآلة، ثم اعرض الصورة والتراكب في خطوة واحدة. وبذلك، يتم العرض على سطح الشاشة مرة واحدة فقط لكل إطار إدخال تمت معالجته. يمكنك الاطّلاع على الفئتين previewOverlayView و MLKDetectionOverlayView في تطبيق العرض التوضيحي النموذجي للحصول على مثال.

الخطوات التالية