在 Android 上使用經過 AutoML 訓練的模型偵測影像中的對象

使用 AutoML Vision Edge 訓練自己的模型後,您可以在應用程式中使用它來偵測影像中的物件。

有兩種方法可以整合從 AutoML Vision Edge 訓練的模型:您可以透過將模型放入應用程式的資產資料夾中來捆綁模型,也可以從 Firebase 動態下載模型。

模型捆綁選項
捆綁在您的應用程式中
  • 該模型是您應用的 APK 的一部分
  • 即使 Android 裝置處於離線狀態,該模型也可以立即使用
  • 不需要 Firebase 項目
使用 Firebase 託管
  • 透過將模型上傳到Firebase Machine Learning來託管模型
  • 減少 APK 大小
  • 模型按需下載
  • 推送模型更新而無需重新發​​布您的應用程式
  • 使用Firebase Remote Config輕鬆進行 A/B 測試
  • 需要 Firebase 項目

在你開始之前

  1. 如果您想下載模型,請確保將Firebase 新增至您的 Android 專案(如果您尚未這樣做)。捆綁模型時不需要這樣做。

  2. 將 TensorFlow Lite Task 庫的依賴項新增至模組的應用程式層級 gradle 檔案中,該檔案通常是app/build.gradle

    將模型與您的應用程式捆綁在一起:

    dependencies {
      // ...
      // Object detection with a bundled Auto ML model
      implementation 'org.tensorflow:tensorflow-lite-task-vision:0.0.0-nightly-SNAPSHOT'
    }
    

    若要從 Firebase 動態下載模型,還需新增 Firebase ML 相依性:

    dependencies {
      // ...
      // Object detection with an Auto ML model deployed to Firebase
      implementation platform('com.google.firebase:firebase-bom:26.1.1')
      implementation 'com.google.firebase:firebase-ml-model-interpreter'
    
      implementation 'org.tensorflow:tensorflow-lite-task-vision:0.0.0-nightly'
    }
    

1.載入模型

配置本地模型來源

要將模型與您的應用程式捆綁在一起:

  1. 從您從 Google Cloud 控制台下載的 zip 檔案中提取模型。
  2. 將您的模型包含在您的應用程式包中:
    1. 如果您的專案中沒有資產資料夾,請透過右鍵單擊app/資料夾,然後按一下新建 > 資料夾 > 資產資料夾來建立資料夾。
    2. 將帶有嵌入元資料的tflite模型檔案複製到資產資料夾中。
  3. 將以下內容新增至應用程式的build.gradle檔案中,以確保 Gradle 在建置應用程式時不會壓縮模型檔案:

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

    模型檔案將包含在應用程式包中並作為原始資產提供。

配置 Firebase 託管的模型來源

若要使用遠端託管模型,請建立RemoteModel對象,並指定您在發布模型時指派給該模型的名稱:

爪哇

// Specify the name you assigned when you deployed the model.
FirebaseCustomRemoteModel remoteModel =
        new FirebaseCustomRemoteModel.Builder("your_model").build();

科特林

// Specify the name you assigned when you deployed the model.
val remoteModel =
    FirebaseCustomRemoteModel.Builder("your_model_name").build()

然後,啟動模型下載任務,指定允許下載的條件。如果裝置上沒有模型,或者有更新版本的模型可用,則任務將從 Firebase 非同步下載模型:

爪哇

DownloadConditions downloadConditions = new DownloadConditions.Builder()
        .requireWifi()
        .build();
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(@NonNull Task<Void> task) {
                // Success.
            }
        });

科特林

val downloadConditions = DownloadConditions.Builder()
    .requireWifi()
    .build()
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
    .addOnSuccessListener {
        // Success.
    }

許多應用程式在其初始化程式碼中啟動下載任務,但您可以在需要使用模型之前隨時執行此操作。

從您的模型建立物件偵測器

配置模型來源後,從其中一個建立一個ObjectDetector物件。

如果您只有本地捆綁的模型,只需從模型檔案建立物件偵測器並配置您想要的置信度分數閾值(請參閱評估您的模型):

爪哇

// Initialization
ObjectDetectorOptions options = ObjectDetectorOptions.builder()
    .setScoreThreshold(0)  // Evaluate your model in the Google Cloud console
                           // to determine an appropriate value.
    .build();
ObjectDetector objectDetector = ObjectDetector.createFromFileAndOptions(context, modelFile, options);

科特林

// Initialization
val options = ObjectDetectorOptions.builder()
    .setScoreThreshold(0)  // Evaluate your model in the Google Cloud console
                           // to determine an appropriate value.
    .build()
val objectDetector = ObjectDetector.createFromFileAndOptions(context, modelFile, options)

如果您有遠端託管模型,則必須在運行之前檢查它是否已下載。您可以使用模型管理器的isModelDownloaded()方法檢查模型下載任務的狀態。

儘管您只需在運行物件偵測器之前確認這一點,但如果您同時擁有遠端託管模型和本機捆綁模型,則在實例化物件偵測器時執行此檢查可能是有意義的:從遠端建立物件偵測器如果已下載,則為模型,否則為本機模型。

爪哇

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener(new OnSuccessListener<Boolean>() {
            @Override
            public void onSuccess(Boolean isDownloaded) {
            }
        });

科特林

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener { success ->

        }

如果您只有遠端託管模型,則應停用與模型相關的功能(例如,灰顯或隱藏部分 UI),直到確認模型已下載。您可以透過將偵聽器附加到模型管理器的download()方法來實現此目的。

一旦您知道您的模型已下載,請從模型檔案建立一個物件偵測器:

爪哇

FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
        .addOnCompleteListener(new OnCompleteListener<File>() {
            @Override
            public void onComplete(@NonNull Task<File> task) {
                File modelFile = task.getResult();
                if (modelFile != null) {
                    ObjectDetectorOptions options = ObjectDetectorOptions.builder()
                            .setScoreThreshold(0)
                            .build();
                    objectDetector = ObjectDetector.createFromFileAndOptions(
                            getApplicationContext(), modelFile.getPath(), options);
                }
            }
        });

科特林

FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
        .addOnSuccessListener { modelFile ->
            val options = ObjectDetectorOptions.builder()
                    .setScoreThreshold(0f)
                    .build()
            objectDetector = ObjectDetector.createFromFileAndOptions(
                    applicationContext, modelFile.path, options)
        }

2. 準備輸入影像

然後,對於要標記的每個影像,從影像建立一個TensorImage物件。您可以使用fromBitmap方法從Bitmap建立TensorImage物件:

爪哇

TensorImage image = TensorImage.fromBitmap(bitmap);

科特林

val image = TensorImage.fromBitmap(bitmap)

如果您的圖像資料不在Bitmap中,您可以載入像素數組,如TensorFlow Lite 文件中所示。

3. 運行物體偵測器

若要偵測影像中的對象,請將TensorImage物件傳遞給ObjectDetectordetect()方法。

爪哇

List<Detection> results = objectDetector.detect(image);

科特林

val results = objectDetector.detect(image)

4. 取得標籤物件的信息

如果物件偵測操作成功,則傳回Detection物件的清單。每個Detection對象代表影像中偵測到的某些內容。您可以獲得每個物件的邊界框及其標籤。

例如:

爪哇

for (Detection result : results) {
    RectF bounds = result.getBoundingBox();
    List<Category> labels = result.getCategories();
}

科特林

for (result in results) {
    val bounds = result.getBoundingBox()
    val labels = result.getCategories()
}

提升即時效能的技巧

如果您想在即時應用程式中標記圖像,請遵循以下指南以獲得最佳幀速率:

  • 對影像標記器的呼叫進行限制。如果在影像貼標機運作時有新的視訊幀可用,請丟棄該幀。如需範例,請參閱快速入門範例應用程式中的VisionProcessorBase類別。
  • 如果您使用影像貼標機的輸出在輸入影像上疊加圖形,請先取得結果,然後在一個步驟中渲染影像並疊加。透過這樣做,每個輸入幀只需渲染到顯示表面一次。有關範例,請參閱快速入門範例應用程式中的CameraSourcePreviewGraphicOverlay類別。
  • 如果您使用 Camera2 API,請以ImageFormat.YUV_420_888格式擷取影像。

    如果您使用較舊的相機 API,請以ImageFormat.NV21格式擷取影像。