AUTOMATIC1111を恨めしく思いながらコマンドライン。
というのも寂しいので、GradioというPythonライブラリを使ってWebUIを実装しました。
Anything v3.0じゃなくてStable Diffusion v1.5でもやることは一緒。
ただ様々なモデルが使えないAMD環境にとっては、Waifuより特化したAnythingの貴重さが光ります。
Gradio
細かな設計など無しに、最小限のステップでGUI化できる主に機械学習プログラムに向いたライブラリらしいです。
AUTOMATIC1111もコレを使って作られています。
準備はライブラリを入れるだけ。
いつものvirtualenv環境に入ったらインストール。
pip install gradio
自作スクリプト
GitHub – gradio-appでパターンを学びながら、既存のスクリプトを融合させました。
流用、応用で書くnoobなのでご了承下さい。
from diffusers import StableDiffusionOnnxPipeline
def generate(prompt, nega_prom, height, width, steps, cfg, seed):
pipe = StableDiffusionOnnxPipeline.from_pretrained(
provider="DmlExecutionProvider",
pipe.safety_checker = lambda images, **kwargs: (images, [False] * len(images))
seed = int(random.randrange(4294967294))
print(f"Seed value : {seed}")
latents = get_latents_from_seed(seed, width, height)
gen_img = pipe(prompt=prompt, negative_prompt=nega_prom, height=height, width=width, num_inference_steps=steps, guidance_scale=cfg, latents=latents).images[0]
gen_img.save(f"./outputs/any3_step{steps}-cfg{cfg}-{seed}.png")
def get_latents_from_seed(seed: int, width: int, height:int) -> np.ndarray:
latents_shape = (1, 4, height // 8, width // 8)
# Gotta use numpy instead of torch, because torch's randn() doesn't support DML
rng = np.random.default_rng(seed)
image_latents = rng.standard_normal(latents_shape).astype(np.float32)
webui = gr.Interface(fn=generate,
gr.Textbox(label = 'Prompt text', value="", lines=2, elem_id="prompt"),
gr.Textbox(label = 'Negative Prompt text', value="", lines=2, elem_id="nega_prom"),
gr.Slider(minimum=64, maximum=1024, step=64, label="縦サイズ(px)", value=768, elem_id="height"),
gr.Slider(minimum=64, maximum=1024, step=64, label="横サイズ(px)", value=512, elem_id="width"),
gr.Slider(minimum=10, maximum=150, step=1, label="ステップ数", value=25, elem_id="steps"),
gr.Slider(minimum=1, maximum=10, step=0.5, label='CFG', value=7.5, elem_id="cfg"),
gr.Textbox(label = 'seed', value=None, placeholder="0 - 4294967294. Blank is random.", elem_id="seed"),
outputs=gr.Image().style(height=768)
import gradio as gr
import click
import datetime
import random
from diffusers import StableDiffusionOnnxPipeline
import numpy as np
def generate(prompt, nega_prom, height, width, steps, cfg, seed):
pipe = StableDiffusionOnnxPipeline.from_pretrained(
"./anything-v3.0",
provider="DmlExecutionProvider",
)
pipe.safety_checker = lambda images, **kwargs: (images, [False] * len(images))
if seed == "":
seed = int(random.randrange(4294967294))
else:
seed = int(seed)
print(f"Seed value : {seed}")
latents = get_latents_from_seed(seed, width, height)
gen_img = pipe(prompt=prompt, negative_prompt=nega_prom, height=height, width=width, num_inference_steps=steps, guidance_scale=cfg, latents=latents).images[0]
gen_img.save(f"./outputs/any3_step{steps}-cfg{cfg}-{seed}.png")
return gen_img
def get_latents_from_seed(seed: int, width: int, height:int) -> np.ndarray:
# 1 is batch size
latents_shape = (1, 4, height // 8, width // 8)
# Gotta use numpy instead of torch, because torch's randn() doesn't support DML
rng = np.random.default_rng(seed)
image_latents = rng.standard_normal(latents_shape).astype(np.float32)
return image_latents
webui = gr.Interface(fn=generate,
inputs=[
gr.Textbox(label = 'Prompt text', value="", lines=2, elem_id="prompt"),
gr.Textbox(label = 'Negative Prompt text', value="", lines=2, elem_id="nega_prom"),
gr.Slider(minimum=64, maximum=1024, step=64, label="縦サイズ(px)", value=768, elem_id="height"),
gr.Slider(minimum=64, maximum=1024, step=64, label="横サイズ(px)", value=512, elem_id="width"),
gr.Slider(minimum=10, maximum=150, step=1, label="ステップ数", value=25, elem_id="steps"),
gr.Slider(minimum=1, maximum=10, step=0.5, label='CFG', value=7.5, elem_id="cfg"),
gr.Textbox(label = 'seed', value=None, placeholder="0 - 4294967294. Blank is random.", elem_id="seed"),
],
outputs=gr.Image().style(height=768)
)
webui.launch()
import gradio as gr
import click
import datetime
import random
from diffusers import StableDiffusionOnnxPipeline
import numpy as np
def generate(prompt, nega_prom, height, width, steps, cfg, seed):
pipe = StableDiffusionOnnxPipeline.from_pretrained(
"./anything-v3.0",
provider="DmlExecutionProvider",
)
pipe.safety_checker = lambda images, **kwargs: (images, [False] * len(images))
if seed == "":
seed = int(random.randrange(4294967294))
else:
seed = int(seed)
print(f"Seed value : {seed}")
latents = get_latents_from_seed(seed, width, height)
gen_img = pipe(prompt=prompt, negative_prompt=nega_prom, height=height, width=width, num_inference_steps=steps, guidance_scale=cfg, latents=latents).images[0]
gen_img.save(f"./outputs/any3_step{steps}-cfg{cfg}-{seed}.png")
return gen_img
def get_latents_from_seed(seed: int, width: int, height:int) -> np.ndarray:
# 1 is batch size
latents_shape = (1, 4, height // 8, width // 8)
# Gotta use numpy instead of torch, because torch's randn() doesn't support DML
rng = np.random.default_rng(seed)
image_latents = rng.standard_normal(latents_shape).astype(np.float32)
return image_latents
webui = gr.Interface(fn=generate,
inputs=[
gr.Textbox(label = 'Prompt text', value="", lines=2, elem_id="prompt"),
gr.Textbox(label = 'Negative Prompt text', value="", lines=2, elem_id="nega_prom"),
gr.Slider(minimum=64, maximum=1024, step=64, label="縦サイズ(px)", value=768, elem_id="height"),
gr.Slider(minimum=64, maximum=1024, step=64, label="横サイズ(px)", value=512, elem_id="width"),
gr.Slider(minimum=10, maximum=150, step=1, label="ステップ数", value=25, elem_id="steps"),
gr.Slider(minimum=1, maximum=10, step=0.5, label='CFG', value=7.5, elem_id="cfg"),
gr.Textbox(label = 'seed', value=None, placeholder="0 - 4294967294. Blank is random.", elem_id="seed"),
],
outputs=gr.Image().style(height=768)
)
webui.launch()
virtualenvディレクトリの直下に好きな名前で保存(自分はgr_4.py)し、パラメータ無しで実行。
(virtualenv) PS C:\temp\virtualenv> python .\gr_4.py
Running on local URL: http://127.0.0.1:7860
To create a public link, set `share=True` in `launch()`.
(virtualenv) PS C:\temp\virtualenv> python .\gr_4.py
Running on local URL: http://127.0.0.1:7860
To create a public link, set `share=True` in `launch()`.
(virtualenv) PS C:\temp\virtualenv> python .\gr_4.py
Running on local URL: http://127.0.0.1:7860
To create a public link, set `share=True` in `launch()`.
表示されるURLをブラウザで開けばOK。
指定できるパラメータは6つ
- プロンプト
- ネガティブプロンプト
- 高さ
- 横幅
- ステップ数
- CFG
- シード値
シード値を空にした場合、ランダムシードが使われます。
画像はoutputsディレクトリにパラメータを付けたファイル名(例:any3_step40-cfg7.5-3795608005.png)でどんどん保存されます。
また、いちいちクリックしなくていい様、プレビュー欄を生成画像サイズと一緒にしてあります。

とりあえず、ようやく表現に凝った絵を試せるようになった、と思えました。
それでもCUDA(AUTOMATIC1111)環境には遠く及びません。
さしあたりでも欲しい機能はコレ。やり方がわからないけど。
複数回生成は一度にn個の画像をInterfaceでどう並べるのか分からない。結合サムネイルを作るなんてなおさら。
スケジューラはDDIMを試してみましたが、収束しない?絵になってしまい頓挫。どうやらonnxで多くのスケジューラがこうなってしまうそうです。
ort_nightly_directml更新がおすすめ
初回構築時には”ort_nightly_directml-1.13.0.dev20221003004”を使いました。
それが今は最新が”ort_nightly_directml-1.14.0.dev20221118001″になっています。
これが生成スピードに大きな影響をあたえるようです。
他の人のコメントでもかなり向上したそうですし、自分も体感できました。

定期的なアップデートがおすすめ。
2022/12/01更新
書いてある2つの機能をバージョンアップ追加しました
AMDのWindowsマシンで動くAnythingV3.0 WebUIを更新(スケジューラと複数枚生成)