Android の画像生成ガイド

MediaPipe Image Generator タスクを使用すると、テキスト プロンプトに基づいて画像を生成できます。このタスクでは、テキストから画像へのモデルを使用して、拡散手法で画像を生成します。

このタスクは、テキスト プロンプトを入力として受け取り、モデルが補強して生成の参照として使用できる条件画像(省略可)も受け取ります。Image Generator は、トレーニングまたは再トレーニング中にモデルに提供された特定のコンセプトに基づいて画像を生成することもできます。詳細については、LoRA でカスタマイズするをご覧ください。

これらの手順で説明するコードサンプルは GitHub で入手できます。このタスクの機能、モデル、構成オプションの詳細については、概要をご覧ください。

サンプルコード

MediaPipe Tasks のサンプルコードは、Android 用 Image Generator アプリの基本的な実装です。このアプリは、独自の Android アプリの開始点として使用できます。また、既存のアプリを変更する際にも参照できます。Image Generator のサンプルコードは GitHub でホストされています。

コードをダウンロードする

次の手順では、git コマンドライン ツールを使用してサンプルコードのローカルコピーを作成する方法について説明します。

サンプルコードをダウンロードするには:

  1. 次のコマンドを使用して、Git リポジトリのクローンを作成します。
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. 必要に応じて、スパース チェックアウトを使用するように Git インスタンスを構成し、Image Generator サンプルアプリのファイルのみを取得します。
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generation/android
    

サンプルコードのローカル バージョンを作成したら、プロジェクトを Android Studio にインポートしてアプリを実行できます。手順については、Android のセットアップ ガイドをご覧ください。

主要コンポーネント

次のファイルには、この画像生成サンプル アプリケーションの重要なコードが含まれています。

  • ImageGenerationHelper.kt: タスクを初期化し、画像生成を処理します。
  • DiffusionActivity.kt: プラグインまたは LoRA 重みが有効になっていない場合に画像を生成します。
  • PluginActivity.kt: プラグイン モデルを実装します。これにより、ユーザーは条件画像を入力として指定できます。
  • LoRAWeightActivity.kt: LoRA 重みにアクセスして処理します。LoRA 重みは、基盤モデルをカスタマイズし、特定のコンセプトの画像を生成するために使用されます。

セットアップ

このセクションでは、Image Generator を使用するように開発環境とコード プロジェクトを設定する主な手順について説明します。プラットフォーム バージョンの要件など、MediaPipe タスクを使用する開発環境の設定に関する一般的な情報については、Android の設定ガイドをご覧ください。

依存関係

Image Generator タスクは com.google.mediapipe:tasks-vision-image-generator ライブラリを使用します。この依存関係を Android アプリの build.gradle ファイルに追加します。

dependencies {
    implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'
}

Android 12(API 31)以降を搭載したデバイスの場合は、ネイティブ OpenCL ライブラリの依存関係を追加します。詳細については、uses-native-library タグに関するドキュメントをご覧ください。

AndroidManifest.xml ファイルに次の uses-native-library タグを追加します。

<uses-native-library android:name="libOpenCL.so" android:required="false" />
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false" />

モデル

MediaPipe Image Generator タスクには、このタスクと互換性のあるトレーニング済みの基盤モデルが必要です。モデルをダウンロードしたら、必要な依存関係をインストールし、モデルを適切な形式に変換します。次に、変換されたモデルを Android デバイスにプッシュします。

Image Generator で使用可能なトレーニング済みモデルの詳細については、タスクの概要のモデルのセクションをご覧ください。

基盤モデルをダウンロードする

Image Generator では、基盤モデルが runwayml/stable-diffusion-v1-5 モデルに基づいて runwayml/stable-diffusion-v1-5 EMA-only モデル形式と一致している必要があります。

依存関係をインストールしてモデルを変換する

$ pip install torch typing_extensions numpy Pillow requests pytorch_lightning absl-py

convert.py スクリプトを実行します。

$ python3 convert.py --ckpt_path <ckpt_path> --output_path <output_path>

変換されたモデルをデバイスにプッシュする

<output_path> フォルダのコンテンツを Android デバイスにプッシュします。

$ adb shell rm -r /data/local/tmp/image_generator/ # Remove any previously loaded weights
$ adb shell mkdir -p /data/local/tmp/image_generator/
$ adb push <output_path>/. /data/local/tmp/image_generator/bins

プラグイン モデルをダウンロードして LoRA 重みを追加する(省略可)

プラグイン モデルを使用する場合は、モデルをダウンロードする必要があるかどうかを確認します。追加のモデルが必要なプラグインの場合、プラグイン モデルは APK にバンドルするか、オンデマンドでダウンロードする必要があります。プラグイン モデルは軽量(約 23 MB)で、APK に直接バンドルできます。ただし、プラグイン モデルはオンデマンドでダウンロードすることをおすすめします。

LoRA でモデルをカスタマイズしている場合は、オンデマンドでダウンロードします。詳細については、LoRA 重み付けのプラグイン モデルをご覧ください。

タスクを作成する

MediaPipe Image Generator タスクは、createFromOptions() 関数を使用してタスクを設定します。createFromOptions() 関数は、構成オプションの値を受け入れます。構成オプションの詳細については、構成オプションをご覧ください。

設定オプション

このタスクには、Android アプリ用の次の構成オプションがあります。

オプション名 説明 値の範囲
imageGeneratorModelDirectory モデルの重みを保存する画像生成モデル ディレクトリ。 PATH
loraWeightsFilePath LoRA 重みファイルのパスを設定します。省略可。モデルが LoRA でカスタマイズされている場合にのみ適用されます。 PATH
errorListener オプションのエラー リスナーを設定します。 N/A

このタスクはプラグイン モデルもサポートしています。これにより、ユーザーはタスク入力に条件画像を含めることができます。基盤モデルは、この画像を拡張して生成のリファレンスとして使用できます。これらの条件画像には、顔の特徴点、エッジの輪郭、深度推定などがあり、モデルは追加のコンテキストと情報として画像の生成に使用します。

基盤モデルにプラグイン モデルを追加する場合は、プラグイン オプションも構成します。顔のランドマーク プラグインは faceConditionOptions、Canny エッジ プラグインは edgeConditionOptions、Depth プラグインは depthConditionOptions を使用します。

Canny エッジのオプション

edgeConditionOptions で次のオプションを設定します。

オプション名 説明 値の範囲 デフォルト値
threshold1 ヒステリシス手順の最初のしきい値。 Float 100
threshold2 ヒステリシス手順の 2 番目のしきい値。 Float 200
apertureSize Sobel 演算子のアパーチャ サイズ。一般的な範囲は 3 ~ 7 です。 Integer 3
l2Gradient デフォルトの L1 ノルムの代わりに、L2 ノルムを使用して画像勾配の振幅を計算するかどうか。 BOOLEAN False
EdgePluginModelBaseOptions プラグイン モデルのパスを設定する BaseOptions オブジェクト。 BaseOptions オブジェクト N/A

これらの構成オプションの仕組みについて詳しくは、Canny エッジ検出機能をご覧ください。

顔のランドマークのオプション

faceConditionOptions で次のオプションを設定します。

オプション名 説明 値の範囲 デフォルト値
minFaceDetectionConfidence 顔検出が成功と見なされるための最小信頼スコア。 Float [0.0,1.0] 0.5
minFacePresenceConfidence 顔のランドマーク検出における顔の存在スコアの最小信頼度スコア。 Float [0.0,1.0] 0.5
faceModelBaseOptions 状態画像を作成するモデルのパスを設定する BaseOptions オブジェクト。 BaseOptions オブジェクト N/A
FacePluginModelBaseOptions プラグイン モデルのパスを設定する BaseOptions オブジェクト。 BaseOptions オブジェクト N/A

これらの構成オプションの仕組みについて詳しくは、顔ランドマークタスクをご覧ください。

奥行きのオプション

depthConditionOptions で次のオプションを設定します。

オプション名 説明 値の範囲 デフォルト値
depthModelBaseOptions 状態画像を作成するモデルのパスを設定する BaseOptions オブジェクト。 BaseOptions オブジェクト N/A
depthPluginModelBaseOptions プラグイン モデルのパスを設定する BaseOptions オブジェクト。 BaseOptions オブジェクト N/A

基盤モデルのみで作成する

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

プラグインを使用して作成する

オプションのプラグイン モデルを適用する場合は、setPluginModelBaseOptions を使用してプラグイン モデルの基本オプションを設定します。プラグイン モデルで、条件画像の作成に追加のダウンロード済みモデルが必要な場合は、BaseOptions にパスを指定します。

顔のランドマーク

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val faceModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("face_landmarker.task")
    .build()

val facePluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("face_landmark_plugin.tflite")
    .build()

val faceConditionOptions = FaceConditionOptions.builder()
    .setFaceModelBaseOptions(faceModelBaseOptions)
    .setPluginModelBaseOptions(facePluginModelBaseOptions)
    .setMinFaceDetectionConfidence(0.3f)
    .setMinFacePresenceConfidence(0.3f)
    .build()

val conditionOptions = ConditionOptions.builder()
    .setFaceConditionOptions(faceConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

カニーエッジ

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val edgePluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("canny_edge_plugin.tflite")
    .build()

val edgeConditionOptions = EdgeConditionOptions.builder()
    .setThreshold1(100.0f)
    .setThreshold2(100.0f)
    .setApertureSize(3)
    .setL2Gradient(false)
    .setPluginModelBaseOptions(edgePluginModelBaseOptions)
    .build()

val conditionOptions = ConditionOptions.builder()
    .setEdgeConditionOptions(edgeConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

奥行き

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val depthModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("depth_model.tflite")
    .build()

val depthPluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("depth_plugin.tflite")
    .build()

val depthConditionOptions =
    ConditionOptions.DepthConditionOptions.builder()
        .setDepthModelBaseOptions(depthModelBaseOptions)
        .setPluginModelBaseOptions(depthPluginModelBaseOptions)
        .build()

val conditionOptions = ConditionOptions.builder()
    .setDepthConditionOptions(depthConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

LoRA 重みを使用して作成する

LoRA 重みを含める場合は、loraWeightsFilePath パラメータを使用してパスの場所を指定します。

val options = ImageGeneratorOptions.builder()
    .setLoraWeightsFilePath(weightsPath)
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

データの準備

Image Generator は、次の入力を受け入れます。

  • prompt(必須): 生成する画像を説明するテキスト プロンプト。
  • iterations(必須): 画像を生成するための反復処理の合計回数。20 が適切な開始点です。
  • seed(必須): 画像生成時に使用される乱数シード。
  • 状態画像(省略可): モデルが生成の参照として使用する画像。プラグイン モデルを使用している場合にのみ適用されます。
  • condition type(省略可): タスクで使用されるプラグイン モデルのタイプ。プラグイン モデルを使用している場合にのみ適用されます。

基盤モデルのみを含む入力

fun setInput(prompt: String, iteration: Int, seed: Int) {
    imageGenerator.setInputs(prompt, iteration, seed)
}

プラグインを使用した入力

オプションのプラグイン モデルを適用する場合は、conditionType パラメータを使用してプラグイン モデルを選択し、sourceConditionImage パラメータを使用して条件イメージを生成します。

オプション名 説明
conditionType 基盤モデルに適用されるプラグイン モデル。 {"FACE", "EDGE", "DEPTH"}
sourceConditionImage 状態画像の作成に使用されたソース画像。 MPImage オブジェクト

プラグイン モデルを使用している場合は、createConditionImage を使用して条件イメージを作成します。

fun createConditionImage(
    inputImage: MPImage,
    conditionType: ConditionType
): Bitmap {
    val result =
        imageGenerator.createConditionImage(inputImage, conditionType)
    return BitmapExtractor.extract(result)
}

条件画像を作成したら、プロンプト、シード、反復処理回数とともに入力として含めます。

imageGenerator.setInputs(
    prompt,
    conditionalImage,
    conditionType,
    iteration,
    seed
)

LoRA 重みのある入力

LoRA 重みを使用している場合は、重みによって表される特定のコンセプトを含む画像を生成する場合は、トークンがテキスト プロンプト内にあることを確認してください。

fun setInput(prompt: String, iteration: Int, seed: Int) {
    imageGenerator.setInputs(prompt, iteration, seed)
}

タスクを実行する

generate() メソッドを使用して、前のセクションで指定した入力を使用して画像を生成します。これにより、単一の生成画像が生成されます。

基盤モデルのみで生成する

fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
    val result = imageGenerator.generate(prompt, iteration, seed)
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

プラグインで生成する

fun generate(
    prompt: String,
    inputImage: MPImage,
    conditionType: ConditionType,
    iteration: Int,
    seed: Int
): Bitmap {
    val result = imageGenerator.generate(
        prompt,
        inputImage,
        conditionType,
        iteration,
        seed
    )
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

LoRA 重みを使用して生成する

LoRA 重みでカスタマイズされたモデルを使用して画像を生成するプロセスは、標準の基盤モデルを使用するプロセスと似ています。トークンがプロンプトに含まれていることを確認して、同じコードを実行します。

fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
    val result = imageGenerator.generate(prompt, iteration, seed)
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

反復生成

Image Generator は、iterations 入力パラメータで定義されているように、各反復処理中に生成された中間画像を出力することもできます。これらの中間結果を表示するには、setInputs メソッドを呼び出し、execute() を呼び出して各ステップを実行します。中間結果を表示するには、showResult パラメータを true に設定します。

fun execute(showResult: Boolean): Bitmap {
    val result = imageGenerator.execute(showResult)

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

    return bitmap
}

結果を処理して表示する

Image Generator は、生成されたイメージ、完了時のタイムスタンプ、入力として指定された条件付きイメージ(存在する場合)を含む ImageGeneratorResult を返します。

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

次の画像は、基盤モデルのみを使用して次の入力から生成されました。

入力:

  • プロンプト: 「ゆるいつば広の帽子をかぶったカラフルな漫画のラクーンが、棒を持って森の中を歩いている。アニメーション、3 分の 4 ビュー、絵画」
  • シード: 312687592
  • 反復処理: 20

生成された画像: