رصد العناصر وتصنيفها وتصنيفها باستخدام نموذج تصنيف مخصّص على نظام التشغيل iOS

تنظيم صفحاتك في مجموعات يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
يمكنك استخدام مجموعة أدوات تعلّم الآلة لرصد الكائنات وتتبُّعها في إطارات الفيديو المتتالية.

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

يمكنك استخدام نموذج مخصّص لتصنيف الصور لتصنيف العناصر التي تم رصدها. يُرجى الرجوع إلى النماذج المخصّصة باستخدام ML Kit للحصول على إرشادات حول متطلبات التوافق مع النماذج، وأين يمكنك العثور على النماذج المدرَّبة مسبقًا، وكيفية تدريب نماذجك الخاصة.

هناك طريقتان لدمج نموذج مخصص. يمكنك تجميع النموذج عن طريق وضعه داخل مجلد مواد العرض لتطبيقك، أو يمكنك تنزيله ديناميكيًا من Firebase. يقارن الجدول التالي بين الخيارين.

نموذج مجمّع نموذج مستضاف
النموذج جزء من ملف .ipa لتطبيقك، مما يزيد من حجمه. النموذج ليس جزءًا من ملف .ipa لتطبيقك. تتم استضافتها من خلال تحميلها إلى Firebase Machine Learning.
يتوفّر النموذج على الفور حتى إذا كان جهاز Android غير متصل بالإنترنت. يتم تنزيل النموذج عند الطلب
لا حاجة لمشروع Firebase مطلوب مشروع Firebase
يجب إعادة نشر تطبيقك لتحديث النموذج نشر تحديثات النموذج بدون إعادة نشر تطبيقك
لا يوجد اختبار A/B مدمج إجراء اختبار أ/ب بسهولة باستخدام ميزة الإعداد عن بُعد في Firebase

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

قبل البدء

  1. تضمين مكتبات ML Kit في Podfile:

    لتجميع نموذج مع تطبيقك:

    pod 'GoogleMLKit/ObjectDetectionCustom', '3.2.0'
    

    لتنزيل نموذج ديناميكيًا من Firebase، أضف التبعية LinkFirebase:

    pod 'GoogleMLKit/ObjectDetectionCustom', '3.2.0'
    pod 'GoogleMLKit/LinkFirebase', '3.2.0'
    
  2. بعد تثبيت لوحات مفاتيح مشروعك أو تحديثها، افتح مشروع Xcode باستخدام .xcworkspace. ML Kit متوافق مع الإصدار 13.2.1 من Xcode أو إصدار أحدث.

  3. إذا كنت ترغب في تنزيل نموذج، فتأكد من إضافة Firebase إلى مشروع iOS، إذا لم تكن قد فعلت ذلك. هذا غير مطلوب عند تجميع النموذج.

1- تحميل النموذج

تهيئة مصدر نموذج محلي

لتجميع النموذج مع تطبيقك:

  1. انسخ ملف النموذج (الذي ينتهي عادةً بـ .tflite أو .lite) إلى مشروع Xcode، مع الحرص على اختيار Copy bundle resources عند تنفيذ ذلك. سيتم تضمين ملف النموذج في حزمة التطبيق، وسيكون متاحًا في ML Kit.

  2. إنشاء كائن LocalModel، مع تحديد المسار إلى ملف النموذج:

    Swift

    let localModel = LocalModel(path: localModelFilePath)

    Objective-C

    MLKLocalModel *localModel =
        [[MLKLocalModel alloc] initWithPath:localModelFilePath];

إعداد مصدر نموذج مستضاف على Firebase

لاستخدام النموذج المستضاف عن بُعد، أنشئ كائن CustomRemoteModel، مع تحديد الاسم الذي عينته للنموذج عند نشره:

Swift

let firebaseModelSource = FirebaseModelSource(
    name: "your_remote_model") // The name you assigned in
                               // the Firebase console.
let remoteModel = CustomRemoteModel(remoteModelSource: firebaseModelSource)

Objective-C

MLKFirebaseModelSource *firebaseModelSource =
    [[MLKFirebaseModelSource alloc]
        initWithName:@"your_remote_model"]; // The name you assigned in
                                            // the Firebase console.
MLKCustomRemoteModel *remoteModel =
    [[MLKCustomRemoteModel alloc]
        initWithRemoteModelSource:firebaseModelSource];

بعد ذلك، ابدأ مهمة تنزيل النموذج، مع تحديد الشروط التي تريد السماح بالتنزيل بموجبها. إذا لم يكن النموذج على الجهاز، أو إذا كان إصدار أحدث من النموذج متاحًا، فسيتم تنزيل النموذج من Firebase بشكل غير متزامن:

Swift

let downloadConditions = ModelDownloadConditions(
  allowsCellularAccess: true,
  allowsBackgroundDownloading: true
)

let downloadProgress = ModelManager.modelManager().download(
  remoteModel,
  conditions: downloadConditions
)

Objective-C

MLKModelDownloadConditions *downloadConditions =
    [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
                                         allowsBackgroundDownloading:YES];

NSProgress *downloadProgress =
    [[MLKModelManager modelManager] downloadModel:remoteModel
                                       conditions:downloadConditions];

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

2. ضبط أداة رصد الكائنات

بعد ضبط مصادر النموذج، يمكنك ضبط أداة رصد الكائنات لحالة الاستخدام باستخدام كائن CustomObjectDetectorOptions. يمكنك تغيير الإعدادات التالية:

إعدادات أداة كشف الكائنات
وضع الاكتشاف STREAM_MODE (تلقائي) | SINGLE_IMAGE_MODE

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

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

اكتشاف كائنات متعددة وتتبعها false (تلقائي) | true

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

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

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

الحد الأدنى لتصنيف التصنيف

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

الحد الأقصى للتصنيفات لكل كائن

الحد الأقصى لعدد التصنيفات لكل كائن ستعرضه أداة الكشف. وفي حال تم ترك السياسة بدون ضبط، سيتم استخدام القيمة التلقائية وهي 10.

إذا لم يكن لديك سوى نموذج مجمّع محليًا، فما عليك سوى إنشاء أداة رصد لكائن من الكائن LocalModel:

Swift

let options = CustomObjectDetectorOptions(localModel: localModel)
options.detectorMode = .singleImage
options.shouldEnableClassification = true
options.shouldEnableMultipleObjects = true
options.classificationConfidenceThreshold = NSNumber(value: 0.5)
options.maxPerObjectLabelCount = 3

Objective-C

MLKCustomObjectDetectorOptions *options =
    [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableClassification = YES;
options.shouldEnableMultipleObjects = YES;
options.classificationConfidenceThreshold = @(0.5);
options.maxPerObjectLabelCount = 3;

إذا كان لديك نموذج تتم استضافته عن بُعد، يجب عليك التحقق من أنه قد تم تنزيله قبل تشغيله. يمكنك التحقق من حالة مهمة تنزيل النموذج باستخدام طريقة مدير النموذج isModelDownloaded(remoteModel:).

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

Swift

var options: CustomObjectDetectorOptions!
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = CustomObjectDetectorOptions(remoteModel: remoteModel)
} else {
  options = CustomObjectDetectorOptions(localModel: localModel)
}
options.detectorMode = .singleImage
options.shouldEnableClassification = true
options.shouldEnableMultipleObjects = true
options.classificationConfidenceThreshold = NSNumber(value: 0.5)
options.maxPerObjectLabelCount = 3

Objective-C

MLKCustomObjectDetectorOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[MLKCustomObjectDetectorOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel];
}
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableClassification = YES;
options.shouldEnableMultipleObjects = YES;
options.classificationConfidenceThreshold = @(0.5);
options.maxPerObjectLabelCount = 3;

إذا لم يكن لديك سوى نموذج تتم استضافته عن بُعد، يجب تعطيل الوظائف ذات الصلة بالنموذج، على سبيل المثال، تعتيم جزء من واجهة المستخدم أو إخفاؤه - إلى أن تؤكد أنه تم تنزيل النموذج.

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

Swift

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidSucceed,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel,
        model.name == "your_remote_model"
        else { return }
    // The model was downloaded and is available on the device
}

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidFail,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel
        else { return }
    let error = userInfo[ModelDownloadUserInfoKey.error.rawValue]
    // ...
}

Objective-C

__weak typeof(self) weakSelf = self;

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel];
              if ([model.name isEqualToString:@"your_remote_model"]) {
                // The model was downloaded and is available on the device
              }
            }];

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidFailNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError];
            }];

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

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

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

Swift

// Live detection and tracking
let options = CustomObjectDetectorOptions(localModel: localModel)
options.shouldEnableClassification = true
options.maxPerObjectLabelCount = 3

// Multiple object detection in static images
let options = CustomObjectDetectorOptions(localModel: localModel)
options.detectorMode = .singleImage
options.shouldEnableMultipleObjects = true
options.shouldEnableClassification = true
options.maxPerObjectLabelCount = 3

Objective-C

// Live detection and tracking
MLKCustomObjectDetectorOptions *options =
    [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel];
options.shouldEnableClassification = YES;
options.maxPerObjectLabelCount = 3;

// Multiple object detection in static images
MLKCustomObjectDetectorOptions *options =
    [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableMultipleObjects = YES;
options.shouldEnableClassification = YES;
options.maxPerObjectLabelCount = 3;

3- إعداد صورة الإدخال

يمكنك إنشاء كائن 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];

4. إنشاء أداة رصد الكائنات وتشغيلها

  1. إنشاء أداة رصد عناصر جديدة:

    Swift

    let objectDetector = ObjectDetector.objectDetector(options: options)

    Objective-C

    MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
  2. بعد ذلك، استخدِم أداة الرصد:

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

    Swift

    objectDetector.process(image) { objects, error in
        guard error == nil, let objects = objects, !objects.isEmpty else {
            // Handle the error.
            return
        }
        // Show results.
    }

    Objective-C

    [objectDetector
        processImage:image
          completion:^(NSArray *_Nullable objects,
                       NSError *_Nullable error) {
            if (objects.count == 0) {
                // Handle the error.
                return;
            }
            // Show results.
         }];

    بشكل متزامن:

    Swift

    var objects: [Object]
    do {
        objects = try objectDetector.results(in: image)
    } catch let error {
        // Handle the error.
        return
    }
    // Show results.

    Objective-C

    NSError *error;
    NSArray *objects =
        [objectDetector resultsInImage:image error:&error];
    // Show results or handle the error.

5- الحصول على معلومات حول الكائنات المصنّفة

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

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

frame تمثل هذه الخاصية CGRect موضع الكائن في الصورة.
trackingID عدد صحيح يعرّف الكائن عبر الصور، أو `nil` في SINGLE_IMAGE_MODE.
labels
label.text تمثل هذه الخاصية الوصف النصي للتصنيف. لا يتم عرضه إلا إذا كانت البيانات الوصفية لنموذج TensorFlow Lite تحتوي على أوصاف تصنيفات.
label.index فهرس التصنيفات ضمن جميع التصنيفات المتوافقة مع المصنِّف.
label.confidence قيمة الثقة لتصنيف الكائن.

Swift

// objects contains one item if multiple object detection wasn't enabled.
for object in objects {
  let frame = object.frame
  let trackingID = object.trackingID
  let description = object.labels.enumerated().map { (index, label) in
    "Label \(index): \(label.text), \(label.confidence), \(label.index)"
  }.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];
  }
}

ضمان تقديم تجربة رائعة للمستخدم

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

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

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

Improving performance

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

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

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