i0switch commited on
Commit
30bb03f
·
verified ·
1 Parent(s): a0c776a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -0
app.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py (IP-Adapter V2アップグレード版)
2
+
3
+ import gradio as gr
4
+ import torch
5
+ import numpy as np
6
+ import cv2
7
+ from PIL import Image
8
+ import time
9
+ import spaces
10
+ import traceback
11
+ import os
12
+
13
+ from diffusers import StableDiffusionPipeline, ControlNetModel
14
+ from insightface.app import FaceAnalysis
15
+
16
+ print("--- アプリケーションの初期化を開始 ---")
17
+
18
+
19
+ try:
20
+ print("モデルのロードを開始...")
21
+ is_cuda_available = torch.cuda.is_available()
22
+ device = "cuda" if is_cuda_available else "cpu"
23
+ dtype = torch.float16 if is_cuda_available else torch.float32
24
+ print(f"実行デバイス: {device}, データ型: {dtype}")
25
+
26
+ print("InsightFaceのプロバイダーとコンテキストIDを設定...")
27
+ providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if is_cuda_available else ['CPUExecutionProvider']
28
+ ctx_id = 0 if is_cuda_available else -1
29
+ print(f"使用するプロバイダー: {providers}, ctx_id: {ctx_id}")
30
+
31
+ face_app = FaceAnalysis(name='buffalo_l', root='./', providers=providers)
32
+ face_app.prepare(ctx_id=ctx_id, det_size=(640, 640))
33
+ print("InsightFaceのロード完了。")
34
+
35
+ source_repo = "InstantX/InstantID"
36
+
37
+ print(f"ControlNetモデル ({source_repo}) のロード開始...")
38
+ controlnet = ControlNetModel.from_pretrained(
39
+ source_repo,
40
+ subfolder="ControlNetModel",
41
+ torch_dtype=dtype
42
+ )
43
+ print("ControlNetモデルのロード完了。")
44
+
45
+ civitai_model_url = "https://civitai.com/api/download/models/90505?type=Model&format=SafeTensor&size=full&fp=fp32"
46
+ local_model_path = "civitai_model.safetensors"
47
+
48
+ if not os.path.exists(local_model_path):
49
+ print(f"{local_model_path} が存在しないため、ダウンロードを開始します...")
50
+ os.system(f'wget -q -O {local_model_path} "{civitai_model_url}"')
51
+ else:
52
+ print(f"{local_model_path} は既に存在するため、ダウンロードをスキップします。")
53
+
54
+ print(f"ローカルパス ({local_model_path}) からパイプラインをロード開始...")
55
+ pipe = StableDiffusionPipeline.from_single_file(
56
+ local_model_path,
57
+ torch_dtype=dtype,
58
+ safety_checker=None,
59
+ use_safetensors=True,
60
+ )
61
+ pipe.controlnet = controlnet
62
+ pipe.to(device)
63
+ print("Stable Diffusionパイプラインのロード完了。")
64
+
65
+ # ★★★★★ ここが最後の追加注文です ★★★★★
66
+ # weight_nameをV2モデルに変更します。
67
+ ip_adapter_repo = "h94/IP-Adapter"
68
+ print(f"IP-Adapter ({ip_adapter_repo}) のロード開始...")
69
+ pipe.load_ip_adapter(
70
+ ip_adapter_repo,
71
+ subfolder="models",
72
+ weight_name="ip-adapter-plus_v2_sd15.bin" # V2の重みファイル名を指定
73
+ )
74
+ print("IP-Adapter V2のロード完了。")
75
+
76
+ print("★★全てのモデルのロードが正常に完了しました★★")
77
+ MODELS_LOADED = True
78
+ except Exception:
79
+ error_details = traceback.format_exc()
80
+ print("モデルのロード中に詳細なエラーが発生しました:")
81
+ print(error_details)
82
+ MODELS_LOADED = False
83
+
84
+ # --- 2. 画像生成関数 (変更なし) ---
85
+ @spaces.GPU(duration=300)
86
+ def generate_image(
87
+ face_image, prompt, negative_prompt, guidance_scale, ip_adapter_scale, num_steps,
88
+ progress=gr.Progress(track_tqdm=True)
89
+ ):
90
+ if not MODELS_LOADED:
91
+ raise gr.Error("モデルがロードされていないため、画像を生成できません。ログを確認してください。")
92
+ if face_image is None:
93
+ raise gr.Error("顔画像をアップロードしてください。")
94
+ if not prompt:
95
+ raise gr.Error("プロンプトを入力してください。")
96
+
97
+ face_image = Image.fromarray(face_image)
98
+ face_info = face_app.get(cv2.cvtColor(np.array(face_image), cv2.COLOR_RGB2BGR))
99
+ if not face_info:
100
+ raise gr.Error("アップロードされた画像から顔を検出できませんでした。")
101
+
102
+ face_info = sorted(face_info, key=lambda x: (x['bbox'][2] - x['bbox'][0]) * (x['bbox'][3] - x['bbox'][1]))[-1]
103
+ face_emb = face_info['embedding']
104
+ pipe.set_ip_adapter_scale(ip_adapter_scale)
105
+ images = pipe(
106
+ prompt=prompt, negative_prompt=negative_prompt, image_embeds=[face_emb], image=face_image,
107
+ controlnet_conditioning_scale=ip_adapter_scale, num_inference_steps=int(num_steps), guidance_scale=guidance_scale,
108
+ ).images
109
+ return images[0]
110
+
111
+ # --- 3. GradioのUIとAPIの定義 (変更なし) ---
112
+ with gr.Blocks() as demo:
113
+ gr.Markdown("# InstantID 画像生成アプリ")
114
+ with gr.Row():
115
+ with gr.Column():
116
+ face_image_input = gr.Image(label="顔写真", type="numpy")
117
+ prompt_input = gr.Textbox(label="プロンプト (例: 1girl, a photo of a cute girl in a suit)")
118
+ negative_prompt_input = gr.Textbox(label="ネガティブプロンプト", value="(lowres, low quality, worst quality:1.2), ugly")
119
+ with gr.Accordion("詳細設定", open=False):
120
+ ip_adapter_scale_slider = gr.Slider(minimum=0, maximum=1.5, step=0.1, value=0.8, label="顔の忠実度 (IP Adapter Scale)")
121
+ guidance_scale_slider = gr.Slider(minimum=1, maximum=10, step=0.5, value=5.0, label="プロンプトへの忠実度 (Guidance Scale)")
122
+ num_steps_slider = gr.Slider(minimum=10, maximum=50, step=1, value=30, label="生成ステップ数 (Steps)")
123
+ generate_button = gr.Button("画像を生成", variant="primary")
124
+ with gr.Column():
125
+ output_image = gr.Image(label="生成結果")
126
+ generate_button.click(
127
+ fn=generate_image,
128
+ inputs=[
129
+ face_image_input, prompt_input, negative_prompt_input, guidance_scale_slider,
130
+ ip_adapter_scale_slider, num_steps_slider
131
+ ],
132
+ outputs=[output_image],
133
+ api_name="generate"
134
+ )
135
+
136
+ demo.queue().launch()
137
+ print("--- Gradioアプリの起動準備完了 ---")