使用 TensorFlow Lite (Android) 建構及部署自訂物件偵測模型

1. 事前準備

在本程式碼研究室中,您將瞭解如何使用 TFLite Model Maker 使用一組訓練圖片訓練自訂物件偵測模型,然後使用 TFLite 工作程式庫將模型部署到 Android 應用程式。您將學會以下內容:

  • 建構 Android 應用程式,可偵測餐點圖片中的食材。
  • 整合 TFLite 預先訓練的物件偵測模型,並查看模型可偵測的限制。
  • 使用名為 salad 和 TFLite 模型製作工具的自訂資料集,訓練自訂物件偵測模型來偵測餐點的食材/成分。
  • 使用 TFLite 工作程式庫將自訂模型部署至 Android 應用程式。

最後,您必須建立與下圖類似的內容:

b9705235366ae162.png

事前準備

本程式碼研究室是專為有經驗的行動裝置開發人員所設計,您應該很熟悉:

  • 使用 Kotlin 和 Android Studio 進行 Android 開發作業
  • 基本 Python 語法

您將會瞭解的內容

  • 如何使用 TFLite Model Maker 訓練自訂物件偵測模型。
  • 如何使用 TFLite 工作程式庫部署 TFLite 物件偵測模型。

軟硬體需求

  • 最新版本的 Android Studio (4.2 以上版本)
  • Android Studio 模擬器或實體 Android 裝置
  • 範例程式碼
  • 關於 Android Kotlin 開發作業的基本知識

2. 物件偵測

物件偵測是一組電腦視覺任務,可偵測及尋找數位圖片中的物件。指定圖片或影片串流時,物件偵測模型可識別出目前已知的一組物件,並提供物件在圖片中位置的相關資訊。

TensorFlow 提供預先訓練及最佳化的行動模型,可偵測車輛、橙色等常見物體。只要利用幾行程式碼,就能將這些預先訓練的模型整合到行動應用程式。但是,您可能想要或需要偵測較具特殊或另類類別的物件。這需要收集您自己的訓練映像檔,然後訓練並部署您自己的物件偵測模型。

TensorFlow Lite

TensorFlow Lite 是一種跨平台機器學習程式庫,可在 Android 和 iOS 行動裝置等邊緣裝置上執行機器學習模型。

TensorFlow Lite 實際上是機器學習套件內用於執行機器學習模型的核心引擎。TensorFlow Lite 生態系統有兩個元件,可讓您輕鬆在行動裝置上訓練及部署機器學習模型:

  • Model Maker 是一種 Python 程式庫,只要編寫幾行程式碼即可輕鬆使用 TensorFlow 訓練模型,不需要具備機器學習方面的專業知識。
  • Task Library 是跨平台的程式庫,只要輕鬆利用行動應用程式中的幾行程式碼,即可輕鬆部署 TensorFlow Lite 模型。

本程式碼研究室聚焦於 TFLite。與 TFLite 和物件偵測無關的概念和程式碼區塊不會說明,而且僅可複製及貼上。

3. 做好準備

下載程式碼

點選下方連結即可下載這個程式碼研究室的所有程式碼:

將下載的 ZIP 檔案解壓縮。這會將根目錄 (odml-pathways-main) 與所有您需要的資源一起解壓縮。在這個程式碼研究室中,您只需要 object-detection/codelab2/android 子目錄中的來源即可。

object-detection/codelab2/android 存放區中的 android 子目錄包含兩個目錄:

  • android_studio_folder.pngstarter:以這個程式碼研究室建立的程式碼。
  • android_studio_folder.pngfinal:完成的範例應用程式的程式碼。

匯入入門應用程式

首先,請將入門應用程式匯入 Android Studio。

  1. 開啟 Android Studio,然後選取 [Import Project (Gradle、Eclipse ADT 等)]
  2. 從您先前下載的原始碼中開啟 starter 資料夾。

7c0f27882a2698ac.png

為確保應用程式支援所有依附元件,請在匯入程序完成後將專案與 gradle 檔案同步處理。

  1. 從 Android Studio 工具列選取 [Sync Project with Gradle Files] (使用 Gradle 檔案同步處理專案) (b451ab2d04d835f9.png)。匯入 starter/app/build.gradle

執行啟動應用程式

您已將專案匯入 Android Studio,那麼您可以第一次執行應用程式了。

透過 USB 將 Android 裝置連接到電腦,或是啟動 Android Studio 模擬器,然後按一下 Android Studio 工具列中的 [執行] ( 執行.png)。

4. 瞭解入門應用程式

為了讓這個程式碼研究室變得簡單,並將重心放在機器學習的位元上,「啟動」應用程式包含一些樣板程式碼,這些指令可以為您執行下列動作:

  • 使用裝置的相機拍攝相片。
  • 其中包含一些圖庫圖片,方便您試用 Android 模擬器上的物件偵測功能。
  • 可讓您在輸入點陣圖上繪製物件偵測結果的便利方法。

您大部分是可以在應用程式骨架中與這些方法互動的方式:

  • fun runObjectDetection(bitmap: Bitmap)當您選擇預設圖片或拍照時,系統就會呼叫這個方法。bitmap 是物件偵測的輸入映像檔。在本程式碼研究室中,您稍後會將物件偵測程式碼新增至此方法。
  • data class DetectionResult(val boundingBoxes: Rect, val text: String) 這是一種資料類別,代表視覺化的物件物件偵測結果。boundingBoxes 是物件所在的矩形,text 是偵測結果字串,會與物件的定界框一併顯示。
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<DetectionResult>): Bitmap這個方法會在輸入 bitmap 上繪製物件偵測結果的 detectionResults,並傳回修改後的複本。

以下是 drawDetectionResult 公用程式方法的輸出範例。

f6b1e6dad726e129.png

5. 新增裝置物件偵測

現在,藉由將預先訓練的 TFLite 模型整合到入門應用程式中,您將建構一個原型。

下載預先訓練的 TFLite 物件偵測模型

TensorFlow Hub 提供多種物件偵測工具模型供您使用。在這個程式碼研究室中,您將會下載 EfficientDet-Lite Object 偵測模型、根據 COCO 2017 資料集進行訓練,針對 TFLite 進行最佳化處理,並且專為行動裝置 CPU、GPU 和 EdgeTPU 的效能所設計。

接著,使用 TFLite 工作程式庫將預先訓練的 TFLite 模型整合到入門應用程式中。TFLite 工作程式庫可讓您輕鬆將行動裝置最佳化的機器學習模型整合至行動應用程式,並支援多種熱門機器學習用途,包括物件偵測、圖片分類和文字分類。您可以載入幾行程式碼以執行 TFLite 模型。

將模型加入入門應用程式

  1. 將您剛下載的模型複製到啟動程式應用程式的 assets 資料夾。您可以在 Android Studio 的「專案」導覽面板中找到該資料夾。

c2609599b7d22641.png

  1. 命名檔案 model.tflite

c83e9397177c4561.png

更新 Gradle 檔案工作程式庫的依附元件

前往 app/build.gradle 檔案,然後將這一行加到 dependencies 設定中:

implementation 'org.tensorflow:tensorflow-lite-task-vision:0.3.1'

將專案與 gradle 檔案同步處理

為確保應用程式能夠使用所有依附元件,請在此時將專案與 gradle 檔案同步處理。從 Android Studio 工具列選取 [Sync Project with Gradle Files] (使用 Gradle 檔案同步處理專案) (b451ab2d04d835f9.png)。

(如果這個按鈕已停用,請務必只匯入 starter/app/build.gradle,而不是匯入整個存放區)。

在映像檔上設定及執行裝置物件偵測

透過 3 個簡單步驟,即可載入及執行物件偵測模型:

  • 準備圖片/串流:TensorImage
  • 建立偵測工具物件:ObjectDetector
  • 連結上述兩個物件:detect(image)

您可以在 runObjectDetection(bitmap: Bitmap) 檔案的 MainActivity.kt 函式中完成這些操作。

/**
* TFLite Object Detection Function
*/
private fun runObjectDetection(bitmap: Bitmap) {
    //TODO: Add object detection code here
}

該函式目前為空白。如要執行 TFLite 物件偵測工具,請繼續按照下列步驟進行。在過程中,Android Studio 會提示您新增必要的匯入項目:

  • org.tensorflow.lite.support.image.TensorImage
  • org.tensorflow.lite.task.vision.detector.ObjectDetector

建立映像檔物件

您要用於這個程式碼研究室的圖片來源,可以來自裝置端的相機,或是您在應用程式使用者介面上選取的預設圖片。輸入的圖片會解碼為 Bitmap 格式,並傳送至 runObjectDetection 方法。

TFLite 提供簡單的 API,可透過 Bitmap 建立 TensorImage。請將下列程式碼新增到 runObjectDetection(bitmap:Bitmap) 的頂端:

// Step 1: create TFLite's TensorImage object
val image = TensorImage.fromBitmap(bitmap)

建立偵測工具執行個體

TFLite 工作程式庫符合建構工具的設計模式。將您的設定傳遞至建構工具,接著從建構工具取得偵測工具。您可以設定幾個選項,包括調整物件偵測工具的敏感度:

  • max results (物件可偵測的物件數量上限)
  • 分數門檻 (物件偵測工具應傳回偵測到的物件有多可靠)
  • 標籤許可清單/拒絕清單 (允許/拒絕預先定義清單中的物件)

指定 TFLite 模型檔案名稱和設定選項,即可初始化物件偵測工具執行個體:

// Step 2: Initialize the detector object
val options = ObjectDetector.ObjectDetectorOptions.builder()
    .setMaxResults(5)
    .setScoreThreshold(0.5f)
    .build()
val detector = ObjectDetector.createFromFileAndOptions(
    this, // the application context
    "model.tflite", // must be same as the filename in assets folder
    options
)

將圖片提交給偵測工具

請將下列程式碼新增到 fun runObjectDetection(bitmap:Bitmap)。這樣即可將圖片提供給偵測工具。

// Step 3: feed given image to the model and print the detection result
val results = detector.detect(image)

完成時,偵測工具會傳回 Detection 清單,每個清單都包含模型在圖片中找到的物件資訊。每個物件的說明如下:

  • boundingBox:宣告物件是否在物件中的存在和矩形
  • categories:物件種類,以及模型對偵測結果的信心程度。此模型會傳回多個類別,最可靠的類別會優先顯示。
  • label:物件類別的名稱。
  • classificationConfidence:介於 0.0 到 1.0 之間的浮點數,1.0 代表 100%

請將下列程式碼新增到 fun runObjectDetection(bitmap:Bitmap)。這會呼叫將結果偵測結果列印至 Logcat 的方法。

// Step 4: Parse the detection result and show it
debugPrint(results)

然後將此 debugPrint() 方法新增至 MainActivity 類別:

private fun debugPrint(results : List<Detection>) {
    for ((i, obj) in results.withIndex()) {
        val box = obj.boundingBox

        Log.d(TAG, "Detected object: ${i} ")
        Log.d(TAG, "  boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")

        for ((j, category) in obj.categories.withIndex()) {
            Log.d(TAG, "    Label $j: ${category.label}")
            val confidence: Int = category.score.times(100).toInt()
            Log.d(TAG, "    Confidence: ${confidence}%")
        }
    }
} 

現在您的物件偵測工具已準備就緒!在 Android Studio 工具列中按一下 [執行] ( 執行.png),即可編譯並執行應用程式。應用程式顯示在裝置上後,輕觸任一預設圖片,即可啟動物件偵測器。接著查看 IDE 中的「Logcat」視窗*(* 16bd6ea224cf8cf1.png*)*,您應該會看到類似下方的內容:

D/TFLite-ODT: Detected object: 0 
D/TFLite-ODT:   boundingBox: (0.0, 15.0) - (2223.0,1645.0)
D/TFLite-ODT:     Label 0: dining table
D/TFLite-ODT:     Confidence: 77%
D/TFLite-ODT: Detected object: 1 
D/TFLite-ODT:   boundingBox: (702.0, 3.0) - (1234.0,797.0)
D/TFLite-ODT:     Label 0: cup
D/TFLite-ODT:     Confidence: 69%

這表示偵測器偵測到 2 個物件。第一個為:

  • 一個物體在 (0, 15) – (2223, 1645) 的矩形內
  • 標籤為餐桌
  • 模型的信心地是第 1 份是餐桌 (77%)

技術上來說,這是讓 TFLite 工作程式庫正常運作所需的一切:您這次已全部完成!恭喜

但是,在 UI 端,您目前仍在起點。現在,您必須在使用者介面上對偵測到的結果進行後續處理,以便對結果進行偵測。

6. 在輸入圖片上繪製偵測結果

在先前的步驟中,您會將偵測結果列印成 logcat:簡單快速。在這個步驟中,您將使用入門應用程式中的公用程式方法,以便執行下列作業:

  • 在圖片上繪製定界框
  • 在定界框內繪製類別名稱和可信度百分比
  1. debugPrint(results) 呼叫替換為下列程式碼片段:
val resultToDisplay = results.map {
    // Get the top-1 category and craft the display text
    val category = it.categories.first()
    val text = "${category.label}, ${category.score.times(100).toInt()}%"

    // Create a data object to display the detection result
    DetectionResult(it.boundingBox, text)
}
// Draw the detection result on the bitmap and show it.
val imgWithResult = drawDetectionResult(bitmap, resultToDisplay)
runOnUiThread {
    inputImageView.setImageBitmap(imgWithResult)
}
  1. 現在,請按一下 Android Studio 工具列中的 [執行] ( 執行.png)。
  2. 應用程式載入後,輕觸其中一個預設圖片即可查看偵測結果。

想用您自己的相片試試看嗎?只要輕觸 [拍照] 按鈕,即可拍攝周遭物體的照片。

8b024362b15096a6.png

7. 訓練自訂物件偵測模型

在上一個步驟中,您將預先訓練的 TFLite 物件偵測模型整合到 Android 應用程式,並發現它可以偵測範例圖片中的常見物件,例如碗或餐桌。然而,您的目標是偵測圖片中的料理成分,因此一般物件偵測並不符合您的用途。您想要使用可偵測成分的訓練資料集來訓練自訂物件偵測模型。

這個資料集包含可用來訓練自訂模型的圖片和標籤。是使用 Open Images Dataset V4 中的映像檔建立而成。

Colaboratory

接下來,請前往 Google Colab 訓練自訂模型。

訓練自訂模型大約需要 30 分鐘。

在此提醒您,您可以下載系統針對您提供的資料集進行預先訓練的模型,然後繼續進行下一個步驟。

8. 將自訂 TFLite 模型整合至 Android 應用程式

現在,您已訓練沙拉偵測模型,進行整合並將它從常見的物件偵測器轉換成特別的沙拉偵測器。

  1. 將沙拉 TFLite 模型複製到 assets 資料夾。將新模式命名為 salad.tflite

91e8d37c4f78eddb.png

  1. 開啟 MainActivity.kt 檔案並找出 ObjectDetector 初始化程式碼。
  2. 將 EfficientDet-Lite 模型 (model.tflite) 替換為沙拉模型 (salad.tflite)
val detector = ObjectDetector.createFromFileAndOptions(
    this, // the application context
    "salad.tflite", // must be same as the filename in assets folder
    options
)
  1. 在 Android Studio 工具列中按一下 [執行] (執行.png),即可使用新模型重新執行應用程式。你看看! 應用程式現在可以辨識起司、沙拉和烘焙食品。

b9705235366ae162.png

9. 恭喜!

您已經使用 TFLite 來訓練自訂模型,並在應用程式中加入「物件偵測」功能。只要準備這項功能就能開始使用!

適用範圍

  • 如何在 TensorFlow Hub 中尋找預先訓練的 TFLite 物件偵測模型
  • 如何使用 TFLite 工作程式庫將反對偵測模型與 Android 應用程式整合
  • 如何使用 TFLite Model Maker 訓練自訂物件偵測模型

後續步驟

  • 使用 Firebase 強化 TFLite 模型部署作業
  • 收集訓練資料來訓練您自己的模型
  • 在您的 Android 應用程式中套用物件偵測

瞭解詳情