اكتشاف الكائنات وتتبعها باستخدام ML Kit على نظام iOS

يمكنك استخدام ML Kit لاكتشاف الكائنات وتتبعها عبر إطارات الفيديو.

عندما تقوم بتمرير صور ML Kit، تقوم ML Kit بإرجاع قائمة تضم ما يصل إلى خمسة كائنات مكتشفة وموضعها في الصورة لكل صورة. عند اكتشاف كائنات في تدفقات الفيديو، يكون لكل كائن معرف يمكنك استخدامه لتتبع الكائن عبر الصور. يمكنك أيضًا تمكين تصنيف الكائنات الخشنة اختياريًا، والذي يقوم بتسمية الكائنات بأوصاف فئات واسعة.

قبل ان تبدأ

  1. إذا لم تكن قد أضفت Firebase إلى تطبيقك بالفعل، فقم بذلك باتباع الخطوات الواردة في دليل البدء .
  2. قم بتضمين مكتبات ML Kit في ملف Podfile الخاص بك:
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionObjectDetection', '6.25.0'
    
    بعد تثبيت أو تحديث Pods لمشروعك، تأكد من فتح مشروع Xcode الخاص بك باستخدام .xcworkspace .
  3. في تطبيقك، قم باستيراد Firebase:

    سويفت

    import Firebase

    ج موضوعية

    @import Firebase;

1. قم بتكوين كاشف الكائنات

لبدء اكتشاف الكائنات وتتبعها، قم أولاً بإنشاء مثيل VisionObjectDetector ، مع تحديد أي إعدادات كاشف تريد تغييرها بشكل اختياري عن الإعدادات الافتراضية.

  1. قم بتكوين كاشف الكائنات لحالة الاستخدام الخاصة بك باستخدام كائن VisionObjectDetectorOptions . يمكنك تغيير الإعدادات التالية:

    إعدادات كاشف الكائنات
    وضع الكشف .stream (افتراضي) | .singleImage

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

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

    كشف وتتبع كائنات متعددة false (افتراضي) | true

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

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

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

    تم تحسين واجهة برمجة التطبيقات (API) للكشف عن الكائنات وتتبعها لحالتي الاستخدام الأساسيتين التاليتين:

    • كشف وتتبع مباشر للكائن الأبرز في عدسة الكاميرا
    • الكشف عن كائنات متعددة في صورة ثابتة

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

    سويفت

    // Live detection and tracking
    let options = VisionObjectDetectorOptions()
    options.detectorMode = .stream
    options.shouldEnableMultipleObjects = false
    options.shouldEnableClassification = true  // Optional
    
    // Multiple object detection in static images
    let options = VisionObjectDetectorOptions()
    options.detectorMode = .singleImage
    options.shouldEnableMultipleObjects = true
    options.shouldEnableClassification = true  // Optional
    

    ج موضوعية

    // Live detection and tracking
    FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init];
    options.detectorMode = FIRVisionObjectDetectorModeStream;
    options.shouldEnableMultipleObjects = NO;
    options.shouldEnableClassification = YES;  // Optional
    
    // Multiple object detection in static images
    FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init];
    options.detectorMode = FIRVisionObjectDetectorModeSingleImage;
    options.shouldEnableMultipleObjects = YES;
    options.shouldEnableClassification = YES;  // Optional
    
  2. احصل على مثيل لـ FirebaseVisionObjectDetector :

    سويفت

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

    ج موضوعية

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

2. قم بتشغيل كاشف الأشياء

لاكتشاف الكائنات وتتبعها، قم بما يلي لكل صورة أو إطار فيديو. إذا قمت بتمكين وضع الدفق، فيجب عليك إنشاء كائنات VisionImage من CMSampleBufferRef s.

  1. قم بإنشاء كائن VisionImage باستخدام UIImage أو CMSampleBufferRef .

    لاستخدام UIImage :

    1. إذا لزم الأمر، قم بتدوير الصورة بحيث تكون خاصية imageOrientation الخاصة بها هي .up .
    2. قم بإنشاء كائن VisionImage باستخدام UIImage الذي تم تدويره بشكل صحيح. لا تحدد أي بيانات تعريف للتدوير — يجب استخدام القيمة الافتراضية، .topLeft .

      سويفت

      let image = VisionImage(image: uiImage)

      ج موضوعية

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    لاستخدام CMSampleBufferRef :

    1. قم بإنشاء كائن VisionImageMetadata الذي يحدد اتجاه بيانات الصورة الموجودة في المخزن المؤقت CMSampleBufferRef .

      للحصول على اتجاه الصورة:

      سويفت

      func imageOrientation(
          deviceOrientation: UIDeviceOrientation,
          cameraPosition: AVCaptureDevice.Position
          ) -> VisionDetectorImageOrientation {
          switch deviceOrientation {
          case .portrait:
              return cameraPosition == .front ? .leftTop : .rightTop
          case .landscapeLeft:
              return cameraPosition == .front ? .bottomLeft : .topLeft
          case .portraitUpsideDown:
              return cameraPosition == .front ? .rightBottom : .leftBottom
          case .landscapeRight:
              return cameraPosition == .front ? .topRight : .bottomRight
          case .faceDown, .faceUp, .unknown:
              return .leftTop
          }
      }

      ج موضوعية

      - (FIRVisionDetectorImageOrientation)
          imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                                 cameraPosition:(AVCaptureDevicePosition)cameraPosition {
        switch (deviceOrientation) {
          case UIDeviceOrientationPortrait:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationLeftTop;
            } else {
              return FIRVisionDetectorImageOrientationRightTop;
            }
          case UIDeviceOrientationLandscapeLeft:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationBottomLeft;
            } else {
              return FIRVisionDetectorImageOrientationTopLeft;
            }
          case UIDeviceOrientationPortraitUpsideDown:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationRightBottom;
            } else {
              return FIRVisionDetectorImageOrientationLeftBottom;
            }
          case UIDeviceOrientationLandscapeRight:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationTopRight;
            } else {
              return FIRVisionDetectorImageOrientationBottomRight;
            }
          default:
            return FIRVisionDetectorImageOrientationTopLeft;
        }
      }

      ثم قم بإنشاء كائن بيانات التعريف:

      سويفت

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      ج موضوعية

      FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
      AVCaptureDevicePosition cameraPosition =
          AVCaptureDevicePositionBack;  // Set to the capture device you used.
      metadata.orientation =
          [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                       cameraPosition:cameraPosition];
    2. قم بإنشاء كائن VisionImage باستخدام كائن CMSampleBufferRef وبيانات تعريف التدوير:

      سويفت

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      ج موضوعية

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  2. قم بتمرير VisionImage إلى إحدى طرق معالجة الصور الخاصة بجهاز كشف الكائنات. يمكنك إما استخدام طريقة process(image:) أو طريقة results() .

    لاكتشاف الكائنات بشكل غير متزامن:

    سويفت

    objectDetector.process(image) { detectedObjects, error in
      guard error == nil else {
        // Error.
        return
      }
      guard let detectedObjects = detectedObjects, !detectedObjects.isEmpty else {
        // No objects detected.
        return
      }
    
      // Success. Get object info here.
      // ...
    }
    

    ج موضوعية

    [objectDetector processImage:image
                      completion:^(NSArray<FIRVisionObject *> * _Nullable objects,
                                   NSError * _Nullable error) {
                        if (error == nil) {
                          return;
                        }
                        if (objects == nil | objects.count == 0) {
                          // No objects detected.
                          return;
                        }
    
                        // Success. Get object info here.
                        // ...
                      }];
    

    للكشف عن الكائنات بشكل متزامن:

    سويفت

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

    ج موضوعية

    NSError *error;
    NSArray<FIRVisionObject *> *objects = [objectDetector resultsInImage:image
                                                                   error:&error];
    if (error == nil) {
      return;
    }
    if (objects == nil | objects.count == 0) {
      // No objects detected.
      return;
    }
    
    // Success. Get object info here.
    // ...
    
  3. إذا نجح استدعاء معالج الصور، فإنه يقوم إما بتمرير قائمة VisionObject إلى معالج الإكمال أو إرجاع القائمة، اعتمادًا على ما إذا كنت قد قمت باستدعاء الطريقة غير المتزامنة أو المتزامنة.

    يحتوي كل VisionObject على الخصائص التالية:

    frame CGRect يشير إلى موضع الكائن في الصورة.
    trackingID عدد صحيح يحدد الكائن عبر الصور. لا شيء في وضع الصورة الواحدة.
    classificationCategory الفئة الخشنة للكائن. إذا لم يتم تمكين التصنيف في كاشف الكائنات، فسيكون هذا دائمًا .unknown .
    confidence قيمة الثقة لتصنيف الكائنات. إذا لم يتم تمكين التصنيف في كاشف الكائنات، أو تم تصنيف الكائن على أنه غير معروف، فهذا nil .

    سويفت

    // detectedObjects contains one item if multiple object detection wasn't enabled.
    for obj in detectedObjects {
      let bounds = obj.frame
      let id = obj.trackingID
    
      // If classification was enabled:
      let category = obj.classificationCategory
      let confidence = obj.confidence
    }
    

    ج موضوعية

    // The list of detected objects contains one item if multiple
    // object detection wasn't enabled.
    for (FIRVisionObject *obj in objects) {
      CGRect bounds = obj.frame;
      if (obj.trackingID) {
        NSInteger id = obj.trackingID.integerValue;
      }
    
      // If classification was enabled:
      FIRVisionObjectCategory category = obj.classificationCategory;
      float confidence = obj.confidence.floatValue;
    }
    

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

للحصول على أفضل تجربة للمستخدم، اتبع هذه الإرشادات في تطبيقك:

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

يمكنك أيضًا الاطلاع على [تطبيق عرض ML Kit Material Design][showcase-link]{: .external } وأنماط التصميم متعدد الأبعاد لمجموعة الميزات التي تدعم التعلم الآلي .

عند استخدام وضع البث في تطبيق في الوقت الفعلي، اتبع هذه الإرشادات لتحقيق أفضل معدلات الإطارات:

  • لا تستخدم اكتشاف الكائنات المتعددة في وضع البث، حيث لن تتمكن معظم الأجهزة من إنتاج معدلات إطارات كافية.

  • قم بتعطيل التصنيف إذا لم تكن بحاجة إليه.

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