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

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

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

جرّبه الآن

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

قبل البدء

  1. أدرِج مجموعات الإعلانات المتسلسلة التالية من ML Kit في ملف Podfile:

    # If you want to use the base implementation:
    pod 'GoogleMLKit/PoseDetection', '7.0.0'
    
    # If you want to use the accurate implementation:
    pod 'GoogleMLKit/PoseDetectionAccurate', '7.0.0'
    
  2. بعد تثبيت وحدات pod في مشروعك أو تعديلها، افتح مشروع 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;
  }
}

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

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

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

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

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

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