دليل تصنيف الصور إلى شرائح لنظام التشغيل Android

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

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

يحتوي مثال رمز MediaPipe Tasks على طريقتَين بسيطتَين لتنفيذ تطبيق "مُقسِّم الصور" لنظام التشغيل Android:

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

تشير الأقسام التالية إلى تطبيق Image Segmenter with a category mask.

تنزيل الرمز

توضِّح لك التعليمات التالية كيفية إنشاء نسخة محلية من مثال الرمز البرمجي باستخدام أداة سطر الأوامر 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_segmentation/android
    

بعد إنشاء نسخة محلية من رمز المثال، يمكنك استيراد المشروع إلى "استوديو Android" وتشغيل التطبيق. للحصول على التعليمات، اطّلِع على دليل الإعداد لنظام التشغيل Android.

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

تحتوي الملفات التالية على الرمز البرمجي المهم لهذا المثال على تطبيق معالجة الصور:

  • ImageSegmenterHelper.kt: تُستخدَم لإعداد مهمة "مُقسِّم الصور" ومعالجة اختيار النموذج والوكيل.
  • CameraFragment.kt: يوفّر واجهة المستخدم ورمز التحكّم في الكاميرا.
  • GalleryFragment.kt: توفّر واجهة المستخدم ورمز التحكّم لاختيار ملفات الصور والفيديوهات.
  • OverlayView.kt: تُستخدَم هذه الفئة لمعالجة نتائج التقسيم وتنسيقها.

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

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

التبعيات

تستخدِم أداة "تقسيم الصور" مكتبة com.google.mediapipe:tasks-vision. أضِف هذا الاعتماد إلى ملف build.gradle في مشروع تطوير تطبيق Android. استورِد العناصر التابعة المطلوبة باستخدام الرمز التالي:

dependencies {
    ...
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

الطراز

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

اختَر النموذج ونزِّله، ثم احفظه في دليل مشروعك:

<dev-project-root>/src/main/assets

استخدِم الطريقة BaseOptions.Builder.setModelAssetPath() لتحديد المسار الذي يستخدمه النموذج. تتم الإشارة إلى هذه الطريقة في مثال الرمز البرمجي في القسم التالي.

في مثال التعليمات البرمجية لفاصل الصور، يتم تعريف النموذج في فئة ImageSegmenterHelper.kt في الدالة setupImageSegmenter().

إنشاء المهمة

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

تتيح مهمة "مُقسِّم الصور" أنواع بيانات الإدخال التالية: الصور الثابتة وملفات الفيديو وأحداث البث المباشر للفيديو. يجب تحديد وضع التشغيل المطابق لنوع بيانات الإدخال عند إنشاء المهمة. اختَر علامة التبويب لنوع بيانات الإدخال لمعرفة كيفية إنشاء هذه المهمة.

صورة

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

فيديو

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

بث مباشر

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .setResultListener((result, inputImage) -> {
         // Process the segmentation result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the segmentation errors here.
    })
    .build()
imagesegmenter = ImageSegmenter.createFromOptions(context, options)
    

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

خيارات الضبط

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

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

IMAGE: وضع الإدخالات باستخدام صورة واحدة.

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

LIVE_STREAM: وضع البث المباشر لبيانات الإدخال ، مثل بيانات الكاميرا في هذا الوضع، يجب استدعاء resultListener لإعداد مستمع لتلقّي النتائج بشكل غير متزامن.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
outputCategoryMask في حال ضبط القيمة على True، يتضمّن الناتج قناع تقسيم كصورة uint8، حيث تشير قيمة كل بكسل إلى قيمة الفئة الفائزة. {True, False} False
outputConfidenceMasks في حال ضبطه على True، يتضمّن الناتج قناع تقسيم كصورة قيمة عائمة، حيث تمثّل كل قيمة عائمة خريطة تقييم الثقة للفئة. {True, False} True
displayNamesLocale لضبط لغة التصنيفات لاستخدامها في الأسماء المعروضة المقدَّمة في البيانات الوصفية لنموذج المهمة، في حال توفّرها. القيمة التلقائية هي en لعبارة English. يمكنك إضافة تصنيفات مترجَمة إلى البيانات الوصفية لنموذج مخصّص باستخدام واجهة برمجة التطبيقات TensorFlow Lite Metadata Writer API. رمز اللغة en
resultListener ضبط مستمع النتائج لتلقّي نتائج التقسيم بشكل غير متزامن عندما يكون أداة تقسيم الصور في وضع LIVE_STREAM لا يمكن استخدامها إلا عند ضبط وضع التشغيل على LIVE_STREAM لا ينطبق لا ينطبق
errorListener تُستخدَم لضبط مستمع أخطاء اختياري. لا ينطبق لم يتم الضبط

إعداد البيانات

تعمل ميزة "تقسيم الصور" مع الصور وملفات الفيديو والفيديوهات المباشرة. تعالج المهمة المعالجة المُسبَقة لإدخال البيانات، بما في ذلك تغيير الحجم والدوران ومعالجة قيم البيانات.

عليك تحويل الصورة أو الإطار المُدخل إلى عنصر com.google.mediapipe.framework.image.MPImage قبل تمريره إلى أداة تقسيم الصور.

صورة

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the users device as a Bitmap object using BitmapFactory.

// Convert an Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

فيديو

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load a video file on the user's device using MediaMetadataRetriever

// From the videos metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. Youll need them
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

بث مباشر

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraXs ImageAnalysis to continuously receive frames
// from the devices camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Androids ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Androids Image object and convert it to
// a MediaPipes Image object.
android.media.Image mediaImage = imageProxy.getImage()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

في مثال رمز "أداة تقسيم الصور"، يتم التعامل مع إعداد البيانات في فئة ImageSegmenterHelper باستخدام الدالة segmentLiveStreamFrame().

تنفيذ المهمة

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

صورة

ImageSegmenterResult segmenterResult = imagesegmenter.segment(image);
    

فيديو

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ImageSegmenterResult segmenterResult =
    imagesegmenter.segmentForVideo(image, frameTimestampMs);
    

بث مباشر

// Run inference on the frame. The segmentations results will be available via
// the `resultListener` provided in the `ImageSegmenterOptions` when the image
// segmenter was created.
imagesegmenter.segmentAsync(image, frameTimestampMs);
    

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

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

في نموذج التعليمات البرمجية لفئة "مُقسِّم الصور"، يتم تعريف دوال segment في ملف ImageSegmenterHelper.kt.

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

عند تنفيذ الاستنتاج، تُعرِض مهمة "مُقسِّم الصور" ImageSegmenterResult عنصرًا يحتوي على نتائج مهمة التقسيم. يعتمد محتوى المخرجات على outputType الذي ضبطته عند ضبط المهمة.

تعرض الأقسام التالية أمثلة على بيانات الإخراج من هذه المهمة:

ثقة الفئة

تعرض الصور التالية تمثيلاً مرئيًا لمخرجات المهمة لفئة قناع الثقة. يحتوي الناتج عن قناع الثقة على قيم عائمة تتراوح بين [0, 1].

فتاتان تركبان حصانًا وفتاة تمشي بجانب الحصان قناع الصورة الذي يحدّد شكل الفتيات والحصان من الصورة السابقة تم التقاط النصف الأيسر من مخطّط الصورة، ولكن لم يتم التقاط النصف الأيمن من الصورة.

الصورة الأصلية وإخراج قناع ثقة الفئة الصورة المصدر من مجموعة بيانات Pascal VOC 2012.

قيمة الفئة

تعرض الصور التالية تمثيلاً مرئيًا لمعدّل إنجاز المهمة لقناع قيمة الفئة. نطاق قناع الفئة هو [0, 255]، وتمثل كل قيمة بكسل فهرس الفئة الفائزة في مخرجات النموذج. يحصل فئة الفهرس الفائزة على أعلى نتيجة بين الفئات التي يمكن للنموذج التعرّف عليها.

فتاتان تركبان حصانًا وفتاة تمشي بجانب الحصان قناع الصورة الذي يحدّد شكل الفتيات والحصان من الصورة السابقة تم حجب شكل الفتيات الثلاث والحصان بدقة

الصورة الأصلية ونتيجة قناع الفئة الصورة المصدر من مجموعة بيانات Pascal VOC 2012.