دليل تضمين الصور لأجهزة iOS

تتيح لك مهمة "إدراج الصور" من MediaPipe تحويل بيانات الصور إلى تمثيل عددي للقيام بمهام معالجة الصور ذات الصلة بالذكاء الاصطناعي، مثل مقارنة تشابه صورتَين.

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

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

مثال التعليمات البرمجية لـ MediaPipe Tasks هو تطبيق أساسي لدمج الصور لنظام التشغيل 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/image_embedder/ios
    

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

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

تحتوي الملفات التالية على الرمز البرمجي المهم لمثال تطبيق "أداة تضمين الصور":

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

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

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

التبعيات

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

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

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

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

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

الطراز

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

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

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

إنشاء المهمة

يمكنك إنشاء مهمة أداة تضمين الصور من خلال استدعاء أحد المهيئات. يقبل مُنشئ ImageEmbedder(options:) قيمًا لخيارات الضبط .

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

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

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

Swift

صورة

import MediaPipeTasksVision

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

let options = ImageEmbedderOptions()
options.baseOptions.modelAssetPath = modelPath
options.quantize = true
options.l2Normalize = true

let imageEmbedder = try ImageEmbedder(options: options)
    

فيديو

import MediaPipeTasksVision

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

let options = ImageEmbedderOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.quantize = true
options.l2Normalize = true

let imageEmbedder = try ImageEmbedder(options: options)
    

بث مباشر

import MediaPipeTasksVision

// Class that conforms to the `ImageEmbedderLiveStreamDelegate` protocol and
// implements the method that the image embedder calls once it finishes
// embedding each input frame.
class ImageEmbedderResultProcessor: NSObject, ImageEmbedderLiveStreamDelegate {

  func imageEmbedder(
    _ imageEmbedder: ImageEmbedder,
    didFinishEmbedding result: ImageEmbedderResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the image embedder result or errors here.

  }
}

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

let options = ImageEmbedderOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.quantize = true
options.l2Normalize = true

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

let imageEmbedder = try ImageEmbedder(options: options)
    

Objective-C

صورة

@import MediaPipeTasksVision;

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

MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.quantize = YES;
options.l2Normalize = YES;

MPPImageEmbedder *imageEmbedder =
  [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
    

فيديو

@import MediaPipeTasksVision;

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

MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.quantize = YES;
options.l2Normalize = YES;

MPPImageEmbedder *imageEmbedder =
  [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
    

بث مباشر

@import MediaPipeTasksVision;

// Class that conforms to the `MPPImageEmbedderLiveStreamDelegate` protocol
// and implements the method that the image embedder calls once it finishes
// embedding each input frame.
@interface APPImageEmbedderResultProcessor : NSObject 

@end

@implementation APPImageEmbedderResultProcessor

-   (void)imageEmbedder:(MPPImageEmbedder *)imageEmbedder
    didFinishEmbeddingWithResult:(MPPImageEmbedderResult *)imageEmbedderResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the image embedder result or errors here.

}

@end

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

MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.quantize = YES;
options.l2Normalize = YES;

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

MPPImageEmbedder *imageEmbedder =
  [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
    

خيارات الضبط

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

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

IMAGE: وضع الإدخالات التي تتضمّن صورة واحدة.

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

LIVE_STREAM: وضع البث المباشر لبيانات الإدخال، مثل الكاميرا. في هذا الوضع، يجب ضبط imageEmbedderLiveStreamDelegate على نسخة من فئة تنفِّذ ImageEmbedderLiveStreamDelegate لتلقّي نتائج دمج إطارات الصور بشكل غير متزامن.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} {RunningMode.image}
l2Normalize ما إذا كان ستتم تسوية متجه الميزة المرتجعة مع معيار L2. لا تستخدِم هذا الخيار إلا إذا كان النموذج لا يحتوي على عملية L2_NORMALIZATION TFLite أصلية. وفي معظم الحالات، يكون هذا هو الحال ويتم بالتالي تحقيق تسويّة L2 من خلال الاستنتاج باستخدام TFLite بدون الحاجة إلى هذا الخيار. منطقية خطأ
quantize ما إذا كان يجب تجزئة البيانات المضمّنة التي تم إرجاعها إلى وحدات بايت من خلال التجزئة باستخدام قيم scaler يُفترض ضمنيًا أن تكون عمليات التضمين ذات معيار وحدة، وبالتالي يمكن ضمان أن تكون قيمة أي سمة هي [ -1.0, 1.0]. استخدِم خيار l2Normalize إذا لم يكن الأمر كذلك. منطقية خطأ

عند ضبط وضع التشغيل على "بث مباشر"، يتطلّب "أداة تضمين الصور" استخدام خيار الإعداد imageEmbedderLiveStreamDelegate الإضافي، ما يتيح لأداة تضمين الصور إرسال نتائج تضمين الصور بشكل غير متزامن. يجب أن ينفذ الرمز المفوَّض imageEmbedder(_:didFinishEmbedding:timestampInMilliseconds:error:)، الذي يستدعيه "أداة تضمين الصور" بعد معالجة نتائج تضمين كل إطار من إطارات الصورة المُدخلة.

اسم الخيار الوصف نطاق القيمة القيمة التلقائية
imageEmbedderLiveStreamDelegate يتيح هذا الخيار لأداة "إدراج الصور" تلقّي نتائج إدراج الصور بشكل غير متزامن في وضع البث المباشر. الفئة التي تم ضبط مثيلها على هذه السمة يجب أن تنفذ الطريقة imageEmbedder(_:didFinishEmbedding: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، يُرجى الرجوع إلى مستندات "مطوّرو تطبيقات Apple" المتعلقين بـ CVPixelBuffer.

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 .

تنفيذ المهمة

لتشغيل "أداة تضمين الصور"، استخدِم الطريقة embed() الخاصة بوضع التشغيل الذي تم تعيينه:

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

تعرض نماذج الرموز البرمجية التالية أمثلة أساسية على كيفية تشغيل أداة "إدراج الصور" في أوضاع التشغيل المختلفة التالية:

Swift

صورة

let result = try imageEmbedder.embed(image: image)
    

فيديو

let result = try imageEmbedder.embed(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

بث مباشر

try imageEmbedder.embedAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

Objective-C

صورة

MPPImageEmbedderResult *result =
  [imageEmbedder embedImage:image error:nil];
    

فيديو

MPPImageEmbedderResult *result =
  [imageEmbedder embedVideoFrame:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

بث مباشر

BOOL success =
  [imageEmbedder embedAsyncImage:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

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

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

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

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

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

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

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

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

ImageEmbedderResult:
  Embedding #0 (sole embedding head):
    float_embedding: {0.0, 0.0, ..., 0.0, 1.0, 0.0, 0.0, 2.0}
    head_index: 0

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

يمكنك مقارنة تشابه عنصرَي إدراج باستخدام الدالة ImageEmbedder.cosineSimilarity.

Swift

let similarity = try ImageEmbedder.cosineSimilarity(
  embedding1: result.embeddingResult.embeddings[0],
  embedding2: otherResult.embeddingResult.embeddings[0])
    

Objective-C

NSNumber *similarity = [MPPImageEmbedder
      cosineSimilarityBetweenEmbedding1:result.embeddingResult.embeddings[0]
                          andEmbedding2:otherResult.embeddingResult.embeddings[0]
                                  error:nil];