追記
AUTOMATIC1111/stable-diffusion-webui にAPIが追加されていました。
初期設定が必要なので webui-user.bat をテキストエディタで開いて
set COMMANDLINE_ARGS=--api
と追記して webui-user.bat を起動すると使えるようになります。
stable-diffusion-webuiに連続生成する機能があるそうです。
ご指摘頂きありがとうございます。
この記事は、Waifu DiffusionやNovelAI Diffusion等でランダムなPromptワードを指定してイラストを自動生成する場合や、APIの使い方の参考にしてください。
はじめに
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」で確認できます。
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()