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

تتيح لك مَهمّة "أداة رصد الكائنات" اكتشاف موقع فئات متعددة من الكائنات. على سبيل المثال، يمكن لأداة كشف الأجسام تحديد موقع الكلاب داخل إحدى الصور. توضح لك هذه الإرشادات كيفية استخدام مهمة Object Detector في نظام iOS. تتوفر عينة التعليمات البرمجية الموضحة في هذه التعليمات على GitHub.

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

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

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

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

تنزيل الرمز

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

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

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

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

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

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

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

تحتوي الملفات التالية على التعليمات البرمجية الهامة لتطبيق مثال Object Detector:

  • ObjectDetectorService.swift: يضبط أداة الرصد وتعالج اختيار النموذج ويُجري الاستنتاج على بيانات الإدخال.
  • CameraViewController.swift: ينفّذ هذا التنسيق واجهة المستخدم لوضع إدخال خلاصة الكاميرا المباشرة ويعرض نتائج الرصد.
  • MediaLibraryViewController.swift: ينفّذ هذا الأسلوب واجهة المستخدم الخاصة بوضع إدخال ملفات الفيديو والصور الثابتة، ويعرض نتائج الرصد.

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

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

التبعيات

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

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

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

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

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

الطراز

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

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

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

إنشاء المهمة

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

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

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

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

Swift

صورة

import MediaPipeTasksVision

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

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

let objectDetector = try ObjectDetector(options: options)
    

حملة فيديو

import MediaPipeTasksVision

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

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

let objectDetector = try ObjectDetector(options: options)
    

بث مباشر

import MediaPipeTasksVision

// Class that conforms to the `ObjectDetectorLiveStreamDelegate` protocol and
// implements the method that the object detector calls once it
// finishes performing detection on each input frame.
class ObjectDetectorResultProcessor: NSObject, ObjectDetectorLiveStreamDelegate {

  func objectDetector(
    _ objectDetector: ObjectDetector,
    didFinishDetection objectDetectionResult: ObjectDetectorResult?,
    timestampInMilliseconds: Int,
    error: Error?) {
    // Process the detection result or errors here.
  }
}

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

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

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

let objectDetector = try ObjectDetector(options: options)
    

Objective-C

صورة

@import MediaPipeTasksVision;

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

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

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

حملة فيديو

@import MediaPipeTasksVision;

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

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

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

بث مباشر

@import MediaPipeTasksVision;

// Class that conforms to the `ObjectDetectorLiveStreamDelegate` protocol and
// implements the method that the object detector calls once it
// finishes performing detection on each input frame.

@interface APPObjectDetectorResultProcessor : NSObject 

@end

@implementation MPPObjectDetectorResultProcessor

-   (void)objectDetector:(MPPObjectDetector *)objectDetector
    didFinishDetectionWithResult:(MPPObjectDetectorResult *)ObjectDetectorResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the detection result or errors here.

}

@end

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

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

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

MPPObjectDetector *objectDetector =
      [[MPPObjectDetector alloc] initWithOptions:options error:nil];
    

خيارات الضبط

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

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

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

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

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

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

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

اسم الخيار الوصف نطاق القيمة القيمة التلقائية
objectDetectorLiveStreamDelegate تعمل هذه السياسة على تفعيل أداة رصد العناصر لتلقّي نتائج الرصد بشكل غير متزامن في وضع البث المباشر. أمّا الفئة التي تم ضبط مثيلها على هذه السمة، فعليها تنفيذ الطريقة objectDetector(_:didFinishDetection: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، يُرجى الاطّلاع على مستندات مطوّري البرامج الخاصة بـ CMعيّنBuffer من Apple.

تنفيذ المهمة

لتشغيل "أداة رصد الكائنات"، استخدِم طريقة detect() الخاصة بوضع التشغيل المحدَّد:

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

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

Swift

صورة

let objectDetector.detect(image:image)
    

حملة فيديو

let objectDetector.detect(videoFrame:image)
    

بث مباشر

let objectDetector.detectAsync(image:image)
    

Objective-C

صورة

MPPObjectDetectorResult *result = [objectDetector detectInImage:image error:nil];
    

حملة فيديو

MPPObjectDetectorResult *result = [objectDetector detectInVideoFrame:image          timestampInMilliseconds:timestamp error:nil];
    

بث مباشر

BOOL success = [objectDetector detectAsyncInImage:image
                          timestampInMilliseconds:timestamp
                                            error:nil];
    

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

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

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

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

  • عند تشغيلها في وضع البث المباشر، تعود مهمة "أداة رصد العناصر" فورًا بدون حظر سلسلة المحادثات الحالية. ويستدعي الطريقة objectDetector(_objectDetector:didFinishDetection:timestampInMilliseconds:error:) مع نتيجة الرصد بعد معالجة كل إطار إدخال. تستدعي أداة رصد الكائنات هذه الطريقة بشكلٍ غير متزامن في قائمة انتظار إرسال تسلسلية مخصصة. لعرض النتائج على واجهة المستخدم، نقل النتائج إلى قائمة الانتظار الرئيسية بعد معالجة النتائج. إذا تم استدعاء الدالة detectAsync عندما تكون مهمة مستكشف الكائنات مشغولة بمعالجة إطار آخر، فإن أداة رصد الكائنات يتجاهل إطار الإدخال الجديد.

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

عند تنفيذ الاستنتاج، تعرض مهمة "أداة رصد الكائنات" كائن ObjectDetectorResult يصف الكائنات التي تم العثور عليها في صورة الإدخال.

ويوضح ما يلي مثالاً على بيانات المخرجات من هذه المهمة:

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

تُظهر الصورة التالية تصورًا لناتج المهمة:

يوضح رمز مثال أداة كشف الكائنات كيفية عرض نتائج الاكتشاف الناتجة عن المهمة، راجع مثال الرمز للحصول على التفاصيل.