MediaPipe を使用した Android でのオンデバイスでの画像生成

1. はじめに

MediaPipe とは

MediaPipe Solutions を使用すると、アプリに機械学習(ML)ソリューションを適用できます。このソリューションが提供するフレームワークでは、事前構築の処理パイプラインを構成して、ユーザーに有益で魅力のある出力を迅速に配信できます。これらのソリューションの多くは、 MediaPipe Model Maker でカスタマイズし、デフォルトのモデルを更新できます。

テキスト画像変換は、MediaPipe Solutions が提供する ML タスクの一つです。

この Codelab では、ほとんど何も入っていない Android アプリから始め、複数のステップを経て、Android デバイスで直接新しい画像を生成できるようにします。

学習内容

  • MediaPipe Tasks を使用して、Android アプリでローカルに実行されるテキスト画像変換を実装する方法。

必要なもの

  • Android Studio のインストール済みバージョン(この Codelab は Android Studio Giraffe で作成およびテストされています)。
  • 8 GB 以上の RAM を搭載した Android デバイス。
  • Android 開発に関する基本的な知識と、事前に作成された Python スクリプトを実行する能力。

2. Android アプリに MediaPipe Tasks を追加する

Android スターター アプリをダウンロードする

この Codelab では、画像生成の基本バージョンで使用する 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 ファイルに移動し、`// Step 1 - Add dependency` までスクロールします。 そこに次の行を追加し、Android Studio の上部のバナーに表示される [Sync Now] ボタンを押します。

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

同期が完了したら、Android Studio の右上にある緑色の [run] 矢印( 7e15a9c9e1620fe7.png)をクリックして、すべてが正しく開いてインストールされていることを確認します。アプリが開き、2 つのラジオボタンと [INITIALIZE] というラベルのボタンが表示されます。そのボタンをクリックすると、テキスト プロンプトとその他のオプション、[GENERATE] というラベルのボタンで構成される別の UI にすぐに移動します。

83c31de8e8a320ee.png 78b8765e832024e3.png

残念ながら、スターター アプリはこれ以上機能しません。このアプリを完成させて、デバイスで新しい画像を生成する方法を学びましょう。

3. 画像生成ツールを設定する

この例では、画像生成作業の大部分は ImageGenerationHelper.kt ファイルで行われます。このファイルを開くと、クラスの上部に imageGenerator という変数があります。これは、画像生成アプリで重い処理を行う Task オブジェクトです。

そのオブジェクトのすぐ下に、initializeImageGenerator() という関数と、// Step 2 - 画像生成ツールを初期化します。というコメントがあります。お察しのとおり、ここで ImageGenerator オブジェクトを初期化します。その関数本体を次のコードに置き換えて、画像生成モデルのパスを設定し、ImageGenerator オブジェクトを初期化します。

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

その下に、setInput() という別の関数があります。この関数は、生成された画像を定義するために使用される プロンプト 文字列、新しい画像を生成する際に Task が実行する 反復 回数、同じシードを使用した場合に同じ画像を生成しながら、同じプロンプトに基づいて画像の新しいバージョンを作成するために使用できる シード 値の 3 つのパラメータを受け取ります。 この関数の目的は、中間ステップを表示する画像を生成しようとしたときに、画像生成ツールの初期パラメータを設定することです。

setInput() の本体(// Step 3 - accept inputs というコメントがある場所)を次の行に置き換えます。

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

次の 2 つのステップで生成が行われます。generate() 関数は setInput と同じ入力を受け取りますが、中間ステップの画像を返さない 1 回限りの呼び出しとして画像を作成します。この関数の本体(// 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

このタスクは同期的に行われるため、バックグラウンド スレッドから関数を呼び出す必要があります。これについては、この Codelab で後ほど詳しく説明します。

このファイルで行う最後のステップは、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 の状態とその他のロジックを処理します。今すぐ開いてください。

ファイルの上部に、// Step 6 - set model path というコメントがあります。ここで、画像生成に必要なモデル ファイルの場所をアプリに伝えます。この例では、値を /data/local/tmp/image_generator/bins/ に設定します。

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

そこから、generateImage() 関数までスクロールします。この関数の下部には、ステップ 7 とステップ 8 があります。これらは、それぞれ返された反復処理または反復処理なしで画像を生成するために使用されます。これらのオペレーションはどちらも同期的に行われるため、コルーチンでラップされています。まず、// Step 7 - Generate without showing iterations を次のコードブロックに置き換えて、ImageGenerationHelper ファイルから generate() を呼び出し、UI の状態を更新します。

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

ステップ 8 は少し複雑です。 execute() 関数は、画像生成の すべてのステップではなく 1 つのステップのみを実行するため、ループを使用して各ステップを個別に呼び出す必要があります。また、現在のステップをユーザーに表示するかどうかを判断する必要があります。最後に、現在の反復処理を表示する場合は、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. 次の画面で、必要なプロパティを設定し、[GENERATE] ボタンをクリックして、ツールが生成する内容を確認します。

e46cfaeb9d3fc235.gif

6. 完了

やりました!この Codelab では、デバイス上でテキスト画像変換機能を Android アプリに追加する方法を学びました。

次のステップ

画像生成タスクでは、次のようなこともできます。

  • ベース画像を使用して、プラグインで生成された画像を構造化する。または、Vertex AI を使用して独自の LoRA ウェイトを追加でトレーニングする。
  • Firebase Storage を使用して、ADB ツールを使用せずにデバイス上のモデル ファイルを取得する。

この試験運用版タスクで作成したクールなものを楽しみにしています。MediaPipe チームの Codelab やコンテンツにご期待ください。