AIに欲しい画像を生成して貰おう！【stable diffusion】

ブログや資料作成をする時にちょうど良いフリー画像が見つからない...
あると思います。

自前で用意出来れば良いのですが写真もなければ絵心もなかったりするともう無理。
じゃあAIに作って貰えば良いと思い最近話題の「stable diffusion」を試してみました。

今回は以下を参考に進めハマりポイント等交えながら進めていきます。

https://qiita.com/hevo2/items/c9c611a5f918d36732f3

## 生成方法

### Stable Diffusion

> オープンソースとして2022年8月に無償公開された描画AIである。ユーザがテキストでキーワードを指定することで、それに応じて画像が自動生成される仕組みとなっている

https://ja.wikipedia.org/wiki/Stable_Diffusion

- キーワードを指定するとそのお題に合った画像を自動生成してくれる
- 画像生成時のテキストである「プロンプト」は「呪文」とも呼ばれ少しコツが必要

## 動作環境

CPU: Apple M1 Max
メモリ: 64 GB

今回重要なのはGPUメモリ。
8GBだとギリギリで大きい画像は生成不可、16GB〜あれば時間はかかるものの動作はするという声が多かったです。

## 事前準備
### Python 3.xインストール

```
% python -V
Python 3.10.6
```

### Condaインストール

```
% conda -V
conda 4.14.0
```

### rustインストール

```
% brew install rustup-init
% rustup-init # 1を選択
% exec $SHELL -l # 起動中のシェルに反映
% rustup update
```

## 作業ディレクトリ作成

gitから必要なファイルをクローンしてそのディレクトリで作業

```
% git clone https://github.com/lstein/stable-diffusion.git
```

```
% cd stable-diffusion
```

## モデルを用意

画像を自動生成するための学習データであるモデルを https://huggingface.co から取得

まずはSign up
![スクリーンショット 2022-09-11 19.12.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231408/f844c9db-3a7b-41b9-ff78-5161e45cf31c.png)
メールアドレス・パスワード入力後、「Username」と「Full name」を追加して登録します。
ただこの２つのみだと400エラーとなり登録出来ず、optionalとなっていますが「Avatar」を追加することで進めました。
![スクリーンショット 2022-09-11 19.13.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231408/8dfc2218-0d7d-41dd-1838-c2138c78654e.png)

登録完了後 https://huggingface.co/CompVis/stable-diffusion-v-1-4-original へ移動
![スクリーンショット 2022-09-11 20.33.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231408/0c9d0a11-54d7-c942-cc3e-4246c5766e41.png)
「Access Repository」ボタンを押して承認するとDLページへ進むので「sd-v1-4.ckpt」をダウンロードします。
![スクリーンショット 2022-09-11 20.33.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231408/7f4863e2-3a30-f0f6-f65d-eb6a50b2f94c.png)
約4GBとかなり大きいファイルなので注意です。

## モデルを設置

先ほどcloneしたプロジェクト内にmodelを設置

```
% mkdir -p models/ldm/stable-diffusion-v1/

% mv ~/Downloads/sd-v1-4.ckpt ./models/ldm/stable-diffusion-v1/model.ckpt
```

## Pythonパッケージのインストール

```
% PIP_EXISTS_ACTION=w CONDA_SUBDIR=osx-arm64 conda env create -f environment-mac.yaml
```

インストール後以下コマンド実行

```
% conda activate ldm
```

ディレクトリ名の前がbaseからldmに切り替わればOK

```
(base) stable-diffusion % # 実行前
(ldm) stable-diffusion % # 実行後
```

初回のみ実行

```
% python scripts/preload_models.py

preloading bert tokenizer...
...success
preloading Kornia requirements (ignore the deprecation warnings)...
...success
preloading CLIP model (Ignore the deprecation warnings)...
Downloading vocab.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 939k/939k [00:01<00:00, 720kB/s]
Downloading merges.txt: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 512k/512k [00:01<00:00, 430kB/s]
Downloading special_tokens_map.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████| 389/389 [00:00<00:00, 51.5kB/s]
：
...success
```

## コマンド実行時エラー

### `ModuleNotFoundError: No module named` エラー

以下のようなエラーが出た場合は不足しているモジュールを追加インストール

```
% python scripts/preload_models.py
Traceback (most recent call last):
  File "scripts/preload_models.py", line 6, in <module>
    from transformers import CLIPTokenizer, CLIPTextModel
ModuleNotFoundError: No module named 'transformers'
```

```
% pip install ＄{モジュール名}
```

今回不足していたもの(condaでインストールすべきだったかも？)

```
pip install ai-tools
pip install clip
pip install cognitive_face
pip install dlib
pip install einops
pip install git+https://github.com/crowsonkb/k-diffusion/
pip install kornia
pip install ldm
pip install numpy
pip install omegaconf
pip install opencv-python # cv2モジュール内包
pip install pytorch_lightning
pip install torchvision
pip install transformers
pip install zprint
```

### モジュール内構文エラー

```
(ldm) stable-diffusion-mac % python scripts/orig_scripts/txt2img.py --n_samples 1 --plms --prompt "a photograph of a space cat"
Traceback (most recent call last):
  File "scripts/orig_scripts/txt2img.py", line 18, in <module>
    from ldm.util                  import instantiate_from_config
  File "/Users/hiro362/miniforge3/envs/ldm/lib/python3.8/site-packages/ldm.py", line 20
    print self.face_rec_model_path
          ^
```
printの記述方法がpython2向けになっている箇所をpython3に合わせる形で修正

```diff
- print self.face_rec_model_path 
+ print(self.face_rec_model_path)
```

### 画像処理エラー

```
ImportError: cannot import name 'PILLOW_VERSION' from 'PIL'
```

pillowモジュールが新しすぎると動かない？

https://cloraordinary.com/cannot-import-name-pillow_version-from-pil%E3%81%AE%E8%A7%A3%E6%B1%BA%E6%96%B9%E6%B3%95

バージョンダウン

```
% conda uninstall pillow
% conda install pillow=6.1
```

### 修正した筈の範囲でエラーが残る場合

conda環境再構築で解消される場合がある

```
% conda env remove -n ldm
% conda env create -f environment-mac.yaml
```

## 画像生成実行

まずは引用元の記事と同じコマンドを実行

```
% python scripts/orig_scripts/txt2img.py --n_samples 1 --plms --prompt "a photograph of a space cat"
# 宇宙猫の写真
Loading model from models/ldm/stable-diffusion-v1/model.ckpt
Global Step: 470000
:
Enjoy.
```
![00000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231408/060e68da-efe9-160d-5962-6ec58edbb4c1.png)
それっぽい画像が生成された。実行する度に結果は変わる模様。
処理時間は512*512で90秒前後、解像度を下げれば早くなる。

画像の保存先は`./outputs/txt2img-samples`

```
% open ./outputs/txt2img-samples
```

もうちょっと複雑な内容の画像をリクエストしてみる

```
% python scripts/orig_scripts/txt2img.py --n_samples 1 --plms --prompt "Kawaii fishing cat with rod on island"
# 島で釣竿を使って釣りをする可愛い猫
```

![000009.1810638898.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231408/15c0b788-17ee-2145-84e5-b345a21efce4.png)
ちょっと予測と違うものが出来た。指定するテキストの書き方は慣れが必要なのかも？

画風の指定も可能で、例えばイラスト風というプロンプトを追加すると雰囲気がガラッと変わる

```
% python scripts/orig_scripts/txt2img.py --n_samples 1 --plms --prompt "kawaii fishing cat with rod on island, Drawing"
# Drawingを追加
```
![00009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231408/c5eeb520-93d5-0f37-6da9-3f382b580551.png)


以下実行で http://localhost:9090 からプロンプトや各種設定をGUI操作も可能となる。
```
% python scripts/dream.py --web
* Initializing, be patient...
:
>> Point your browser at http://127.0.0.1:9090.
```

![スクリーンショット 2022-09-12 13.39.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231408/5dc3101f-d251-dc36-2027-4a13f8ab1c7c.png)


### エフェクトを凝りたい人向けの呪文生成ツール

https://promptomania.com/

## どういう仕組みで生成されているのか？

以下の記事が分かりやすかった

https://www.nico-soda.jp/blog/post/20220907_000121.html

### GAN（従来の主流）
学習データから新しい画像を生成する

### Diffusion Model
ノイズデータから元の画像を復元する

## 環境が無くても試せる方法

Midjourneyを使えばクラウド上で画像生成が可能（1アカウント25枚までなら無料）

https://kigyolog.com/article.php?id=1690

## 著作権はどうなっているのか？

現時点では生成者に帰属し商用利用も可能。
ただ批判的な声もあり

https://gigazine.net/news/20220815-stable-diffusion-controversy-ai-infringes-artists/

ユーザーのモラル次第では規制もあり得るかも？

Midjourney等代行サービスを使用する場合はサービス側が権利を持つようなので注意

> Midjourneyで作成した絵は、"作成者本人の創作だけ"で作られたものではなく、作成者＋MidjourneyのAIの作品なので、自作の絵を公開する際の権利関係とは少し異なります。

有料プランに入れば商用使用可能

> 前述のとおり、商用利用したい場合は、必ず有料プランに加入する必要があります。
> また、年間総収入100万ドル以上の企業の場合は、エンタープライズプランに加入する必要がありますので注意しましょう。
> ベータ版ということもあり、規約は随時更新されているので最新情報は公式ページもご確認下さい。

## 今後のトライ

- よりイメージ通りの画像を生成する方法の調査
- 固有名詞（商品名や人名）は正しく反映されないものが殆ど。可能であれば学習させてみたい