คู่มือการตรวจหาจุดสังเกตของมือสำหรับ Android

งานเครื่องมือจุดสังเกตของมือ MediaPipe จะช่วยให้คุณตรวจหาจุดสังเกตของมือในรูปภาพได้ คำแนะนำเหล่านี้จะแสดงวิธีใช้เครื่องมือจุดสังเกตสำหรับแอป Android ตัวอย่างโค้ดที่อธิบายไว้ในวิธีการเหล่านี้มีอยู่ใน GitHub

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับความสามารถ โมเดล และตัวเลือกการกำหนดค่า ของงานนี้ โปรดดูภาพรวม

ตัวอย่างโค้ด

โค้ดตัวอย่างงาน MediaPipe Tasks เป็นการใช้งานที่เรียบง่ายของเครื่องมือจุดสังเกต แอปสำหรับ 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/hand_landmarker/android
    

หลังจากสร้างโค้ดตัวอย่างในเวอร์ชันในเครื่องแล้ว คุณจะนำเข้าโปรเจ็กต์ได้ ลงใน Android Studio และเรียกใช้แอป ดูวิธีการได้ที่ คู่มือการการตั้งค่าสำหรับ Android

องค์ประกอบสำคัญ

ไฟล์ต่อไปนี้มีโค้ดที่สำคัญสำหรับจุดสังเกตของมือนี้ แอปพลิเคชันตัวอย่างการตรวจจับ:

  • HandLandmarkerHelper.kt - เริ่มใช้ตัวตรวจจับจุดสังเกตของมือ รวมถึงจัดการโมเดลและมอบสิทธิ์ มากมาย
  • MainActivity.kt - ใช้งานแอปพลิเคชัน รวมถึงการเรียกใช้ HandLandmarkerHelper

ตั้งค่า

ส่วนนี้จะอธิบายขั้นตอนสำคัญในการตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์ และ โครงการโค้ดสำหรับใช้ Handจุดสังเกต โดยเฉพาะ สำหรับข้อมูลทั่วไปเกี่ยวกับ การตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์ของคุณสำหรับการใช้งาน MediaPipe ซึ่งรวมถึง โปรดดูข้อกำหนดเวอร์ชันของแพลตฟอร์ม คู่มือการตั้งค่าสำหรับ Android

การอ้างอิง

งานเครื่องมือไฮไลต์ด้วยมือใช้ com.google.mediapipe:tasks-vision ไลบรารี เพิ่มทรัพยากร Dependency นี้ลงในไฟล์ build.gradle ของแอป Android

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

รุ่น

งานจุดสังเกตของมือ MediaPipe ต้องการ Bundle โมเดลที่ผ่านการฝึก ซึ่งสามารถทำงานร่วมกับ งานนี้ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับโมเดลที่ผ่านการฝึกและพร้อมใช้งานสำหรับเครื่องมือจุดสังเกตแบบมือ ดูภาพรวมงานส่วนโมเดล

เลือกและดาวน์โหลดโมเดล และเก็บไว้ในไดเรกทอรีโปรเจ็กต์ของคุณ:

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

ระบุเส้นทางของโมเดลภายในพารามิเตอร์ ModelAssetPath ใน โค้ดตัวอย่าง มีการกำหนดโมเดลใน HandLandmarkerHelper.kt ไฟล์:

baseOptionBuilder.setModelAssetPath(MP_HAND_LANDMARKER_TASK)

สร้างงาน

งานเครื่องมือจุดสังเกตแบบมือของ MediaPipe ใช้ฟังก์ชัน createFromOptions() เพื่อตั้งค่า งาน ฟังก์ชัน createFromOptions() จะยอมรับค่าสำหรับการกำหนดค่า ตัวเลือก ดูข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกการกําหนดค่าได้ที่ ตัวเลือกการกำหนดค่า

เครื่องมือไฮไลต์ด้วยมือรองรับการป้อนข้อมูล 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)
    

การใช้โค้ดตัวอย่างของเครื่องมือไฮไลต์ด้วยมือจะช่วยให้ผู้ใช้สามารถสลับระหว่าง โหมดการประมวลผลข้อมูล วิธีนี้ทำให้โค้ดการสร้างงานซับซ้อนขึ้นและ อาจไม่เหมาะกับกรณีการใช้งานของคุณ คุณดูรหัสนี้ได้ใน setupHandLandmarker() ในฟังก์ชัน HandLandmarkerHelper.kt

ตัวเลือกการกำหนดค่า

งานนี้มีตัวเลือกการกำหนดค่าต่อไปนี้สำหรับแอป Android

ชื่อตัวเลือก คำอธิบาย ช่วงค่า ค่าเริ่มต้น
runningMode ตั้งค่าโหมดการทำงานสำหรับงาน มี 3 แบบ โหมด:

รูปภาพ: โหมดสำหรับอินพุตรูปภาพเดียว

วิดีโอ: โหมดสำหรับเฟรมที่ถอดรหัสของวิดีโอ

LIVE_STREAM: โหมดสำหรับสตรีมแบบสดของอินพุต เช่น ข้อมูลจากกล้อง ในโหมดนี้ resultsListener ต้องเป็น ถูกเรียกให้ตั้งค่า Listener เพื่อรับผลลัพธ์ แบบไม่พร้อมกัน
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
numHands จำนวนมือสูงสุดที่ตัวตรวจจับจุดสังเกตของมือตรวจพบ Any integer > 0 1
minHandDetectionConfidence คะแนนความเชื่อมั่นขั้นต่ำสำหรับการตรวจจับมือ โมเดลการตรวจจับฝ่ามือประสบความสำเร็จ 0.0 - 1.0 0.5
minHandPresenceConfidence คะแนนความเชื่อมั่นขั้นต่ำสำหรับคะแนนการตรวจหาบุคคลในมือ โมเดลการตรวจจับจุดสังเกต ในโหมดวิดีโอและโหมดสตรีมแบบสด หากคะแนนความเชื่อมั่นของมือจากโมเดลจุดสังเกตของมืออยู่ต่ำกว่า เครื่องมือจุดสังเกตของมือจะทริกเกอร์โมเดลการตรวจจับฝ่ามือ มิเช่นนั้น อัลกอริทึมการติดตามมือที่มีน้ำหนักเบา จะระบุตำแหน่งของ สำหรับการตรวจหาจุดสังเกตในภายหลัง 0.0 - 1.0 0.5
minTrackingConfidence คะแนนความเชื่อมั่นขั้นต่ำสำหรับการติดตามมือที่จะพิจารณา สำเร็จ นี่คือเกณฑ์ IoU ของกรอบล้อมรอบระหว่างมือใน เฟรมปัจจุบันกับเฟรมสุดท้าย ในโหมดวิดีโอและโหมดสตรีมของ เครื่องมือแลนด์มาร์กด้วยมือ หากการติดตามล้มเหลว เครื่องมือจุดสังเกตของมือจะเรียกใช้มือ การตรวจจับ ไม่เช่นนั้นระบบจะข้ามการตรวจจับมือ 0.0 - 1.0 0.5
resultListener ตั้งค่า Listener ผลลัพธ์เพื่อรับผลลัพธ์การตรวจจับ แบบไม่พร้อมกันเมื่อเครื่องมือจุดสังเกตของมืออยู่ในโหมดสตรีมแบบสด มีผลเมื่อตั้งค่าโหมดวิ่งเป็น LIVE_STREAM เท่านั้น ไม่มี ไม่มี
errorListener ตั้งค่า Listener ข้อผิดพลาดที่ไม่บังคับ ไม่มี ไม่มี

เตรียมข้อมูล

เครื่องมือไฮไลต์ด้วยมือทำงานร่วมกับรูปภาพ ไฟล์วิดีโอ และวิดีโอสตรีมแบบสด งาน จัดการการประมวลผลอินพุตข้อมูลล่วงหน้า ซึ่งรวมถึงการปรับขนาด การหมุน และค่า การแปลงเป็นรูปแบบมาตรฐาน

โค้ดต่อไปนี้แสดงวิธีส่งต่อข้อมูลสำหรับการประมวลผล วิทยานิพนธ์ ตัวอย่างจะให้รายละเอียดเกี่ยวกับวิธีจัดการข้อมูลจากรูปภาพ ไฟล์วิดีโอ และการเผยแพร่ สตรีมวิดีโอ

รูปภาพ

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

ใน โค้ดตัวอย่างเครื่องมือจุดสังเกตแบบมือ การจัดเตรียมข้อมูลมีการจัดการใน HandLandmarkerHelper.kt

เรียกใช้งาน

ใช้เมธอด HandLandmarker.detect...() ที่เฉพาะเจาะจงสำหรับประเภทข้อมูลดังกล่าว ใช้ detect()สำหรับรูปภาพแต่ละรูป detectForVideo() สำหรับเฟรมในไฟล์วิดีโอ และ detectAsync()สำหรับสตรีมวิดีโอ เมื่อคุณดำเนินการตรวจหาใน สตรีมวิดีโอ โปรดตรวจสอบว่าคุณได้เรียกใช้การตรวจจับในชุดข้อความแยกต่างหากเพื่อหลีกเลี่ยงการตรวจพบ บล็อกชุดข้อความอินเทอร์เฟซผู้ใช้

ตัวอย่างโค้ดต่อไปนี้แสดงตัวอย่างง่ายๆ ของวิธีเรียกใช้เครื่องมือจุดสังเกตของมือ ในโหมดข้อมูลที่แตกต่างกันเหล่านี้

รูปภาพ

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)
    

โปรดทราบดังต่อไปนี้

  • เมื่อทำงานในโหมดวิดีโอหรือโหมดสตรีมแบบสด คุณต้อง ระบุการประทับเวลาของเฟรมป้อนข้อมูลในงานเครื่องมือจุดสังเกตของมือ
  • เมื่อเรียกใช้ในโหมดรูปภาพหรือวิดีโอ งานเครื่องมือไฮไลต์ด้วยมือจะ บล็อกชุดข้อความปัจจุบันจนกว่าจะประมวลผลรูปภาพอินพุตเสร็จสิ้น หรือ เฟรม หากต้องการหลีกเลี่ยงการบล็อกอินเทอร์เฟซผู้ใช้ ให้เรียกใช้การประมวลผลใน เทรดพื้นหลัง
  • เมื่อทำงานในโหมดสตรีมแบบสด งานเครื่องมือไฮไลต์ด้วยมือจะไม่บล็อก ชุดข้อความปัจจุบันแต่จะแสดงอีกครั้งทันที ระบบจะเรียกใช้ผลลัพธ์ Listener พร้อมผลลัพธ์การตรวจจับทุกครั้งที่ประมวลผลเสร็จแล้ว เฟรมอินพุต หากมีการเรียกฟังก์ชันการตรวจจับเมื่องานเครื่องมือไฮไลต์ด้วยมือ ไม่ว่างในการประมวลผลเฟรมอื่น งานจะไม่สนใจเฟรมอินพุตใหม่

ใน โค้ดตัวอย่างสำหรับเครื่องมือไฮไลต์ด้วยมือ, detect, detectForVideo และ มีการกำหนดฟังก์ชัน detectAsync ในฟังก์ชัน HandLandmarkerHelper.kt

จัดการและแสดงผลลัพธ์

เครื่องมือไฮไลต์ด้วยมือจะสร้างออบเจ็กต์ผลลัพธ์ที่เป็นจุดสังเกตสำหรับมือสำหรับการตรวจหาแต่ละครั้ง วิ่งได้ วัตถุผลลัพธ์มีจุดสังเกตของมือในพิกัดรูปภาพ มือ จุดสังเกตในพิกัดโลกและความถนัดของมือ(ซ้าย/ขวา) ของที่ตรวจพบ มือ

ตัวอย่างต่อไปนี้แสดงตัวอย่างข้อมูลเอาต์พุตจากงานนี้

เอาต์พุต HandLandmarkerResult มี 3 คอมโพเนนต์ คอมโพเนนต์แต่ละรายการคืออาร์เรย์ โดยที่องค์ประกอบแต่ละรายการจะมีผลลัพธ์ต่อไปนี้สำหรับมือข้างเดียวที่ตรวจพบ

  • ความถนัดของมือ

    ความถนัดของมือแสดงให้เห็นว่ามือที่ตรวจพบเป็นมือซ้ายหรือมือขวา

  • จุดสังเกต

    มีจุดสังเกต 21 จุด แต่ละรายการประกอบด้วยพิกัด x, y และ z พิกัด x และ y จะได้รับการปรับให้เป็น [0.0, 1.0] ตามความกว้างของภาพและ ตามลำดับ พิกัด z แสดงความลึกของจุดสังเกต โดยมี ความลึกที่ข้อมือซึ่งเป็นจุดเริ่มต้น ยิ่งค่าน้อยเท่าไหร่ ก็ยิ่งใกล้ ที่สำคัญคือกล้อง ขนาดของ z ใช้มาตราส่วนใกล้เคียงกับ x

  • สถานที่สำคัญของโลก

    นอกจากนี้ สัญลักษณ์มือ 21 ข้างยังแสดงเป็นพิกัดของโลกด้วย จุดสังเกตแต่ละแห่ง ประกอบด้วย x, y และ z ซึ่งจะแสดงพิกัด 3 มิติตามจริงใน เมตรที่มีจุดกำเนิดอยู่ที่จุดศูนย์กลางเรขาคณิตของมือ

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)

รูปภาพต่อไปนี้แสดงการแสดงภาพเอาต์พุตของงาน

โค้ดตัวอย่างของเครื่องมือไฮไลต์ด้วยมือสาธิตวิธีการแสดง ผลลัพธ์ที่ส่งคืนจากงาน โปรดดู OverlayView เพื่อดูรายละเอียดเพิ่มเติม