Android の画像生成ガイド

MediaPipe Image Generator タスクを使用すると、テキスト プロンプトに基づいて画像を生成できます。このタスクでは、text-to-image モデルを使用して拡散技術で画像を生成します。

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

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

サンプルコード

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

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

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

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

  1. 次のコマンドを使用して、git リポジトリのクローンを作成します。
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. 必要に応じて、スパース チェックアウトを使用するように Git インスタンスを構成します。これにより、Image Generator のサンプルアプリのファイルのみが取得されます。
    cd mediapipe-samples
    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 重みにアクセスして処理します。

セットアップ

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

依存関係

画像生成ツールタスクは 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 タグに関するドキュメントをご覧ください。

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

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

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

画像生成ツールでは、基盤モデルが次のモデルに基づいて stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only モデル形式と一致している必要があります: stable-diffusion-v1-5/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 を使用し、深度プラグインは 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)
    

Canny エッジ

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)

データの準備

画像生成ツールでは、次の入力を使用できます。

  • prompt(必須): 生成する画像の説明を含むテキスト プロンプト。
  • iterations(必須): 画像を生成する合計反復回数。20 を出発点として使用することをおすすめします。
  • seed(必須): 画像生成時に使用される乱数シード。
  • condition image(省略可): モデルが生成の参照として使用する画像。プラグイン モデルを使用している場合にのみ適用されます。
  • 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() メソッドを使用して、前のセクションで指定した入力を使用して画像を生成します。これにより、1 つの生成画像が生成されます。

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

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
}

反復生成

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

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

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

    return bitmap
}

結果を処理して表示する

画像生成ツールは ImageGeneratorResult を返します。これには、生成された画像、完了時のタイムスタンプ、条件付き画像(入力として提供された場合)が含まれます。

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

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

入力:

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

生成された画像:

プロンプトに沿って生成されたアライグマの画像