راهنمای تشخیص نشانه های دستی برای اندروید، راهنمای تشخیص نشانه های دستی برای اندروید

وظیفه MediaPipe Hand Landmarker به شما این امکان را می دهد که نشانه های دست ها را در یک تصویر تشخیص دهید. این دستورالعمل‌ها به شما نشان می‌دهند که چگونه از Hand Landmarker با برنامه‌های Android استفاده کنید. نمونه کد شرح داده شده در این دستورالعمل ها در GitHub موجود است.

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

نمونه کد

کد مثال MediaPipe Tasks یک پیاده سازی ساده از یک برنامه Hand Landmarker برای اندروید است. این مثال از دوربین یک دستگاه اندروید فیزیکی برای شناسایی مداوم نشانه‌های دستی استفاده می‌کند، و همچنین می‌تواند از تصاویر و ویدیوهای گالری دستگاه برای تشخیص استاتیک نشانه‌های دستی استفاده کند.

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

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

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

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

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

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

اجزای کلیدی

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

  • HandLandmarkerHelper.kt - آشکارساز نشانه دستی را راه‌اندازی می‌کند و مدل و انتخاب نماینده را کنترل می‌کند.
  • MainActivity.kt - برنامه را پیاده سازی می کند، از جمله فراخوانی HandLandmarkerHelper .

راه اندازی

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

وابستگی ها

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

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

مدل

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

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

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

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

baseOptionBuilder.setModelAssetPath(MP_HAND_LANDMARKER_TASK)

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

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

Hand Landmarker از 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)
    

اجرای کد نمونه Hand Landmarker به کاربر اجازه می دهد تا بین حالت های پردازش جابجا شود. این رویکرد کد ایجاد کار را پیچیده‌تر می‌کند و ممکن است برای مورد استفاده شما مناسب نباشد. می توانید این کد را در تابع setupHandLandmarker() در فایل HandLandmarkerHelper.kt ببینید.

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

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

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

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

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

LIVE_STREAM: حالت پخش زنده داده های ورودی، مانند دوربین. در این حالت، resultListener باید فراخوانی شود تا شنونده ای را برای دریافت نتایج به صورت ناهمزمان تنظیم کند.
{ IMAGE, VIDEO, LIVE_STREAM } IMAGE
numHands حداکثر تعداد دست های شناسایی شده توسط آشکارساز نشانه دستی. Any integer > 0 1
minHandDetectionConfidence حداقل امتیاز اطمینان برای تشخیص دست برای موفقیت در مدل تشخیص کف دست. 0.0 - 1.0 0.5
minHandPresenceConfidence حداقل امتیاز اطمینان برای امتیاز حضور دست در مدل تشخیص نقطه عطف دست. در حالت ویدیو و حالت پخش زنده، اگر امتیاز اطمینان حضور دست از مدل نقطه عطف دست کمتر از این آستانه باشد، Hand Landmarker مدل تشخیص کف دست را فعال می‌کند. در غیر این صورت، یک الگوریتم ردیابی دست سبک، مکان دست(ها) را برای تشخیص نشانه های بعدی تعیین می کند. 0.0 - 1.0 0.5
minTrackingConfidence حداقل امتیاز اطمینان برای ردیابی دست که موفقیت آمیز در نظر گرفته شود. این آستانه جعبه محدود کننده IoU بین دست ها در فریم فعلی و آخرین فریم است. در حالت ویدیو و حالت جریان از Hand Landmarker، اگر ردیابی ناموفق باشد، Hand Landmarker تشخیص دست را فعال می‌کند. در غیر این صورت، تشخیص دست را نادیده می گیرد. 0.0 - 1.0 0.5
resultListener شنونده نتیجه را طوری تنظیم می کند که وقتی نشانگر دستی در حالت پخش زنده است، نتایج تشخیص را به صورت ناهمزمان دریافت کند. فقط زمانی قابل اجراست که حالت اجرا روی LIVE_STREAM تنظیم شده باشد N/A N/A
errorListener یک شنونده خطای اختیاری را تنظیم می کند. N/A N/A

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

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

در کد نمونه Hand Landmarker، آماده سازی داده ها در فایل HandLandmarkerHelper.kt انجام می شود.

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

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

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

تصویر

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)
    

به موارد زیر توجه کنید:

  • هنگام اجرا در حالت ویدیو یا حالت پخش زنده، باید مهر زمانی فریم ورودی را نیز به کار Hand Landmarker ارائه دهید.
  • هنگام اجرا در حالت تصویر یا ویدیو، کار Hand Landmarker تا زمانی که پردازش تصویر یا فریم ورودی به پایان برسد، رشته فعلی را مسدود می کند. برای جلوگیری از مسدود کردن رابط کاربری، پردازش را در یک رشته پس‌زمینه اجرا کنید.
  • هنگام اجرا در حالت پخش زنده، کار Hand Landmarker رشته فعلی را مسدود نمی کند، اما بلافاصله برمی گردد. هر بار که پردازش یک فریم ورودی را تمام کند، شنونده نتیجه خود را با نتیجه تشخیص فراخوانی می کند. اگر زمانی که کار Hand Landmarker مشغول پردازش فریم دیگری است، تابع تشخیص فراخوانی شود، کار کادر ورودی جدید را نادیده می گیرد.

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

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

Hand Landmarker یک شی نتیجه نشانگر دستی را برای هر اجرا تشخیص تولید می کند. شی نتیجه شامل نشانه های دست در مختصات تصویر، نشانه های دست در مختصات جهان و دست (چپ/راست) دست های شناسایی شده است.

شکل زیر نمونه ای از داده های خروجی از این کار را نشان می دهد:

خروجی 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)

تصویر زیر تصویری از خروجی کار را نشان می دهد:

کد مثال Hand Landmarker نحوه نمایش نتایج بازگشتی از کار را نشان می دهد، برای جزئیات بیشتر به کلاس OverlayView مراجعه کنید.