คำแนะนำการฝังรูปภาพสำหรับ Android

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

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

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

โค้ดตัวอย่าง 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/image_embedder/android
    

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

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

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

  • ImageEmbedderHelper.kt: เริ่มต้นเครื่องมือฝังรูปภาพและจัดการโมเดลและมอบสิทธิ์ มากมาย
  • MainActivity.kt: ใช้งานแอปพลิเคชันและประกอบคอมโพเนนต์อินเทอร์เฟซผู้ใช้

ตั้งค่า

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

การอ้างอิง

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

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

รุ่น

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

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

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

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

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

สร้างงาน

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

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

รูปภาพ

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.IMAGE)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

วิดีโอ

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.VIDEO)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

สตรีมแบบสด

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setResultListener((result, inputImage) -> {
         // Process the embedding result here.
    })
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

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

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

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

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

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

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

LIVE_STREAM: โหมดสำหรับสตรีมแบบสดของอินพุต เช่น ข้อมูลจากกล้อง ในโหมดนี้ resultsListener ต้องเป็น ถูกเรียกให้ตั้งค่า Listener เพื่อรับผลลัพธ์ แบบไม่พร้อมกัน
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
l2_normalize เลือกว่าจะแปลงเวกเตอร์ฟีเจอร์ที่ส่งคืนด้วยบรรทัดฐาน L2 หรือไม่ ใช้ตัวเลือกนี้เฉพาะในกรณีที่โมเดลไม่มีโฆษณาเนทีฟ L2_NORMALIZATION TFLite Op. ในกรณีส่วนใหญ่ กรณีเช่นนี้มักจะเกิดขึ้น และ การปรับมาตรฐาน L2 จึงทำได้ผ่านการอนุมาน TFLite โดยไม่จำเป็นต้อง สำหรับตัวเลือกนี้ Boolean False
quantize ควรแปลงการฝังที่แสดงผลเป็นไบต์เป็นไบต์ผ่านหรือไม่ การวัดสเกลาร์ การฝังจะถูกสันนิษฐานโดยนัยว่าเป็นหน่วยบรรทัดฐานและ ดังนั้น ทุกมิติข้อมูลต้องมีค่าเป็น [-1.0, 1.0] ใช้ ตัวเลือก l2_normalize หากไม่เป็นเช่นนั้น Boolean False
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();
    

ในโค้ดตัวอย่าง การจัดเตรียมข้อมูลจะดำเนินการใน ImageEmbedderHelper.kt

เรียกใช้งาน

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

รูปภาพ

ImageEmbedderResult embedderResult = imageEmbedder.embed(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.
ImageEmbedderResult embedderResult =
    imageEmbedder.embedForVideo(image, frameTimestampMs);
    

สตรีมแบบสด


// Run inference on the frame. The embedding results will be available
// via the `resultListener` provided in the `ImageEmbedderOptions` when
// the image embedder was created.
imageEmbedder.embedAsync(image, frameTimestampMs);
    

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

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

ในโค้ดตัวอย่าง ฟังก์ชัน embed กำหนดไว้ใน ImageEmbedderHelper.kt

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

หลังจากเรียกใช้การอนุมาน งานเครื่องมือฝังรูปภาพจะแสดงผล ImageEmbedderResult ที่มีรายการการฝัง (ทั้งจุดทศนิยมหรือ สเกลาร์-ควอนซ์) สำหรับรูปภาพอินพุต

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

ImageEmbedderResult:
  Embedding #0 (sole embedding head):
    float_embedding: {0.0, 0.0, ..., 0.0, 1.0, 0.0, 0.0, 2.0}
    head_index: 0

ผลการค้นหานี้มาจากการฝังรูปภาพต่อไปนี้

คุณสามารถเปรียบเทียบความคล้ายคลึงกันของการฝัง 2 รายการโดยใช้ ImageEmbedder.cosineSimilarity โปรดดูโค้ดต่อไปนี้สำหรับ

// Compute cosine similarity.
double similarity = ImageEmbedder.cosineSimilarity(
  result.embeddingResult().embeddings().get(0),
  otherResult.embeddingResult().embeddings().get(0));