Stable DiffusionをGoogle Colaboratory上で動かして神絵ガチャを回してみる

## はじめに

最近神絵生成AIが話題ですね。
絵描きの端くれとしてこの波に乗り遅れるわけにはいかない！ということで、つい最近公開された [Stable Diffusion](https://github.com/CompVis/stable-diffusion) を [Google Colaboratory](https://colab.research.google.com/) （以下Google Colab）上で実行して遊べるようにしてみました。 :paintbrush:
[こちら](https://github.com/CompVis/stable-diffusion#diffusers-integration) に記載されている [diffusers library](https://github.com/huggingface/diffusers/tree/main#new--stable-diffusion-is-now-fully-compatible-with-diffusers) を使用してサクッと動かすのがゴールです。

以下環境構築をしてコードを動かすまでのまとめです。
作成したGoogle Colabのノートブックは [GitHub](https://github.com/jkff-mv/stable-diffusion-text2img-example) で公開しているため、過程とかどうでもいいから使ってみたい方は [こちら](https://colab.research.google.com/github/jkff-mv/stable-diffusion-text2img-example/blob/master/stable_diffusion_text2img_example.ipynb) からどうぞ。

## Stable Diffusionについて

オープンソースの画像生成AIです。
私は機械学習の専門家ではないので技術的なことは詳しくないですが、テキストから画像を生成するtext-to-imageのモデルだそうです。

処理に若干時間がかかりますが、こちらの [デモサイト](https://huggingface.co/spaces/stabilityai/stable-diffusion
) でとりあえず使用感を試せます。
添付の画像は「concept art, realistic, soft lighting, pale color, landscape of cumulonimbus background, summer, sunset, twilight, coast, starry sky」というテキストから生成されたものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/b013e4f3-1588-bd5a-d79b-00b5e0ee50db.png)

画像生成の処理を専用のサーバで行うことができる [DreamStudio Beta](http://beta.dreamstudio.ai/) というサービスも存在します。
こちらはアカウント登録が必要ですが、アカウント登録をすると2ポンド分のクレジットがもらえ、クレジットを使い切るまでは爆速での画像生成を体験できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/068a7abe-8b29-9ee3-cf62-311924826b05.png)

・・・ということで、お試しで数回触ってみるだけであれば上記のサイトで十分です。
ただせっかくオープンソースで公開されていますし、実際に触ると分かりますが同じテキストでもランダムにいろいろ生成されるので神絵が出るまでガチャを繰り返したいという場合は自分で実行環境を用意するのがよさそうです。

## Google Colaboratoryについて

ブラウザ上でPythonのコードを実行できるサービスです。 :snake:
もう少し詳しく言うと、Googleが提供しているJupyter Notebookのマネージドサービス的なものです。
こんな感じにコードを実行したり結果を表示したりできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/1067b203-9a5e-79de-fdfc-2b8bcdb2627b.png)

ブラウザ上でコードを実行できるサービスは他にもいろいろありますが、Google ColabではGPUが使えます、しかも無料で！
ということで機械学習の実行環境として重宝されています。

ただ無料で機能制限なく使い放題というわけではなく [こちら](https://research.google.com/colaboratory/faq.html#limitations-and-restrictions) にあるように制限も存在します。
有名なのが12時間ルールというもので、12時間経つと実行環境が初期化されてしまいます。
もちろん作成したコード、正確には「ノートブック」というドキュメントはちゃんと保存されており、ノートブック内のコードを再実行することで実行環境を再構築できます。

・・・ということで、今回はGoogle Colab上にStable Diffusionの実行環境を構築して、無料で爆速画像生成＆神絵ガチャを回してみたいと思います！

## Stable Diffusionを使うための事前準備

Google Colab上に実行環境を構築する前にStable Diffusionを使うための準備を行います。

### Hugging Faceのアカウント作成

まずはStable Diffusionのモデルを使用するために [Hugging Face](https://huggingface.co/) へのユーザ登録を済ませます。
ページ右上の「Sign Up」から画面の指示に従ってポチポチしていってください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/5dd02aac-733f-45c0-0bbc-3b415940c45b.png)

### Stable Diffusionのモデルの使用に関する規約への同意

モデルを使用するにあたり、規約（CreativeML OpenRAIL-Mライセンス、およびメールアドレスとユーザー名がモデルの作成者と共有されること）に同意する必要があります。
[こちら](https://huggingface.co/CompVis/stable-diffusion-v1-4) にアクセスし同意できる方は「Access repository」をクリックしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/da73d0c0-ec46-6698-3708-c1ac869eff03.png)

### Hugging Faceのアクセストークンの発行

diffusers libraryを実行する際に使用するアクセストークンを発行します。
[こちら](https://huggingface.co/settings/tokens) にアクセスし「New Token」より自分のアクセストークンを発行し、控えておいてください。

トークンの名前は自分で分かるものであれば何でも構いません。
権限は「read」で十分でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/a5baba2f-9719-c05e-70c7-910b6abff29b.png)

## Google Colabの実行環境構築

Stable Diffusionを使うための準備が終わったのでGoogle Colab上に実行環境を構築していきます。

### ノートブックの作成

Googleアカウントでログインした状態で [こちら](https://colab.research.google.com/) にアクセスし「ノートブックを新規作成」をクリックします。
作成したノートブックはGoogleドライブに自動で保存されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/c0bac95d-6c7b-0e10-05f7-d16502508aee.png)

以下作成したノートブックにいろいろな処理を記載していきます。

### GPUの使用

実行環境でGPUを使用するために「編集」→「ノートブックの設定」からGPUを割り当てます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/866d2c78-28eb-12a5-87dc-2f8349b4cfb6.png)

割り当てが問題なく行えているかどうかは以下のコードで確認できます。

```
!nvidia-smi -L
```

### 依存関係のインストール

以下のコードを実行し、必要なライブラリをインストールします。

```
!pip install --upgrade diffusers==0.12.1 transformers==4.26.0 accelerate==0.16.0 scipy==1.* ftfy==6.*
```

### セットアップ

Stable Diffusionのモデルのダウンロードやパイプラインの構築を行います。
予め発行したHugging Faceのアクセストークンを `access_token` に設定し、以下のコードを実行します。

```python
import torch
from diffusers import StableDiffusionPipeline

#@title Settings
access_token = "your-access-token"  #@param {type:"string"}

# パイプラインを構築する。
pipe = StableDiffusionPipeline.from_pretrained(
  "CompVis/stable-diffusion-v1-4",
  torch_dtype=torch.float16,
  use_auth_token=access_token
).to("cuda")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/c9776bd6-c5a7-c931-e9ce-3d6018d7ef4d.png)

### 画像生成

画像を生成します。
生成したい画像の内容を `prompt` に記述し、以下のコードを実行します。

```python
from IPython.display import display_png, Image
from torch import autocast

#@title Parameters
prompt = "a description of the image"  #@param {type:"string"}

# 画像を生成する。
with autocast("cuda"):
  image = pipe(prompt).images[0]

# 画像を保存する。
file_name = "image.png"
image.save(file_name)

# 画像を表示する。
display_png(Image(file_name))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/af30a56c-fdeb-abeb-29af-39a7932512d4.png)

### 神絵ガチャを回す

自分で環境構築を行うとこういうことが自由に行えるのがいいですよね。
大量の画像を生成し、生成した画像をGoogleドライブに保存してみます。
なお、ガチャを回しすぎるとGoogle Colabのリソース制限に引っかかってしばらくGPUが利用できなくなるのでほどほどに（ドキュメントによると状況によって変動する動的な使用制限を設けているとのことで、どのくらい使ったら制限に引っかかるのかはよく分かりません・・・）。

まずはGoogleドライブをマウントするために以下のコードを実行します。

```python
from google.colab import drive
drive.mount("/content/drive")
```

画像を生成します。
パラメータを設定して以下のコードを実行します。

* `prompt` ：生成したい画像の内容。
* `number_of_images` ：生成する画像数。
* `drive_directory` ：保存先ドライブのディレクトリ。

```python
import datetime
import os
from torch import autocast

#@title Parameters
prompt = "a description of the image"  #@param {type:"string"}
number_of_images = 10  #@param {type:"slider", min:1, max:100, step:1}
drive_directory = "/content/drive/MyDrive/output"  #@param {type:"string"}

# 画像の保存先となるディレクトリがなければ作成する。
os.makedirs(drive_directory, exist_ok=True)

# 画像のファイル名が被らないようにするための文字列を用意する。
yyyymmddhhmmss = datetime.datetime.now().strftime("%Y%m%d%H%M%S")

# 指定した回数、画像生成＆保存を繰り返す。
for i in range(number_of_images):
  with autocast("cuda"):
    image = pipe(prompt).images[0]

  file_path = os.path.join(drive_directory, f"image-{yyyymmddhhmmss}-{i:03}.png")
  image.save(file_path)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/73043195-c631-7433-5738-e1ec33e2716f.png)

神絵ガチャ無料10連の結果です。
こんな感じに画像がマイドライブの `output` 配下に保存されます。 :tada:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529034/3e285b0c-1c67-7ad7-6ac5-31696b942e24.png)

今回はGoogleドライブに保存しましたが、他にもローカルにDLすることも可能です。
詳しくは [こちら](https://colab.research.google.com/notebooks/io.ipynb) を参照ください。

## まとめ

生成した画像の中からいい感じのものを選んでベースとして使えば、背景とか描くのだいぶ楽になりそうな予感。
今後はこういったツールもうまく使いこなしながら創作活動していきたいですね。

あと [こちらのブログ](https://huggingface.co/blog/stable_diffusion) によると画像生成時に他にもパラメータを設定できるようなので、気が向いたらまたいろいろ触ってみようと思います。

## 主な更新履歴

### 2023/02/05

2023/02/05現在 `StableDiffusionPipeline.from_pretrained` の実行時に `TypeError: getattr(): attribute name must be string` となってしまう件を修正しました。

* diffusersライブラリを0.2.4から0.12.1を使用するように変更しました。
* ライブラリのバージョンアップに伴い、使い方が変わった部分があるので一部コードを修正しました。