ジャコ Lab

プログラミング関連のメモ帳的ブログです

diffusers で GLIGEN を試してみる

github.com

diffusers v0.20.0 で対応された GLIGEN (Grounded Language-to-Image GENeration) を試してみます。

GLIGEN はバウンディングボックスとその矩形に対するキャプションを用いて、プロンプト+キャプション付き矩形で Text-to-Image を行うようです。

はじめに

diffusers v0.20.0 のリリースノートでは、2つの方法が紹介されています。

1つは Grounded generation で、もう1つは Grounded inpainting です。

Grounded generation は通常の Text-to-Image に キャプション付き矩形 を加えたものになり、 Grounded inpainting は、キャプション付き矩形で Inpaint を行うものになります。マスク画像の代わりにキャプション付き矩形を扱う感じになります。

Grounded generation

モデルのロード等

パイプラインの準備は非常に簡単です。Adapter や ControlNet は不要のため StableDiffusionGLIGENPipeline でモデルをロードするだけとなります。

import torch
from diffusers import StableDiffusionGLIGENPipeline

# パイプラインの準備
pipe = StableDiffusionGLIGENPipeline.from_pretrained(
    "masterful/gligen-1-4-generation-text-box",
    variant="fp16",
    torch_dtype=torch.float16
).to("cuda")

バウンディングボックスの準備

boxes = [[0.1387, 0.2051, 0.4277, 0.7090], [0.4980, 0.4355, 0.8516, 0.7266]]
phrases = ["a waterfall", "a modern high speed train running through the tunnel"]

ボックスは、数値の二次元配列となり若干わかりづらいですが、 [x1, y1, x2, y2] の配列のようです。
数値自体は 0~1の数字に見えるので、出力画像の百分率で矩形位置を指定するようです。

パイプライン実行

# パイプラインの実行
prompt = "a waterfall and a modern high speed train running through the tunnel in a beautiful forest with fall foliage"
image = pipe(
    prompt=prompt,
    gligen_boxes=boxes,
    gligen_phrases=phrases,
    gligen_scheduled_sampling_beta=1,
).images[0]

# 実行結果
image

見慣れないパラメータとしては gligen_ から始まるパラメータですね。 gligen_boxesgligen_phrases は前段階で準備した矩形とそのキャプションになるのでわかるとして、 gligen_scheduled_sampling_beta に何か 1 を設定しています。

gligen_scheduled_sampling_beta (float, defaults to 0.3)
Scheduled Sampling factor from GLIGEN: Open-Set Grounded Text-to-Image Generation. Scheduled Sampling factor is only varied for scheduled sampling during inference for improved quality and controllability.
Google 翻訳 — GLIGEN のスケジュールされたサンプリング係数: Open-Set Grounded Text-to-Image Generation。スケジュールされたサンプリング係数は、品質と制御性を向上させるために、推論中にスケジュールされたサンプリングに対してのみ変更されます。

よくある、係数でした。 1 に近づくほど GLIGEN の影響力が大きくなるとかでしょうか?

実行結果

Grounded generation の実行結果

実行結果が正しいか確認してみます。

プロンプトの確認
プロンプト
a waterfall and a modern high speed train running through the tunnel in a beautiful forest with fall foliage
Google 翻訳 — 滝と紅葉の美しい森のトンネルを走る現代の高速列車

, 紅葉の美しい森 現代の高速列車 というキーワードがあり、どこに何が描画されるかプロンプトからはわかりませんが、結果はあっていそうです。

キャプションの確認
矩形1
[0.1387, 0.2051, 0.4277, 0.7090]: a waterfall
矩形2
[0.4980, 0.4355, 0.8516, 0.7266]: a modern high speed train running through the tunnel

バウンディングボックスにより 滝の位置現代の高速列車の位置 が指示されました。

矩形を可視化

次に boxes について、数値のままだとどこを指定しているのかわからないので、可視化してみます。

バウンディングボックスを可視化

期待通りの位置に描画されています。

Grounded inpainting

続いて、キャプション付き矩形による Inpaint です。通常の Inpaint や ControlNet の Inpaint は以下でやりました。

zako-lab929.hatenablog.com

zako-lab929.hatenablog.com

モデルのロード等

GLIGEN 版の Inpaint では StableDiffusionGLIGENPipeline を使います。パイプライン自体は Grounded generation と同じです。ロードするモデルが異なります。

import torch
from diffusers import StableDiffusionGLIGENPipeline

# パイプラインの準備
pipe = StableDiffusionGLIGENPipeline.from_pretrained(
    "masterful/gligen-1-4-inpainting-text-box",
    variant="fp16",
    torch_dtype=torch.float16
).to("cuda")

元画像の準備

from diffusers.utils import load_image

# 元画像
init_image_url = "https://hf.co/datasets/huggingface/documentation-images/resolve/main/diffusers/gligen/livingroom_modern.png"
init_image = load_image(init_image_url)

元画像

バウンディングボックスの準備

# 枠の設定と枠の情報
boxes = [[0.2676, 0.6088, 0.4773, 0.7183]]
phrases = ["a birthday cake"]

パイプライン実行

# パイプラインの実行
prompt = "a birthday cake"
image = pipe(
    prompt=prompt,
    gligen_phrases=phrases,
    gligen_inpaint_image=init_image,
    gligen_boxes=boxes,
    gligen_scheduled_sampling_beta=1,
).images[0]

# 実行結果
make_image_grid([init_image, image], rows=1, cols=2)

実行結果

Grounded inpainting の実行結果

さて Grounded generation 同様、結果が正しいか確認してみます。

プロンプトの確認
プロンプト
a birthday cake

プロンプトからはどこが Inpaint されるかわかりませんが、ケーキらしきものは描画されています。

キャプションの確認
矩形1
[0.2676, 0.6088, 0.4773, 0.7183]: a birthday cake

バウンディングボックスにより バースデーケーキの位置 が指示されました。

矩形を可視化

(左) 元画像の矩形位置 | (右) 出力結果の矩形位置

どうやら期待通りに出力できていそうです。

ちなみに元画像が「640x640」で、出力画像が「512x512」でしたが、 バウンディングボックスは百分率指定なので、元画像が大きくても矩形位置に影響はありませんでした。

まとめ

Inpaint については、 バウンディングボックス を用意するか、 マスク画像 を用意するかの違いで、準備のしやすさに違いは出ますが、
Text-to-Image の方は、プロンプトに追加して更に位置を指示できるので、期待通りの構図を作りやすそうです。

GLIGEN でモデルを好きなものに変えられたら凄そうです。