دليل التعرّف على الإيماءات لنظام التشغيل 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/gesture_recognizer/android
    

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

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

تحتوي الملفات التالية على التعليمة البرمجية الهامة لتطبيق نموذج التعرف على إيماءة اليد هذا:

  • GestureRecognizerHelper.kt - يضبط أداة التعرّف على الإيماءات والتعامل مع النموذج والتحديد المفوَّض.
  • MainActivity.kt - لتنفيذ التطبيق، بما في ذلك استدعاء GestureRecognizerHelper وGestureRecognizerResultsAdapter.
  • GestureRecognizerResultsAdapter.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

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

baseOptionBuilder.setModelAssetPath(MP_RECOGNIZER_TASK)

إنشاء المهمة

تستخدم مهمة أداة التعرّف على إيماءة MediaPipe الوظيفة createFromOptions() لإعداد المهمة. تقبل الدالة createFromOptions() قيم خيارات الضبط. لمزيد من المعلومات حول خيارات الضبط، راجِع خيارات الضبط.

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

صورة

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

val optionsBuilder =
    GestureRecognizer.GestureRecognizerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()
gestureRecognizer =
    GestureRecognizer.createFromOptions(context, options)
    

حملة فيديو

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

val optionsBuilder =
    GestureRecognizer.GestureRecognizerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()
gestureRecognizer =
    GestureRecognizer.createFromOptions(context, options)
    

البث المباشر

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

val optionsBuilder =
    GestureRecognizer.GestureRecognizerOptions.builder()
        .setBaseOptions(baseOptions)
        .setMinHandDetectionConfidence(minHandDetectionConfidence)
        .setMinTrackingConfidence(minHandTrackingConfidence)
        .setMinHandPresenceConfidence(minHandPresenceConfidence)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.LIVE_STREAM)

val options = optionsBuilder.build()
gestureRecognizer =
    GestureRecognizer.createFromOptions(context, options)
    

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

خيارات الضبط

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

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

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

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

البث المباشر: وضع بث مباشر لبيانات الإدخال، مثل الكاميرا. في هذا الوضع، يجب استدعاء resultsListener لإعداد أداة معالجة الصوت لكي تتلقى النتائج بشكل غير متزامن.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numHands يمكن رصد الحدّ الأقصى لعدد الأيدي من خلال "GestureRecognizer". Any integer > 0 1
minHandDetectionConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة ليتم اعتبار رصد اليد ناجحًا في نموذج اكتشاف راحة اليد. 0.0 - 1.0 0.5
minHandPresenceConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة لنتيجة تواجد اليد في نموذج رصد معالِم اليد. في وضع الفيديو ووضع البث المباشر في "أداة التعرّف على الإيماءات"، إذا كانت النتيجة الواثقة من تواجد اليد من نموذج المَعلم لليد أقل من هذا الحدّ، سيتم تشغيل نموذج "رصد راحة اليد". وبخلاف ذلك، يتم استخدام خوارزمية تتبُّع بسيطة لليد لتحديد موقع اليد أو الأيدي من أجل رصدها لاحقًا. 0.0 - 1.0 0.5
minTrackingConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة ليتم اعتبار تتبُّع اليد ناجحًا. هذا هو الحدّ الأدنى لوحدات وحدات القياس بين الأيدي في الإطار الحالي والإطار الأخير. في وضع الفيديو ووضع البث في "أداة التعرّف على الإيماءات"، إذا تعذّر تتبُّع الإيماءات، ستعمل هذه الميزة على تفعيل ميزة رصد اليد. وبخلاف ذلك، يتم تخطي رصد اليدين. 0.0 - 1.0 0.5
cannedGesturesClassifierOptions خيارات ضبط سلوك مصنِّف الإيماءات الجاهزة الإيماءات الجاهزة هي ["None", "Closed_Fist", "Open_Palm", "Pointing_Up", "Thumb_Down", "Thumb_Up", "Victory", "ILoveYou"]
.
  • لغة الأسماء المعروضة: اللغة التي سيتم استخدامها للأسماء المعروضة المحدّدة من خلال البيانات الوصفية لنموذج TFLite، إن توفّرت.
  • الحد الأقصى للنتائج: الحد الأقصى لعدد نتائج التصنيف الأعلى تقييمًا المطلوب عرضها. وإذا كانت القيمة أقل من 0، سيتم عرض جميع النتائج المتاحة.
  • حد الدرجة: النتيجة التي يتم رفض النتائج التي لا تحتها. وفي حال ضبطها على 0، سيتم عرض جميع النتائج المتاحة.
  • قائمة الفئات المسموح بها: القائمة المسموح بها لأسماء الفئات وإذا لم تكن هذه المجموعة فارغة، فستتم فلترة نتائج التصنيف التي لا تندرج فئتها ضمن هذه المجموعة. الأحداث المتنافية مع قائمة العناوين المحظورة
  • قائمة الحظر للفئات: القائمة المرفوضة لأسماء الفئات وإذا لم تكن هذه المجموعة فارغة، ستتم فلترة نتائج التصنيف التي تتضمن فئتها في هذه المجموعة. الأحداث المتنافية مع القائمة المسموح بها.
    • لغة الأسماء المعروضة: any string
    • الحد الأقصى للنتائج: any integer
    • حدّ النتيجة: 0.0-1.0
    • القائمة المسموح بها للفئات: vector of strings
    • قائمة الحظر للفئة: vector of strings
    • لغة الأسماء المعروضة: "en"
    • الحد الأقصى للنتائج: -1
    • حدّ النتيجة: 0
    • القائمة المسموح بها للفئات: فارغة
    • قائمة الحظر للفئة: فارغة
    customGesturesClassifierOptions خيارات ضبط سلوك مصنِّف الإيماءات المخصّصة
  • لغة الأسماء المعروضة: اللغة التي سيتم استخدامها للأسماء المعروضة المحدّدة من خلال البيانات الوصفية لنموذج TFLite، إن توفّرت.
  • الحد الأقصى للنتائج: الحد الأقصى لعدد نتائج التصنيف الأعلى تقييمًا المطلوب عرضها. وإذا كانت القيمة أقل من 0، سيتم عرض جميع النتائج المتاحة.
  • حد الدرجة: النتيجة التي يتم رفض النتائج التي لا تحتها. وفي حال ضبطها على 0، سيتم عرض جميع النتائج المتاحة.
  • قائمة الفئات المسموح بها: القائمة المسموح بها لأسماء الفئات وإذا لم تكن هذه المجموعة فارغة، فستتم فلترة نتائج التصنيف التي لا تندرج فئتها ضمن هذه المجموعة. الأحداث المتنافية مع قائمة العناوين المحظورة
  • قائمة الحظر للفئات: القائمة المرفوضة لأسماء الفئات وإذا لم تكن هذه المجموعة فارغة، ستتم فلترة نتائج التصنيف التي تتضمن فئتها في هذه المجموعة. الأحداث المتنافية مع القائمة المسموح بها.
    • لغة الأسماء المعروضة: any string
    • الحد الأقصى للنتائج: any integer
    • حدّ النتيجة: 0.0-1.0
    • القائمة المسموح بها للفئات: vector of strings
    • قائمة الحظر للفئة: vector of strings
    • لغة الأسماء المعروضة: "en"
    • الحد الأقصى للنتائج: -1
    • حدّ النتيجة: 0
    • القائمة المسموح بها للفئات: فارغة
    • قائمة الحظر للفئة: فارغة
    resultListener يعمل هذا الإعداد على ضبط أداة معالجة النتائج لتلقّي نتائج التصنيف بشكل غير متزامن عندما يكون أداة التعرّف على الإيماءات في وضع البث المباشر. لا يمكن استخدام هذا الخيار إلا عند ضبط وضع التشغيل على LIVE_STREAM. ResultListener لا ينطبق لا ينطبق
    errorListener لضبط أداة معالجة الأخطاء الاختيارية. ErrorListener لا ينطبق لا ينطبق

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

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

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

    صورة

    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()
        

    في الرمز البرمجي لأداة التعرّف على الإيماءات، تتم معالجة عملية إعداد البيانات في ملف GestureRecognizerHelper.kt.

    تنفيذ المهمة

    تستخدم "أداة التعرّف على الإيماءات" الدوال recognize وrecognizeForVideo وrecognizeAsync لعرض الاستنتاجات. بالنسبة إلى التعرف على الإيماءات، فإن ذلك يتضمن المعالجة المسبقة لبيانات الإدخال واكتشاف اليدين في الصورة واكتشاف العلامات المعالم لليد والتعرف على إيماءة اليد من المعالم.

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

    صورة

    val result = gestureRecognizer?.recognize(mpImage)
        

    حملة فيديو

    val timestampMs = i * inferenceIntervalMs
    
    gestureRecognizer?.recognizeForVideo(mpImage, timestampMs)
        ?.let { recognizerResult ->
            resultList.add(recognizerResult)
        }
        

    البث المباشر

    val mpImage = BitmapImageBuilder(rotatedBitmap).build()
    val frameTime = SystemClock.uptimeMillis()
    
    gestureRecognizer?.recognizeAsync(mpImage, frameTime)
        

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

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

    في الرمز النموذجي لأداة التعرّف على الإيماءات، يتم تحديد الدوال recognize وrecognizeForVideo وrecognizeAsync في ملف GestureRecognizerHelper.kt.

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

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

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

    يحتوي GestureRecognizerResult الناتج على أربعة مكوِّنات، وكل مكوِّن هو مصفوفة، حيث يحتوي كل عنصر على النتيجة التي تم اكتشافها ليد واحدة تم اكتشافها.

    • الإنصاف

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

    • الإيماءات

      فئات الإيماءات المعروفة للأيدي التي تم رصدها

    • المَعالم

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

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

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

    GestureRecognizerResult:
      Handedness:
        Categories #0:
          index        : 0
          score        : 0.98396
          categoryName : Left
      Gestures:
        Categories #0:
          score        : 0.76893
          categoryName : Thumb_Up
      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)
    

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

    في الرمز النموذجي لأداة التعرّف على الإيماءات، تعالج الفئة GestureRecognizerResultsAdapter في الملف GestureRecognizerResultsAdapter.kt النتائج.