งานเครื่องมือฝังรูปภาพ MediaPipe ช่วยให้คุณแปลงข้อมูลรูปภาพเป็นตัวเลขเพื่อทำงานด้านการประมวลผลรูปภาพที่เกี่ยวข้องกับ ML ได้ เช่น การเปรียบเทียบความคล้ายคลึงกันของรูปภาพ 2 รูป วิธีการเหล่านี้จะแสดงวิธีใช้ เครื่องมือฝังรูปภาพกับแอป Android
ดูข้อมูลเพิ่มเติมเกี่ยวกับความสามารถ โมเดล และตัวเลือกการกำหนดค่าของงานนี้ได้ที่ภาพรวม
ตัวอย่างโค้ด
โค้ดตัวอย่างงาน MediaPipe Tasks เป็นการใช้งานแอปเครื่องมือฝังรูปภาพสำหรับ Android แบบง่ายๆ ตัวอย่างนี้ใช้กล้องบนอุปกรณ์ Android จริงเพื่อฝังรูปภาพอย่างต่อเนื่อง อีกทั้งยังเรียกใช้เครื่องมือฝังกับไฟล์ภาพที่จัดเก็บไว้ในอุปกรณ์ได้ด้วย
คุณสามารถใช้แอปนี้เป็นจุดเริ่มต้นสำหรับแอป Android ของคุณเองหรือใช้อ้างอิงเมื่อแก้ไขแอปที่มีอยู่ โค้ดตัวอย่างของเครื่องมือฝังรูปภาพโฮสต์อยู่ใน GitHub
ดาวน์โหลดโค้ด
วิธีการต่อไปนี้แสดงวิธีสร้างสำเนาโค้ดตัวอย่างในเครื่องโดยใช้เครื่องมือบรรทัดคำสั่ง git
วิธีดาวน์โหลดโค้ดตัวอย่าง
- โคลนที่เก็บ Git โดยใช้คำสั่งต่อไปนี้
git clone https://github.com/google-ai-edge/mediapipe-samples
- (ไม่บังคับ) กำหนดค่าอินสแตนซ์ 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
เพิ่มทรัพยากร Dependency นี้ไปยังไฟล์ build.gradle
ของโครงการการพัฒนาแอป Android ของคุณ
นำเข้าทรัพยากร Dependency ที่จำเป็นด้วยรหัสต่อไปนี้
dependencies {
...
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
รุ่น
งานเครื่องมือฝังรูปภาพ MediaPipe ต้องใช้โมเดลที่ผ่านการฝึกซึ่งเข้ากันได้กับงานนี้ ดูข้อมูลเพิ่มเติมเกี่ยวกับโมเดลที่ผ่านการฝึกที่พร้อมใช้งานสำหรับเครื่องมือฝังรูปภาพได้ในภาพรวมของงานส่วนโมเดล
เลือกและดาวน์โหลดโมเดล แล้วจัดเก็บไว้ในไดเรกทอรีโปรเจ็กต์ โดยทำดังนี้
<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 โหมดดังนี้ IMAGE: โหมดสำหรับการป้อนข้อมูลรูปภาพเดียว วิดีโอ: โหมดสำหรับเฟรมที่ถอดรหัสของวิดีโอ 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));