id:touch-sp さん、ご助言ありがとうございました!
どうしてエラーが発生するのか理解に繋がりました 🙇
早速、 IP-Adapter FaceID に再チャレンジしてみようと思います。
はじめに振り返り
過去にチャレンジして動かせなかった記事はこちらです。
原因
自分は pip install diffusers
を使って PyPI に公開されている最新 diffusers を使用してました。この時、インストールされるバージョンは現時点で v0.27.2
です。
一方で、参照しているドキュメントは MAIN
のものだったのが原因です。
つまり v0.27.2
では実装されていない機能を試そうとしていたわけです。
ドキュメントを v0.27.2
の版にすると IP-Adapter FaceID のブロックがごっそりとありません。
よって、main ブランチの機能を動かすために以下のご助言になったわけですね。
mainブランチをインストールすれば前回のスクリプトは動作すると思います。 pip install git+https://github.com/huggingface/diffusers
早速 pip install のところを見直して試してみる!
実行結果!
FaceAnalysis の部分をわからないなりに理解してみる!
最終的に pipeline に渡す
id_embeds
が出来ていれば良いのだが。。。
ref_images_embeds = [] app = FaceAnalysis(name="buffalo_l", providers=['CUDAExecutionProvider', 'CPUExecutionProvider']) app.prepare(ctx_id=0, det_size=(640, 640)) image = cv2.cvtColor(np.asarray(image), cv2.COLOR_BGR2RGB) faces = app.get(image) image = torch.from_numpy(faces[0].normed_embedding) ref_images_embeds.append(image.unsqueeze(0)) ref_images_embeds = torch.stack(ref_images_embeds, dim=0).unsqueeze(0) neg_ref_images_embeds = torch.zeros_like(ref_images_embeds) id_embeds = torch.cat([neg_ref_images_embeds, ref_images_embeds]).to(dtype=torch.float16, device="cuda")
わからないなりにコメントを入れてみた
# 入れ物 ref_images_embeds = [] # FaceAnalysis を準備する app = FaceAnalysis(name="buffalo_l", providers=['CUDAExecutionProvider', 'CPUExecutionProvider']) app.prepare(ctx_id=0, det_size=(640, 640)) # OpenCV で扱えるように色空間を RGB -> BGR 変換する image = cv2.cvtColor(np.asarray(image), cv2.COLOR_BGR2RGB) # 顔情報を取得 faces = app.get(image) # 顔情報から埋め込みパラメータ?を作成する image = torch.from_numpy(faces[0].normed_embedding) ref_images_embeds.append(image.unsqueeze(0)) ref_images_embeds = torch.stack(ref_images_embeds, dim=0).unsqueeze(0) neg_ref_images_embeds = torch.zeros_like(ref_images_embeds) id_embeds = torch.cat([neg_ref_images_embeds, ref_images_embeds]).to(dtype=torch.float16, device="cuda")
スクリプト全体
モジュール群をインストールする
!pip install git+https://github.com/huggingface/diffusers !pip install -U transformers accelerate peft controlnet_aux onnxruntime-gpu insightface
モデル群をロードする
import torch import cv2 import numpy as np from diffusers import StableDiffusionPipeline, DDIMScheduler # ベースもデールをロードする pipe = StableDiffusionPipeline.from_pretrained( "runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16, ).to("cuda") # スケジューラを設定する pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config) # IP-Adapter FaceID をロードする pipe.load_ip_adapter( "h94/IP-Adapter-FaceID", subfolder=None, weight_name="ip-adapter-faceid_sd15.bin", image_encoder_folder=None ) # IP-Adapter のスケールを設定する pipe.set_ip_adapter_scale(0.6)
画像埋め込み情報?を作る
import cv2 import numpy as np from insightface.app import FaceAnalysis from diffusers.utils import load_image # Image Embedding に使用する画像をロードする image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/ip_mask_girl1.png" image = load_image(image_url) # FaceAnalysis を準備する app = FaceAnalysis(name="buffalo_l", providers=['CUDAExecutionProvider', 'CPUExecutionProvider']) app.prepare(ctx_id=0, det_size=(640, 640)) # OpenCV で扱えるように色空間を RGB -> BGR 変換する image = cv2.cvtColor(np.asarray(image), cv2.COLOR_BGR2RGB) # 顔情報を取得 faces = app.get(image) # 顔情報から埋め込みパラメータ?を作成する image = torch.from_numpy(faces[0].normed_embedding) ref_images_embeds = [] ref_images_embeds.append(image.unsqueeze(0)) ref_images_embeds = torch.stack(ref_images_embeds, dim=0).unsqueeze(0) neg_ref_images_embeds = torch.zeros_like(ref_images_embeds) id_embeds = torch.cat([neg_ref_images_embeds, ref_images_embeds]).to(dtype=torch.float16, device="cuda")
パイプラインを実行する
import torch # シードを設定する generator = torch.Generator(device="cpu").manual_seed(42) # パイプラインを実行する prompt = "A photo of a girl" negative_prompt = "monochrome, lowres, bad anatomy, worst quality, low quality" images = pipe( prompt, negative_prompt=negative_prompt, ip_adapter_image_embeds=[id_embeds], num_inference_steps=20, num_images_per_prompt=4, generator=generator ).images
生成された画像を出力
from datetime import datetime from zoneinfo import ZoneInfo # Asia/Tokyo タイムゾーンの現在時刻を YYYYMMDDhhmmss 形式で得る formattedNow = datetime.now(tz=ZoneInfo("Asia/Tokyo")).strftime("%Y%m%d%H%M%S") for idx, image in enumerate(images): # 実行結果 image.save(f"image_{formattedNow}_{idx}_{generator.initial_seed()}.png")
まとめ
自分が使用している diffusers のバージョンはわかっていましたが、
まさか参照しているドキュメントが 新しすぎる とは思いませんでした。。。
しかし、まだ疑問が残るところがありますね。
main ブランチの diffusers では、 IP-Adapter FaceID が コミュニティパイプライン から Core に移動したのは良いとして、移動する前の v0.27.2
で出来ないのはなんでなんでしょうね。
まぁしかし、何にせよ、IP-Adapter FaceID が動いたので OK ですね!