คู่มือการแบ่งกลุ่มรูปภาพสำหรับ Android

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

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

ตัวอย่างโค้ดงานของ MediaPipe มีการติดตั้งใช้งานแอปเครื่องมือแบ่งรูปภาพอย่างง่าย 2 แบบสำหรับ 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/image_segmentation/android
    

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

องค์ประกอบหลัก

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

  • ImageSegmenterHelper.kt - เริ่มต้นงานเครื่องมือแบ่งรูปภาพ และจัดการโมเดลและมอบสิทธิ์การเลือก
  • CameraFragment.kt - มีอินเทอร์เฟซผู้ใช้และโค้ดการควบคุมสำหรับกล้อง
  • GalleryFragment.kt - มีอินเทอร์เฟซผู้ใช้และรหัสการควบคุมสำหรับเลือกไฟล์รูปภาพและวิดีโอ
  • OverlayView.kt - จัดการและจัดรูปแบบผลลัพธ์การแบ่งกลุ่ม

ตั้งค่า

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

การอ้างอิง

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

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

รุ่น

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

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

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

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

ในโค้ดตัวอย่างของเครื่องมือแบ่งกลุ่มรูปภาพ โมเดลจะได้รับการกำหนดในคลาส ImageSegmenterHelper.kt ในฟังก์ชัน setupImageSegmenter()

สร้างงาน

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

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

รูปภาพ

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

วิดีโอ

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

สตรีมแบบสด

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .setResultListener((result, inputImage) -> {
         // Process the segmentation result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the segmentation errors here.
    })
    .build()
imagesegmenter = ImageSegmenter.createFromOptions(context, options)
    

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

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

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

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

IMAGE: โหมดสำหรับการป้อนข้อมูลรูปภาพเดียว

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

LIVE_Stream: โหมดสำหรับสตรีมแบบสดของข้อมูลอินพุต เช่น จากกล้อง ในโหมดนี้ ต้องมีการเรียกใช้ resultsListener เพื่อตั้งค่า Listener เพื่อรับผลลัพธ์แบบไม่พร้อมกัน
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
outputCategoryMask หากตั้งค่าเป็น True เอาต์พุตจะมีมาสก์การแบ่งกลุ่มเป็นรูปภาพ uint8 ซึ่งค่าพิกเซลแต่ละค่าบ่งชี้ถึงค่าหมวดหมู่ที่ชนะ {True, False} False
outputConfidenceMasks หากตั้งค่าเป็น True เอาต์พุตจะมีมาสก์การแบ่งกลุ่มลูกค้าเป็นภาพค่าลอยตัว โดยค่าทศนิยมแต่ละค่าแสดงแมปคะแนนความเชื่อมั่นของหมวดหมู่ {True, False} True
displayNamesLocale ตั้งค่าภาษาของป้ายกำกับที่จะใช้กับชื่อที่แสดงซึ่งระบุไว้ในข้อมูลเมตาของโมเดลของงาน หากมี ค่าเริ่มต้นคือ en สำหรับภาษาอังกฤษ คุณเพิ่มป้ายกำกับที่แปลเป็นภาษาท้องถิ่นลงในข้อมูลเมตาของโมเดลที่กำหนดเองได้โดยใช้ TensorFlow Lite Metadata Writer API รหัสภาษา en
resultListener ตั้งค่า Listener ผลลัพธ์ให้รับผลลัพธ์การแบ่งกลุ่มแบบไม่พร้อมกันเมื่อตัวแบ่งกลุ่มรูปภาพอยู่ในโหมดสตรีมแบบสด ใช้ได้เมื่อตั้งค่าโหมดการทำงานเป็น LIVE_STREAM เท่านั้น ไม่มีข้อมูล ไม่มีข้อมูล
errorListener ตั้งค่า Listener ข้อผิดพลาดที่ไม่บังคับ ไม่มีข้อมูล ไม่ได้ตั้งค่า

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

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

คุณต้องแปลงรูปภาพหรือเฟรมอินพุตเป็นออบเจ็กต์ 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 user’s device as a Bitmap object using BitmapFactory.

// Convert an Android’s Bitmap object to a MediaPipe’s 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 video’s metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. You’ll need them
// to calculate the timestamp of each frame later.

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

// Convert the Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

สตรีมแบบสด

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

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

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

ในโค้ดตัวอย่างเครื่องมือแบ่งรูปภาพ ฟังก์ชัน segmentLiveStreamFrame() จะจัดการการเตรียมข้อมูลในคลาส ImageSegmenterHelper

เรียกใช้งาน

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

รูปภาพ

ImageSegmenterResult segmenterResult = imagesegmenter.segment(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.
ImageSegmenterResult segmenterResult =
    imagesegmenter.segmentForVideo(image, frameTimestampMs);
    

สตรีมแบบสด

// Run inference on the frame. The segmentations results will be available via
// the `resultListener` provided in the `ImageSegmenterOptions` when the image
// segmenter was created.
imagesegmenter.segmentAsync(image, frameTimestampMs);
    

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

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

ในโค้ดตัวอย่างเครื่องมือแบ่งรูปภาพ ฟังก์ชัน segment จะกำหนดไว้ในไฟล์ ImageSegmenterHelper.kt

แฮนเดิลและแสดงผลลัพธ์

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

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

ความเชื่อมั่นของหมวดหมู่

รูปภาพต่อไปนี้แสดงภาพเอาต์พุตงานสำหรับมาสก์ความเชื่อมั่นของหมวดหมู่ เอาต์พุตมาสก์ความเชื่อมั่นมีค่าทศนิยมระหว่าง [0, 1]

เอาต์พุตมาสก์ความเชื่อมั่นของรูปภาพและหมวดหมู่ต้นฉบับ รูปภาพต้นฉบับจากชุดข้อมูล Pascal VOC 2012

ค่าของหมวดหมู่

รูปภาพต่อไปนี้แสดงภาพเอาต์พุตงานสำหรับมาสก์ค่าหมวดหมู่ ช่วงมาสก์หมวดหมู่คือ [0, 255] และค่าพิกเซลแต่ละค่าแสดงถึงดัชนีหมวดหมู่ที่ชนะของเอาต์พุตโมเดล ดัชนีหมวดหมู่ที่ชนะจะมีคะแนนสูงสุดในหมวดหมู่ที่โมเดลจดจำได้

เอาต์พุตมาสก์รูปภาพและหมวดหมู่ต้นฉบับ รูปภาพต้นฉบับจากชุดข้อมูล Pascal VOC 2012