LoginSignup
10
9

More than 1 year has passed since last update.

stable-diffusion-webuiのtxt2imgをAPIでランダムワード生成自動化

Last updated at Posted at 2022-10-21

追記

AUTOMATIC1111/stable-diffusion-webui にAPIが追加されていました。

初期設定が必要なので webui-user.bat をテキストエディタで開いて

webui-user.bat
set COMMANDLINE_ARGS=--api

と追記して webui-user.bat を起動すると使えるようになります。

stable-diffusion-webuiに連続生成する機能があるそうです。
ご指摘頂きありがとうございます。

この記事は、Waifu DiffusionやNovelAI Diffusion等でランダムなPromptワードを指定してイラストを自動生成する場合や、APIの使い方の参考にしてください。

はじめに

hoge_2.gif

AUTOMATIC1111/stable-diffusion-webuiでは、固定されたPromptワードで毎回ボタンをクリックして生成するため、自動生成する方法を考えました。

SeleniumとWebDriverを使用する方法も考えましたがGradioでUIが生成され
ていたため、AUTOMATIC1111/stable-diffusion-webuiからフォークされたリポジトリを使用しました。

かんたんなPythonプログラム例も張っておきます。

全て自己責任でお願い致します。

準備

AUTOMATIC1111/stable-diffusion-webuiをkritaから動かすために開発されているリポジトリですが、APIが実装されていて更新頻度も高かったのでこちらを使用しました。

AUTOMATIC1111/stable-diffusion-webuiの初期設定と同様にckptファイルを「models\Stable-diffusion」フォルダに配置します。
APIからckptファイルを選択できるようですが、うまくいかなかったので一種類のみ配置します。

NovelAIの場合はhypernetworkのptファイルを「models\hypernetworks」に配置します。

webui.batを開いて起動します。

hypernetworkはAPIで指定できないようなので「http://127.0.0.1:7860」をブラウザで開いて設定します。

APIは「http://127.0.0.1:8000/docs」で確認できます。

Pythonでtxt2img
requests.post(url="http://127.0.0.1:8000/txt2img", json=params).json()

プログラム例

画像サイズは 「"orig_width"」と「 "orig_height"」で指定します。
生成された画像は、「"outputs/krita-out"」フォルダに保存され、「outputs\txt2img-images」フォルダにも512×512の画像が生成されます。
「"sd_model"」はckptファイルの選択ですが、「"model.ckpt"」のままでも自動で選択されました。

固定ワードで連続生成

import requests

params = {
  "restore_faces": False,
  "face_restorer": "CodeFormer",
  "codeformer_weight": 0.5,
  "sd_model": "model.ckpt",
  "prompt": "masterpiece, high quality, full body , a girl , looking at viewer",
  "negative_prompt": "lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry",
  "seed": -1,
  "seed_enable_extras": False,
  "subseed": -1,
  "subseed_strength": 0,
  "seed_resize_from_h": 0,
  "seed_resize_from_w": 0,
  "sampler_name": "Euler a",
  "steps": 30,
  "cfg_scale": 7.5,
  "denoising_strength": 0.35,
  "batch_count": 1,
  "batch_size": 1,
  "base_size": 512,
  "max_size": 768,
  "tiling": False,
  "highres_fix": False,
  "firstphase_height": 512,
  "firstphase_width": 512,
  "upscaler_name": "None",
  "filter_nsfw": False,
  "include_grid": False,
  "sample_path": "outputs/krita-out",
  "orig_width": 512,
  "orig_height": 512
}

def main():
    while True:
        try:
            r = requests.post(url="http://127.0.0.1:8000/txt2img", json=params).json()
            if r['outputs'] == []:
                    break
            print( 'Prompt:' + r['info'].split(':')[1].replace(', "all_prompts"','').replace('"','') + ' で生成しました。' )
        except:
            break
        
if __name__ == "__main__":
    main()

固定ワード+ランダムワードで連続生成

ランダムPromptワード「"random_prompt"」各行の「,」で区切られたワード1つをランダムで選択して、上から順番につなげ固定Promptワード「"default_prompt"」Promptワードを生成します。
例1
masterpiece, high quality, full body, a girl , blond hair ,School uniforms ,check skert ,Long hair , Beach , Summer , fox ears
例2
masterpiece, high quality, full body, a girl ,Red hair , Chinese dresses ,denim skert , twin-tail hair , countryside , Autumn , bear ears

import requests
import random

f = {
    "prompt":{
        "default_prompt": "masterpiece, high quality, full body, a girl",
        "random_prompt":[
            "Red hair, blue hair, blond hair, silver hair",
            "School uniforms, Chinese dresses",
            "denim shorts,check skert,denim skert",
            "Long hair, short hair, twin-tail hair, ponytail",
            "city, Beach, countryside",
            "Spring, Summer, Autumn, Winter",
            "Cat ears, fox ears, bear ears"
        ]
    },
    "negative_prompt":{
        "default_negative_prompt": "lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry",
        "random_negative_prompt": [
            "dog year"
        ]
    },
    "params":{
        "restore_faces": "False",
        "face_restorer": "CodeFormer",
        "codeformer_weight": 0.5,
        "sd_model": "model.ckpt",
        "seed": -1,
        "seed_enable_extras": "False",
        "subseed": -1,
        "subseed_strength": 0,
        "seed_resize_from_h": 0,
        "seed_resize_from_w": 0,
        "sampler_name": "Euler a",
        "steps": 30,
        "cfg_scale": 7.5,
        "denoising_strength": 0.35,
        "batch_count": 1,
        "batch_size": 1,
        "base_size": 512,
        "max_size": 768,
        "tiling": "False",
        "highres_fix": "False",
        "firstphase_height": 512,
        "firstphase_width": 512,
        "upscaler_name": "None",
        "filter_nsfw": "False",
        "include_grid": "False",
        "sample_path": "outputs/krita-out",
        "orig_width": 512,
        "orig_height": 512
    }
}

def bool_check(s):
    if isinstance( s, str ) and s.lower() == 'false':
        return False
    elif isinstance( s, str ) and s.lower() == 'true':
        return True
    return s

def main():
    while True:
        try:
            f['params']['prompt'] = f['prompt']['default_prompt'] + ''.join([' ,'+_.split(",")[random.randrange(len(_.split(",")))] for _ in f['prompt']['random_prompt']])
            f['params']['negative_prompt'] = f['negative_prompt']['default_negative_prompt'] + ''.join([' ,'+_.split(",")[random.randrange(len(_.split(",")))] for _ in f['negative_prompt']['random_negative_prompt']])

            for _ in f['params']:
                f['params'][_] = bool_check(f['params'][_])

            r = requests.post(url="http://127.0.0.1:8000/txt2img", json=f['params']).json()
            
            if r['outputs'] == []:
                print('Error')
                break
				
            print( 'Prompt:' + r['info'].split(':')[1].replace(', "all_prompts"','').replace('"','') + ' で生成しました。' )
            
        except Exception as e:
            print(e)
            print(r)
            print('Error')
            break
        
if __name__ == "__main__":
    main()
10
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9