i0switch commited on
Commit
15d234b
·
verified ·
1 Parent(s): 4fd7fe3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +21 -23
app.py CHANGED
@@ -1,18 +1,18 @@
1
- # app.py — InstantID × Beautiful Realistic Asians v7(ZeroGPU 対応フル版)
2
  # 2025-06-22
3
 
4
  ##############################################################################
5
- # 0. 旧 API → 新 API 互換パッチ(必ず diffusers より前に実行)
6
  ##############################################################################
7
  from huggingface_hub import hf_hub_download
8
  import huggingface_hub as _hf_hub
9
 
10
- # diffusers-0.27 import する cached_download() を v0.28+ でも使えるように別名定義
11
  if not hasattr(_hf_hub, "cached_download"):
12
  _hf_hub.cached_download = hf_hub_download
13
 
14
  ##############################################################################
15
- # 1. 標準ライブラリ & 外部ライブラリ
16
  ##############################################################################
17
  import os, io, base64, subprocess, traceback
18
  from pathlib import Path
@@ -37,7 +37,7 @@ from basicsr.utils.download_util import load_file_from_url
37
  from realesrgan import RealESRGANer
38
 
39
  ##############################################################################
40
- # 2. キャッシュ/永続ディレクトリ
41
  ##############################################################################
42
  PERSIST_BASE = Path("/data")
43
  CACHE_ROOT = (
@@ -72,7 +72,7 @@ REALESRGAN_URL = (
72
  )
73
 
74
  ##############################################################################
75
- # 4. ユーティリティ:堅牢ダウンロード
76
  ##############################################################################
77
  def download(url: str, dst: Path, attempts: int = 2):
78
  if dst.exists():
@@ -87,7 +87,7 @@ def download(url: str, dst: Path, attempts: int = 2):
87
  return dst
88
 
89
  ##############################################################################
90
- # 5. グローバル(lazy-load される)
91
  ##############################################################################
92
  pipe: Optional[StableDiffusionControlNetPipeline] = None
93
  face_analyser: Optional[FaceAnalysis] = None
@@ -97,26 +97,26 @@ upsampler: Optional[RealESRGANer] = None
97
  # 6. パイプライン初期化
98
  ##############################################################################
99
  def initialize_pipelines():
100
- """最初の推論時に一度だけ呼び出す"""
101
  global pipe, face_analyser, upsampler
102
  if pipe is not None:
103
  return
104
 
105
  print("[INIT] Downloading model assets …")
106
 
107
- # (1) ベースモデル & IP-Adapter
108
  bra_ckpt = download(BRA_V7_URL, MODELS_DIR / "bra_v7.safetensors")
109
  ip_bin = download(IP_ADAPTER_BIN_URL, MODELS_DIR / "ip_adapter.bin")
110
  ip_lora = download(IP_ADAPTER_LORA_URL, LORA_DIR / "ip_adapter_faceid.lora")
111
 
112
- # (2) ControlNet (InstantID)
113
  controlnet = ControlNetModel.from_pretrained(
114
- "InstantID/ControlNet-Mediapipe-Face",
 
115
  torch_dtype=torch.float16,
116
  cache_dir=str(MODELS_DIR),
117
  )
118
 
119
- # (3) Diffusers Pipeline
120
  pipe_tmp = StableDiffusionControlNetPipeline.from_pretrained(
121
  "runwayml/stable-diffusion-v1-5",
122
  controlnet=controlnet,
@@ -132,10 +132,9 @@ def initialize_pipelines():
132
  subfolder="scheduler",
133
  cache_dir=str(MODELS_DIR),
134
  )
135
- # IP-Adapter:LoRA を適用
136
  pipe_tmp.load_ip_adapter(ip_bin)
137
- ip_layers = AttnProcsLayers(pipe_tmp.unet.attn_processors)
138
- ip_layers.load_lora_weights(
139
  ip_lora, adapter_name="ip_faceid", safe_load=True
140
  )
141
  pipe_tmp.set_adapters(["ip_faceid"], adapter_weights=[0.6])
@@ -143,13 +142,13 @@ def initialize_pipelines():
143
 
144
  pipe = pipe_tmp
145
 
146
- # (4) InsightFace
147
  face_analyser = FaceAnalysis(
148
  name="buffalo_l", root=str(MODELS_DIR), providers=["CUDAExecutionProvider"]
149
  )
150
  face_analyser.prepare(ctx_id=0, det_size=(640, 640))
151
 
152
- # (5) Real-ESRGAN
153
  esrgan_ckpt = download(REALESRGAN_URL, UPSCALE_DIR / "realesrgan_x4plus.pth")
154
  upsampler = RealESRGANer(
155
  scale=4,
@@ -177,7 +176,7 @@ NEG_PROMPT = (
177
  )
178
 
179
  ##############################################################################
180
- # 8. 生成関数(GPU を掴む)
181
  ##############################################################################
182
  @spaces.GPU(duration=60)
183
  def generate_core(
@@ -198,10 +197,9 @@ def generate_core(
198
  if pipe is None:
199
  initialize_pipelines()
200
 
201
- np_face = np.array(face_img)
202
- faces = face_analyser.get(np_face)
203
  if len(faces) == 0:
204
- raise ValueError("顔が検出できませんでした。別の画像でお試しください。")
205
 
206
  pipe.set_adapters(["ip_faceid"], adapter_weights=[ip_scale])
207
 
@@ -275,7 +273,7 @@ with gr.Blocks(title="InstantID × BRA v7 (ZeroGPU)") as demo:
275
  )
276
 
277
  ##############################################################################
278
- # 10. FastAPI エンドポイント
279
  ##############################################################################
280
  app = FastAPI()
281
 
@@ -314,6 +312,6 @@ async def api_generate(
314
  raise HTTPException(status_code=500, detail=str(e))
315
 
316
  ##############################################################################
317
- # 11. Launch(Gradio が自動で Uvicorn を立ち上げる)
318
  ##############################################################################
319
  demo.queue(default_concurrency_limit=2).launch(share=False)
 
1
+ # app.py — InstantID × Beautiful Realistic Asians v7(ZeroGPU 対応・CrucibleAI ControlNet)
2
  # 2025-06-22
3
 
4
  ##############################################################################
5
+ # 0. 旧 API → 新 API 互換パッチ(必ず diffusers import の前に置く)
6
  ##############################################################################
7
  from huggingface_hub import hf_hub_download
8
  import huggingface_hub as _hf_hub
9
 
10
+ # diffusers-0.27 が参照する cached_download() を v0.28+ でも使えるように注入
11
  if not hasattr(_hf_hub, "cached_download"):
12
  _hf_hub.cached_download = hf_hub_download
13
 
14
  ##############################################################################
15
+ # 1. 標準 & 外部ライブラリ
16
  ##############################################################################
17
  import os, io, base64, subprocess, traceback
18
  from pathlib import Path
 
37
  from realesrgan import RealESRGANer
38
 
39
  ##############################################################################
40
+ # 2. キャッシュ & パス
41
  ##############################################################################
42
  PERSIST_BASE = Path("/data")
43
  CACHE_ROOT = (
 
72
  )
73
 
74
  ##############################################################################
75
+ # 4. ダウンローダ
76
  ##############################################################################
77
  def download(url: str, dst: Path, attempts: int = 2):
78
  if dst.exists():
 
87
  return dst
88
 
89
  ##############################################################################
90
+ # 5. グローバル変数(lazy-load
91
  ##############################################################################
92
  pipe: Optional[StableDiffusionControlNetPipeline] = None
93
  face_analyser: Optional[FaceAnalysis] = None
 
97
  # 6. パイプライン初期化
98
  ##############################################################################
99
  def initialize_pipelines():
 
100
  global pipe, face_analyser, upsampler
101
  if pipe is not None:
102
  return
103
 
104
  print("[INIT] Downloading model assets …")
105
 
106
+ # 6-1 ベースモデル & IP-Adapter
107
  bra_ckpt = download(BRA_V7_URL, MODELS_DIR / "bra_v7.safetensors")
108
  ip_bin = download(IP_ADAPTER_BIN_URL, MODELS_DIR / "ip_adapter.bin")
109
  ip_lora = download(IP_ADAPTER_LORA_URL, LORA_DIR / "ip_adapter_faceid.lora")
110
 
111
+ # 6-2 ControlNet(CrucibleAI / diffusion_sd15)
112
  controlnet = ControlNetModel.from_pretrained(
113
+ "CrucibleAI/ControlNetMediaPipeFace", # ← 公開リポジトリ :contentReference[oaicite:0]{index=0}
114
+ subfolder="diffusion_sd15", # ← SD-1.5 用フォルダ :contentReference[oaicite:1]{index=1}
115
  torch_dtype=torch.float16,
116
  cache_dir=str(MODELS_DIR),
117
  )
118
 
119
+ # 6-3 Diffusers パイプライン
120
  pipe_tmp = StableDiffusionControlNetPipeline.from_pretrained(
121
  "runwayml/stable-diffusion-v1-5",
122
  controlnet=controlnet,
 
132
  subfolder="scheduler",
133
  cache_dir=str(MODELS_DIR),
134
  )
135
+ # IP-Adapter
136
  pipe_tmp.load_ip_adapter(ip_bin)
137
+ AttnProcsLayers(pipe_tmp.unet.attn_processors).load_lora_weights(
 
138
  ip_lora, adapter_name="ip_faceid", safe_load=True
139
  )
140
  pipe_tmp.set_adapters(["ip_faceid"], adapter_weights=[0.6])
 
142
 
143
  pipe = pipe_tmp
144
 
145
+ # 6-4 InsightFace
146
  face_analyser = FaceAnalysis(
147
  name="buffalo_l", root=str(MODELS_DIR), providers=["CUDAExecutionProvider"]
148
  )
149
  face_analyser.prepare(ctx_id=0, det_size=(640, 640))
150
 
151
+ # 6-5 Real-ESRGAN
152
  esrgan_ckpt = download(REALESRGAN_URL, UPSCALE_DIR / "realesrgan_x4plus.pth")
153
  upsampler = RealESRGANer(
154
  scale=4,
 
176
  )
177
 
178
  ##############################################################################
179
+ # 8. 生成関数(GPU アタッチ)
180
  ##############################################################################
181
  @spaces.GPU(duration=60)
182
  def generate_core(
 
197
  if pipe is None:
198
  initialize_pipelines()
199
 
200
+ faces = face_analyser.get(np.array(face_img))
 
201
  if len(faces) == 0:
202
+ raise ValueError("顔が検出できませんでした。別の画像をお試しください。")
203
 
204
  pipe.set_adapters(["ip_faceid"], adapter_weights=[ip_scale])
205
 
 
273
  )
274
 
275
  ##############################################################################
276
+ # 10. FastAPI REST
277
  ##############################################################################
278
  app = FastAPI()
279
 
 
312
  raise HTTPException(status_code=500, detail=str(e))
313
 
314
  ##############################################################################
315
+ # 11. Launch(Gradio が自動で Uvicorn を起動)
316
  ##############################################################################
317
  demo.queue(default_concurrency_limit=2).launch(share=False)