คำแนะนำการตรวจจับวัตถุสำหรับ Android

ภารกิจตัวตรวจจับวัตถุช่วยให้คุณตรวจหาการมีอยู่และตำแหน่งของวัตถุหลายคลาสได้ เช่น เครื่องมือตรวจจับวัตถุสามารถหาตำแหน่งสุนัขในรูปภาพ วิธีการเหล่านี้แสดงวิธีใช้งานตัวตรวจจับวัตถุใน 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/object_detection/android
    

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

คอมโพเนนต์หลัก

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

  • ObjectDetectorHelper.kt - เริ่มต้นตัวตรวจจับวัตถุและจัดการโมเดลและการเลือกตัวแทน
  • MainActivity.kt - ใช้แอปพลิเคชันและประกอบคอมโพเนนต์อินเทอร์เฟซผู้ใช้
  • OverlayView.kt - จัดการและแสดงผลลัพธ์

ตั้งค่า

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

การอ้างอิง

ตัวตรวจจับวัตถุใช้ไลบรารี com.google.mediapipe:tasks-vision เพิ่มข้อกำหนดนี้ลงในไฟล์ build.gradle ของโปรเจ็กต์การพัฒนาแอป Android นําเข้าข้อกําหนดเบื้องต้นที่จําเป็นด้วยโค้ดต่อไปนี้

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

รุ่น

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

เลือกและดาวน์โหลดโมเดล จากนั้นจัดเก็บไว้ในไดเรกทอรีโปรเจ็กต์

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

ใช้เมธอด BaseOptions.Builder.setModelAssetPath() เพื่อระบุเส้นทางที่โมเดลใช้ ดูตัวอย่างโค้ดได้ที่ส่วนถัดไป

สร้างงาน

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

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

รูปภาพ

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

วิดีโอ

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

ไลฟ์สด

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(model.tflite).build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
      // Process the detection result here.
    })
    .setErrorListener((result, inputImage) -> {
      // Process the classification errors here.
    })
   .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

การใช้โค้ดตัวอย่างของโปรแกรมตรวจจับวัตถุช่วยให้ผู้ใช้สลับระหว่างโหมดการประมวลผลได้ แนวทางนี้ทําให้โค้ดการสร้างงานซับซ้อนขึ้นและอาจไม่เหมาะกับกรณีการใช้งานของคุณ คุณจะเห็นโค้ดนี้ในฟังก์ชัน setupObjectDetector() ของคลาส ObjectDetectorHelper

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

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

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

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

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

LIVE_STREAM: โหมดสตรีมแบบสดของข้อมูลอินพุต เช่น จากกล้อง ในโหมดนี้ คุณต้องเรียกใช้ resultListener เพื่อตั้งค่า Listener เพื่อรับผลลัพธ์แบบไม่พร้อมกัน
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
displayNamesLocales ตั้งค่าภาษาของป้ายกำกับที่จะใช้สำหรับชื่อที่แสดงซึ่งระบุไว้ในข้อมูลเมตาของโมเดลของงาน (หากมี) ค่าเริ่มต้นคือ en สำหรับภาษาอังกฤษ คุณเพิ่มป้ายกำกับที่แปลแล้วลงในข้อมูลเมตาของโมเดลที่กำหนดเองได้โดยใช้ TensorFlow Lite Metadata Writer API รหัสภาษา en
maxResults กําหนดจํานวนสูงสุดของผลการค้นหาที่ตรวจพบซึ่งได้คะแนนสูงสุดที่จะแสดง (ไม่บังคับ) ตัวเลขบวกใดก็ได้ -1 (แสดงผลลัพธ์ทั้งหมด)
scoreThreshold ตั้งค่าเกณฑ์คะแนนการคาดการณ์ที่จะลบล้างเกณฑ์ที่ระบุไว้ในข้อมูลเมตาของโมเดล (หากมี) ระบบจะปฏิเสธผลลัพธ์ที่ต่ำกว่าค่านี้ ตัวเลขทศนิยม ไม่ได้ตั้งค่า
categoryAllowlist ตั้งค่ารายการชื่อหมวดหมู่ที่อนุญาต (ไม่บังคับ) หากไม่ว่างเปล่า ระบบจะกรองผลการตรวจหาที่มีชื่อหมวดหมู่ไม่อยู่ในชุดนี้ออก ระบบจะไม่สนใจชื่อหมวดหมู่ที่ซ้ำกันหรือไม่รู้จัก ตัวเลือกนี้ใช้ร่วมกับ categoryDenylist ไม่ได้ และการใช้ทั้ง 2 ตัวเลือกจะทำให้เกิดข้อผิดพลาด สตริงใดก็ได้ ไม่ได้ตั้งค่า
categoryDenylist ตั้งค่ารายการชื่อหมวดหมู่ที่ไม่อนุญาต (ไม่บังคับ) หากไม่ว่างเปล่า ระบบจะกรองผลการตรวจหาที่มีชื่อหมวดหมู่อยู่ในชุดนี้ออก ระบบจะไม่สนใจชื่อหมวดหมู่ที่ซ้ำกันหรือไม่รู้จัก ตัวเลือกนี้ใช้ร่วมกันกับ categoryAllowlist ไม่ได้ และการใช้ทั้ง 2 ตัวเลือกจะทำให้เกิดข้อผิดพลาด สตริงใดก็ได้ ไม่ได้ตั้งค่า
resultListener ตั้งค่าโปรแกรมรับฟังผลลัพธ์ให้รับผลลัพธ์การตรวจจับแบบไม่พร้อมกันเมื่อตัวตรวจจับวัตถุอยู่ในโหมดสตรีมแบบสด คุณจะใช้ตัวเลือกนี้ได้ก็ต่อเมื่อตั้งค่า runningMode เป็น LIVE_STREAM เท่านั้น ไม่เกี่ยวข้อง ไม่ได้ตั้งค่า

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

คุณต้องแปลงรูปภาพหรือเฟรมอินพุตเป็นออบเจ็กต์ com.google.mediapipe.framework.image.MPImage ก่อนส่งไปยังโปรแกรมตรวจจับวัตถุ

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

รูปภาพ

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the users device as a Bitmap object using BitmapFactory.

// Convert an Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

วิดีโอ

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load a video file on the user's device using MediaMetadataRetriever

// From the videos metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT values. Use these values
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

ไลฟ์สด

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraXs ImageAnalysis to continuously receive frames
// from the devices camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Androids ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Androids Image object and convert it to
// a MediaPipes Image object.
android.media.Image mediaImage = imageProxy.getImage()
MPImage mpImage = new MediaImageBuilder(mediaImage).build();
    

ในโค้ดตัวอย่างของโปรแกรมตรวจจับวัตถุ การเตรียมข้อมูลจะดำเนินการในคลาส ObjectDetectorHelper ภายในฟังก์ชัน detectImage(), detectVideoFile(), detectLivestreamFrame()

เรียกใช้งาน

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

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

รูปภาพ

ObjectDetectorResult detectionResult = objectDetector.detect(image);
    

วิดีโอ

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ObjectDetectorResult detectionResult =
    objectDetector.detectForVideo(image, frameTimestampMs);
    

ไลฟ์สด

// Run inference on the frame. The detection results will be available
// via the `resultListener` provided in the `ObjectDetectorOptions` when
// the object detector was created.
objectDetector.detectAsync(image, frameTimestampMs);
    

ตัวอย่างโค้ดของโปรแกรมตรวจจับวัตถุแสดงการใช้งานโหมดเหล่านี้อย่างละเอียด detect(), detectVideoFile() และ detectAsync() โค้ดตัวอย่างนี้ช่วยให้ผู้ใช้สลับระหว่างโหมดการประมวลผลได้ ซึ่งอาจไม่จำเป็นสำหรับกรณีการใช้งานของคุณ

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

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

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

เมื่อทำการอนุมาน งานตรวจจับวัตถุจะแสดงผลออบเจ็กต์ ObjectDetectorResult ซึ่งอธิบายวัตถุที่พบในรูปภาพอินพุต

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

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

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

สุนัข 2 ตัวที่ไฮไลต์ด้วยกรอบล้อมรอบ

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