إعداد دليل رصد المعالم في Android

تتيح لك مَهمّة MediaPipe Pose تجاهّرل رصد معالم الأجسام البشرية في صورة أو فيديو. يمكنك استخدام هذه المهمة لتحديد الأماكن الرئيسية للجسم وتحليل وضعية الجسم وتصنيف الحركات. تستعين هذه المهمة بنماذج تعلُّم الآلة التي تعمل مع الصور أو الفيديوهات الفردية. تُخرج المهمة معالم وضعية الجسم في إحداثيات الصور وفي إحداثيات العالم ثلاثية الأبعاد.

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

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

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

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

تنزيل الرمز

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

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

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

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

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

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

  • PoseLandmarkerHelper.kt - لإعداد معلَم الوضعية والتعامل مع النموذج والتحديد المفوَّض.
  • CameraFragment.kt - التعامل مع كاميرا الجهاز ومعالجة بيانات إدخال الصور والفيديو.
  • GalleryFragment.kt: للتفاعل مع OverlayView لعرض الصورة أو الفيديو الناتج
  • OverlayView.kt - تنفيذ العرض للأوضاع التي تم رصدها

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

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

التبعيات

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

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

الطراز

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

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

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

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

val modelName = "pose_landmarker_lite.task"
baseOptionsBuilder.setModelAssetPath(modelName)

إنشاء المهمة

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

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

صورة

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

val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
    

حملة فيديو

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

val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
    

البث المباشر

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

val optionsBuilder = 
    poseLandmarker.poseLandmarkerOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinPoseDetectionConfidence(minPoseDetectionConfidence)
        .setMinTrackingConfidence(minPoseTrackingConfidence)
        .setMinPosePresenceConfidence(minposePresenceConfidence)
        .setNumPoses(maxNumPoses)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.LIVE_STREAM)

val options = optionsBuilder.build()
poseLandmarker = poseLandmarker.createFromOptions(context, options)
    

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

خيارات الضبط

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

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

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

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

البث المباشر: وضع بث مباشر لبيانات الإدخال، مثل الكاميرا. في هذا الوضع، يجب استدعاء resultsListener لإعداد أداة معالجة الصوت لكي تتلقى النتائج بشكل غير متزامن.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numposes تمثّل هذه السمة الحد الأقصى لعدد الأوضاع التي يمكن رصدها من خلال أداة Pose Builders. Integer > 0 1
minPoseDetectionConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة ليتم اعتبار ميزة اكتشاف الوضعية ناجحة. Float [0.0,1.0] 0.5
minPosePresenceConfidence الحد الأدنى لدرجة الثقة لنتيجة التواجد في الوضعية في رصد المَعلمات التي يتم رصدها. Float [0.0,1.0] 0.5
minTrackingConfidence تمثّل هذه السمة الحد الأدنى لدرجة الثقة ليتم اعتبار تتبُّع الوضعية ناجحًا. Float [0.0,1.0] 0.5
outputSegmentationMasks ما إذا كانت أداة Pose تجاهُل تُظهر قناع تصنيف للوضع الذي تم رصده. Boolean False
resultListener تعمل هذه السياسة على ضبط أداة معالجة النتائج لكي تتلقّى نتائج المؤشر بشكل غير متزامن عندما تكون أداة Pose Builderer في وضع البث المباشر. لا يمكن استخدام هذا الخيار إلا عند ضبط وضع التشغيل على LIVE_STREAM. ResultListener N/A
errorListener لضبط أداة معالجة الأخطاء الاختيارية. ErrorListener N/A

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

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

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

صورة

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

في مثال تعليمة Pose Builderer، تتم معالجة عملية إعداد البيانات في ملف PoseLandmarkerHelper.kt.

تنفيذ المهمة

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

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

صورة

val result = poseLandmarker.detect(mpImage)
    

حملة فيديو

val timestampMs = i * inferenceIntervalMs

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

البث المباشر

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

poseLandmarker.detectAsync(mpImage, frameTime)
    

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

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

في رمز نموذج Pose Builderer، يتم تحديد الدوال detect وdetectForVideo وdetectAsync في ملف PoseLandmarkerHelper.kt.

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

تعرض أداة Pose Brander كائن poseLandmarkerResult لكل عملية اكتشاف. يحتوي كائن النتيجة على إحداثيات لكل مَعلم وضعية.

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

PoseLandmarkerResult:
  Landmarks:
    Landmark #0:
      x            : 0.638852
      y            : 0.671197
      z            : 0.129959
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.634599
      y            : 0.536441
      z            : -0.06984
      visibility   : 0.999909
      presence     : 0.999958
    ... (33 landmarks per pose)
  WorldLandmarks:
    Landmark #0:
      x            : 0.067485
      y            : 0.031084
      z            : 0.055223
      visibility   : 0.9999997615814209
      presence     : 0.9999984502792358
    Landmark #1:
      x            : 0.063209
      y            : -0.00382
      z            : 0.020920
      visibility   : 0.999976
      presence     : 0.999998
    ... (33 world landmarks per pose)
  SegmentationMasks:
    ... (pictured below)

يحتوي الناتج على كلٍّ من الإحداثيات التي تمت تسويتها (Landmarks) والإحداثيات العالمية (WorldLandmarks) لكل مَعلم.

يحتوي الناتج على الإحداثيات التالية التي تمت تسويتها (Landmarks):

  • x وy: إحداثيات مَعلم تمت تسويتها بين 0.0 و1.0 على عرض الصورة (x) وارتفاعها (y).

  • z: عمق المعالم، وعمق عند منتصف الوركين كلما كانت القيمة أصغر، اقترب المَعلم من الكاميرا. يستخدم مقدار z المقياس نفسه تقريبًا مثل x.

  • visibility: احتمالية ظهور المَعلَم داخل الصورة

يحتوي الناتج على الإحداثيات العالمية التالية (WorldLandmarks):

  • x وy وz: إحداثيات ثلاثية الأبعاد واقعية بالمتر مع منتصف الوركين باعتبارها نقطة الانطلاق

  • visibility: احتمالية ظهور المَعلَم داخل الصورة

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

ويمثل قناع التصنيف الاختياري احتمالية انتماء كل بكسل لشخص تم اكتشافه. الصورة التالية هي قناع تجزئة لناتج المهمة:

يوضح رمز نموذج Poseاخerer كيفية عرض النتائج التي يتم إرجاعها من المهمة. راجع الفئة OverlayView لمزيد من التفاصيل.