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

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

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

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

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

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

تنزيل الرمز

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

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

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

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

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

تحتوي الملفات التالية على الكود المهم لمثال تحديد المكان هذا app:

  • PoseLandmarkerHelper.kt - يؤدي إلى تهيئة معلم الوضع والتعامل مع النموذج والمفوض التحديد.
  • CameraFragment.kt - يعالج كاميرا الجهاز ويعالج بيانات الصورة وإدخال الفيديو.
  • GalleryFragment.kt - يتفاعل مع OverlayView لعرض الصورة أو الفيديو الناتجين.
  • OverlayView.kt - لتطبيق العرض للأوضاع التي تم اكتشافها.

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

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

التبعيات

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

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

الطراز

تتطلب مهمة MediaPipe Pose Insightser حزمة نموذج مدرّبة ومتوافقة مع هذه المهمة. لمزيد من المعلومات حول النماذج المدرَّبة المتاحة لـ Pose Scroller، يُرجى راجِع نظرة عامة على المهام في قسم "النماذج".

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

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

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

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

إنشاء المهمة

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

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

صورة

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 Lookerer للمستخدم إمكانية التبديل بين أوضاع المعالجة. تجعل هذه الطريقة رمز إنشاء المهمة أكثر تعقيدًا قد لا تكون مناسبة لحالة الاستخدام لديك. يمكنك رؤية هذا الرمز في دالة setupPoseLandmarker() في PoseLandmarkerHelper.kt الملف.

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

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

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

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

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

LIVE_STREAM: وضع البث المباشر للإدخال البيانات، مثل تلك الواردة من الكاميرا. في هذا الوضع، يجب أن يكون resultListener يتم استدعاءها لإعداد مستمع للحصول على النتائج بشكل غير متزامن.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numposes الحد الأقصى لعدد الوضعيات التي يمكن رصدها بواسطة أداة جذب الصور 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 Markdown يُخرج قناع تجزئة للجهاز الذي تم رصده وضعية. Boolean False
resultListener تعيين أداة معالجة النتيجة لتلقي نتائج المعلم بشكل غير متزامن عندما يكون Pose Insights في وضع البث المباشر لا يمكن استخدام الإذن إلا عند ضبط "وضع التشغيل" على LIVE_STREAM ResultListener N/A
errorListener تضبط هذه السياسة أداة معالجة للأخطاء اختيارية. ErrorListener N/A

تجهيز البيانات

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

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

صورة

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 Marker، يتم التعامل مع إعداد البيانات في PoseLandmarkerHelper.kt الملف.

تنفيذ المهمة

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

تعرض نماذج الرموز التالية أمثلة بسيطة حول كيفية تشغيل Pose Scroller. في أوضاع البيانات المختلفة هذه:

صورة

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 Insightser
  • عند التشغيل في وضع الصورة أو الفيديو، فإن كتل مهمة Pose Insightser سلسلة التعليمات الحالية إلى أن تنتهي من معالجة صورة أو إطار الإدخال. إلى تجنب حظر موضع المستخدم، وتنفيذ المعالجة في الخلفية .
  • عند تفعيل وضع البث المباشر، يتم عرض مهمة Pose Metricser. على الفور ولا تحظر سلسلة المحادثات الحالية سيؤدي إلى استدعاء النتيجة المستمع مع نتيجة الرصد في كل مرة ينتهي فيها من معالجة إطار الإدخال.

في مثال الرمز الخاص بأداة Pose Lookerer، يمكن استخدام detect وdetectForVideo يتم تحديد دوال detectAsync في PoseLandmarkerHelper.kt الملف.

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

يعرض Pose Markdown كائنًا 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 Lookerer طريقة عرض النتائج التي تم إرجاعها. من المهمة، راجع OverlayView لمزيد من التفاصيل.