راهنمای تشخیص نقطه عطف برای Android

وظیفه MediaPipe Pose Landmarker به شما امکان می دهد نشانه های بدن انسان را در یک تصویر یا ویدیو تشخیص دهید. شما می توانید از این کار برای شناسایی مکان های کلیدی بدن، تجزیه و تحلیل وضعیت بدن و دسته بندی حرکات استفاده کنید. این کار از مدل‌های یادگیری ماشینی (ML) استفاده می‌کند که با تصاویر یا ویدیوهای منفرد کار می‌کنند. وظیفه خروجی نقاط عطف ژست بدن در مختصات تصویر و در مختصات جهان سه بعدی است.

نمونه کد شرح داده شده در این دستورالعمل ها در GitHub موجود است. برای اطلاعات بیشتر در مورد قابلیت‌ها، مدل‌ها و گزینه‌های پیکربندی این کار، به نمای کلی مراجعه کنید.

نمونه کد

کد مثال MediaPipe Tasks یک پیاده سازی ساده از یک برنامه Pose Landmarker برای اندروید است. این مثال از دوربین یک دستگاه اندروید فیزیکی برای تشخیص وضعیت‌ها در یک جریان ویدیویی مداوم استفاده می‌کند. این برنامه همچنین می‌تواند حالت‌ها را در تصاویر و ویدیوهای گالری دستگاه تشخیص دهد.

می‌توانید از برنامه به‌عنوان نقطه شروع برای برنامه اندرویدی خود استفاده کنید یا هنگام تغییر برنامه موجود به آن مراجعه کنید. کد نمونه Pose Landmarker در GitHub میزبانی می شود.

کد را دانلود کنید

دستورالعمل های زیر به شما نشان می دهد که چگونه با استفاده از ابزار خط فرمان git یک کپی محلی از کد مثال ایجاد کنید.

برای دانلود کد نمونه:

  1. با استفاده از دستور زیر مخزن git را کلون کنید:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. به صورت اختیاری، نمونه git خود را برای استفاده از پرداخت پراکنده پیکربندی کنید، بنابراین فقط فایل‌های برنامه نمونه Pose Landmarker را داشته باشید:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/pose_landmarker/android
    

پس از ایجاد یک نسخه محلی از کد نمونه، می توانید پروژه را به اندروید استودیو وارد کرده و برنامه را اجرا کنید. برای دستورالعمل‌ها، به راهنمای راه‌اندازی برای Android مراجعه کنید.

اجزای کلیدی

فایل‌های زیر حاوی کد حیاتی برای این برنامه کاربردی نمونه نقطه‌نما هستند:

  • PoseLandmarkerHelper.kt - نشانگر پوز را راه اندازی می کند و مدل و انتخاب نماینده را مدیریت می کند.
  • CameraFragment.kt - دوربین دستگاه را کنترل می کند و داده های ورودی تصویر و ویدیو را پردازش می کند.
  • GalleryFragment.kt - برای نمایش تصویر یا ویدیوی خروجی با OverlayView تعامل دارد.
  • OverlayView.kt - نمایشگر پوزهای شناسایی شده را پیاده سازی می کند.

برپایی

این بخش مراحل کلیدی را برای راه اندازی محیط توسعه و پروژه های کد به طور خاص برای استفاده از Pose Landmarker توضیح می دهد. برای اطلاعات کلی در مورد تنظیم محیط توسعه خود برای استفاده از وظایف MediaPipe، از جمله الزامات نسخه پلت فرم، به راهنمای راه اندازی برای Android مراجعه کنید.

وابستگی ها

وظیفه Pose Landmarker از کتابخانه com.google.mediapipe:tasks-vision استفاده می کند. این وابستگی را به فایل build.gradle برنامه اندروید خود اضافه کنید:

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

مدل

وظیفه MediaPipe Pose Landmarker به یک بسته مدل آموزش دیده نیاز دارد که با این کار سازگار باشد. برای اطلاعات بیشتر در مورد مدل‌های آموزش‌دیده موجود برای Pose Landmarker، به بخش مدل‌های نمای کلی کار مراجعه کنید.

مدل را انتخاب و دانلود کنید و آن را در فهرست پروژه خود ذخیره کنید:

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

مسیر مدل را در پارامتر ModelAssetPath مشخص کنید. در کد مثال، مدل در فایل PoseLandmarkerHelper.kt تعریف شده است:

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

کار را ایجاد کنید

وظیفه MediaPipe Pose Landmarker از تابع createFromOptions() برای تنظیم کار استفاده می کند. تابع createFromOptions() مقادیری را برای گزینه های پیکربندی می پذیرد. برای اطلاعات بیشتر در مورد گزینه های پیکربندی، گزینه های پیکربندی را ببینید.

Pose Landmarker از انواع داده‌های ورودی زیر پشتیبانی می‌کند: تصاویر ثابت، فایل‌های ویدیویی، و جریان‌های ویدیویی زنده. هنگام ایجاد کار، باید حالت اجرای مربوط به نوع داده ورودی خود را مشخص کنید. برای مشاهده نحوه ایجاد کار، برگه را برای نوع داده ورودی خود انتخاب کنید.

تصویر

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 Landmarker به کاربر اجازه می دهد تا بین حالت های پردازش جابجا شود. این رویکرد کد ایجاد کار را پیچیده‌تر می‌کند و ممکن است برای مورد استفاده شما مناسب نباشد. می توانید این کد را در تابع setupPoseLandmarker() در فایل PoseLandmarkerHelper.kt مشاهده کنید.

گزینه های پیکربندی

این کار دارای گزینه های پیکربندی زیر برای برنامه های Android است:

نام گزینه شرح محدوده ارزش مقدار پیش فرض
runningMode حالت اجرا را برای کار تنظیم می کند. سه حالت وجود دارد:

IMAGE: حالت برای ورودی های تک تصویر.

VIDEO: حالت برای فریم های رمزگشایی شده یک ویدیو.

LIVE_STREAM: حالت پخش زنده داده های ورودی، مانند دوربین. در این حالت، resultListener باید فراخوانی شود تا شنونده ای را برای دریافت نتایج به صورت ناهمزمان تنظیم کند.
{ IMAGE, VIDEO, LIVE_STREAM } IMAGE
numposes حداکثر تعداد پوزی که می تواند توسط Pose Landmarker شناسایی شود. 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 Landmarker یک ماسک تقسیم‌بندی را برای ژست شناسایی شده خروجی می‌دهد یا خیر. Boolean False
resultListener شنونده نتیجه را طوری تنظیم می کند که وقتی Pose Landmarker در حالت پخش زنده است، نتایج نشانگر را به صورت ناهمزمان دریافت کند. فقط زمانی قابل استفاده است که حالت اجرا روی LIVE_STREAM تنظیم شده باشد ResultListener N/A
errorListener یک شنونده خطای اختیاری را تنظیم می کند. ErrorListener N/A

داده ها را آماده کنید

Pose Landmarker با تصاویر، فایل‌های ویدیویی و جریان‌های ویدیویی زنده کار می‌کند. این وظیفه، پیش پردازش ورودی داده، از جمله تغییر اندازه، چرخش و نرمال سازی مقدار را انجام می دهد.

کد زیر نحوه واگذاری داده ها را برای پردازش نشان می دهد. این نمونه‌ها شامل جزئیات نحوه مدیریت داده‌ها از تصاویر، فایل‌های ویدیویی و جریان‌های ویدیویی زنده است.

تصویر

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 Landmarker، آماده سازی داده ها در فایل PoseLandmarkerHelper.kt انجام می شود.

وظیفه را اجرا کنید

بسته به نوع داده ای که با آن کار می کنید، از متد poseLandmarker.detect...() که مخصوص آن نوع داده است استفاده کنید. از detect() برای تصاویر جداگانه، detectForVideo() برای فریم در فایل های ویدئویی و detectAsync() برای جریان های ویدئویی استفاده کنید. هنگامی که در حال انجام تشخیص در یک جریان ویدیویی هستید، مطمئن شوید که تشخیص‌ها را در یک رشته جداگانه اجرا می‌کنید تا از مسدود کردن رشته بین کاربر جلوگیری کنید.

نمونه کد زیر نمونه‌های ساده‌ای از نحوه اجرای Pose Landmarker در این حالت‌های داده مختلف را نشان می‌دهد:

تصویر

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 Landmarker ارائه دهید.
  • هنگامی که در حالت تصویر یا ویدیو اجرا می شود، وظیفه Pose Landmarker رشته فعلی را مسدود می کند تا زمانی که پردازش تصویر یا فریم ورودی به پایان برسد. برای جلوگیری از مسدود کردن interpose کاربر، پردازش را در یک رشته پس‌زمینه اجرا کنید.
  • هنگامی که در حالت پخش زنده اجرا می شود، وظیفه Pose Landmarker بلافاصله برمی گردد و رشته فعلی را مسدود نمی کند. هر بار که پردازش یک فریم ورودی را تمام می کند، شنونده نتیجه را با نتیجه تشخیص فراخوانی می کند.

در کد مثال Pose Landmarker، توابع detect ، detectForVideo و detectAsync در فایل PoseLandmarkerHelper.kt تعریف شده‌اند.

کنترل و نمایش نتایج

Pose Landmarker یک شی 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 Landmarker نحوه نمایش نتایج بازگشتی از کار را نشان می دهد، برای جزئیات بیشتر به کلاس OverlayView مراجعه کنید.