رصد العناصر وتتبعها باستخدام ML Kit على نظام التشغيل iOS

يمكنك استخدام أدوات تعلّم الآلة لرصد العناصر وتتبّعها في إطارات الفيديو المتتالية.

عند تمرير صورة إلى أدوات تعلّم الآلة، ترصد هذه الأداة ما يصل إلى خمسة عناصر في الصورة بالإضافة إلى موضع كل عنصر في الصورة. وعند رصد العناصر في الفيديوهات المضمّنة، يكون لكل عنصر معرّف فريد يمكنك استخدامه لتتبُّع العنصر من إطار إلى آخر. يمكنك أيضًا تفعيل التصنيف التقريبي للعناصر بشكل اختياري، والذي يصنِّف العناصر ذات الأوصاف العامة للفئات.

تجربة السمات والبيانات

قبل البدء

  1. أدرِج مجموعات تعلّم الآلة التالية في Podfile:
    pod 'GoogleMLKit/ObjectDetection', '3.2.0'
    
  2. بعد تثبيت أو تحديث مجموعات Pods لمشروعك، افتح مشروع Xcode باستخدام .xcworkspace. تتوفّر هذه الأداة في الإصدار 12.4 من Xcode أو إصدار أحدث.

1- ضبط أداة رصد الكائنات

لرصد العناصر وتتبّعها، أنشئ أولاً مثيلاً من ObjectDetector ويمكنك اختياريًا تحديد أي إعدادات أداة رصد تريد تغييرها من الإعدادات التلقائية.

  1. اضبط أداة رصد الكائنات لحالة الاستخدام الخاصة بك باستخدام كائن ObjectDetectorOptions. يمكنك تغيير الإعدادات التالية:

    إعدادات أداة رصد العناصر
    وضع الرصد .stream (الخيار التلقائي) | .singleImage

    في وضع البث (التلقائي)، تعمل أداة رصد الكائنات بوقت استجابة منخفض جدًا، ولكنها قد تؤدي إلى نتائج غير مكتملة (مثل فئات أو مربّعات حدود غير محدّدة) عند استدعاءات أداة الرصد القليلة الأولى. في وضع البث أيضًا، تعيّن أداة الرصد أرقام تعريف تتبُّع للعناصر، والتي يمكنك استخدامها لتتبُّع العناصر على مستوى الإطارات. استخدِم هذا الوضع عندما تريد تتبُّع العناصر أو عندما يكون من المهم أن يكون وقت الاستجابة طويلاً، كما هو الحال عند معالجة عمليات بث الفيديوهات في الوقت الفعلي.

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

    رصد عناصر متعددة وتتبّعها false (الخيار التلقائي) | true

    لتحديد ما إذا كنت تريد اكتشاف وتتبع ما يصل إلى خمسة عناصر أو العنصر الأكثر بروزًا فقط (تلقائي).

    تصنيف الكائنات false (الخيار التلقائي) | true

    تحديد ما إذا كان سيتم تصنيف العناصر المكتشفة في فئات تقريبية أم لا. عند تفعيل هذه الميزة، تصنّف أداة رصد الأجسام الأجسام ضمن الفئات التالية: سلع الأزياء والطعام والسلع المنزلية والأماكن والنباتات.

    ويتم تحسين واجهة برمجة التطبيقات الخاصة برصد الكائنات وتتبّعها لحالة الاستخدام الأساسية التالية:

    • الرصد المباشر لأبرز العناصر في عدسة الكاميرا وتتبّعها
    • يشير ذلك المصطلح إلى رصد عناصر متعددة في صورة ثابتة.

    لضبط واجهة برمجة التطبيقات لحالات الاستخدام هذه:

Swift

// Live detection and tracking
let options = ObjectDetectorOptions()
options.shouldEnableClassification = true

// Multiple object detection in static images
let options = ObjectDetectorOptions()
options.detectorMode = .singleImage
options.shouldEnableMultipleObjects = true
options.shouldEnableClassification = true

Objective-C

// Live detection and tracking
MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init];
options.shouldEnableClassification = YES;

// Multiple object detection in static images
MLKObjectDetectorOptions *options = [[MLKOptions alloc] init];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableMultipleObjects = YES;
options.shouldEnableClassification = YES;
  1. الحصول على مثيل من ObjectDetector:

Swift

let objectDetector = ObjectDetector.objectDetector()

// Or, to change the default settings:
let objectDetector = ObjectDetector.objectDetector(options: options)

Objective-C

MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector];

// Or, to change the default settings:
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];

2. تحضير صورة الإدخال

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

أنشِئ عنصر 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

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

  // Success. Get object info here.
  // ...
}

Objective-C

[objectDetector processImage:image
                  completion:^(NSArray * _Nullable objects,
                               NSError * _Nullable error) {
                    if (error == nil) {
                      return;
                    }
                    if (objects.count == 0) {
                      // No objects detected.
                      return;
                    }

                    // Success. Get object info here.
                  }];

لاكتشاف العناصر في آن واحد:

Swift

var objects: [Object]
do {
  objects = try objectDetector.results(in: image)
} catch let error {
  print("Failed to detect object with error: \(error.localizedDescription).")
  return
}
guard !objects.isEmpty else {
  print("Object detector returned no results.")
  return
}

// Success. Get object info here.

Objective-C

NSError *error;
NSArray *objects = [objectDetector resultsInImage:image error:&error];
if (error == nil) {
  return;
}
if (objects.count == 0) {
  // No objects detected.
  return;
}

// Success. Get object info here.

4. الحصول على معلومات حول العناصر التي تم رصدها

إذا نجح طلب معالج الصور، يتم تمرير قائمة Object إلى معالج الإكمال أو عرض القائمة، بناءً على ما إذا كنت قد استدعيت الطريقة غير المتزامنة أو المتزامنة.

يحتوي كل Object على السمات التالية:

frame تمثّل هذه السمة CGRect للإشارة إلى موضع العنصر في الصورة.
trackingID عدد صحيح يعرّف الكائن في الصور، أو "nil" في وضع الصورة الواحدة.
labels مصفوفة من التصنيفات تصف العنصر الذي تعرضه أداة الرصد. وتكون الخاصية فارغة في حال ضبط خيار أداة الرصد shouldEnableClassification على false.

Swift

// objects contains one item if multiple object detection wasn't enabled.
for object in objects {
  let frame = object.frame
  let trackingID = object.trackingID

  // If classification was enabled:
  let description = object.labels.enumerated().map { (index, label) in
    "Label \(index): \(label.text), \(label.confidence)"
    }.joined(separator:"\n")

}

Objective-C

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (MLKObject *object in objects) {
  CGRect frame = object.frame;
  NSNumber *trackingID = object.trackingID;
  for (MLKObjectLabel *label in object.labels) {
    NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu",
      label.text, label.confidence, (unsigned long)label.index];
    ...
  }
}

تحسين سهولة الاستخدام والأداء

لأفضل تجربة مستخدم، يُرجى اتّباع الإرشادات التالية في تطبيقك:

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

ويمكنك أيضًا التحقق من مجموعة أنماط الميزات المستندة إلى تعلُم الآلة في التصميم المتعدد الأبعاد.

عند استخدام وضع البث في تطبيق الوقت الفعلي، يُرجى اتّباع الإرشادات التالية لتحقيق أفضل عدد من اللقطات:

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