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

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

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

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

رمز مثال "مهام MediaPipe" هو تنفيذ أساسي لتطبيق "أداة الكشف عن العناصر" لنظام التشغيل 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.

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

تحتوي الملفات التالية على الرمز البرمجي المهم لتطبيق مثال "كاشف الأجسام":

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

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

يصف هذا القسم الخطوات الرئيسية لإعداد بيئة التطوير ومشاريع الترميز لاستخدام أداة رصد الكائنات. للحصول على معلومات عامة عن إعداد بيئة التطوير لاستخدام مهام 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 نموذجًا مدرَّبًا متوافقًا مع هذه المهمة. لمزيد من المعلومات عن النماذج المدربة المتاحة لميزة "مُعترِف الأجسام"، اطّلِع على قسم نماذج ضمن النظرة العامة على المهمة.

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

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

إنشاء المهمة

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

إذا لم تكن بحاجة إلى أداة رصد الكائنات التي تم إعدادها باستخدام خيارات إعداد مخصّصة، يمكنك استخدام أداة إعداد 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: هو الوضع الخاص بإدخالات الصور الفردية.

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

LIVE_STREAM: وضع البث المباشر لبيانات المعالجة التي يتم إدخالها، مثل البيانات الواردة من كاميرا في هذا الوضع، يجب استدعاء resultListener لإعداد مستمع لتلقّي النتائج بشكل غير متزامن.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
displayNamesLocales لضبط لغة التصنيفات المراد استخدامها للأسماء المعروضة المقدمة في البيانات الوصفية لنموذج المهمة، إذا كانت متوفرة. اللغة التلقائية هي en للغة الإنجليزية. يمكنك إضافة تصنيفات مترجَمة إلى البيانات الوصفية لنموذج مخصّص باستخدام TensorFlow Lite Metadata Writer 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 تنسيقات صور iOS UIImage وCVPixelBuffer و CMSampleBuffer.

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، يُرجى الرجوع إلى مستندات مطوّري تطبيقات Apple المتعلّقة بـ UIImage .

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 من خلال iOS AVCaptureVideoDataOutput.

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 .

تنفيذ المهمة

لتشغيل "كاشف الأجسام"، استخدِم طريقة 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:). يسمح رمز المثال للمستخدم بالتبديل بين أوضاع المعالجة التي قد لا تكون مطلوبة لحالة الاستخدام.

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

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

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

  • عند التشغيل في وضع البث المباشر، تُعرض مهمة "كاشف الأجسام" على الفور ولا تحظر سلسلة المحادثات الحالية. وهو يستدعي الطريقة 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

تعرض الصورة التالية عرضًا مرئيًا لمعدّل تكرار المهمة:

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