ติดป้ายกำกับรูปภาพด้วยโมเดลที่กำหนดเองใน Android

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

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

รวมกลุ่มไม่ได้จัดกลุ่ม
ชื่อไลบรารีcom.google.mlkit:image-labeling-customcom.google.android.gms:play-services-mlkit-image-labeling-custom
การใช้งานไปป์ไลน์จะลิงก์กับแอปของคุณแบบคงที่ ณ เวลาบิลด์ไปป์ไลน์จะดาวน์โหลดแบบไดนามิกผ่านบริการ Google Play
ขนาดแอปขนาดเพิ่มขึ้นประมาณ 3.8 MBขนาดที่เพิ่มขึ้นประมาณ 200 KB
เวลาในการเริ่มต้นไปป์ไลน์จะพร้อมใช้งานทันทีอาจต้องรอให้ไปป์ไลน์ดาวน์โหลดก่อนการใช้งานครั้งแรก
ขั้นในวงจร APIเวอร์ชันสำหรับผู้ใช้ทั่วไป (GA)เบต้า

การรวมโมเดลที่กำหนดเองมี 2 วิธี ได้แก่ รวมโมเดลเข้าด้วยกันโดย ใส่ไว้ในโฟลเดอร์เนื้อหาของแอป หรือดาวน์โหลดแบบไดนามิก จาก Firebase ตารางต่อไปนี้จะเปรียบเทียบ 2 ตัวเลือกนี้

โมเดลแบบกลุ่ม โมเดลที่โฮสต์
โมเดลนี้เป็นส่วนหนึ่งของ APK ของแอป ซึ่งจะเพิ่มขนาด โมเดลนี้ไม่ได้เป็นส่วนหนึ่งของ APK ของคุณ ซึ่งโฮสต์โดยการอัปโหลดไปยัง แมชชีนเลิร์นนิงของ Firebase
โมเดลดังกล่าวจะพร้อมใช้งานทันที แม้ว่าอุปกรณ์ Android จะออฟไลน์อยู่ โมเดลจะดาวน์โหลดแบบออนดีมานด์
ไม่จำเป็นต้องมีโปรเจ็กต์ Firebase ต้องมีโปรเจ็กต์ Firebase
คุณต้องเผยแพร่แอปอีกครั้งเพื่ออัปเดตโมเดล พุชการอัปเดตโมเดลโดยไม่เผยแพร่แอปซ้ำ
ไม่มีการทดสอบ A/B ในตัว การทดสอบ A/B ที่ง่ายดายด้วยการกำหนดค่าระยะไกลของ Firebase

ลองเลย

ก่อนเริ่มต้น

  1. ตรวจสอบว่าได้รวมในไฟล์ build.gradle ระดับโปรเจ็กต์แล้ว ที่เก็บ Maven ของ Google ทั้งใน buildscript และ allprojects ส่วน

  2. เพิ่มทรัพยากร Dependency สำหรับไลบรารี ML Kit Android ลงในโมดูล ไฟล์ Gradle ระดับแอป ซึ่งมักจะเป็น app/build.gradle เลือกตัวเลือกใดตัวเลือกหนึ่ง ทรัพยากร Dependency ต่อไปนี้ตามความต้องการของคุณ

    สำหรับการรวมไปป์ไลน์เข้ากับแอป

    dependencies {
      // ...
      // Use this dependency to bundle the pipeline with your app
      implementation 'com.google.mlkit:image-labeling-custom:17.0.3'
    }
    

    สำหรับการใช้ไปป์ไลน์ในบริการ 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'
    }
    
  3. หากเลือกใช้ไปป์ไลน์ในบริการ 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>
    

    นอกจากนี้ คุณยังตรวจสอบความพร้อมใช้งานของไปป์ไลน์และส่งคำขอดาวน์โหลดผ่าน ModuleInstallClient API ของบริการ Google Play

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

  4. เพิ่มทรัพยากร Dependency linkFirebase หากต้องการดาวน์โหลดแบบไดนามิก จาก Firebase ได้ดังนี้

    สำหรับการดาวน์โหลดโมเดลแบบไดนามิกจาก Firebase ให้เพิ่ม linkFirebase การพึ่งพา:

    dependencies {
      // ...
      // Image labeling feature with model downloaded from Firebase
      implementation 'com.google.mlkit:image-labeling-custom:17.0.3'
      // 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'
    }
    
  5. หากต้องการดาวน์โหลดโมเดล โปรดตรวจสอบว่า เพิ่ม Firebase ลงในโปรเจ็กต์ Android หากคุณยังไม่ได้ดำเนินการ ทั้งนี้ไม่จำเป็นต้องทำขั้นตอนนี้เมื่อคุณรวมกลุ่มโมเดล

1. โหลดโมเดล

กำหนดค่าต้นทางของโมเดลในเครื่อง

วิธีการรวมโมเดลกับแอปมีดังนี้

  1. คัดลอกไฟล์โมเดล (โดยปกติจะลงท้ายด้วย .tflite หรือ .lite) ไปยังไฟล์ assets/ โฟลเดอร์ (คุณอาจต้องสร้างโฟลเดอร์ก่อนโดย คลิกขวาที่โฟลเดอร์ app/ แล้วคลิก ใหม่ > โฟลเดอร์ > โฟลเดอร์ชิ้นงาน)

  2. จากนั้นเพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle ของแอปเพื่อให้ Gradle ไม่บีบอัดไฟล์โมเดลเมื่อสร้างแอป

    android {
        // ...
        aaptOptions {
            noCompress "tflite"
            // or noCompress "lite"
        }
    }
    

    ไฟล์โมเดลจะรวมอยู่ในแพ็กเกจแอปและพร้อมให้ ML Kit ใช้งาน เป็นเนื้อหาดิบ

  3. สร้างออบเจ็กต์ 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 ไปยังออบเจ็กต์ของ ImageLabeler process() วิธี

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();
}

เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์

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

  • หากคุณใช้แท็ก 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