IBM Cloud GPUサーバー環境で Stable Diffusionの画像変換(image2image) を実行

#### はじめに


Stable Diffusion というディープ・ラーニングのオープンソースとして公開された学習モデルを使用して、画像から画像の変換を [IBM Cloud のGPUサーバー(VSI)](https://www.ibm.com/jp-ja/cloud/gpu) で検証したログです。


Stable Diffusion は Google Colab で実施する方法が多く紹介されているのを見かけますが、筆者はGoogle Colab無料実行枠の上限を超えたため、検証アカウントを保持していた IBM Cloud で GPU サーバーを立てて環境を作成して、元の画像を有名な画風に変換する検証を実施してみることにしました。

---
当記事では Stable Diffusion の説明は他の方々による多くの情報が存在しているため省略します。
なお Stable Diffusion のtext-to-image は [Hugging Faceのページでデモが公開](https://stablediffusionweb.com/#demo) されているので試しの確認が可能です。(とても楽しいです)

一例：
![santa_claus_Fuji.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/4081fdeb-eeac-2f41-c098-5d6f86daaf03.png)





---


#### 環境


* IBM Cloud Classic VSI(仮想マシン) : flavor  [AC1.8x60](https://cloud.ibm.com/gen1/infrastructure/provision/vs?type=hourly&location=dal13&imageItemId=5952&portSpeed=187&profile=AC1_8X60X25&clearCache=true
)　(8 vCPU, 60GB Memory, OS : Ubuntu 20.04, disk: 100GB)

* IBM Cloud Object Storage : 元の画像の配置先として使用。(単なるWeb上の配置で任意です。)

* Stable Diffusion 使用モデル：[stable-diffusion-v-1-5](https://huggingface.co/runwayml/stable-diffusion-v1-5)
　=> 学習済みモデルをサーバーにダウンロードして使用します。

* 前提として [Hugging Face](https://huggingface.co/) のユーザー登録とTokenの取得、ライセンスの確認を実施しています。

---


#### 環境構築


環境構築/実行コードは "Running the model locally" を参考にしました。

https://github.com/huggingface/diffusers/tree/main#new--stable-diffusion-is-now-fully-compatible-with-diffusers

##### 1. 仮想マシンのオーダー

IBM Cloud で GPU の VSI を注文します。
GPU サーバーは ロケーションが限られておりダラスを選択しています。


![スクリーンショット 2022-12-11 11.35.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/a68b9a31-ba78-2c6b-8381-8915b2e8caf6.png)

プロファイルは AC1.8X60、OSは Ubuntu 20.04 を選択しています。
任意のssh 鍵を登録。

![スクリーンショット 2022-12-11 11.32.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/921ff601-8ac6-a34e-6d12-0a030ab55792.png)


ストレージはデフォルト 25GBですが 100GB を選択しています。

![スクリーンショット 2022-12-11 11.32.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/61d92f4c-d10e-715a-96f1-9936244a898b.png)

アドオンはデフォルトのまま。

![スクリーンショット 2022-12-11 11.32.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/44bff690-4a23-f1a4-a76c-6b75be65b4db.png)


1時間 およそ 1.42 ドルです。

![スクリーンショット 2022-12-11 11.32.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/94cbdab7-ad64-3064-2cc2-7ce043b9b47e.png)


上記でオーダーし数分~10分程度で作成が完了していました。

-----

##### 2. ログイン、OS確認

```
% ssh -i id_rsa_demo-vm101 root@xxx.xx.xxx.xx
root@testvsi01:~# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.5 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
root@testvsi01:~#
```
---


##### 3. 各種モジュールのインストール


① cuda-toolkit のインストール

GPU サーバーを使用するためのモジュールを導入しています。

参照：
・[IBM Cloud Docs: GPU ドライバーおよびソフトウェア・パッケージのインストール](https://cloud.ibm.com/docs/virtual-servers?topic=virtual-servers-installing-gpu-drivers-and-software-packages&locale=ja)
・[NVIDIA CUDA Installation Guide for Linux](https://docs.nvidia.com/cuda/cuda-installation-guide-linux/)
・[CUDA Toolkit 12.0 Downloads](https://developer.nvidia.com/cuda-downloads)


モジュール取得

```
root@testvsi01:~# wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-keyring_1.0-1_all.deb
--2022-12-11 02:45:17--  https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-keyring_1.0-1_all.deb
Resolving developer.download.nvidia.com (developer.download.nvidia.com)... 152.195.19.142
Connecting to developer.download.nvidia.com (developer.download.nvidia.com)|152.195.19.142|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4328 (4.2K) [application/x-deb]
Saving to: ‘cuda-keyring_1.0-1_all.deb’

cuda-keyring_1.0-1_all.d 100%[==================================>]   4.23K  --.-KB/s    in 0s
2022-12-11 02:45:17 (59.9 MB/s) - ‘cuda-keyring_1.0-1_all.deb’ saved [4328/4328]
```

導入

```
root@testvsi01:~# sudo dpkg -i cuda-keyring_1.0-1_all.deb
Selecting previously unselected package cuda-keyring.
(Reading database ... 63548 files and directories currently installed.)
Preparing to unpack cuda-keyring_1.0-1_all.deb ...
Unpacking cuda-keyring (1.0-1) ...
Setting up cuda-keyring (1.0-1) ..
```

```
root@testvsi01:~# sudo apt-get update
```

```
root@testvsi01:~# sudo apt-get -y install cuda
```

=> こちらの実行時間が長く、完了まで8分程度要しました。


これで nvidia-smi コマンドが実行可能となり、GPU稼働を確認できます。

```
root@testvsi01:~# nvidia-smi
Sun Dec 11 02:56:38 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.60.13    Driver Version: 525.60.13    CUDA Version: 12.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla P100-PCIE...  Off  | 00000000:00:07.0 Off |                    0 |
| N/A   32C    P0    26W / 250W |      0MiB / 16384MiB |      1%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
root@testvsi01:~#
```

---

続いてその他のモジュールを導入します。
Stable Diffusion の環境構築手順や、実行時にエラーが発生して追加で実施した内容です。環境によって異なると思われますのでご参考程度でご覧ください。

apt update 実行

```
root@testvsi01:~# sudo apt update
Hit:1 http://mirrors.service.networklayer.com/ubuntu focal InRelease
Hit:2 http://mirrors.service.networklayer.com/ubuntu focal-updates InRelease
Hit:3 http://mirrors.service.networklayer.com/ubuntu focal-backports InRelease
Hit:4 http://mirrors.service.networklayer.com/ubuntu focal-security InRelease
Hit:5 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64  InRelease
Reading package lists... Done
Building dependency tree
Reading state information... Done
57 packages can be upgraded. Run 'apt list --upgradable' to see them.
root@testvsi01:~# sudo apt -y upgrade
```

---

② pip 導入
```
root@testvsi01:~# sudo apt install pip
```
---


③ git-lefs 導入

```
root@testvsi01:~# sudo apt-get -y install git-lfs
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  git-lfs
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 3316 kB of archives.
After this operation, 11.1 MB of additional disk space will be used.
Get:1 http://mirrors.service.networklayer.com/ubuntu focal/universe amd64 git-lfs amd64 2.9.2-1 [3316 kB]
Fetched 3316 kB in 0s (56.2 MB/s)
Selecting previously unselected package git-lfs.
(Reading database ... 133156 files and directories currently installed.)
Preparing to unpack .../git-lfs_2.9.2-1_amd64.deb ...
Unpacking git-lfs (2.9.2-1) ...
Setting up git-lfs (2.9.2-1) ...
Processing triggers for man-db (2.9.1-1) ...
root@testvsi01:~#
```

```
root@testvsi01:~# git lfs install
Error: Failed to call git rev-parse --git-dir: exit status 128
Git LFS initialized.
```

```
root@testvsi01:~# git lfs install --skip-repo
Git LFS initialized.
```

エラーが発生していますが、--skip-repo をつけて回避できるのでそのまま進みました。


---

④ diffusers transformers scipy の upgrade


```
root@testvsi01:~# pip install --upgrade diffusers transformers scipy
Collecting diffusers
  Downloading diffusers-0.10.2-py3-none-any.whl (503 kB)
     |████████████████████████████████| 503 kB 32.7 MB/s

~ 長いので省略 ~ 

Installing collected packages: numpy, tqdm, packaging, filelock, typing-extensions, huggingface-hub, Pillow, regex, diffusers, tokenizers, transformers, scipy
Successfully installed Pillow-9.3.0 diffusers-0.10.2 filelock-3.8.2 huggingface-hub-0.11.1 numpy-1.23.5 packaging-22.0 regex-2022.10.31 scipy-1.9.3 tokenizers-0.13.2 tqdm-4.64.1 transformers-4.25.1 typing-extensions-4.4.0
root@testvsi01:~#
```

---

⑤ huggingface-cli へのログイン


```
root@testvsi01:~# huggingface-cli login

    _|    _|  _|    _|    _|_|_|    _|_|_|  _|_|_|  _|      _|    _|_|_|      _|_|_|_|    _|_|      _|_|_|  _|_|_|_|
    _|    _|  _|    _|  _|        _|          _|    _|_|    _|  _|            _|        _|    _|  _|        _|
    _|_|_|_|  _|    _|  _|  _|_|  _|  _|_|    _|    _|  _|  _|  _|  _|_|      _|_|_|    _|_|_|_|  _|        _|_|_|
    _|    _|  _|    _|  _|    _|  _|    _|    _|    _|    _|_|  _|    _|      _|        _|    _|  _|        _|
    _|    _|    _|_|      _|_|_|    _|_|_|  _|_|_|  _|      _|    _|_|_|      _|        _|    _|    _|_|_|  _|_|_|_|

    To login, `huggingface_hub` now requires a token generated from https://huggingface.co/settings/tokens .

Token:
```


ここで事前に取得していた Token を入力します。

```
Add token as git credential? (Y/n) y
Token is valid.
Cannot authenticate through git-credential as no helper is defined on your machine.
You might have to re-authenticate when pushing to the Hugging Face Hub.
Run the following command in your terminal in case you want to set the 'store' credential helper as default.

git config --global credential.helper store

Read https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage for more details.
Token has not been saved to git credential helper.
Your token has been saved to /root/.huggingface/token
Login successful
root@testvsi01:~#
```

---

⑥ torch 導入

```
root@testvsi01:~/test# pip3 install torch
Collecting torch
  Downloading torch-1.13.0-cp38-cp38-manylinux1_x86_64.whl (890.2 MB)
     |████████████████████████████████| 890.2 MB 5.3 kB/s

~ 長いので省略 ~ 

Installing collected packages: nvidia-cuda-nvrtc-cu11, nvidia-cuda-runtime-cu11, nvidia-cublas-cu11, nvidia-cudnn-cu11, torch
Successfully installed nvidia-cublas-cu11-11.10.3.66 nvidia-cuda-nvrtc-cu11-11.7.99 nvidia-cuda-runtime-cu11-11.7.99 nvidia-cudnn-cu11-8.5.0.96 torch-1.13.0
root@testvsi01:~/test#

```

⑦ accelerate 導入

```
root@testvsi01:~/test# pip install accelerate
Collecting accelerate
  Downloading accelerate-0.15.0-py3-none-any.whl (191 kB)
     |████████████████████████████████| 191 kB 30.2 MB/s

~ 長いので省略 ~ 

Installing collected packages: psutil, accelerate
Successfully installed accelerate-0.15.0 psutil-5.9.4
root@testvsi01:~/test#
```

---

⑧ 学習モデル "stable-diffusion-v1-5" のダウンロード


```
root@testvsi01:~# mkdir test
root@testvsi01:~# cd test
root@testvsi01:~/test# git clone https://huggingface.co/runwayml/stable-diffusion-v1-5
Cloning into 'stable-diffusion-v1-5'...
remote: Enumerating objects: 149, done.
remote: Counting objects: 100% (149/149), done.
remote: Compressing objects: 100% (141/141), done.
remote: Total 149 (delta 57), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (149/149), 534.08 KiB | 4.11 MiB/s, done.
Resolving deltas: 100% (57/57), done.
Filtering content:  33% (2/6), 788.70 MiB | 115.85 MiB/s
Filtering content: 100% (6/6), 12.25 GiB | 99.47 MiB/s, done.
Encountered 2 file(s) that may not have been copied correctly on Windows:
	v1-5-pruned-emaonly.ckpt
	v1-5-pruned.ckpt

See: `git lfs help smudge` for more details.
root@testvsi01:~/test#
```


```
root@testvsi01:~/test# ls -l
total 4
drwxr-xr-x 10 root root 4096 Dec 11 03:07 stable-diffusion-v1-5
```


---

#### 変換に使用する元の画像

元の画像はいらすとやさんで提供されているシンプルな山の絵を使用します。


![mountain_yama.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/0c6d9318-aba5-484b-e662-3f83a424adc7.png)


-----

#### 実行する Python スクリプト

test.py というスクリプトで実行します。

「#prompt = xxxx」と「#images[0].save("xxxx")を実行毎に変更し「モネ」、「ピカソ」、「草間彌生」、「葛飾北斎」、「ルノワール」、「ジブリ」、「デジタル(人ではなく電子的な修飾)」風のイメージを作成します。
(prompt の文言を変更することで幅広い創作イメージを作成することが可能です。(prompt 呪文))



```test.py
import requests
import torch
from PIL import Image
from io import BytesIO
import warnings ###
warnings.filterwarnings('ignore') ###

#from diffusers import StableDiffusionPipeline
from diffusers import StableDiffusionImg2ImgPipeline

device = "cuda"

#pipe = StableDiffusionPipeline.from_pretrained("./stable-diffusion-v1-5")

model_id_or_path = "./stable-diffusion-v1-5"

pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
    model_id_or_path,
    revision="fp16",
    torch_dtype=torch.float16,
)

pipe = pipe.to(device)

# 元のイメージ, IBM Cloud Object Storage に保管
url = "https://xxxxx.s3.ams03.cloud-object-storage.appdomain.cloud/mountain_yama.png"

response = requests.get(url)
init_image = Image.open(BytesIO(response.content)).convert("RGB")
init_image = init_image.resize((768, 512))


## 画風の種類, 実行時に変更
prompt = "Monet style"
#prompt = "Picaso style"
#prompt = "Kusama Yayoi style"
#prompt = "Hokusai style"
#prompt = "Renoir Yayoi style"
#prompt = "Ghibli style"
#prompt = "digital art"


images = pipe(prompt=prompt, image=init_image, strength=0.70, guidance_scale=7.5).images


# イメージの保存, 実行時に変更

images[0].save("Monet.png")
#images[0].save("Picaso.png")
#images[0].save("Yayoi.png")
#images[0].save("Hokusai.png")
#images[0].save("Renoir.png")
#images[0].save("Ghibli.png")
#images[0].save("digital.png")
```


test.py に実行権限を付与します。



```
root@testvsi01:~/test# ls -l
total 8
drwxr-xr-x 10 root root 4096 Dec 11 03:07 stable-diffusion-v1-5
-rw-r--r--  1 root root 1341 Dec 11 03:09 test.py


root@testvsi01:~/test# chmod 755 test.py
root@testvsi01:~/test# ls -l
total 8
drwxr-xr-x 10 root root 4096 Dec 11 03:07 stable-diffusion-v1-5
-rwxr-xr-x  1 root root 1341 Dec 11 03:09 test.py
```

----

#### 実行

test.py を実行します。

```
root@testvsi01:~/test# python3 test.py
100%|███████████████████████████████████████████████████████████████| 35/35 [00:17<00:00,  2.02it/s]
```

1回 17秒程度で完了します。


test.py 内の prompt, images の対象箇所を画風毎に手動で変更、繰り返し実行してイメージを作成します。

```
root@testvsi01:~/test# ls -ltr
total 2044
drwxr-xr-x 10 root root   4096 Dec 11 03:07 stable-diffusion-v1-5
-rw-r--r--  1 root root 297853 Dec 11 03:49 Yayoi.png
-rw-r--r--  1 root root 291996 Dec 11 03:50 Monet.png
-rw-r--r--  1 root root 322896 Dec 11 03:52 Picaso.png
-rw-r--r--  1 root root 300580 Dec 11 03:53 Hokusai.png
-rw-r--r--  1 root root 311417 Dec 11 03:55 Renoir.png
-rw-r--r--  1 root root 239714 Dec 11 03:57 Ghibli.png
-rwxr-xr-x  1 root root   1372 Dec 11 03:57 test.py
-rw-r--r--  1 root root 307026 Dec 11 03:58 digital.png
```



---

#### 実行結果のイメージ

強度(strength)は 0.7 固定です。


* 元のイメージ
![mountain_yama.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/0c6d9318-aba5-484b-e662-3f83a424adc7.png)

* モネ風
![Monet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/2e111eb4-6ca4-3b93-5126-d1ffb8530300.png)

* ピカソ風
![Picaso.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/57303a0e-58c3-9929-8e61-02a81c99fa37.png)

* 草間彌生 風
![Yayoi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/ba12bd24-6ad7-31fd-d2b7-4b8a116e7eb0.png)

* ジブリ風
![Ghibli.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/be4791aa-f06a-5750-d9a9-d9274d192bff.png)

* 葛飾北斎 風
![Hokusai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/97b2f53b-8740-d90a-0920-e286c291b77d.png)

* ルノワール 風
![Renoir.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/13dc6d44-ec67-07c0-5a9a-b947e780b939.png)

* デジタル 風
![digital.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/a82ecd23-d4e8-23e8-5275-7c5ed4eb940e.png)






---

#### 強度の違いによる結果出力確認


"Monet Style" で images で指定する strength(強度) を変更した場合の結果を確認しました。

対象行抜粋：

```
images = pipe(prompt=prompt, image=init_image, strength=xxx(ここを変更), guidance_scale=7.5).images
```

---

* strength=0.25

```
root@testvsi01:~/test# python3 test.py
100%|███████████████████████████████████████████████████████████████| 12/12 [00:06<00:00,  1.92it/s]
root@testvsi01:~/test#
```

=> 実行時間 6 秒程度


![Monet25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/abf59808-fc08-b14d-b73d-916f7589be44.png)

少し木が生えた程度です。


---

* strength=0.85

```
root@testvsi01:~/test# python3 test.py
100%|███████████████████████████████████████████████████████████████| 42/42 [00:20<00:00,  2.03it/s]
```

=> 実行時間 20 秒程度


![Monet85.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/f9283cdf-e50f-445c-bbb3-8fef1242fd63.png)


睡蓮が多く出現しました。


---

* strength=1.0

```
root@testvsi01:~/test# python3 test.py
100%|███████████████████████████████████████████████████████████████| 49/49 [00:24<00:00,  2.04it/s]
root@testvsi01:~/test#
```

![Monet100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/2d03af15-2051-18bf-4022-504110afcc2f.png)

=> 実行時間 24 秒程度

元の形がなくなりほぼモネの絵の雰囲気です...
また、強度が高いと実行時間が長くなるという結果でした。


---
#### 参考情報

これから IBM Cloud を始められるへのご参考情報です。

・  [IBM Cloud チェックリストの概要](https://cloud.ibm.com/docs/overview?topic=overview-get-started-checklist)


---

#### おわりに

・筆者のスキル背景はインフラ寄りのシステム・エンジニアです。機械学習やpythonはほぼ初心者です。
　Stable Diffusion の情報を見かけて数時間Google Colabで勉強後、GPUサーバーで動かしたということが上記の結果です。
　その程度のレベルですが、それだけ Stable Diffusionは初心者でも取り組みやすいと言えると思います。


・課金が気になっていましたがおおよそ2時間くらい実施し2.8ドル程度でした。


・環境が再現できるように[イメージ・テンプレート](https://cloud.ibm.com/docs/image-templates?topic=image-templates-creating-an-image-template&locale=ja)を作成しています。取得後にサーバー課金を無くすためにデバイスはキャンセルしています。


・IBM Cloud Watson Studio サービスの GPU 環境で Notebookで実行するのも良さそうです。

・Web or アプリ実装したいなと思いつついます。


以上です。