使用 MediaPipe 在 Android 上產生裝置端圖片

1. 簡介

什麼是 MediaPipe?

MediaPipe Solutions 可讓您將機器學習 (ML) 解決方案套用至應用程式。這項服務提供設定預先建構的處理管道架構,可為使用者提供即時、引人入勝且實用的輸出內容。您甚至可以使用 MediaPipe Model Maker 自訂許多這類解決方案,以便更新預設模型。

文字轉圖像生成是 MediaPipe Solutions 提供的多項 ML 工作之一。

在本程式碼研究室中,您將從幾乎沒有任何內容的 Android 應用程式開始,然後逐步完成多個步驟,直到能夠直接在 Android 裝置上產生新圖片為止。

課程內容

  • 如何使用 MediaPipe Tasks,在 Android 應用程式中本機執行文字轉圖像生成作業。

軟硬體需求

  • 已安裝的 Android Studio 版本 (本程式碼研究室是使用 Android Studio Giraffe 編寫及測試)。
  • Android 裝置的 RAM 至少為 8 GB。
  • 具備 Android 開發的基本知識,並能執行預先編寫的 Python 指令碼。

2. 將 MediaPipe 工作新增至 Android 應用程式

下載 Android 範例應用程式

本程式碼研究室會從預先製作的範例開始,其中包含將用於基本版本圖片產生的 UI。您可以在官方 MediaPipe 範例存放區 這裡找到該啟動應用程式。按一下「Code」>「Download ZIP」,複製存放區或下載 zip 檔案。

將應用程式匯入 Android Studio

  1. 開啟 Android Studio。
  2. 在「Welcome to Android Studio」畫面中,選取右上角的「Open」

a0b5b070b802e4ea.png

  1. 前往複製或下載存放區的位置,然後開啟 codelabs/image_generation_basic/android/start 目錄
  2. 在此階段,應用程式不應編譯,因為您尚未加入 MediaPipe Tasks 依附元件。

您可以修正應用程式並讓其執行,方法是前往 build.gradle 檔案,然後向下捲動至 // 步驟 1 - 新增依附元件。接著,加入下列一行,然後按一下 Android Studio 頂端橫幅中的「Sync Now」按鈕。

// Step 1 - Add dependency
implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'

同步處理完成後,請按一下 Android Studio 右上方的綠色「run」箭頭 ( 7e15a9c9e1620fe7.png),確認所有項目都已正確開啟及安裝。應用程式會開啟至畫面,其中有兩個單選按鈕和一個標示為「INITIALIZE」的按鈕。點選該按鈕後,系統應會立即轉到另一個 UI,其中包含文字提示和其他選項,以及標示為「GENERATE」的按鈕。

83c31de8e8a320ee.png 78b8765e832024e3.png

很抱歉,這就是初始應用程式的範圍,現在是時候學習如何完成這個應用程式,並開始在裝置上產生新圖片了!

3. 設定圖片產生器

在這個範例中,大部分的圖片產生工作都會在 ImageGenerationHelper.kt 檔案中執行。開啟這個檔案後,您會在類別頂端看到名為 imageGenerator 的變數。這是在圖片生成應用程式中負責執行繁重工作的工作物件。

在該物件下方,您會看到一個名為 initializeImageGenerator() 的函式,其中含有以下註解:// 步驟 2 - 初始化圖片產生器。如您所料,這裡是初始化 ImageGenerator 物件的位置。將該函式主體替換為以下程式碼,設定圖片生成模型路徑並初始化 ImageGenerator 物件:

// Step 2 - initialize the image generator
val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

在下方,您會看到另一個名為 setInput() 的函式。這個函式會接受三個參數:用於定義產生的圖片的提示字串、產生新圖片時 Task 應執行的迭代次數,以及種子值,可用於根據相同提示建立圖片的新版本,並在使用相同的種子時產生相同圖片。這個函式的目的是,當您嘗試建立顯示中間步驟的圖片時,為圖片產生器設定這些初始參數。

請將 setInput() 主體 (您會看到註解 // Step 3 - accept inputs) 替換為這行程式碼:

// Step 3 - accept inputs
imageGenerator.setInputs(prompt, iteration, seed)

接下來的兩個步驟是產生過程。generate() 函式會接受與 setInput 相同的輸入內容,但會以一次性呼叫的方式建立圖片,不會傳回任何中繼步驟圖片。您可以將這個函式的主體 (包含註解「// Step 4 - generate without showing iterations」) 替換為以下內容:

// Step 4 - generate without showing iterations
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap

請注意,這項工作會同步執行,因此您必須從背景執行緒呼叫函式。您稍後將在本程式碼研究室中進一步瞭解這項功能。

在這個檔案中,您要採取的最後一個步驟是填入 execute() 函式 (標示為步驟 5)。這個方法會接受參數,指出應否針對單一步驟 (透過 ImageGenerator execute() 函式執行) 產生中繼圖片。將函式主體替換為以下程式碼:

// Step 5 - generate with iterations
val result = imageGenerator.execute(showResult)

if (result == null || result.generatedImage() == null) {
    return Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888)
        .apply {
            val canvas = Canvas(this)
            val paint = Paint()
            paint.color = Color.WHITE
            canvas.drawPaint(paint)
        }
}

val bitmap =
    BitmapExtractor.extract(result.generatedImage())

return bitmap

以上就是輔助檔案的內容。在下一節中,您將填寫 ViewModel 檔案,以便處理本範例的邏輯。

4. 整合應用程式

MainViewModel 檔案會處理 UI 狀態和與此範例應用程式相關的其他邏輯。現在就來開啟這個檔案吧。

您應該會在檔案頂端看到註解 // 步驟 6 - 設定模型路徑。您可以在這裡告訴應用程式如何找到用於產生圖片的必要模型檔案。在本範例中,您會將值設為 /data/local/tmp/image_generator/bins/。

// Step 6 - set model path
private val MODEL_PATH = "/data/local/tmp/image_generator/bins/"

接著,向下捲動至 generateImage() 函式。在這個函式的底部,您會看到步驟 7 和步驟 8,分別用於產生含有或不含已傳回迭代的圖片。由於這兩項作業都會同步執行,您會發現它們會在協同程式中包裝。您可以先將 // 步驟 7 - 產生不顯示疊代內容的程式碼替換為這段程式碼,以便從 ImageGenerationHelper 檔案呼叫 generate(),然後更新 UI 狀態。

// Step 7 - Generate without showing iterations
val result = helper?.generate(prompt, iteration, seed)
_uiState.update {
    it.copy(outputBitmap = result)
}

步驟 8 就比較複雜了。由於 execute() 函式只會執行一個步驟,而非所有圖片產生步驟,因此您必須透過迴圈個別呼叫每個步驟。您也需要判斷是否應向使用者顯示目前的步驟。最後,如果應顯示目前的迭代作業,您將更新 UI 狀態。您現在可以執行所有這些操作。

// Step 8 - Generate with showing iterations
helper?.setInput(prompt, iteration, seed)
for (step in 0 until iteration) {
    isDisplayStep =
        (displayIteration > 0 && ((step + 1) % displayIteration == 0))
    val result = helper?.execute(isDisplayStep)

    if (isDisplayStep) {
        _uiState.update {
            it.copy(
                outputBitmap = result,
                generatingMessage = "Generating... (${step + 1}/$iteration)",
            )
        }
    }
}

此時,您能安裝應用程式、初始化圖片產生器,然後根據文字提示建立新圖片

不過,現在當您嘗試初始化圖片產生器時,應用程式會停止運作。這是因為您需要將模型檔案複製到裝置。如要取得已知可用的第三方模型最新資訊,並將這些模型轉換為適用於此 MediaPipe 工作項的模型,然後複製到裝置上,請參閱官方文件的這一節

除了將檔案直接複製到開發人員裝置,您也可以設定 Firebase Storage,讓系統在執行階段直接將必要檔案下載到使用者裝置。

5. 部署及測試應用程式

完成所有步驟後,您應該會擁有一個可接受文字提示,並在裝置端產生新圖片的應用程式!請將應用程式部署到實體 Android 裝置上進行測試,但請記得,您需要使用至少有 8 GB 記憶體的裝置進行測試。

  1. 按一下 Android Studio 工具列中的「Run」圖示 ( 7e15a9c9e1620fe7.png) 執行應用程式。
  2. 選取產生步驟的類型 (最終或經過疊代),然後按下「INITIALIZE」按鈕。
  3. 在下一個畫面中,設定所需的任何屬性,然後按一下「產生」按鈕,查看工具產生的結果。

e46cfaeb9d3fc235.gif

6. 恭喜!

你成功了!在本程式碼研究室中,您已瞭解如何在 Android 應用程式中新增裝置端文字轉圖片功能。

後續步驟

您可以透過圖像生成任務執行更多操作,包括:

  • 使用基礎圖片透過外掛程式建構生成的圖片,或是透過 Vertex AI 訓練自己的額外 LoRA 權重。
  • 使用 Firebase Storage 擷取裝置上的模型檔案,不必使用 ADB 工具。

我們期待看到您透過這個實驗性任務製作的所有精彩作品,也請密切留意 MediaPipe 團隊推出的更多程式碼研究室和內容!