เมื่อคุณส่งภาพไปยัง ML Kit จะตรวจหาวัตถุในภาพได้สูงสุด 5 รายการ พร้อมกับตำแหน่งของแต่ละวัตถุในรูปภาพ เมื่อตรวจพบวัตถุใน สตรีมวิดีโอ โดยออบเจ็กต์แต่ละรายการจะมีรหัสที่ไม่ซ้ำกันซึ่งใช้ติดตามออบเจ็กต์ได้ จากเฟรมหนึ่งไปอีกเฟรม
คุณสามารถใช้โมเดลการจัดประเภทรูปภาพที่กำหนดเองเพื่อจัดประเภทออบเจ็กต์ที่ ตรวจพบ โปรดดูข้อมูลที่หัวข้อรุ่นที่กำหนดเองด้วย ML Kit สำหรับ คำแนะนำเกี่ยวกับข้อกำหนดความเข้ากันได้ของโมเดล วิธีค้นหาโมเดลก่อนการฝึก และวิธีฝึกโมเดลของคุณเอง
มี 2 วิธีในการรวมโมเดลที่กำหนดเอง คุณสามารถรวมกลุ่มโมเดลได้โดย ใส่ลงในโฟลเดอร์เนื้อหาของแอป หรือคุณจะดาวน์โหลดแบบไดนามิกก็ได้ จาก Firebase ตารางต่อไปนี้จะเปรียบเทียบทั้ง 2 ตัวเลือก
โมเดลแบบกลุ่ม | โมเดลที่โฮสต์ |
---|---|
โมเดลนี้เป็นส่วนหนึ่งของ APK ของแอป ซึ่งจะเพิ่มขนาด | โมเดลนี้ไม่ได้เป็นส่วนหนึ่งของ APK ของคุณ ซึ่งโฮสต์โดยการอัปโหลดไปยัง แมชชีนเลิร์นนิงของ Firebase |
โมเดลดังกล่าวจะพร้อมใช้งานทันที แม้ว่าอุปกรณ์ Android จะออฟไลน์อยู่ | โมเดลจะดาวน์โหลดแบบออนดีมานด์ |
ไม่จำเป็นต้องมีโปรเจ็กต์ Firebase | ต้องมีโปรเจ็กต์ Firebase |
คุณต้องเผยแพร่แอปอีกครั้งเพื่ออัปเดตโมเดล | พุชการอัปเดตโมเดลโดยไม่เผยแพร่แอปซ้ำ |
ไม่มีการทดสอบ A/B ในตัว | การทดสอบ A/B ที่ง่ายดายด้วยการกำหนดค่าระยะไกลของ Firebase |
ลองเลย
- ดูแอป Vision Quickstart สำหรับตัวอย่างการใช้งานโมเดล Bundle และ แอปการเริ่มต้นอย่างรวดเร็วของ automl สำหรับ ตัวอย่างการใช้โมเดลที่โฮสต์
- ดูการจัดแสดงดีไซน์ Material สำหรับการติดตั้งใช้งาน API นี้แบบครบวงจร
ก่อนเริ่มต้น
ตรวจสอบว่าได้รวมในไฟล์
build.gradle
ระดับโปรเจ็กต์แล้ว ที่เก็บ Maven ของ Google ทั้งในbuildscript
และallprojects
ส่วนเพิ่มทรัพยากร Dependency สำหรับไลบรารี ML Kit Android ลงในโมดูล ไฟล์ Gradle ระดับแอป ซึ่งปกติจะเป็น
app/build.gradle
:สำหรับการรวมโมเดลกับแอป ให้ทำดังนี้
dependencies { // ... // Object detection & tracking feature with custom bundled model implementation 'com.google.mlkit:object-detection-custom:17.0.2' }
สำหรับการดาวน์โหลดโมเดลแบบไดนามิกจาก Firebase ให้เพิ่ม
linkFirebase
การพึ่งพา:dependencies { // ... // Object detection & tracking feature with model downloaded // from firebase implementation 'com.google.mlkit:object-detection-custom:17.0.2' 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
หากต้องการใช้โมเดลที่โฮสต์จากระยะไกล ให้สร้างออบเจ็กต์ CustomRemoteModel
โดยใช้
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. } });
แอปจำนวนมากเริ่มงานดาวน์โหลดในโค้ดเริ่มต้น แต่คุณ จากนั้นคุณจะสามารถทำได้ทุกเมื่อก่อนที่จะต้องใช้โมเดลนี้
2. กำหนดค่าตัวตรวจจับออบเจ็กต์
หลังจากคุณกำหนดค่าแหล่งที่มาของโมเดล ให้กำหนดค่าตัวตรวจจับออบเจ็กต์สำหรับ
Use Case กับออบเจ็กต์ CustomObjectDetectorOptions
คุณสามารถเปลี่ยน
การตั้งค่าต่อไปนี้:
การตั้งค่าตัวตรวจจับวัตถุ | |
---|---|
โหมดการตรวจจับ |
STREAM_MODE (ค่าเริ่มต้น) | วันที่ SINGLE_IMAGE_MODE
ใน ใน |
ตรวจหาและติดตามวัตถุหลายรายการ |
false (ค่าเริ่มต้น) | วันที่ true
สามารถตรวจจับและติดตามวัตถุได้สูงสุด 5 รายการ หรือเฉพาะวัตถุที่พบมากที่สุด ออบเจ็กต์ที่โดดเด่น (ค่าเริ่มต้น) |
จำแนกประเภทวัตถุ |
false (ค่าเริ่มต้น) | วันที่ true
แยกประเภทออบเจ็กต์ที่ตรวจพบโดยใช้ข้อมูลที่ระบุหรือไม่
โมเดลตัวแยกประเภทที่กำหนดเอง วิธีใช้การแยกประเภทที่กำหนดเอง
คุณต้องตั้งค่าเป็น |
เกณฑ์ความเชื่อมั่นในการจัดประเภท |
คะแนนความเชื่อมั่นขั้นต่ำของป้ายกำกับที่ตรวจพบ หากไม่ได้ตั้งค่าไว้ รายการใดรายการหนึ่ง จะมีการใช้เกณฑ์ตัวแยกประเภทที่ระบุโดยข้อมูลเมตาของโมเดล ถ้าโมเดลไม่มีข้อมูลเมตาหรือข้อมูลเมตาไม่มี ระบุเกณฑ์ของตัวแยกประเภท โดยเกณฑ์เริ่มต้นที่มีค่าเท่ากับ 0.0 |
ป้ายกำกับสูงสุดต่อออบเจ็กต์ |
จำนวนป้ายกำกับสูงสุดต่อออบเจ็กต์ที่ตัวตรวจจับจะ ผลตอบแทน หากไม่ได้ตั้งค่า ระบบจะใช้ค่าเริ่มต้น 10 |
API การติดตามและตรวจจับออบเจ็กต์ได้รับการเพิ่มประสิทธิภาพสำหรับการใช้งานหลัก 2 รายการนี้ กรณี:
- การตรวจจับแบบเรียลไทม์และการติดตามวัตถุที่โดดเด่นที่สุดในกล้อง ช่องมองภาพ
- การตรวจจับวัตถุหลายรายการจากภาพนิ่ง
หากต้องการกำหนดค่า API สำหรับกรณีการใช้งานเหล่านี้ด้วยโมเดลที่รวมในเครื่อง ให้ทำดังนี้
Kotlin
// Live detection and tracking val customObjectDetectorOptions = CustomObjectDetectorOptions.Builder(localModel) .setDetectorMode(CustomObjectDetectorOptions.STREAM_MODE) .enableClassification() .setClassificationConfidenceThreshold(0.5f) .setMaxPerObjectLabelCount(3) .build() // Multiple object detection in static images val customObjectDetectorOptions = CustomObjectDetectorOptions.Builder(localModel) .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE) .enableMultipleObjects() .enableClassification() .setClassificationConfidenceThreshold(0.5f) .setMaxPerObjectLabelCount(3) .build() val objectDetector = ObjectDetection.getClient(customObjectDetectorOptions)
Java
// Live detection and tracking CustomObjectDetectorOptions customObjectDetectorOptions = new CustomObjectDetectorOptions.Builder(localModel) .setDetectorMode(CustomObjectDetectorOptions.STREAM_MODE) .enableClassification() .setClassificationConfidenceThreshold(0.5f) .setMaxPerObjectLabelCount(3) .build(); // Multiple object detection in static images CustomObjectDetectorOptions customObjectDetectorOptions = new CustomObjectDetectorOptions.Builder(localModel) .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE) .enableMultipleObjects() .enableClassification() .setClassificationConfidenceThreshold(0.5f) .setMaxPerObjectLabelCount(3) .build(); ObjectDetector objectDetector = ObjectDetection.getClient(customObjectDetectorOptions);
หากคุณมีโมเดลที่โฮสต์จากระยะไกล คุณจะต้องตรวจสอบว่ามีการ
ซึ่งดาวน์โหลดมาก่อนที่จะเรียกใช้ คุณตรวจสอบสถานะการดาวน์โหลดโมเดลได้
โดยใช้เมธอด isModelDownloaded()
ของผู้จัดการโมเดล
แม้ว่าคุณจะต้องยืนยันข้อมูลนี้ก่อนเรียกใช้ตัวตรวจจับเท่านั้น แต่หากคุณ มีทั้งโมเดลที่โฮสต์จากระยะไกลและโมเดลที่รวมอยู่ภายใน ความรู้สึกที่จะดำเนินการตรวจสอบนี้เมื่อเริ่มต้นตัวตรวจจับรูปภาพ: สร้าง ตัวตรวจจับจากโมเดลระยะไกล หากดาวน์โหลดแล้ว และจาก หากไม่เป็นเช่นนั้น
Kotlin
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener { isDownloaded -> val optionsBuilder = if (isDownloaded) { CustomObjectDetectorOptions.Builder(remoteModel) } else { CustomObjectDetectorOptions.Builder(localModel) } val customObjectDetectorOptions = optionsBuilder .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE) .enableClassification() .setClassificationConfidenceThreshold(0.5f) .setMaxPerObjectLabelCount(3) .build() val objectDetector = ObjectDetection.getClient(customObjectDetectorOptions) }
Java
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Boolean isDownloaded) { CustomObjectDetectorOptions.Builder optionsBuilder; if (isDownloaded) { optionsBuilder = new CustomObjectDetectorOptions.Builder(remoteModel); } else { optionsBuilder = new CustomObjectDetectorOptions.Builder(localModel); } CustomObjectDetectorOptions customObjectDetectorOptions = optionsBuilder .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE) .enableClassification() .setClassificationConfidenceThreshold(0.5f) .setMaxPerObjectLabelCount(3) .build(); ObjectDetector objectDetector = ObjectDetection.getClient(customObjectDetectorOptions); } });
หากคุณมีเฉพาะโมเดลที่โฮสต์จากระยะไกล คุณควรปิดใช้โมเดลที่เกี่ยวข้องกับ
เช่น เป็นสีเทาหรือซ่อนบางส่วนของ 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. } });
3. เตรียมรูปภาพอินพุต
สร้างวัตถุInputImage
จากรูปภาพ
เครื่องมือตรวจจับวัตถุจะทำงานโดยตรงจาก Bitmap
, NV21 ByteBuffer
หรือ
YUV_420_888 media.Image
การสร้าง InputImage
จากแหล่งที่มาเหล่านั้นคือ
แนะนำหากคุณมีสิทธิ์การเข้าถึงโดยตรง หากคุณสร้าง
InputImage
จากแหล่งที่มาอื่นๆ เราจะจัดการ Conversion เป็นการภายในสำหรับ
และอาจมีประสิทธิภาพน้อยลง
คุณสามารถสร้าง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
ร่วมกับองศาการหมุน
4. เรียกใช้ตัวตรวจจับวัตถุ
Kotlin
objectDetector .process(image) .addOnFailureListener(e -> {...}) .addOnSuccessListener(results -> { for (detectedObject in results) { // ... } });
Java
objectDetector .process(image) .addOnFailureListener(e -> {...}) .addOnSuccessListener(results -> { for (DetectedObject detectedObject : results) { // ... } });
5. รับข้อมูลเกี่ยวกับออบเจ็กต์ที่ติดป้ายกำกับ
หากการเรียก process()
สำเร็จ ระบบจะส่งรายการ DetectedObject
ไปยัง
ผู้ฟังที่ประสบความสำเร็จ
DetectedObject
แต่ละรายการจะมีพร็อพเพอร์ตี้ต่อไปนี้
กรอบล้อมรอบ | Rect ที่ระบุตำแหน่งของออบเจ็กต์ในส่วน
รูปภาพ |
||||||
รหัสติดตาม | จำนวนเต็มที่ระบุออบเจ็กต์ในรูปภาพ Null in SINGLE_IMAGE_mode | ||||||
ป้ายกำกับ |
|
Kotlin
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (detectedObject in results) { val boundingBox = detectedObject.boundingBox val trackingId = detectedObject.trackingId for (label in detectedObject.labels) { val text = label.text val index = label.index val confidence = label.confidence } }
Java
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (DetectedObject detectedObject : results) { Rect boundingBox = detectedObject.getBoundingBox(); Integer trackingId = detectedObject.getTrackingId(); for (Label label : detectedObject.getLabels()) { String text = label.getText(); int index = label.getIndex(); float confidence = label.getConfidence(); } }
สร้างประสบการณ์ของผู้ใช้ที่ดี
โปรดปฏิบัติตามหลักเกณฑ์ต่อไปนี้ในแอปเพื่อให้ผู้ใช้ได้รับประสบการณ์ที่ดีที่สุด
- การตรวจจับออบเจ็กต์ที่ประสบความสำเร็จขึ้นอยู่กับความซับซ้อนของภาพของออบเจ็กต์ ใน วัตถุที่มีคุณลักษณะทางภาพจำนวนน้อยอาจต้องให้ตรวจจับได้ เพื่อใช้ส่วนที่ใหญ่กว่าของรูปภาพ คุณควรให้คำแนะนำแก่ผู้ใช้เกี่ยวกับ ซึ่งเหมาะสำหรับวัตถุที่ต้องการตรวจจับ
- เมื่อใช้การจำแนกประเภท หากต้องการตรวจหาวัตถุที่ไม่ตก อยู่ในหมวดหมู่ที่สนับสนุนอย่างชัดเจน ใช้การจัดการพิเศษสำหรับสิ่งที่ไม่ทราบ ออบเจ็กต์
นอกจากนี้ คุณยังดู แอปแสดงดีไซน์ Material ของ ML Kit และ ดีไซน์ Material คอลเล็กชันรูปแบบของฟีเจอร์ที่ขับเคลื่อนด้วยแมชชีนเลิร์นนิง
Improving performance
หากคุณต้องการใช้การตรวจหาออบเจ็กต์ในแอปพลิเคชันแบบเรียลไทม์ ให้ทำตามสิ่งต่อไปนี้ เพื่อให้ได้อัตราเฟรมที่ดีที่สุดอย่าใช้โหมดสตรีมมิงในแอปพลิเคชันแบบเรียลไทม์ การตรวจจับวัตถุ เนื่องจากอุปกรณ์ส่วนใหญ่จะไม่สามารถสร้างอัตราเฟรมที่เพียงพอ
- หากคุณใช้แท็ก
Camera
หรือcamera2
API, รวมถึงควบคุมการเรียกไปที่ตัวตรวจจับ หากวิดีโอใหม่ เฟรมพร้อมใช้งานขณะที่ตัวตรวจจับกำลังทำงาน ให้วางเฟรม โปรดดูVisionProcessorBase
ในแอปตัวอย่างการเริ่มต้นอย่างรวดเร็วสำหรับตัวอย่าง - หากคุณใช้
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