คุณใช้ ML Kit เพื่อจดจำเอนทิตีในรูปภาพและติดป้ายกำกับได้ API นี้รองรับโมเดลการจัดประเภทรูปภาพที่กำหนดเองอย่างหลากหลาย โปรดอ่านโมเดลที่กำหนดเองที่มี ML Kit เพื่อดูคำแนะนำเกี่ยวกับข้อกำหนดความเข้ากันได้ของโมเดล ตำแหน่งที่ฝึกโมเดลก่อนการฝึก และวิธีฝึกโมเดลของคุณเอง
การผสานรวมการติดป้ายกำกับรูปภาพกับโมเดลที่กำหนดเองมี 2 วิธี ได้แก่ การรวมไปป์ไลน์เป็นส่วนหนึ่งของแอป หรือการใช้ไปป์ไลน์แบบเลิกรวมกลุ่มซึ่งขึ้นอยู่กับบริการ Google Play หากคุณเลือกไปป์ไลน์ที่เลิกรวมกลุ่ม แอปจะมีขนาดเล็กลง ดูรายละเอียดได้ในตารางด้านล่าง
รวมกลุ่ม | ไม่ได้จัดกลุ่ม | |
---|---|---|
ชื่อไลบรารี | com.google.mlkit:image-labeling-custom | com.google.android.gms:play-services-mlkit-image-labeling-custom |
การใช้งาน | ไปป์ไลน์จะลิงก์กับแอปของคุณแบบคงที่ ณ เวลาบิลด์ | ระบบจะดาวน์โหลดไปป์ไลน์แบบไดนามิกผ่านบริการ Google Play |
ขนาดแอป | ขนาดเพิ่มขึ้นประมาณ 3.8 MB | เพิ่มขนาดได้ประมาณ 200 KB |
เวลาเริ่ม | ไปป์ไลน์จะพร้อมใช้ทันที | อาจต้องรอให้ดาวน์โหลดไปป์ไลน์ก่อนใช้งานครั้งแรก |
ขั้นของวงจร API | เวอร์ชันสำหรับผู้ใช้ทั่วไป (GA) | เบต้า |
การผสานรวมโมเดลที่กำหนดเองทำได้ 2 วิธี ได้แก่ รวมโมเดลโดยใส่ไว้ในโฟลเดอร์เนื้อหาของแอป หรือดาวน์โหลดจาก Firebase แบบไดนามิก ตารางต่อไปนี้จะเปรียบเทียบตัวเลือกทั้งสอง
โมเดลที่ให้มาด้วย | โมเดลที่โฮสต์ |
---|---|
รูปแบบนี้เป็นส่วนหนึ่งของ APK ของแอป ซึ่งจะเพิ่มขนาด | โมเดลนี้ไม่ได้เป็นส่วนหนึ่งของ APK ของคุณ โดยโฮสต์โดยการอัปโหลดไปยัง Firebase Machine Learning |
โมเดลนี้จะพร้อมใช้งานทันทีแม้ว่าอุปกรณ์ Android จะออฟไลน์อยู่ | มีการดาวน์โหลดโมเดลตามคำขอ |
ไม่จำเป็นต้องใช้โปรเจ็กต์ Firebase | ต้องมีโปรเจ็กต์ Firebase |
คุณต้องเผยแพร่แอปอีกครั้งเพื่ออัปเดตโมเดล | พุชการอัปเดตโมเดลโดยไม่ต้องเผยแพร่แอปอีกครั้ง |
ไม่มีการทดสอบ A/B ในตัว | การทดสอบ A/B ง่ายๆ ด้วยการกำหนดค่าระยะไกลของ Firebase |
ลองเลย
- โปรดดูแอป Vision Quickstart สำหรับตัวอย่างการใช้งานโมเดลแพ็กเกจและแอป Automl Quickstart สำหรับตัวอย่างการใช้งานโมเดลที่โฮสต์
ก่อนเริ่มต้น
ในไฟล์
build.gradle
ระดับโปรเจ็กต์ ให้ตรวจสอบว่าได้ใส่ที่เก็บ Maven ของ Google ไว้ทั้งในส่วนbuildscript
และallprojects
เพิ่มทรัพยากร Dependency สำหรับไลบรารี Android ของ ML Kit ลงในไฟล์ Gradle ระดับแอปของโมดูล ซึ่งโดยปกติจะอยู่ที่
app/build.gradle
เลือกทรัพยากร Dependency ต่อไปนี้ 1 รายการตามความต้องการของคุณสำหรับการรวมไปป์ไลน์กับแอป ให้ทำดังนี้
dependencies { // ... // Use this dependency to bundle the pipeline with your app implementation 'com.google.mlkit:image-labeling-custom:17.0.2' }
สำหรับการใช้ไปป์ไลน์ในบริการ Google Play
dependencies { // ... // Use this dependency to use the dynamically downloaded pipeline in Google Play Services implementation 'com.google.android.gms:play-services-mlkit-image-labeling-custom:16.0.0-beta5' }
หากเลือกใช้ไปป์ไลน์ในบริการ Google Play คุณสามารถกำหนดค่าแอปให้ดาวน์โหลดไปป์ไลน์ลงในอุปกรณ์โดยอัตโนมัติหลังจากติดตั้งแอปจาก Play Store แล้ว โดยเพิ่มประกาศต่อไปนี้ในไฟล์
AndroidManifest.xml
ของแอป<application ...> ... <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="custom_ica" /> <!-- To use multiple downloads: android:value="custom_ica,download2,download3" --> </application>
นอกจากนี้คุณยังตรวจสอบความพร้อมใช้งานของไปป์ไลน์อย่างชัดแจ้งและส่งคำขอดาวน์โหลดผ่านบริการ Google Play ได้ที่ ModuleInstallClient API
หากคุณไม่เปิดใช้การดาวน์โหลดไปป์ไลน์ขณะติดตั้งหรือขอการดาวน์โหลดอย่างชัดแจ้ง ระบบจะดาวน์โหลดไปป์ไลน์เมื่อคุณเรียกใช้ผู้ติดป้ายกำกับเป็นครั้งแรก คำขอของคุณก่อนการดาวน์โหลดจะเสร็จสมบูรณ์จะไม่สร้างผลลัพธ์ใดๆ
เพิ่มทรัพยากร Dependency
linkFirebase
หากคุณต้องการดาวน์โหลดโมเดลจาก Firebase แบบไดนามิกสำหรับการดาวน์โหลดโมเดลแบบไดนามิกจาก Firebase ให้เพิ่มการอ้างอิง
linkFirebase
:dependencies { // ... // Image labeling feature with model downloaded from Firebase implementation 'com.google.mlkit:image-labeling-custom:17.0.2' // Or use the dynamically downloaded pipeline in Google Play Services // implementation 'com.google.android.gms:play-services-mlkit-image-labeling-custom:16.0.0-beta5' implementation 'com.google.mlkit:linkfirebase:17.0.0' }
หากต้องการดาวน์โหลดโมเดล ให้ตรวจสอบว่าคุณเพิ่ม Firebase ลงในโปรเจ็กต์ Android หากยังไม่ได้ทำ ขั้นตอนนี้ไม่จำเป็นเมื่อรวมโมเดลเข้าด้วยกัน
1. โหลดโมเดล
กำหนดค่าต้นทางของโมเดลในเครื่อง
วิธีรวมโมเดลเข้ากับแอป
คัดลอกไฟล์โมเดล (โดยปกติจะลงท้ายด้วย
.tflite
หรือ.lite
) ไปยังโฟลเดอร์assets/
ของแอป (คุณอาจต้องสร้างโฟลเดอร์ก่อนโดยคลิกขวาที่โฟลเดอร์app/
แล้วคลิกใหม่ > โฟลเดอร์ > โฟลเดอร์ชิ้นงาน)จากนั้นเพิ่มข้อมูลต่อไปนี้ลงในไฟล์
build.gradle
ของแอปเพื่อให้มั่นใจว่า Gradle จะไม่บีบอัดไฟล์โมเดลเมื่อสร้างแอปandroid { // ... aaptOptions { noCompress "tflite" // or noCompress "lite" } }
ไฟล์โมเดลจะรวมอยู่ในแพ็กเกจแอปและพร้อมให้เล่นใน ML Kit เป็นเนื้อหาดิบ
สร้างออบเจ็กต์
LocalModel
โดยระบุเส้นทางไปยังไฟล์โมเดล:Kotlin
val localModel = LocalModel.Builder() .setAssetFilePath("model.tflite") // or .setAbsoluteFilePath(absolute file path to model file) // or .setUri(URI to model file) .build()
Java
LocalModel localModel = new LocalModel.Builder() .setAssetFilePath("model.tflite") // or .setAbsoluteFilePath(absolute file path to model file) // or .setUri(URI to model file) .build();
กำหนดค่าแหล่งที่มาของโมเดลที่โฮสต์ใน Firebase
หากต้องการใช้โมเดลที่โฮสต์จากระยะไกล ให้สร้างออบเจ็กต์ RemoteModel
ด้วย FirebaseModelSource
โดยระบุชื่อที่คุณกำหนดโมเดลเมื่อคุณเผยแพร่:
Kotlin
// Specify the name you assigned in the Firebase console. val remoteModel = CustomRemoteModel .Builder(FirebaseModelSource.Builder("your_model_name").build()) .build()
Java
// Specify the name you assigned in the Firebase console. CustomRemoteModel remoteModel = new CustomRemoteModel .Builder(new FirebaseModelSource.Builder("your_model_name").build()) .build();
จากนั้นเริ่มงานดาวน์โหลดโมเดล โดยระบุเงื่อนไขที่ต้องการอนุญาตให้ดาวน์โหลด หากโมเดลไม่ได้อยู่ในอุปกรณ์ หรือหากมีโมเดลเวอร์ชันใหม่ งานจะดาวน์โหลดโมเดลแบบไม่พร้อมกันจาก Firebase
Kotlin
val downloadConditions = DownloadConditions.Builder() .requireWifi() .build() RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener { // Success. }
Java
DownloadConditions downloadConditions = new DownloadConditions.Builder() .requireWifi() .build(); RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(@NonNull Task task) { // Success. } });
แอปจำนวนมากเริ่มต้นงานดาวน์โหลดในโค้ดการเริ่มต้น แต่คุณสามารถเริ่มงานได้ทุกเมื่อก่อนที่จะต้องใช้โมเดล
กำหนดค่าผู้ติดป้ายกำกับรูปภาพ
หลังจากที่กำหนดค่าแหล่งที่มาของโมเดลแล้ว ให้สร้างออบเจ็กต์ ImageLabeler
จากต้นทางดังกล่าว
โดยมีตัวเลือกดังต่อไปนี้
ตัวเลือก | |
---|---|
confidenceThreshold
|
คะแนนความเชื่อมั่นขั้นต่ำของป้ายกำกับที่ตรวจพบ หากไม่ได้ตั้งค่า ระบบจะใช้เกณฑ์ของตัวแยกประเภทที่ระบุโดยข้อมูลเมตาของโมเดล หากโมเดลไม่มีข้อมูลเมตาหรือข้อมูลเมตาไม่ได้ระบุเกณฑ์ของตัวแยกประเภท ระบบจะใช้เกณฑ์เริ่มต้นที่ 0.0 |
maxResultCount
|
จำนวนป้ายกำกับสูงสุดที่จะแสดง หากไม่ได้ตั้งค่า ระบบจะใช้ค่าเริ่มต้น 10 |
หากคุณมีเฉพาะโมเดลที่รวมในเครื่อง เพียงสร้างผู้ติดป้ายกำกับจากออบเจ็กต์ LocalModel
ดังนี้
Kotlin
val customImageLabelerOptions = CustomImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0.5f) .setMaxResultCount(5) .build() val labeler = ImageLabeling.getClient(customImageLabelerOptions)
Java
CustomImageLabelerOptions customImageLabelerOptions = new CustomImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0.5f) .setMaxResultCount(5) .build(); ImageLabeler labeler = ImageLabeling.getClient(customImageLabelerOptions);
หากคุณมีโมเดลที่โฮสต์จากระยะไกล คุณจะต้องตรวจสอบว่าโมเดลดังกล่าวได้รับการดาวน์โหลดแล้วก่อนที่จะเรียกใช้ คุณจะตรวจสอบสถานะของงานการดาวน์โหลดโมเดลได้โดยใช้เมธอด isModelDownloaded()
ของตัวจัดการโมเดล
แม้ว่าคุณจะต้องยืนยันสิ่งนี้ก่อนที่จะเรียกใช้ผู้ติดป้ายกำกับ แต่ถ้าคุณมีทั้งโมเดลที่โฮสต์จากระยะไกลและโมเดลที่รวมในเครื่อง คุณอาจต้องทำการตรวจสอบนี้เมื่อเริ่มต้นผู้ติดป้ายกำกับรูปภาพ นั่นคือ สร้างป้ายกำกับจากโมเดลระยะไกลหากดาวน์โหลดไว้แล้ว และจากโมเดลในเครื่อง
Kotlin
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener { isDownloaded -> val optionsBuilder = if (isDownloaded) { CustomImageLabelerOptions.Builder(remoteModel) } else { CustomImageLabelerOptions.Builder(localModel) } val options = optionsBuilder .setConfidenceThreshold(0.5f) .setMaxResultCount(5) .build() val labeler = ImageLabeling.getClient(options) }
Java
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Boolean isDownloaded) { CustomImageLabelerOptions.Builder optionsBuilder; if (isDownloaded) { optionsBuilder = new CustomImageLabelerOptions.Builder(remoteModel); } else { optionsBuilder = new CustomImageLabelerOptions.Builder(localModel); } CustomImageLabelerOptions options = optionsBuilder .setConfidenceThreshold(0.5f) .setMaxResultCount(5) .build(); ImageLabeler labeler = ImageLabeling.getClient(options); } });
หากคุณมีเฉพาะโมเดลที่โฮสต์จากระยะไกล คุณควรปิดใช้ฟังก์ชันการทำงานเกี่ยวกับโมเดล เช่น ทำให้เป็นสีเทาหรือซ่อนบางส่วนของ UI จนกว่าคุณจะยืนยันว่าได้ดาวน์โหลดโมเดลแล้ว ซึ่งทำได้โดยการแนบ Listener ลงในเมธอด download()
ของตัวจัดการโมเดล ดังนี้
Kotlin
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener { // Download complete. Depending on your app, you could enable the ML // feature, or switch from the local model to the remote model, etc. }
Java
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void v) { // Download complete. Depending on your app, you could enable // the ML feature, or switch from the local model to the remote // model, etc. } });
2. เตรียมรูปภาพอินพุต
จากนั้นสร้างออบเจ็กต์InputImage
จากรูปภาพแต่ละรูปภาพที่ต้องการติดป้ายกำกับ เครื่องมือติดป้ายกำกับรูปภาพจะทำงานได้เร็วที่สุดเมื่อคุณใช้ Bitmap
หรือหากคุณใช้ Camera2 API ระบบจะใช้ YUV_420_888 media.Image
ซึ่งระบบจะแนะนำเมื่อเป็นไปได้
คุณสร้างออบเจ็กต์ InputImage
จากแหล่งที่มาที่แตกต่างกันได้ โดยแต่ละรายการจะมีคำอธิบายอยู่ด้านล่าง
ใช้ media.Image
หากต้องการสร้างออบเจ็กต์ InputImage
จากออบเจ็กต์ media.Image
เช่น เมื่อคุณจับภาพจากกล้องของอุปกรณ์ ให้ส่งวัตถุ media.Image
และการหมุนรูปภาพไปยัง InputImage.fromMediaImage()
หากใช้ไลบรารี
CameraX คลาส OnImageCapturedListener
และ ImageAnalysis.Analyzer
จะคำนวณค่าการหมุนให้คุณ
Kotlin
private class YourImageAnalyzer : ImageAnalysis.Analyzer { override fun analyze(imageProxy: ImageProxy) { val mediaImage = imageProxy.image if (mediaImage != null) { val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) // Pass image to an ML Kit Vision API // ... } } }
Java
private class YourAnalyzer implements ImageAnalysis.Analyzer { @Override public void analyze(ImageProxy imageProxy) { Image mediaImage = imageProxy.getImage(); if (mediaImage != null) { InputImage image = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees()); // Pass image to an ML Kit Vision API // ... } } }
หากไม่ได้ใช้คลังภาพที่มีระดับการหมุนของภาพ คุณจะคํานวณจากองศาการหมุนของอุปกรณ์และการวางแนวของเซ็นเซอร์กล้องในอุปกรณ์ได้ดังนี้
Kotlin
private val ORIENTATIONS = SparseIntArray() init { ORIENTATIONS.append(Surface.ROTATION_0, 0) ORIENTATIONS.append(Surface.ROTATION_90, 90) ORIENTATIONS.append(Surface.ROTATION_180, 180) ORIENTATIONS.append(Surface.ROTATION_270, 270) } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Throws(CameraAccessException::class) private fun getRotationCompensation(cameraId: String, activity: Activity, isFrontFacing: Boolean): Int { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. val deviceRotation = activity.windowManager.defaultDisplay.rotation var rotationCompensation = ORIENTATIONS.get(deviceRotation) // Get the device's sensor orientation. val cameraManager = activity.getSystemService(CAMERA_SERVICE) as CameraManager val sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION)!! if (isFrontFacing) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360 } else { // back-facing rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360 } return rotationCompensation }
Java
private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0, 0); ORIENTATIONS.append(Surface.ROTATION_90, 90); ORIENTATIONS.append(Surface.ROTATION_180, 180); ORIENTATIONS.append(Surface.ROTATION_270, 270); } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private int getRotationCompensation(String cameraId, Activity activity, boolean isFrontFacing) throws CameraAccessException { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int rotationCompensation = ORIENTATIONS.get(deviceRotation); // Get the device's sensor orientation. CameraManager cameraManager = (CameraManager) activity.getSystemService(CAMERA_SERVICE); int sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION); if (isFrontFacing) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360; } else { // back-facing rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360; } return rotationCompensation; }
จากนั้นส่งออบเจ็กต์ media.Image
และค่าองศาการหมุนไปที่ InputImage.fromMediaImage()
:
Kotlin
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
การใช้ URI ของไฟล์
หากต้องการสร้างออบเจ็กต์ InputImage
จาก URI ของไฟล์ ให้ส่งบริบทของแอปและ URI ของไฟล์ไปยัง InputImage.fromFilePath()
ซึ่งจะเป็นประโยชน์เมื่อคุณใช้ Intent ACTION_GET_CONTENT
เพื่อแจ้งให้ผู้ใช้เลือกรูปภาพจากแอปแกลเลอรี
Kotlin
val image: InputImage try { image = InputImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
Java
InputImage image; try { image = InputImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
หากใช้ ByteBuffer
หรือ ByteArray
หากต้องการสร้างออบเจ็กต์ InputImage
จาก ByteBuffer
หรือ ByteArray
ให้คำนวณระดับการหมุนรูปภาพตามที่อธิบายไว้ก่อนหน้านี้สำหรับอินพุต media.Image
จากนั้นสร้างออบเจ็กต์ InputImage
ที่มีบัฟเฟอร์หรืออาร์เรย์ พร้อมความสูง ความกว้าง รูปแบบการเข้ารหัสสี และระดับการหมุนของรูปภาพ ดังนี้
Kotlin
val image = InputImage.fromByteBuffer( byteBuffer, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 ) // Or: val image = InputImage.fromByteArray( byteArray, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 )
Java
InputImage image = InputImage.fromByteBuffer(byteBuffer, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 ); // Or: InputImage image = InputImage.fromByteArray( byteArray, /* image width */480, /* image height */360, rotation, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 );
ใช้ Bitmap
หากต้องการสร้างออบเจ็กต์ InputImage
จากออบเจ็กต์ Bitmap
ให้ประกาศต่อไปนี้
Kotlin
val image = InputImage.fromBitmap(bitmap, 0)
Java
InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);
รูปภาพแสดงด้วยวัตถุ Bitmap
ร่วมกับองศาการหมุน
3. เรียกใช้เครื่องมือติดป้ายกำกับรูปภาพ
หากต้องการติดป้ายกำกับวัตถุในรูปภาพ ให้ส่งออบเจ็กต์ image
ไปยังเมธอด process()
ของ ImageLabeler
Kotlin
labeler.process(image) .addOnSuccessListener { labels -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
Java
labeler.process(image) .addOnSuccessListener(new OnSuccessListener<List<ImageLabel>>() { @Override public void onSuccess(List<ImageLabel> labels) { // Task completed successfully // ... } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
4. รับข้อมูลเกี่ยวกับเอนทิตีที่ติดป้ายกำกับ
หากการดำเนินการติดป้ายกำกับรูปภาพสำเร็จ ระบบจะส่งรายการออบเจ็กต์ImageLabel
ไปยัง Listener ที่สำเร็จ ออบเจ็กต์ ImageLabel
แต่ละรายการแสดงถึงสิ่งที่ติดป้ายกำกับในรูปภาพ คุณดูข้อความอธิบายของแต่ละป้ายกำกับ (หากมีในข้อมูลเมตาของไฟล์โมเดล TensorFlow Lite) คะแนนความเชื่อมั่น และดัชนีได้ เช่น
Kotlin
for (label in labels) { val text = label.text val confidence = label.confidence val index = label.index }
Java
for (ImageLabel label : labels) { String text = label.getText(); float confidence = label.getConfidence(); int index = label.getIndex(); }
เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์
หากต้องการติดป้ายกำกับรูปภาพในแอปพลิเคชันแบบเรียลไทม์ ให้ทำตามหลักเกณฑ์ต่อไปนี้เพื่อให้ได้อัตราเฟรมที่ดีที่สุด
- หากใช้ API
Camera
หรือcamera2
ให้ควบคุมการเรียกใช้ไปยังผู้ติดป้ายกำกับรูปภาพ หากเฟรมวิดีโอใหม่พร้อมใช้งานขณะที่ผู้ติดป้ายกำกับรูปภาพกำลังทำงาน ให้วางเฟรมดังกล่าว ดูคลาสVisionProcessorBase
ในแอปตัวอย่าง Quickstart - หากคุณใช้
CameraX
API โปรดตรวจสอบว่าได้ตั้งค่ากลยุทธ์ Backpressure ไว้เป็นค่าเริ่มต้นImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
ซึ่งจะช่วยรับประกันว่าระบบจะนำส่งรูปภาพเพียง 1 รูปเพื่อทำการวิเคราะห์ต่อครั้ง หากมีการสร้างรูปภาพเพิ่มเติมเมื่อเครื่องมือวิเคราะห์ไม่ว่าง ระบบจะนำรูปภาพเหล่านั้นออกโดยอัตโนมัติและไม่เข้าคิวสำหรับการนำส่ง เมื่อปิดรูปภาพที่วิเคราะห์แล้วโดยเรียกใช้ ImageProxy.close() ระบบจะส่งรูปภาพล่าสุดถัดไป - หากคุณใช้เอาต์พุตของผู้ติดป้ายกำกับรูปภาพเพื่อวางซ้อนกราฟิกบนรูปภาพอินพุต ให้รับผลลัพธ์จาก ML Kit ก่อน จากนั้นจึงแสดงผลรูปภาพและการวางซ้อนในขั้นตอนเดียว ซึ่งจะแสดงผลบนพื้นผิวแสดงผลเพียงครั้งเดียวต่อเฟรมอินพุตแต่ละเฟรม ดูคลาส
CameraSourcePreview
และGraphicOverlay
ในแอปตัวอย่างสำหรับการเริ่มต้นใช้งานอย่างรวดเร็ว - หากคุณใช้ Camera2 API ให้จับภาพในรูปแบบ
ImageFormat.YUV_420_888
หากคุณใช้ Camera API เวอร์ชันเก่า ให้จับภาพในรูปแบบImageFormat.NV21