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

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

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

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

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

يمكنك استخدام التطبيق كنقطة بداية لتطبيق Android الخاص بك، أو الرجوع إليه عند تعديل تطبيق حالي. تتم استضافة مثال الرمز البرمجي لمصنّف الصور على 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_classification/android
    

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

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

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

  • ImageClassifierHelper.kt - يؤدي إلى تهيئة مصنف الصور والتعامل مع النموذج والتفويض التحديد.
  • MainActivity.kt - لتنفيذ التطبيق، بما في ذلك طلب الرقم ImageClassificationHelper ClassificationResultsAdapter
  • ClassificationResultsAdapter.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() لتحديد المسار الذي يستخدمه النموذج. يُشار إلى هذه الطريقة في مثال التعليمة البرمجية في المثال التالي .

في جلسة المعمل، مثال على رمز أداة تصنيف الصور، يتم تحديد النموذج في ImageClassifierHelper.kt الملف.

إنشاء المهمة

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

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

صورة

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

فيديو

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

بث مباشر

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
         // Process the classification result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the classification errors here.
    })
    .build()
imageClassifier = ImageClassifier.createFromOptions(context, options)
    

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

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

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

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

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

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

LIVE_STREAM: وضع البث المباشر للإدخال البيانات، مثل تلك الواردة من الكاميرا. في هذا الوضع، يجب أن يكون resultListener يتم استدعاءها لإعداد مستمع للحصول على النتائج بشكل غير متزامن.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocale لتعيين لغة التسميات لاستخدامها في الأسماء المعروضة المقدمة في بيانات التعريف لنموذج المهمة، إن وجد. القيمة التلقائية هي en لمدة الإنجليزية. يمكنك إضافة تصنيفات مترجَمة إلى البيانات الوصفية لنموذج مخصّص. باستخدام TensorFlow Lite Metadata Writer API رمز اللغة en
maxResults لضبط الحد الأقصى الاختياري لنتائج التصنيف الأعلى تقييمًا إرجاع. إذا كانت قيمة 0، سيتم عرض جميع النتائج المتاحة. أي أرقام موجبة -1
scoreThreshold لتعيين الحد الأدنى لنتيجة التنبؤ الذي يلغي الحد المقدم في بيانات التعريف للنموذج (إن وجدت). يتم رفض النتائج التي تكون أدنى من هذه القيمة. أي عدد عائم لم يتم ضبط الوضع
categoryAllowlist تضبط هذه السياسة القائمة الاختيارية لأسماء الفئات المسموح بها. إذا لم تكن فارغة، سيتم وضع نتائج التصنيف التي لا يوجد اسم فئته بها في هذه المجموعة بفلترته. ويتم تجاهل أسماء الفئات المكرّرة أو غير المعروفة. لا يمكن لأحد الطرفين استخدام هذا الخيار إلا بعد استخدام categoryDenylist. يؤدي كلا الخيارين إلى خطأ. أي سلاسل لم يتم ضبط الوضع
categoryDenylist تحدِّد هذه السياسة القائمة الاختيارية لأسماء الفئات غير المسموح بها. في حال حذف نتائج التصنيف التي يكون اسم فئتها في هذه المجموعة غير فارغة، ستتم فلترتها . ويتم تجاهل أسماء الفئات المكرّرة أو غير المعروفة. يتوفّر هذا الخيار حصرية مع categoryAllowlist واستخدام النتيجتين معًا إلى حدوث خطأ. أي سلاسل لم يتم ضبط الوضع
resultListener تعمل هذه السياسة على ضبط أداة معالجة النتائج لتلقّي نتائج التصنيف. بشكل غير متزامن عندما يكون مصنِّف الصور في البث المباشر الحالي. لا يمكن استخدام الإذن إلا عند ضبط "وضع التشغيل" على 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();
    

في جلسة المعمل، مثال على رمز مصنّف الصور، يتم التعامل مع إعداد البيانات في ImageClassifierHelper.kt الملف.

تنفيذ المهمة

يمكنك استدعاء الدالة classify المرتبطة بوضع الجري لعرض الاستنتاجات. تعرض واجهة برمجة التطبيقات Image Classifier API الفئات المحتملة للعنصر داخل الصورة أو الإطار الذي تم إدخاله.

صورة

ImageClassifierResult classifierResult = imageClassifier.classify(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.
ImageClassifierResult classifierResult =
    imageClassifier.classifyForVideo(image, frameTimestampMs);
    

بث مباشر

// Run inference on the frame. The classifications results will be available 
// via the `resultListener` provided in the `ImageClassifierOptions` when 
// the image classifier was created.
imageClassifier.classifyAsync(image, frameTimestampMs);
    

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

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

في جلسة المعمل، مثال على رمز لمصنِّف الصور، يتم تحديد دوال classify في ImageClassifierHelper.kt الملف.

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

عند تنفيذ الاستنتاج، تعرض مهمة "مصنِّف الصور" الكائن 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

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

في جلسة المعمل، مثال على رمز مصنِّف الصور، الفئة ClassificationResultsAdapter في ClassificationResultsAdapter.kt معالجة النتائج:

fun updateResults(imageClassifierResult: ImageClassifierResult? = null) {
    categories = MutableList(adapterSize) { null }
    if (imageClassifierResult != null) {
        val sortedCategories = imageClassifierResult.classificationResult()
            .classifications()[0].categories().sortedBy { it.index() }
        val min = kotlin.math.min(sortedCategories.size, categories.size)
        for (i in 0 until min) {
            categories[i] = sortedCategories[i]
        }
    }
}