環偶記

環の偶に書く記録

環(素人) v.s. Stable Diffusion

AIの限界もあるとはいえ中々

はじめに

 今Stable Diffuisonがアツい!ということでローカルにインストールして動かしてみました。

 AIに絵を書かせるというのは過去にもあって、This cat dies not existは架空の猫を生成し続けていました。不定期にサイトを開いては猫に擬態し損ねたエイリアンになってしまった画像を見て笑っていましたよね。

https://thiscatdoesnotexist.com/

gigazine.net

 時は流れついに言葉を入れるとなんでも対応してくれるまでに至ったと思うと感慨深いですね。自動生成猫と違って何も言わないと何も作ってくれないので、目標として自分用にアニメキャラクターっぽいアイコンをつくることにしました。果たしてどれほどまでにうまくいくのでしょうか。でも上のやつとか(AIが作った割には)良くないですか!?

スペック

CPU:AMD Ryzen 5 2600

メモリ:16GB

GPUNVIDIA GeForce GTX 1060 6GB

後書いとく必要あるやつ思い出したら追記します

 これで 1 Stepあたり1.2秒前後で処理されています。何かの参考になれば

インストール

 巷に転がっているので各自調べてください(知恵袋並感)。詰まったところはあったので書いてきます。

①CUDAをインストールするときにはpyTorchが対応しているバージョンをインストールしましょう。CUDA1.17をインストールしてpyTorch対応無いやん!って適当なpyTorchインストールしたら動きませんでした。1.16をインストールしてpyTorchをアンインストール&対応バージョンインストールで動きました。

②NSFWで画像が黒塗りになる問題はパッケージが保存されているフォルダ、Windowsでいうところの

C:\Users\User\AppData\Local\Programs\Python\Python310\Lib\site-packages\diffusers\pipelines\stable_diffusion\safety_checker.py

(pythonのバージョンは各自差し替え)

の中身をいい感じに消すと黒塗りにされなくなります。

images[idx] = np.zeros(images[idx].shape)  # black image

ここをコメントアウトしてcontinueとかに差し替えるといいでしょう。

 

呪文

 ぶっちゃけ未だに完全に理解できてませんが、以下のサイトを参考に色々書いています。

lexica.art

 呪文と出力画像9枚が見られるので良さそうな画像に付いている呪文から良さげなものを選びましょう。

 今書いている呪文はこちらで…

modern anime style kawaii girl with blue eyes. long blond hair, twintail, japanese high school uniform, symmetrical facial features, front, smile, shinkai makoto, rule of thirds, extreme detail, detailed drawing, Unreal Engine 4k 8k ultra HD pixiv

 以下詳細:

modern anime style kawaii girl →実写が出てきてないので多分効いてる

with blue eyes→青目率半々、それ以外のパーツが青になることも

long blond hair→longはイマイチ、blondはかなり効いているが色の細かいバリエーションは少ないかなと感じた。

twintail→ほぼ効いてない

japanese high school uniform→AIが制服っていうんなら多分これも制服なんだろうな…って感じのものが多数

symmetrical facial features→わからん

front→半々

smile→後に出てくる画像を見るとわかるが、笑顔にするために顔歪められがち。消していいと思う

shinkai makoto→時々背景が新海誠らしいきれいな空になって楽しめる

rule of thirds, extreme detail, detailed drawing→呪文 意味不明

Unreal Engine 4k 8k ultra HD→呪文 意味はわかるけどさあ…

pixiv→効いてるかの判別無理じゃない? 

 とにかく試すしか無いぞ!

 

Seed値

 好きな絵があった場合そのSeed値を基にStep数を増やせばより良いものができるらしいのですがSeed値を出力する方法がわかりませんでした。調べても出てこなかったのですが代わりにSeed値を指定して出力する方法は見つけたのでとりあえずテストすることに。Seedを設定して画像生成するのは以下のコード

with autocast(DEVICE):
    myseed = 31
    generator = torch.Generator("cuda").manual_seed(myseed)
    steps = 50
    image = pipe(prompt, guidance_scale=7.5, num_inference_steps=steps, generator=generator)["sample"][0]

 とりあえずこの条件で複数回出力すると同じ画像が生成されることがわかりました。良かった。

 次にこのSeed値は数値らしいのですが一応文字列入れたらどうなるかテストしました。

myseed = "int"

これで動かすと案の定以下のエラーが出ました。整数を入れましょう。

RuntimeError: manual_seed expected a long, but got str

 つまりランダムな整数を作ってSeed値にし、画像出力時にファイル名にそれを書いておけば遡って当たることも可能というわけです。なので、やらなければならないのはlong型 (python3であればint型) のランダム数字生成コードを作ることですね。調べたところpythonのint型に上限がないようなので、とりあえず行けるところまで行くか!と適当に数を置いたら、

myseed = random.randint(-2 ** 64, 2 ** 64)

以下のエラーが出てしまいました。long型の範囲ということで恐らく問題ないであろう-2^63から2^63-1までに設定し直して再実行したところ現状エラーは吐いていません。

RuntimeError: Overflow when unpacking long

myseed = random.randint(-2 ** 63, 2 ** 63-1)

 とりあえずSeed値がわかった上で出力したものの中から良さげなものを選んで、Step数を増やしてみましょう。

↑がStep=50でSeedを固定してStep100で出力したものがこちら↓

??????

なんか悪くなってない?というわけで125stepsと150stepsで出力すると…

125

150

 …見なかったことにしよう!

 どのみちSeedを気にするより前に出力してしまった絵はSeedを逆引き出来ないのでどうしようもないのが悲しいところ。こればっかりは運ですね。

感想

 画像を大量に生成して、見れたものではないような絵(たくさん)の中からちゃんと人間に見える絵(すくない)を探し出してきてさらにその中から自分の心に響く絵を探し出すという砂金採りみたいなことを楽しくやり続けています。絵がかけない人にとっては生成した絵をレタッチするくらいで十分それっぽくできるのがいいですね。今回のようにアイコン程度の何かを作りたい時にはデザインと構図を考えなくていいのでとても楽だと思いますよ。

 一方でこれを商用利用すると考えると相当厳しいだろうと思いました。絵柄も統一できないし計算コストの割に合わないだろうなと思います。

 個人的にに注目すべきかなと思った点は服のデザインで、絶対に人間には思いつかないであろう非機能的なデザインとAI特有のガバガバの塗り方もあって、想像力で足りない点を補うと面白そうなものができそうだと思いました。

 あと腕から先(特に手!手!手!)は絶対に書かせてはいけない。エルドラージが生まれるぞ!

(※イメージ)

 お気に入りも見つけられたので(seed値が残って無いのが残念) これからもちょくちょく試していきたいと思います。

 

おまけ

今動かしてるコード

import datetime
import torch
from diffusers import StableDiffusionPipeline
from torch import autocast
import random

 

MODEL_ID = "CompVis/stable-diffusion-v1-4"
DEVICE = "cuda"
YOUR_TOKEN = "各自生成したトークンを使用

pipe = StableDiffusionPipeline.from_pretrained(MODEL_ID, revision="fp16", torch_dtype=torch.float16, use_auth_token=YOUR_TOKEN)
pipe.to(DEVICE)

prompt = "modern anime style kawaii girl with blue eyes. long blond hair, twintail, japanese high school uniform, symmetrical facial features, front, pripara, blue archive, shinkai makoto, rule of thirds, extreme detail, detailed drawing, Unreal Engine 4k 8k ultra HD pixiv"

for i in range(15):
    with autocast(DEVICE):
        myseed = random.randint(-2 ** 63, 2 ** 63-1)
        generator = torch.Generator("cuda").manual_seed(myseed)
        steps = 50
        image = pipe(prompt, guidance_scale=7.5, num_inference_steps=steps, generator=generator)["sample"][0]
        dt_ontime = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        image.save(f"保存先\\{myseed}_{dt_ontime}.png")