Android 快速入門

這個頁面說明如何使用 TensorFlow Lite 建構 Android 應用程式,以分析即時攝影機畫面並識別物件。這種機器學習用途稱為「物件偵測」。範例應用程式透過 Google Play 服務 使用 TensorFlow Lite 視覺工作程式庫,以便執行物件偵測機器學習模型。這是使用 TensorFlow Lite 建構機器學習應用程式的建議方法。

Object detection animated demo

設定並執行範例

在本練習的第一部分,請從 GitHub 下載範例程式碼,並使用 Android Studio 執行。本文件接下來的章節將探討範例程式碼的相關部分,以便您將這些程式碼套用至自己的 Android 應用程式。您需要安裝下列版本的工具

  • Android Studio 4.2 或以上版本
  • Android SDK 21 或以上版本

取得範例程式碼

建立範例程式碼的本機副本,以便您建構及執行。

複製並設定範例程式碼

  1. 複製 git 存放區
    git clone https://github.com/tensorflow/examples.git
    
  2. 設定您的 git 執行個體以使用稀疏簽出,讓您只有物件偵測範例應用程式的檔案
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/object_detection/android_play_services
    

匯入並執行專案

使用 Android Studio 從下載的範例程式碼建立專案、建構專案並執行。

匯入並建構範例程式碼專案

  1. 啟動 Android Studio
  2. 在 Android Studio 的「Welcome」(歡迎使用) 頁面中,選擇「Import Project」(匯入專案),或選取「File」(檔案) > 「New」(新增) > 「Import Project」(匯入專案)。
  3. 瀏覽至包含 build.gradle 檔案的範例程式碼目錄 (...examples/lite/examples/object_detection/android_play_services/build.gradle),然後選取該目錄。

選取這個目錄後,Android Studio 會建立新專案並加以建構。建構完成後,Android Studio 會在「Build Output」(建構輸出) 狀態面板中顯示 BUILD SUCCESSFUL 訊息。

執行專案

  1. 在 Android Studio 中,依序選取「Run」(執行) > 「Run…」(執行…) 和「MainActivity」,即可執行專案。
  2. 選取已連接相機的 Android 裝置,以測試應用程式。

範例應用程式的運作方式

範例應用程式使用預先訓練的物件偵測模型 (例如 mobilenetv1.tflite,採用 TensorFlow Lite 格式),在 Android 裝置攝影機的即時視訊串流中尋找物件。這項功能的程式碼主要位於下列檔案中

  • ObjectDetectorHelper.kt - 初始化執行階段環境、啟用硬體加速,並執行物件偵測機器學習模型。
  • CameraFragment.kt - 建構相機圖片資料串流、準備模型資料,並顯示物件偵測結果。

接下來的章節將說明這些程式碼檔案的主要元件,以便您修改 Android 應用程式來新增這項功能。

建構應用程式

接下來的章節說明建構您自己的 Android 應用程式並執行範例應用程式中所示模型的主要步驟。這些操作說明以稍早顯示的範例應用程式做為參考點。

新增專案依附元件

在您的基本 Android 應用程式中,新增用於執行 TensorFlow Lite 機器學習模型和存取機器學習資料公用程式函式的專案依附元件。這些公用程式函式可將圖片等資料轉換為模型可處理的張量資料格式。

範例應用程式透過 Google Play 服務 使用 TensorFlow Lite 視覺工作程式庫,以便執行物件偵測機器學習模型。下列操作說明說明如何將必要的程式庫依附元件新增至您自己的 Android 應用程式專案。

新增模組依附元件

  1. 在使用 TensorFlow Lite 的 Android 應用程式模組中,更新模組的 build.gradle 檔案以加入下列依附元件。在範例程式碼中,這個檔案位於這裡:...examples/lite/examples/object_detection/android_play_services/app/build.gradle

    ...
    dependencies {
    ...
        // Tensorflow Lite dependencies
        implementation 'org.tensorflow:tensorflow-lite-task-vision-play-services:0.4.2'
        implementation 'com.google.android.gms:play-services-tflite-gpu:16.1.0'
    ...
    }
    
  2. 在 Android Studio 中,依序選取「File」(檔案) > 「Sync Project with Gradle Files」(將專案與 Gradle 檔案同步),即可同步專案依附元件。

初始化 Google Play 服務

當您使用 Google Play 服務 執行 TensorFlow Lite 模型時,必須先初始化服務才能使用。如果您想要搭配服務使用硬體加速支援 (例如 GPU 加速),也必須在這個初始化程序中啟用該支援。

使用 Google Play 服務初始化 TensorFlow Lite

  1. 建立 TfLiteInitializationOptions 物件並修改,以啟用 GPU 支援

    val options = TfLiteInitializationOptions.builder()
        .setEnableGpuDelegateSupport(true)
        .build()
    
  2. 使用 TfLiteVision.initialize() 方法啟用 Play 服務執行階段的使用權,並設定監聽器來驗證是否已成功載入

    TfLiteVision.initialize(context, options).addOnSuccessListener {
        objectDetectorListener.onInitialized()
    }.addOnFailureListener {
        // Called if the GPU Delegate is not supported on the device
        TfLiteVision.initialize(context).addOnSuccessListener {
            objectDetectorListener.onInitialized()
        }.addOnFailureListener{
            objectDetectorListener.onError("TfLiteVision failed to initialize: "
                    + it.message)
        }
    }
    

初始化機器學習模型解譯器

透過載入模型檔案並設定模型參數,初始化 TensorFlow Lite 機器學習模型解譯器。TensorFlow Lite 模型包含 .tflite 檔案,其中含有模型程式碼。您應將模型儲存在開發專案的 src/main/assets 目錄中,例如

.../src/main/assets/mobilenetv1.tflite`

初始化模型

  1. .tflite 模型檔案新增至開發專案的 src/main/assets 目錄,例如 ssd_mobilenet_v1
  2. 設定 modelName 變數以指定您的機器學習模型檔案名稱

    val modelName = "mobilenetv1.tflite"
    
  3. 設定模型的選項,例如預測門檻和結果集大小

    val optionsBuilder =
        ObjectDetector.ObjectDetectorOptions.builder()
            .setScoreThreshold(threshold)
            .setMaxResults(maxResults)
    
  4. 使用選項啟用 GPU 加速,並允許程式碼在裝置上不支援加速時正常失敗

    try {
        optionsBuilder.useGpu()
    } catch(e: Exception) {
        objectDetectorListener.onError("GPU is not supported on this device")
    }
    
    
  5. 使用這個物件中的設定建構包含模型的 TensorFlow Lite ObjectDetector 物件

    objectDetector =
        ObjectDetector.createFromFileAndOptions(
            context, modelName, optionsBuilder.build())
    

如要進一步瞭解如何搭配 TensorFlow Lite 使用硬體加速委派,請參閱 TensorFlow Lite 委派

準備模型資料

您準備要供模型解譯的資料時,會將圖片等現有資料轉換為 Tensor 資料格式,以便模型處理。Tensor 中的資料必須具有特定維度或形狀,才能與用於訓練模型的資料格式相符。根據您使用的模型,您可能需要轉換資料以符合模型預期的格式。範例應用程式使用 ImageAnalysis 物件,從相機子系統擷取圖片影格。

準備要由模型處理的資料

  1. 建構 ImageAnalysis 物件,以擷取所需格式的圖片

    imageAnalyzer =
        ImageAnalysis.Builder()
            .setTargetAspectRatio(AspectRatio.RATIO_4_3)
            .setTargetRotation(fragmentCameraBinding.viewFinder.display.rotation)
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .setOutputImageFormat(OUTPUT_IMAGE_FORMAT_RGBA_8888)
            .build()
            ...
    
  2. 將分析器連接至相機子系統,並建立點陣圖緩衝區以包含從相機接收的資料

            .also {
            it.setAnalyzer(cameraExecutor) { image ->
                if (!::bitmapBuffer.isInitialized) {
                    bitmapBuffer = Bitmap.createBitmap(
                        image.width,
                        image.height,
                        Bitmap.Config.ARGB_8888
                    )
                }
                detectObjects(image)
            }
        }
    
  3. 擷取模型所需的特定圖片資料,並傳遞圖片旋轉資訊

    private fun detectObjects(image: ImageProxy) {
        // Copy out RGB bits to the shared bitmap buffer
        image.use { bitmapBuffer.copyPixelsFromBuffer(image.planes[0].buffer) }
        val imageRotation = image.imageInfo.rotationDegrees
        objectDetectorHelper.detect(bitmapBuffer, imageRotation)
    }    
    
  4. 完成任何最終資料轉換,並將圖片資料新增至 TensorImage 物件,如範例應用程式的 ObjectDetectorHelper.detect() 方法所示

    val imageProcessor = ImageProcessor.Builder().add(Rot90Op(-imageRotation / 90)).build()
    
    // Preprocess the image and convert it into a TensorImage for detection.
    val tensorImage = imageProcessor.process(TensorImage.fromBitmap(image))
    

執行預測

使用正確格式的圖片資料建立 TensorImage 物件後,您就可以針對該資料執行模型以產生預測或*推論*。在範例應用程式中,這個程式碼包含在 ObjectDetectorHelper.detect() 方法中。

執行模型並從圖片資料產生預測

  • 將圖片資料傳遞至預測函式,以執行預測

    val results = objectDetector?.detect(tensorImage)
    

處理模型輸出

針對物件偵測模型執行圖片資料後,模型會產生預測結果清單,您的應用程式程式碼必須透過執行額外的業務邏輯、向使用者顯示結果或採取其他動作來處理這些結果。範例應用程式中的物件偵測模型會產生偵測到物件的預測和邊界框清單。在範例應用程式中,預測結果會傳遞至監聽器物件,以進行後續處理並顯示給使用者。

處理模型預測結果

  1. 使用監聽器模式將結果傳遞至您的應用程式程式碼或使用者介面物件。範例應用程式使用這種模式,將偵測結果從 ObjectDetectorHelper 物件傳遞至 CameraFragment 物件

    objectDetectorListener.onResults( // instance of CameraFragment
        results,
        inferenceTime,
        tensorImage.height,
        tensorImage.width)
    
  2. 根據結果採取行動,例如向使用者顯示預測。範例應用程式會在 CameraPreview 物件上繪製重疊圖層以顯示結果

    override fun onResults(
      results: MutableList<Detection>?,
      inferenceTime: Long,
      imageHeight: Int,
      imageWidth: Int
    ) {
        activity?.runOnUiThread {
            fragmentCameraBinding.bottomSheetLayout.inferenceTimeVal.text =
                String.format("%d ms", inferenceTime)
    
            // Pass necessary information to OverlayView for drawing on the canvas
            fragmentCameraBinding.overlay.setResults(
                results ?: LinkedList<Detection>(),
                imageHeight,
                imageWidth
            )
    
            // Force a redraw
            fragmentCameraBinding.overlay.invalidate()
        }
    }
    

後續步驟