![見出し画像](https://assets.st-note.com/production/uploads/images/128549308/rectangle_large_type_2_c8e611343454db8d55c29cf73d093cd6.jpeg?width=800)
WSL2でInstantIDを試してみる
「チューニング不要の新しい最先端の方法であり、単一画像のみでアイデンティティを保持した生成を実現し、さまざまなダウンストリーム タスクをサポート」するらしい「InstantID : Zero-shot Identity-Preserving Generation in Seconds」を試してみます。
使用するPCはドスパラさんの「GALLERIA UL9C-R49」。スペックは
・CPU: Intel® Core™ i9-13900HX Processor
・Mem: 64 GB
・GPU: NVIDIA® GeForce RTX™ 4090 Laptop GPU(16GB)・GPU: NVIDIA® GeForce RTX™ 4090 (24GB)
・OS: Ubuntu22.04 on WSL2(Windows 11)
です。
準備
python環境
venvを構築して、
python3 -m venv instantid
cd $_
source bin/activate
pip installします。
pip install opencv-python transformers accelerate insightface onnxruntime-gpu diffusers
InstantID環境
リポジトリをクローンします。
git clone https://github.com/InstantID/InstantID.git
cd InstantID
チェックポイントを ./checkpoints ディレクトリにダウンロードします。
huggingface_hubパッケージをインストールし、pythonを起動。
pip install huggingface_hub
python
以下を流し込んで、3つのファイルをダウンロードします。
from huggingface_hub import hf_hub_download
hf_hub_download(repo_id="InstantX/InstantID", filename="ControlNetModel/config.json", local_dir="./checkpoints")
hf_hub_download(repo_id="InstantX/InstantID", filename="ControlNetModel/diffusion_pytorch_model.safetensors", local_dir="./checkpoints")
hf_hub_download(repo_id="InstantX/InstantID", filename="ip-adapter.bin", local_dir="./checkpoints")
つづいて、antelopev2.zip - Google Drive を ./models ディレクトリに配置します。wgetやcurlコマンドですと面倒なので、ブラウザでダウンロードして配置します。ダウンロードしたzipファイルをunzipします。
unzip antelopev2.zip -d models
以下のように展開されます。
$ find models/
models/
models/antelopev2
models/antelopev2/scrfd_10g_bnkps.onnx
models/antelopev2/genderage.onnx
models/antelopev2/glintr100.onnx
models/antelopev2/1k3d68.onnx
models/antelopev2/2d106det.onnx
流し込むコード
(1) モデルをロードするコード
READMEのUsageにあるサンプルコードのままですと動きませんでした。
・2箇所あるモデルロードの引数にdevice_map="auto" を追加
・StableDiffusionXLInstantIDPipeline.from_pretrainedメソッドの戻り値に帯する .cuda() を削除
修正後のコードは以下です。
import diffusers
from diffusers.utils import load_image
from diffusers.models import ControlNetModel
import cv2
import torch
import numpy as np
from PIL import Image
from insightface.app import FaceAnalysis
from pipeline_stable_diffusion_xl_instantid import StableDiffusionXLInstantIDPipeline, draw_kps
# prepare 'antelopev2' under ./models
app = FaceAnalysis(name='antelopev2', root='./', providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])
app.prepare(ctx_id=0, det_size=(640, 640))
# prepare models under ./checkpoints
face_adapter = f'./checkpoints/ip-adapter.bin'
controlnet_path = f'./checkpoints/ControlNetModel'
# load IdentityNet
controlnet = ControlNetModel.from_pretrained(
controlnet_path,
device_map="auto",
torch_dtype=torch.float16
)
base_model = 'wangqixun/YamerMIX_v8' # from https://civitai.com/models/84040?modelVersionId=196039
pipe = StableDiffusionXLInstantIDPipeline.from_pretrained(
base_model,
controlnet=controlnet,
device_map="auto",
torch_dtype=torch.float16
)
# load adapter
pipe.load_ip_adapter_instantid(face_adapter)
(2) 画像を生成するコード
a. こちらもサンプルコードのままだとエラーになります。修正箇所は以下です。代入先の変数imageを face_imageに文字列置換します。
image = load_image(file_path)
b. negative_prompt変数が使用されていないので、コメントアウトしておきます。ま、pipelineに設定しても良いのですが。
c. 何度も繰り返し実行できるように関数にしておきます。引数としては
・画像ファイルへのパス
・プロンプト(任意)
です。
d. 生成した画像は確認したいですよね?ついでに、showもしましょう。
e. 生成した画像のファイルへの保存(save)もファイル名が重複しないようにしておきます。
修正後のコードはこちら。
import os
import time
def i(
file_path: str,
prompt: str=None,
):
# load an image
face_image = load_image(file_path)
# prepare face emb
face_info = app.get(cv2.cvtColor(np.array(face_image), cv2.COLOR_RGB2BGR))
face_info = sorted(face_info, key=lambda x:(x['bbox'][2]-x['bbox'][0])*x['bbox'][3]-x['bbox'][1])[-1] # only use the maximum face
face_emb = face_info['embedding']
face_kps = draw_kps(face_image, face_info['kps'])
if not prompt:
prompt = "film noir style, ink sketch|vector, male man, highly detailed, sharp focus, ultra sharpness, monochrome, high contrast, dramatic shadows, 1940s style, mysterious, cinematic"
#negative_prompt = "ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vibrant, colorful"
# generate image
pipe.set_ip_adapter_scale(0.8)
image = pipe(
prompt,
image_embeds=face_emb,
image=face_kps,
controlnet_conditioning_scale=0.8,
).images[0]
# save a generated image to "./outputs/image_%Y%m%d_%H%M%S.jpg"
image_basename = os.path.splitext(os.path.basename(file_path))[0]
outdir="outputs"
os.makedirs(outdir, exist_ok=True)
image.save(outdir + os.sep + image_basename + "_" + time.strftime('%Y%m%d_%H%M%S') + ".jpg")
# show image
image.show()
(3) 修正後コードのまとめ
流し込みやすいように、まとめておきます。
import diffusers
from diffusers.utils import load_image
from diffusers.models import ControlNetModel
import cv2
import torch
import numpy as np
from PIL import Image
from insightface.app import FaceAnalysis
from pipeline_stable_diffusion_xl_instantid import StableDiffusionXLInstantIDPipeline, draw_kps
# prepare 'antelopev2' under ./models
app = FaceAnalysis(name='antelopev2', root='./', providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])
app.prepare(ctx_id=0, det_size=(640, 640))
# prepare models under ./checkpoints
face_adapter = f'./checkpoints/ip-adapter.bin'
controlnet_path = f'./checkpoints/ControlNetModel'
# load IdentityNet
controlnet = ControlNetModel.from_pretrained(
controlnet_path,
device_map="auto",
torch_dtype=torch.float16
)
base_model = 'wangqixun/YamerMIX_v8' # from https://civitai.com/models/84040?modelVersionId=196039
pipe = StableDiffusionXLInstantIDPipeline.from_pretrained(
base_model,
controlnet=controlnet,
device_map="auto",
torch_dtype=torch.float16
)
# load adapter
pipe.load_ip_adapter_instantid(face_adapter)
import os
import time
def i(
file_path: str,
prompt: str=None,
):
# load an image
face_image = load_image(file_path)
# prepare face emb
face_info = app.get(cv2.cvtColor(np.array(face_image), cv2.COLOR_RGB2BGR))
face_info = sorted(face_info, key=lambda x:(x['bbox'][2]-x['bbox'][0])*x['bbox'][3]-x['bbox'][1])[-1] # only use the maximum face
face_emb = face_info['embedding']
face_kps = draw_kps(face_image, face_info['kps'])
if not prompt:
prompt = "film noir style, ink sketch|vector, male man, highly detailed, sharp focus, ultra sharpness, monochrome, high contrast, dramatic shadows, 1940s style, mysterious, cinematic"
#negative_prompt = "ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vibrant, colorful"
# generate image
pipe.set_ip_adapter_scale(0.8)
image = pipe(
prompt,
image_embeds=face_emb,
image=face_kps,
controlnet_conditioning_scale=0.8,
).images[0]
# save a generated image to "./outputs/image_%Y%m%d_%H%M%S.jpg"
image_basename = os.path.splitext(os.path.basename(file_path))[0]
outdir="outputs"
os.makedirs(outdir, exist_ok=True)
image.save(outdir + os.sep + image_basename + "_" + time.strftime('%Y%m%d_%H%M%S') + ".jpg")
# show image
image.show()
ためしてみる
作成したコードをpythonに流し込みます。
そして、サンプルにあった誰かに似ている画像を入力にして、
![](https://assets.st-note.com/img/1706006781136-1LOzn3FHXL.png?width=800)
とりあえず、景気よく9枚ぐらい作りましょう。
for idx in range(9):
i("./examples/musk_resize.jpeg")
生成された画像はこちら。
![](https://assets.st-note.com/img/1706007077376-KEIgJUNLda.png?width=800)
1枚あたりの画像生成時間は 32秒でした。
100%|██████████████████████████████████████████████████████████████████████████████████████| 50/50 [00:32<00:00, 1.54it/s]
GPUリソース
メモリ使用量の変化
(1) コントロールネットモデルをロード
専用GPUメモリ 3.6GB
# load IdentityNet
controlnet = ControlNetModel.from_pretrained(
controlnet_path,
device_map="auto",
torch_dtype=torch.float16
)
![](https://assets.st-note.com/img/1706007157892-nfYqN7b4dA.png)
(2) StableDiffusionXLInstantIDPipelineでモデルYamerMIX_v8をロード
専用GPUメモリ 10.5GB(+6.9GB)
base_model = 'wangqixun/YamerMIX_v8' # from https://civitai.com/models/84040?modelVersionId=196039
pipe = StableDiffusionXLInstantIDPipeline.from_pretrained(
base_model,
controlnet=controlnet,
device_map="auto",
torch_dtype=torch.float16
)
![](https://assets.st-note.com/img/1706007283236-L4xzbHZ0yc.png)
(3) 画像生成している最中
専用GPUメモリ 22.3GB(+11.8GB)
![](https://assets.st-note.com/img/1706007373547-1HLsqjyjWg.png)
グラフ
以下の記事で書いた方法でプロットしたグラフはこちら。
緑色が今回の画像生成で使用した RTX 4090(24GB)のグラフです。
GPU使用率
![](https://assets.st-note.com/img/1706008965743-MnjDLOHK84.png?width=800)
メモリ使用量
![](https://assets.st-note.com/img/1706008979869-8r3kIvGn8J.png?width=800)
温度
![](https://assets.st-note.com/img/1706008994041-FN2nXquo0K.png?width=800)
まとめ
ロードするモデルに依りますが、RTX 4090(24GB)ならば普通に動くことがわかりました。
おまけ
ベースモデルを本家SDXLに変更
base_model = 'stabilityai/stable-diffusion-xl-base-1.0'
生成した画像がこちら。
![](https://assets.st-note.com/img/1706013400416-9haR8vvSjV.png?width=800)
HuggingFaceのデモ
こちらも普通にローカルで動きます。
![](https://assets.st-note.com/img/1706016475021-2i0ByjOJrs.png?width=800)
関連
この記事が気に入ったらサポートをしてみませんか?