دليل التعرّف على المعالم في نظام Android يدويًا

تتيح لك مهمة MediaPipe Handmarker اكتشاف معالم الأيدي في الصورة. توضح لك هذه التعليمات كيفية استخدام أداة جذب الاهتمام مع تطبيقات Android. تتوفر عينة التعليمات البرمجية الموضحة في هذه التعليمات على GitHub.

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

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

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

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

تنزيل الرمز

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

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

  1. استنسِخ مستودع git باستخدام الأمر التالي:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. يمكنك اختياريًا ضبط مثيل git لاستخدام طريقة الدفع المتفرقة، وبالتالي لا يكون لديك سوى ملفات مثال تطبيق Hand يوجد لدى مَعلمة، كالتالي:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/hand_landmarker/android
    

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

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

تحتوي الملفات التالية على الرمز الأساسي لتطبيق نموذج اكتشاف مَعلم اليد هذا:

  • HandLandmarkerHelper.kt - يضبط أداة رصد معلَم اليدين وتعالج النموذج والتحديد المفوَّض.
  • MainActivity.kt - لتنفيذ التطبيق، بما في ذلك استدعاء HandLandmarkerHelper.

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

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

التبعيات

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

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

الطراز

تتطلب مهمة MediaPipe Handmarker مجموعة من نماذج مدرَّبة متوافقة مع هذه المهمة. لمزيد من المعلومات حول النماذج المدربة المتاحة من أجل مؤشر اليد اليدوية، راجع قسم النماذج الذي يقدم نظرة عامة على المهمة.

حدد النموذج ونزّله وخزّنه في دليل المشروع:

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

حدِّد مسار النموذج ضمن المَعلمة ModelAssetPath. في مثال الرمز البرمجي، يتم تحديد النموذج في ملف HandLandmarkerHelper.kt:

baseOptionBuilder.setModelAssetPath(MP_HAND_LANDMARKER_TASK)

إنشاء المهمة

تستخدم مهمة MediaPipe Handmarker الدالة createFromOptions() لإعداد المهمة. تقبل الدالة createFromOptions() قيمًا لخيارات الضبط. لمزيد من المعلومات حول خيارات الضبط، يُرجى الاطّلاع على خيارات الضبط.

تتوافق أداة Handmarker مع 3 أنواع من بيانات الإدخال، وهي الصور الثابتة وملفات الفيديو والبث المباشر. تحتاج إلى تحديد وضع التشغيل المقابل لنوع بيانات الإدخال عند إنشاء المهمة. اختر علامة التبويب المقابلة لنوع بيانات الإدخال لمعرفة كيفية إنشاء المهمة وتشغيل الاستنتاج.

صورة

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    HandLandmarker.HandLandmarkerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setNumHands(maxNumHands)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()

handLandmarker =
    HandLandmarker.createFromOptions(context, options)
    

حملة فيديو

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    HandLandmarker.HandLandmarkerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setNumHands(maxNumHands)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()

handLandmarker =
    HandLandmarker.createFromOptions(context, options)
    

البث المباشر

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_HAND_LANDMARKER_TASK)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    HandLandmarker.HandLandmarkerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setNumHands(maxNumHands)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()

handLandmarker =
    HandLandmarker.createFromOptions(context, options)
    

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

خيارات الضبط

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

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

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

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

البث المباشر: وضع بث مباشر لبيانات الإدخال، مثل الكاميرا. في هذا الوضع، يجب استدعاء resultsListener لإعداد أداة معالجة الصوت لكي تتلقى النتائج بشكل غير متزامن.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numHands الحد الأقصى لعدد الأيدي التي يتم رصدها بواسطة أداة رصد معلَمة اليد Any integer > 0 1
minHandDetectionConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة ليتم اعتبار رصد اليد ناجحًا في نموذج اكتشاف راحة اليد. 0.0 - 1.0 0.5
minHandPresenceConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة لنتيجة تواجد اليد في نموذج رصد معالِم اليد. في وضع الفيديو ووضع البث المباشر، إذا كانت نتيجة الثقة في تواجد اليد من نموذج علامات اليد أقل من هذا الحدّ، تشغّل أداة قياس راحة اليد نموذج رصد راحة اليد. وبخلاف ذلك، تحدّد خوارزمية تتبُّع بسيطة لليد موقع الأيدي من أجل رصد المعالم لاحقًا. 0.0 - 1.0 0.5
minTrackingConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة ليتم اعتبار تتبُّع اليد ناجحًا. هذا هو الحدّ الأدنى لوحدات وحدات القياس بين الأيدي في الإطار الحالي والإطار الأخير. في وضع "الفيديو" ووضع "البث" في أداة قياس اليد، إذا تعذّر إتمام عملية التتبُّع، تشغّل أداة Handمجموعة ميزة "رصد اليد". وفي حال عدم تنفيذ هذا الإجراء، يتخطّى الجهاز ميزة رصد اليد. 0.0 - 1.0 0.5
resultListener يعمل هذا الإعداد على ضبط أداة معالجة النتائج لتلقّي نتائج الرصد بشكل غير متزامن عندما يكون معلَم اليد في وضع البث المباشر. لا ينطبق هذا الإجراء إلا عند ضبط وضع التشغيل على LIVE_STREAM. لا ينطبق لا ينطبق
errorListener لضبط أداة معالجة الأخطاء الاختيارية. لا ينطبق لا ينطبق

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

تتوافق أداة Handmarker مع الصور وملفّات الفيديو وبثّ الفيديو المباشر. تعالج المهمة المعالجة المسبقة لإدخال البيانات، بما في ذلك تغيير الحجم والتدوير وتسوية القيمة.

يوضح الرمز البرمجي التالي كيفية تسليم البيانات للمعالجة. وتشمل هذه النماذج تفاصيل حول كيفية التعامل مع البيانات الواردة من الصور وملفات الفيديو وأحداث البث المباشر.

صورة

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

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(image).build()
    

حملة فيديو

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

val argb8888Frame =
    if (frame.config == Bitmap.Config.ARGB_8888) frame
    else frame.copy(Bitmap.Config.ARGB_8888, false)

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(argb8888Frame).build()
    

البث المباشر

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

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(rotatedBitmap).build()
    

في مثال التعليمات البرمجية لـHand Brander، تتم معالجة عملية إعداد البيانات في ملف HandLandmarkerHelper.kt.

تنفيذ المهمة

واستنادًا إلى نوع البيانات التي تستخدمها، استخدِم طريقة HandLandmarker.detect...() الخاصة بنوع البيانات هذا. استخدِم detect() للصور الفردية، وdetectForVideo() للإطارات في ملفات الفيديو، وdetectAsync() للفيديوهات المضمَّنة. عند إجراء عمليات رصد ضمن مصدر بيانات فيديو، احرص على تنفيذ عمليات الرصد في سلسلة محادثات منفصلة لتجنُّب حظر سلسلة التعليمات التي تتضمّن واجهة المستخدم.

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

صورة

val result = handLandmarker?.detect(mpImage)
    

حملة فيديو

val timestampMs = i * inferenceIntervalMs

handLandmarker?.detectForVideo(mpImage, timestampMs)
    ?.let { detectionResult ->
        resultList.add(detectionResult)
    }
    

البث المباشر

val mpImage = BitmapImageBuilder(rotatedBitmap).build()
val frameTime = SystemClock.uptimeMillis()

handLandmarker?.detectAsync(mpImage, frameTime)
    

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

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

في مثال الرمز "Handmarker"، يتم تحديد الدوال detect وdetectForVideo وdetectAsync في ملف HandLandmarkerHelper.kt.

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

تنشئ أداة قياس اليد كائن نتيجة مؤشر اليد لكل عملية اكتشاف. يحتوي كائن النتيجة على معالم لليد في إحداثيات الصور، ومعالم لليد في إحداثيات العالم، واليد(اليد اليسرى/اليمنى) لليدين المكتشفة.

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

يحتوي ناتج HandLandmarkerResult على ثلاثة مكوّنات. كل مكوّن هو مصفوفة، حيث يحتوي كل عنصر فيها على النتائج التالية ليد واحدة تم اكتشافها:

  • الإنصاف

    تشير ميزة "استخدام اليد" إلى ما إذا كانت الأيدي التي تم رصدها هما اليد اليسرى أو اليمنى.

  • المَعالم

    هناك 21 معلمًا على اليد، يتألف كل منها من إحداثيات x وy وz. تتم تسوية إحداثيتَي x وy لتصبح [0.0 و1.0] في عرض الصورة وارتفاعها، على التوالي. يمثل التنسيق z عمق المعلم، حيث يكون العمق في المعصم هو الأصل. كلما كانت القيمة أصغر، اقترب المعلم الرئيسي من الكاميرا. يستخدم مقدار z مقياسًا مماثلاً تقريبًا لمقياس x.

  • معالم عالمية

    ويتم عرض 21 معلمًا يدويًا في الإحداثيات العالمية. ويتألف كل معلَم من x وy وz، ما يمثّل إحداثيات ثلاثية الأبعاد حقيقية بمقاييس، وتتكوّن من نقطة الأصل في المركز الهندسي لليد.

HandLandmarkerResult:
  Handedness:
    Categories #0:
      index        : 0
      score        : 0.98396
      categoryName : Left
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : -3.41E-7
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
    ... (21 landmarks for a hand)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
    ... (21 world landmarks for a hand)

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

يوضح رمز نموذج مؤشر اليد أداة الجذب كيفية عرض النتائج التي تم إرجاعها من المهمة. راجع فئة OverlayView لمزيد من التفاصيل.