دليل تصنيف الصور لنظام التشغيل iOS

تتيح لك مهمة "مصنِّف الصور" تصنيف الصور. يمكنك استخدام هذه المهمة لتحديد ما تمثله الصورة بين مجموعة من الفئات المحددة في وقت التدريب. توضّح لك هذه التعليمات كيفية استخدام "مصنِّف الصور" في تطبيقات iOS. يتوفّر نموذج الرمز البرمجي الموضّح في هذه التعليمات على GitHub.

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

مثال على الرمز البرمجي

رمز مثال "مهام MediaPipe" هو تنفيذ أساسي لتطبيق "مصنِّف الصور" على نظام التشغيل iOS. يستخدم المثال الكاميرا الموجودة على جهاز iOS لتصنيف الكائنات بشكل مستمر، ويمكن أيضًا استخدام الصور والفيديوهات من معرض الأجهزة لتصنيف الكائنات بشكل ثابت.

يمكنك استخدام التطبيق كنقطة بداية لتطبيق iOS أو الرجوع إليه عند تعديل تطبيق حالي. تتم استضافة رمز المثال عن أداة تصنيف الصور على GitHub.

تنزيل الرمز

توضّح لك التعليمات التالية كيفية إنشاء نسخة محلية من نموذج الرمز باستخدام أداة سطر الأوامر git.

لتنزيل نموذج الرمز:

  1. استنساخ مستودع git باستخدام الأمر التالي:

    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. اختياريًا، يمكنك ضبط مثيل git لاستخدام عملية دفع متفرقة، بحيث لا يكون لديك سوى الملفات الخاصة بالتطبيق التجريبي Image Classifier:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_classification/ios/
    

بعد إنشاء نسخة محلية من نموذج الرمز البرمجي، يمكنك تثبيت مكتبة مهام MediaPipe وفتح المشروع باستخدام Xcode وتشغيل التطبيق. وللحصول على التعليمات، يُرجى الاطّلاع على دليل الإعداد لنظام التشغيل iOS.

المكوّنات الرئيسية

تحتوي الملفات التالية على الرمز المهمّ لتطبيق "مصنِّف الصور" كمثال:

  • ImageClassifierService.swift: ينفّذ مصنِّف الصور هذا ويعالج اختيار النموذج ثم يجري الاستنتاج على بيانات الإدخال.
  • CameraViewController.swift: لتنفيذ واجهة المستخدم لوضع إدخال خلاصة الكاميرا المباشرة وعرض النتائج بيانيًا.
  • MediaLibraryViewController.swift لتنفيذ واجهة المستخدم لوضع إدخال ملفات الفيديو والصور الثابتة وعرض النتائج بشكل مرئي.

ضبط إعدادات الجهاز

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

التبعيات

يستخدم مصنِّف الصور مكتبة MediaPipeTasksVision التي يجب تثبيتها باستخدام CocoaPods. وتتوافق المكتبة مع تطبيقي Swift وObjective-C ولا تتطلب أي إعداد إضافي بلغة محدّدة.

للحصول على تعليمات حول تثبيت CocoaPods على نظام التشغيل macOS، يُرجى الرجوع إلى دليل تثبيت CocoaPods. للحصول على تعليمات عن كيفية إنشاء Podfile باستخدام المجموعات المتسلسلة اللازمة لتطبيقك، راجِع المقالة استخدام CocoaPods.

أضِف لوحة MediaPipeTasksVision في Podfile باستخدام الرمز التالي:

target 'MyImageClassifierApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

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

الطراز

تتطلب مهمة مصنِّف صور MediaPipe نموذجًا مدرّبًا ومتوافقًا مع هذه المهمة. للحصول على مزيد من المعلومات حول النماذج المدرَّبة المتاحة في "مصنِّف الصور"، يمكنك الاطّلاع على قسم النماذج في قسم "نظرة عامة" على المهمة.

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

استخدِم السمة BaseOptions.modelAssetPath لتحديد مسار النموذج في حِزمة تطبيقك. للاطّلاع على مثال على الرمز البرمجي، يُرجى مراجعة القسم التالي.

إنشاء المهمة

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

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

تتوافق مهمة "مصنِّف الصور" مع 3 أنواع من بيانات الإدخال: الصور الثابتة وملفات الفيديو وبث الفيديو المباشر. وفقًا للإعدادات التلقائية، بإمكان ImageClassifier(modelPath:) إعداد مهمة للصور الثابتة. إذا كنت تريد إعداد مهمتك لمعالجة ملفات الفيديو أو أحداث بث الفيديو المباشر، استخدِم ImageClassifier(options:) لتحديد وضع تشغيل الفيديو أو البث المباشر. يتطلّب وضع البث المباشر أيضًا خيار إعداد "imageClassifierLiveStreamDelegate" الإضافي، الذي يتيح "مصنِّف الصور" عرض نتائج تصنيف الصور إلى المستخدم المفوَّض بشكل غير متزامن.

اختَر علامة التبويب المقابلة لوضع الجري لمعرفة كيفية إنشاء المهمة وتنفيذ الاستنتاج.

Swift

صورة

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageClassifierOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.maxResults = 5

let imageClassifier = try ImageClassifier(options: options)
    

فيديو

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageClassifierOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.maxResults = 5

let imageClassifier = try ImageClassifier(options: options)
    

أحداث بث مباشر

import MediaPipeTasksVision

// Class that conforms to the `ImageClassifierLiveStreamDelegate` protocol and
// implements the method that the image classifier calls once it
// finishes performing classification on each input frame.
class ImageClassifierResultProcessor: NSObject, ImageClassifierLiveStreamDelegate {

   func imageClassifier(
    _ imageClassifier: ImageClassifier,
    didFinishClassification result: ImageClassifierResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the image classifier result or errors here.

  }
}

let modelPath = Bundle.main.path(
  forResource: "model",
  ofType: "tflite")

let options = ImageClassifierOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.maxResults = 5

// Assign an object of the class to the `imageClassifierLiveStreamDelegate`
// property.
let processor = ImageClassifierResultProcessor()
options.imageClassifierLiveStreamDelegate = processor

let imageClassifier = try ImageClassifier(options: options)
    

Objective-C

صورة

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.maxResults = 5;

MPPImageClassifier *imageClassifier =
      [[MPPImageClassifier alloc] initWithOptions:options error:nil];
    

فيديو

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.maxResults = 5;

MPPImageClassifier *imageClassifier =
      [[MPPImageClassifier alloc] initWithOptions:options error:nil];
    

أحداث بث مباشر

@import MediaPipeTasksVision;

// Class that conforms to the `MPPImageClassifierLiveStreamDelegate` protocol
// and implements the method that the image classifier calls once it finishes
// performing classification on each input frame.

@interface APPImageClassifierResultProcessor : NSObject 

@end

@implementation APPImageClassifierResultProcessor

-   (void)imageClassifier:(MPPImageClassifier *)imageClassifier
    didFinishClassificationWithResult:(MPPImageClassifierResult *)imageClassifierResult
              timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                                error:(NSError *)error {

    // Process the image classifier result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.maxResults = 5;

// Assign an object of the class to the `imageClassifierLiveStreamDelegate`
// property.
APPImageClassifierResultProcessor *processor = [APPImageClassifierResultProcessor new];
options.imageClassifierLiveStreamDelegate = processor;

MPPImageClassifier *imageClassifier =
      [[MPPImageClassifier alloc] initWithOptions:options error:nil];
    

خيارات الإعداد

تتضمّن هذه المهمة خيارات الضبط التالية لتطبيقات iOS:

اسم الخيار الوصف نطاق القيمة القيمة التلقائية
runningMode لضبط وضع التشغيل للمهمة. هناك ثلاثة أوضاع:

IMAGE: هو الوضع الخاص بإدخالات الصور الفردية.

الفيديو: وضع الإطارات التي تم فك ترميزها في فيديو

LIVE_STREAM: وضع البث المباشر لبيانات الإدخال، مثل الكاميرا. في هذا الوضع، يجب استدعاء كائن resultsListener لإعداد أداة استماع لتلقّي النتائج بشكل غير متزامن.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
displayNamesLocale لضبط لغة التصنيفات المراد استخدامها للأسماء المعروضة المقدمة في البيانات الوصفية لنموذج المهمة، إذا كانت متوفرة. اللغة التلقائية هي en للغة الإنجليزية. يمكنك إضافة تصنيفات مترجَمة إلى البيانات الوصفية لنموذج مخصّص باستخدام TensorFlow Lite Metadata Writer API. رمز اللغة en
maxResults تحدد الحد الأقصى الاختياري لنتائج تصنيف أعلى الدرجات لعرضها. وإذا كانت < 0، سيتم عرض جميع النتائج المتاحة. أي أرقام موجبة -1
scoreThreshold لتعيين الحد الأدنى لنتيجة التوقعات الذي يلغي الحد المقدم في البيانات الوصفية للنموذج (إن وُجد). يتم رفض النتائج التي تكون أدنى من هذه القيمة. أي عدد عائم لم يتم التحديد
categoryAllowlist تضبط هذه السياسة القائمة الاختيارية لأسماء الفئات المسموح بها. إذا كانت غير فارغة، فستتم تصفية نتائج التصنيف التي لا يوجد اسم الفئة لها في هذه المجموعة. ويتم تجاهل أسماء الفئات المكرّرة أو غير المعروفة. لا يقتصر استخدام هذا الخيار على categoryDenylist ويؤدي استخدام كلاهما إلى حدوث خطأ. أي سلاسل لم يتم التحديد
categoryDenylist تحدِّد هذه السياسة القائمة الاختيارية لأسماء الفئات غير المسموح بها. إذا كانت غير فارغة، فسيتم تصفية نتائج التصنيف التي يكون اسم الفئة في هذه المجموعة بها. ويتم تجاهل أسماء الفئات المكرّرة أو غير المعروفة. لا يقتصر استخدام هذا الخيار على categoryAllowlist ويؤدي استخدام كلا الخيارين إلى حدوث خطأ. أي سلاسل لم يتم التحديد
resultListener تضبط أداة معالجة النتائج على تلقّي نتائج التصنيف بشكل غير متزامن عندما يكون "مصنِّف الصور" في وضع البث المباشر. لا يمكن استخدام الإذن إلا عند ضبط "وضع التشغيل" على LIVE_STREAM لا ينطبق لم يتم التحديد

إعدادات البث المباشر

عند ضبط وضع التشغيل على البث المباشر، يتطلّب "مصنِّف الصور" خيار ضبط "imageClassifierLiveStreamDelegate" الإضافي، ما يتيح للمصنِّف عرض نتائج التصنيف بشكل غير متزامن. ينفِّذ المفوَّض طريقة imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:) التي يطلبها "مصنِّف الصور" بعد معالجة نتائج التصنيف لكل إطار.

اسم الخيار الوصف نطاق القيمة القيمة التلقائية
imageClassifierLiveStreamDelegate تعمل هذه السياسة على تفعيل مصنِّف الصور من تلقّي نتائج التصنيف بشكل غير متزامن في وضع البث المباشر. الفئة التي تم ضبط مثيلها على هذه السمة يجب أن تنفذ الطريقة imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:). غير منطبق لم يتم التحديد

تجهيز البيانات

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

اختَر تنسيق صورة لنظام التشغيل iOS استنادًا إلى حالة الاستخدام ووضع التشغيل الذي يتطلّبه تطبيقك.ويقبل MPImage تنسيقات الصور UIImage وCVPixelBuffer وCMSampleBuffer على أجهزة iOS.

UIImage

يناسب تنسيق UIImage تمامًا أوضاع الجري التالية:

  • الصور: الصور من حِزمة تطبيق أو معرض مستخدمين أو نظام ملفات بتنسيقات UIImage يمكن تحويل الصور إلى عنصر MPImage.

  • الفيديوهات: استخدِم AVAssetImageGenerator لاستخراج إطارات الفيديو إلى تنسيق CGImage، ثم حوِّلها إلى UIImage صورة

Swift

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    

Objective-C

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

في هذا المثال، يتم إعداد MPImage باستخدام الاتجاه التلقائي UIImage.Orientation.Up. يمكنك إعداد MPImage باستخدام أي من قيم UIImage.Orientation المتوافقة. لا يتيح "مصنِّف الصور" الاتجاهات التي يتم عكسها، مثل .upMirrored و.downMirrored و.leftMirrored و.rightMirrored.

لمزيد من المعلومات حول UIImage، يمكنك الرجوع إلى وثائق مطوّري برامج UIImage من Apple.

CVPixelBuffer

يُعدّ تنسيق CVPixelBuffer مناسبًا تمامًا للتطبيقات التي تنشئ إطارات وتستخدم إطار عمل CoreImage لنظام التشغيل iOS في المعالجة.

يناسب تنسيق CVPixelBuffer تمامًا أوضاع الجري التالية:

  • الصور: إنّ التطبيقات التي تنشئ صور CVPixelBuffer بعد إجراء بعض المعالجة باستخدام إطار العمل CoreImage في iOS يمكن إرسالها إلى "مصنِّف الصور" في وضع تشغيل الصور.

  • الفيديوهات: يمكن تحويل إطارات الفيديو إلى تنسيق CVPixelBuffer لمعالجتها، ثم إرسالها إلى "مصنِّف الصور" في وضع الفيديو.

  • البث المباشر: إنّ التطبيقات التي تستخدم كاميرا iOS لإنشاء الإطارات يمكن تحويلها إلى تنسيق CVPixelBuffer لمعالجتها قبل إرسالها إلى "أداة تصنيف الصور" في وضع "البث المباشر".

Swift

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    

Objective-C

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

لمزيد من المعلومات حول CVPixelBuffer، يمكنك الرجوع إلى وثائق مطوّري أعمال CVPixelBuffer من Apple.

CMSampleBuffer

يخزّن تنسيق CMSampleBuffer عيّنات وسائط من نوع موحد، وهو مناسب جدًا لوضع تشغيل البث المباشر. يتم عرض الإطارات المباشرة من كاميرات iOS بشكل غير متزامن بتنسيق CMSampleBuffer من خلال AVCaptureVideoDataOutput على iOS.

Swift

// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    

Objective-C

// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

لمزيد من المعلومات حول CMSampleBuffer، يُرجى الرجوع إلى وثائق مطوّري أعمال CMSampleBuffer من Apple.

تنفيذ المهمة

لتشغيل "مصنِّف الصور"، استخدِم الطريقة classify() الخاصة بوضع التشغيل المخصّص:

  • صورة ثابتة: classify(image:)
  • الفيديو: classify(videoFrame:timestampInMilliseconds:)
  • البث المباشر: classifyAsync(image:timestampInMilliseconds:)

يعرض مصنِّف الصور الفئات المحتملة للكائن داخل إطار الإدخال أو الصورة.

تعرض نماذج الرموز التالية أمثلة أساسية حول كيفية تشغيل "مصنِّف الصور" في أوضاع التشغيل المختلفة هذه:

Swift

صورة

let result = try imageClassifier.classify(image: image)
    

فيديو

let result = try imageClassifier.classify(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

أحداث بث مباشر

try imageClassifier.classifyAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objective-C

صورة

MPPImageClassifierResult *result = [imageClassifier classifyImage:image
                                                            error:nil];
    

فيديو

MPPImageClassifierResult *result = [imageClassifier classifyVideoFrame:image
                                               timestampInMilliseconds:timestamp
                                                                 error:nil];
    

أحداث بث مباشر

BOOL success = [imageClassifier classifyAsyncImage:image
                          timestampInMilliseconds:timestamp
                                            error:nil];
    

يوضّح المثال على رمز مصنِّف الصور عمليات تنفيذ كل وضع من هذه الأوضاع بمزيد من التفصيل classify(image:) وclassify(videoFrame:timestampInMilliseconds:) وclassifyAsync(image:timestampInMilliseconds:). يسمح مثال الرمز للمستخدم بالتبديل بين أوضاع المعالجة التي قد لا تكون مطلوبة لحالة الاستخدام.

يُرجى ملاحظة ما يلي:

  • عند التشغيل في وضع الفيديو أو وضع البث المباشر، يجب أيضًا توفير الطابع الزمني لإطار الإدخال لمهمة "مصنِّف الصور".

  • عند استخدام وضع "الصور" أو "الفيديو"، تحجب مهمة "مصنِّف الصور" سلسلة المحادثات الحالية حتى تنتهي من معالجة الصورة أو الإطار المُدخَلين. ولتجنّب حظر سلسلة التعليمات الحالية، يمكنك تنفيذ المعالجة في سلسلة محادثات في الخلفية باستخدام إطار عمل iOSDispatch أو NSOperation.

  • عند تفعيل "وضع البث المباشر"، تظهر مهمة "مصنِّف الصور" على الفور ولا تحجب سلسلة المحادثات الحالية. وهو يستدعي الطريقة imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:) مع نتيجة التصنيف بعد معالجة كل إطار إدخال. ويستدعي "مصنِّف الصور" هذه الطريقة بشكل غير متزامن على قائمة انتظار إرسال تسلسلية مخصصة. لعرض النتائج على واجهة المستخدم، يُرجى إرسال النتائج إلى قائمة الانتظار الرئيسية بعد معالجة النتائج. إذا تم استدعاء دالة classifyAsync عندما تكون مهمة مصنِّف الصور مشغولة بمعالجة إطار آخر، يتجاهل مصنِّف الصور إطار الإدخال الجديد.

التعامل مع العملاء وعرض النتائج

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

في ما يلي مثال على بيانات الإخراج من هذه المهمة:

ImageClassifierResult:
 Classifications #0 (single classification head):
  head index: 0
  category #0:
   category name: "/m/01bwb9"
   display name: "Passer domesticus"
   score: 0.91406
   index: 671
  category #1:
   category name: "/m/01bwbt"
   display name: "Passer montanus"
   score: 0.00391
   index: 670

تم الحصول على هذه النتيجة من خلال تشغيل مصنِّف الطيور على:

يوضّح رمز نموذج "مصنِّف الصور" كيفية عرض نتائج التصنيف التي تم عرضها من المهمة. راجِع مثال الرمز البرمجي لمعرفة التفاصيل.