i0switch commited on
Commit
2da6c3a
·
verified ·
1 Parent(s): bebb126

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +239 -155
app.py CHANGED
@@ -1,191 +1,275 @@
1
- # app.py — BRA v7 (AIGaming repo) × InstantID × ZeroGPU
2
- # 2025-06-22
3
- ##############################################################################
4
- # torchvision 0.17+ 互換パッチ(functional_tensor → functional)
5
- ##############################################################################
6
- import sys, types
7
- try:
8
- import torchvision.transforms.functional as F
9
- if "torchvision.transforms.functional_tensor" not in sys.modules:
10
- faux = types.ModuleType("torchvision.transforms.functional_tensor")
11
- # 必要最低限だけ持たせる
12
- faux.rgb_to_grayscale = getattr(F, "rgb_to_grayscale", None)
13
- sys.modules["torchvision.transforms.functional_tensor"] = faux
14
- except Exception as e:
15
- print("[WARN] torchvision compatibility patch failed:", e)
16
 
17
- ##############################################################################
18
- # 0. diffusers-0.27 互換: cached_download() パッチ
19
- ##############################################################################
20
- from huggingface_hub import hf_hub_download
21
- import huggingface_hub as _hf
22
- if not hasattr(_hf, "cached_download"):
23
- _hf.cached_download = hf_hub_download
24
 
25
- ##############################################################################
26
- # 1. ライブラリ
27
- ##############################################################################
28
- import os, io, base64, subprocess, traceback
29
  from pathlib import Path
30
- from typing import Optional
31
- import numpy as np
32
- import torch, gradio as gr, spaces
33
- from fastapi import FastAPI, UploadFile, File, Form, HTTPException
34
  from PIL import Image
35
  from diffusers import (
36
- StableDiffusionControlNetPipeline,
37
- ControlNetModel,
38
- DPMSolverMultistepScheduler,
39
  )
40
- from diffusers.loaders import AttnProcsLayers
41
  from insightface.app import FaceAnalysis
42
- from realesrgan import RealESRGANer
43
 
44
  ##############################################################################
45
- # 2. キャッシュパス
46
  ##############################################################################
47
- ROOT = Path("/data") if Path("/data").exists() else Path.home() / ".cache/instantid"
48
- MODELS = ROOT / "models"; LORA = ROOT / "lora"; UPSCALE = ROOT / "realesrgan"
49
- for p in (MODELS, LORA, UPSCALE): p.mkdir(parents=True, exist_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
  ##############################################################################
52
- # 3. モデル ID / ファイル
53
  ##############################################################################
54
- # --- BRA v7 (公開) ---
55
- BRA_REPO = "AIGaming/beautiful_realistic_asians"
56
- BRA_FILE = "beautifulRealistic_v7.safetensors"
57
- BRA_REV = "801a9b1999dd7018e58a1e2b432fdccd3d1d723d" # 固定 revision
58
 
59
- # --- IP-Adapter 本体 & LoRA ---
60
- IP_REPO, IP_BIN = "h94/IP-Adapter", "models/ip-adapter-plus-face_sd15.bin"
61
- LORA_REPO,IP_LORA = "h94/IP-Adapter-FaceID", "ip-adapter-faceid-plusv2_sd15_lora.safetensors"
 
 
 
62
 
63
- # --- ControlNet (MediaPipe Face) ---
64
- CN_REPO, CN_SUBF = "CrucibleAI/ControlNetMediaPipeFace", "diffusion_sd15"
 
 
 
 
65
 
66
- # --- Real-ESRGAN ---
67
- ESRGAN_REPO, ESRGAN_FILE = "aimagelab/realesrgan", "RealESRGAN_x4plus.pth"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
- ##############################################################################
70
- # 4. HF Hub ダウンロード
71
- ##############################################################################
72
- def dl(repo: str, file: str, sub: str | None = None, rev: str | None = None) -> Path:
73
- return Path(hf_hub_download(repo, file, subfolder=sub,
74
- revision=rev, cache_dir=str(MODELS)))
 
 
 
 
 
 
 
75
 
76
  ##############################################################################
77
- # 5. グローバル
78
  ##############################################################################
79
- pipe: Optional[StableDiffusionControlNetPipeline] = None
80
- face_analyser: Optional[FaceAnalysis] = None
81
- upsampler: Optional[RealESRGANer] = None
82
 
83
- ##############################################################################
84
- # 6. 初期化
85
- ##############################################################################
86
- def init():
87
- global pipe, face_analyser, upsampler
88
- if pipe is not None:
89
- return
90
- print("[INIT] downloading models…")
91
-
92
- # 6-1 BRA v7
93
- bra_ckpt = dl(BRA_REPO, BRA_FILE, rev=BRA_REV)
94
-
95
- # 6-2 ControlNet
96
- cn = ControlNetModel.from_pretrained(
97
- CN_REPO, subfolder=CN_SUBF, torch_dtype=torch.float16,
98
- cache_dir=str(MODELS)
99
- )
100
 
101
- # 6-3 Pipeline from .safetensors + ControlNet
102
- pipe_ = StableDiffusionControlNetPipeline.from_single_file(
103
- bra_ckpt, controlnet=cn, torch_dtype=torch.float16,
104
- safety_checker=None
105
- )
106
- pipe_.scheduler = DPMSolverMultistepScheduler.from_config(pipe_.scheduler.config)
107
-
108
- # 6-4 IP-Adapter
109
- ip_lora = dl(LORA_REPO, IP_LORA)
110
-
111
- ### 最終修正 ### subfolder引数に空文字列""を渡し、TypeErrorを回避する
112
- pipe_.load_ip_adapter(IP_REPO, "", weight_name=IP_BIN, cache_dir=str(MODELS))
113
-
114
- AttnProcsLayers(pipe_.unet.attn_processors).load_lora_weights(
115
- ip_lora, adapter_name="ip_faceid", safe_load=True
116
- )
117
- pipe_.set_adapters(["ip_faceid"], adapter_weights=[0.6])
118
- pipe_.to("cuda"); pipe_ = pipe_
119
 
120
- pipe = pipe_
121
- face_analyser = FaceAnalysis(
122
- name="buffalo_l", root=str(MODELS), providers=["CUDAExecutionProvider"]
123
- ); face_analyser.prepare(ctx_id=0, det_size=(640,640))
 
 
 
124
 
125
- esr = dl(ESRGAN_REPO, ESRGAN_FILE)
126
- upsampler = RealESRGANer(scale=4, model_path=str(esr), half=True,
127
- tile=512, tile_pad=10, pre_pad=0, gpu_id=0)
128
- print("[INIT] ready.")
129
 
130
- ##############################################################################
131
- # 7. プロンプト
132
- ##############################################################################
133
- BASE = "(masterpiece:1.2), best quality, ultra-realistic, RAW photo, 8k, cinematic lighting, textured skin, "
134
- NEG = "verybadimagenegative_v1.3, ng_deepnegative_v1_75t, (worst quality:2), (low quality:2), lowres, blurry, bad anatomy, bad hands, extra digits, watermark, signature"
 
 
 
 
135
 
136
  ##############################################################################
137
- # 8. 生成コア
138
  ##############################################################################
139
- @spaces.GPU(duration=60)
140
- def generate(face: Image.Image, subj: str, add: str, neg: str,
141
- cfg: float, ipw: float, steps: int, w: int, h: int,
142
- up: bool, upf: int, progress=gr.Progress(track_tqdm=True)):
143
- if pipe is None:
144
- init()
145
- if len(face_analyser.get(np.array(face))) == 0:
146
- raise ValueError("顔が検出できません。他の画像でお試しください。")
147
- pipe.set_adapters(["ip_faceid"], adapter_weights=[ipw])
148
- img = pipe(prompt=BASE+subj+", "+add,
149
- negative_prompt=NEG+", "+neg,
150
- num_inference_steps=steps, guidance_scale=cfg,
151
- image=face, width=w, height=h).images[0]
152
- if up:
153
- upsampler.scale = int(upf)
154
- img, _ = upsampler.enhance(np.array(img)); img = Image.fromarray(img)
155
- return img
156
 
157
  ##############################################################################
158
- # 9. Gradio UI
159
  ##############################################################################
160
- with gr.Blocks(title="BRA v7 × InstantID (ZeroGPU)") as demo:
161
- gr.Markdown("## BRA v7 × InstantID")
162
- with gr.Row():
163
- f = gr.Image(type="pil", label="Face ID"); s = gr.Textbox(label="被写体説明")
164
- ap = gr.Textbox(label="追加プロンプト"); ng = gr.Textbox(label="追加ネガ")
165
- with gr.Row():
166
- cf = gr.Slider(1,20,7.5,0.5,"CFG"); ip = gr.Slider(0.1,1.0,0.6,0.05,"IP-Adapter Weight")
167
- with gr.Row():
168
- st = gr.Slider(10,50,30,1,"Steps"); W = gr.Slider(512,1024,768,64,"W"); H = gr.Slider(512,1024,768,64,"H")
169
- with gr.Row():
170
- up = gr.Checkbox(label="Real-ESRGAN"); upf = gr.Radio([4,8], value=4, label="アップスケール")
171
- btn = gr.Button("Generate"); out = gr.Image(type="pil", label="Result")
172
- btn.click(generate, [f,s,ap,ng,cf,ip,st,W,H,up,upf], out, show_progress=True)
 
 
 
173
 
174
- ##############################################################################
175
- # 10. FastAPI
176
- ##############################################################################
177
- app = FastAPI()
 
 
 
 
 
 
 
 
 
 
 
178
 
179
- @app.post("/api/generate")
180
- async def api_gen(subj: str=Form(...), cfg: float=Form(7.5), stp: int=Form(30),
181
- ipw: float=Form(0.6), W: int=Form(768), H: int=Form(768),
182
- file: UploadFile=File(...)):
183
- img = Image.open(io.BytesIO(await file.read())).convert("RGB")
184
- res = generate(img, subj, "", "", cfg, ipw, stp, W, H, False, 4)
185
- buf = io.BytesIO(); res.save(buf,"PNG")
186
- return {"image":"data:image/png;base64,"+base64.b64encode(buf.getvalue()).decode()}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
  ##############################################################################
189
- # 11. Launch
190
  ##############################################################################
191
- demo.queue(default_concurrency_limit=2).launch(share=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py — InstantID × Beautiful Realistic Asians v7 (ZeroGPU-friendly, persistent cache)
2
+ """Persistent-cache backend for InstantID portrait generation.
3
+ * 依存モデルは /data が書込可ならそこへ、それ以外は ~/.cache に保存
4
+ * wget を使った簡易リトライ DL
5
+ """
6
+ # --- ★ Monkey-Patch: torchvision 0.17+ で消えた functional_tensor を補完 ---
7
+ import types, sys
8
+ from torchvision.transforms import functional as F
 
 
 
 
 
 
 
9
 
10
+ mod = types.ModuleType("torchvision.transforms.functional_tensor")
11
+ # 必要なのは rgb_to_grayscale だけなのでこれだけエイリアス
12
+ mod.rgb_to_grayscale = F.rgb_to_grayscale
13
+ sys.modules["torchvision.transforms.functional_tensor"] = mod
14
+ # ---------------------------------------------------------------------------
 
 
15
 
16
+
17
+ import os, subprocess, cv2, torch, spaces, gradio as gr, numpy as np
 
 
18
  from pathlib import Path
 
 
 
 
19
  from PIL import Image
20
  from diffusers import (
21
+ StableDiffusionPipeline, ControlNetModel,
22
+ DPMSolverMultistepScheduler, AutoencoderKL,
 
23
  )
 
24
  from insightface.app import FaceAnalysis
 
25
 
26
  ##############################################################################
27
+ # 0. キャッシュ用ディレクトリ
28
  ##############################################################################
29
+ PERSIST_BASE = Path("/data")
30
+ CACHE_ROOT = (
31
+ PERSIST_BASE / "instantid_cache"
32
+ if PERSIST_BASE.exists() and os.access(PERSIST_BASE, os.W_OK)
33
+ else Path.home() / ".cache" / "instantid_cache"
34
+ )
35
+ print("cache →", CACHE_ROOT)
36
+
37
+ MODELS_DIR = CACHE_ROOT / "models"
38
+ LORA_DIR = MODELS_DIR / "Lora" # FaceID LoRA などを置く
39
+ EMB_DIR = CACHE_ROOT / "embeddings"
40
+ UPSCALE_DIR = CACHE_ROOT / "realesrgan"
41
+ for p in (MODELS_DIR, LORA_DIR, EMB_DIR, UPSCALE_DIR):
42
+ p.mkdir(parents=True, exist_ok=True)
43
+
44
+ def dl(url: str, dst: Path, attempts: int = 2):
45
+ """wget + リトライの簡易ダウンローダ"""
46
+ if dst.exists():
47
+ print("✓", dst.relative_to(CACHE_ROOT)); return
48
+ for i in range(1, attempts + 1):
49
+ print(f"⬇ {dst.name} (try {i}/{attempts})")
50
+ if subprocess.call(["wget", "-q", "-O", str(dst), url]) == 0:
51
+ return
52
+ raise RuntimeError(f"download failed → {url}")
53
 
54
  ##############################################################################
55
+ # 1. 必要アセットのダウンロード
56
  ##############################################################################
57
+ print("— asset check —")
 
 
 
58
 
59
+ # 1-A. ベース checkpoint
60
+ BASE_CKPT = MODELS_DIR / "beautiful_realistic_asians_v7_fp16.safetensors"
61
+ dl(
62
+ "https://civitai.com/api/download/models/177164?type=Model&format=SafeTensor&size=pruned&fp=fp16",
63
+ BASE_CKPT,
64
+ )
65
 
66
+ # 1-B. FaceID LoRA(Δのみ)
67
+ LORA_FILE = LORA_DIR / "ip-adapter-faceid-plusv2_sd15_lora.safetensors"
68
+ dl(
69
+ "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sd15_lora.safetensors",
70
+ LORA_FILE,
71
+ )
72
 
73
+ # 1-C. textual inversion Embeddings
74
+ EMB_URLS = {
75
+ "ng_deepnegative_v1_75t.pt": [
76
+ "https://huggingface.co/datasets/gsdf/EasyNegative/resolve/main/ng_deepnegative_v1_75t.pt",
77
+ "https://huggingface.co/mrpxl2/animetarotV51.safetensors/raw/cc3008c0148061896549a995cc297aef0af4ef1b/ng_deepnegative_v1_75t.pt",
78
+ ],
79
+ "badhandv4.pt": [
80
+ "https://huggingface.co/datasets/gsdf/ConceptLab/resolve/main/badhandv4.pt",
81
+ "https://huggingface.co/nolanaatama/embeddings/raw/main/badhandv4.pt",
82
+ ],
83
+ "CyberRealistic_Negative-neg.pt": [
84
+ "https://huggingface.co/datasets/gsdf/ConceptLab/resolve/main/CyberRealistic_Negative-neg.pt",
85
+ "https://huggingface.co/wsj1995/embeddings/raw/main/CyberRealistic_Negative-neg.civitai.info",
86
+ ],
87
+ "UnrealisticDream.pt": [
88
+ "https://huggingface.co/datasets/gsdf/ConceptLab/resolve/main/UnrealisticDream.pt",
89
+ "https://huggingface.co/imagepipeline/UnrealisticDream/raw/main/f84133b4-aad8-44be-b9ce-7e7e3a8c111f.pt",
90
+ ],
91
+ }
92
+ for fname, urls in EMB_URLS.items():
93
+ dst = EMB_DIR / fname
94
+ for idx, u in enumerate(urls, 1):
95
+ try:
96
+ dl(u, dst); break
97
+ except RuntimeError:
98
+ if idx == len(urls): raise
99
+ print(" ↳ fallback URL …")
100
 
101
+ # 1-D. Real-ESRGAN weights (×8)
102
+ RRG_WEIGHTS = UPSCALE_DIR / "RealESRGAN_x8plus.pth"
103
+ RRG_URLS = [
104
+ "https://huggingface.co/NoCrypt/Superscale_RealESRGAN/resolve/main/RealESRGAN_x8plus.pth",
105
+ "https://huggingface.co/ai-forever/Real-ESRGAN/raw/main/RealESRGAN_x8.pth",
106
+ "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.1/8x_NMKD-Superscale_100k.pth",
107
+ ]
108
+ for idx, link in enumerate(RRG_URLS, 1):
109
+ try:
110
+ dl(link, RRG_WEIGHTS); break
111
+ except RuntimeError:
112
+ if idx == len(RRG_URLS): raise
113
+ print(" ↳ fallback URL …")
114
 
115
  ##############################################################################
116
+ # 2. ランタイム初期化
117
  ##############################################################################
118
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
119
+ dtype = torch.float16 if torch.cuda.is_available() else torch.float32
120
+ print("device:", device, "| dtype:", dtype)
121
 
122
+ providers = (
123
+ ["CUDAExecutionProvider", "CPUExecutionProvider"]
124
+ if torch.cuda.is_available()
125
+ else ["CPUExecutionProvider"]
126
+ )
127
+ face_app = FaceAnalysis(name="buffalo_l", root=str(CACHE_ROOT), providers=providers)
128
+ face_app.prepare(ctx_id=(0 if torch.cuda.is_available() else -1), det_size=(640, 640))
 
 
 
 
 
 
 
 
 
 
129
 
130
+ # ControlNet + SD パイプライン
131
+ controlnet = ControlNetModel.from_pretrained(
132
+ "InstantX/InstantID", subfolder="ControlNetModel", torch_dtype=dtype
133
+ )
134
+ pipe = StableDiffusionPipeline.from_single_file(
135
+ BASE_CKPT, torch_dtype=dtype, safety_checker=None, use_safetensors=True, clip_skip=2
136
+ )
137
+ pipe.vae = AutoencoderKL.from_pretrained(
138
+ "stabilityai/sd-vae-ft-mse", torch_dtype=dtype
139
+ ).to(device)
140
+ pipe.controlnet = controlnet
141
+ pipe.scheduler = DPMSolverMultistepScheduler.from_config(
142
+ pipe.scheduler.config, use_karras_sigmas=True, algorithm_type="sde-dpmsolver++"
143
+ )
 
 
 
 
144
 
145
+ # --- ここが核心:画像エンコーダ込みで公式レポから直接ロード ------------------
146
+ pipe.load_ip_adapter(
147
+ "h94/IP-Adapter", # Hugging Face Hub ID
148
+ subfolder="models", # ip-adapter-plus-face_sd15.bin が入っているフォルダ
149
+ weight_name="ip-adapter-plus-face_sd15.bin",
150
+ )
151
+ # ---------------------------------------------------------------------------
152
 
153
+ # FaceID LoRA(差分 LoRA のみ)
154
+ pipe.load_lora_weights(str(LORA_DIR), weight_name=LORA_FILE.name)
155
+ pipe.set_ip_adapter_scale(0.65)
 
156
 
157
+ # textual inversion 読み込み
158
+ for emb in EMB_DIR.glob("*.*"):
159
+ try:
160
+ pipe.load_textual_inversion(emb, token=emb.stem)
161
+ print("emb loaded →", emb.stem)
162
+ except Exception:
163
+ print("emb skip →", emb.name)
164
+ pipe.to(device)
165
+ print("pipeline ready ✔")
166
 
167
  ##############################################################################
168
+ # 3. アップスケーラ
169
  ##############################################################################
170
+ try:
171
+ from basicsr.archs.rrdb_arch import RRDBNet
172
+ try:
173
+ from realesrgan import RealESRGAN
174
+ except ImportError:
175
+ from realesrgan import RealESRGANer as RealESRGAN
176
+ rrdb = RRDBNet(3, 3, 64, 23, 32, scale=8)
177
+ upsampler = RealESRGAN(device, rrdb, scale=8)
178
+ upsampler.load_weights(str(RRG_WEIGHTS))
179
+ UPSCALE_OK = True
180
+ except Exception as e:
181
+ print("Real-ESRGAN disabled →", e)
182
+ UPSCALE_OK = False
 
 
 
 
183
 
184
  ##############################################################################
185
+ # 4. プロンプト & 生成関数
186
  ##############################################################################
187
+ BASE_PROMPT = (
188
+ "(masterpiece:1.2), best quality, ultra-realistic, RAW photo, 8k,\n"
189
+ "photo of {subject},\n"
190
+ "cinematic lighting, golden hour, rim light, shallow depth of field,\n"
191
+ "textured skin, high detail, shot on Canon EOS R5, 85 mm f/1.4, ISO 200,\n"
192
+ "<lora:ip-adapter-faceid-plusv2_sd15_lora:0.65>, (face),\n"
193
+ "(aesthetic:1.1), (cinematic:0.8)"
194
+ )
195
+ NEG_PROMPT = (
196
+ "ng_deepnegative_v1_75t, CyberRealistic_Negative-neg, UnrealisticDream, "
197
+ "(worst quality:2), (low quality:1.8), lowres, (jpeg artifacts:1.2), "
198
+ "painting, sketch, illustration, drawing, cartoon, anime, cgi, render, 3d, "
199
+ "monochrome, grayscale, text, logo, watermark, signature, username, "
200
+ "(MajicNegative_V2:0.8), bad hands, extra digits, fused fingers, malformed limbs, "
201
+ "missing arms, missing legs, (badhandv4:0.7), BadNegAnatomyV1-neg, skin blemishes, acnes, age spot, glans"
202
+ )
203
 
204
+ @spaces.GPU(duration=90)
205
+ def generate(
206
+ face_np, subject, add_prompt, add_neg, cfg, ip_scale, steps, w, h, upscale, up_factor,
207
+ progress=gr.Progress(track_tqdm=True),
208
+ ):
209
+ if face_np is None or face_np.size == 0:
210
+ raise gr.Error("顔画像をアップロードしてください。")
211
+
212
+ prompt = BASE_PROMPT.format(subject=(subject.strip() or "a beautiful 20yo woman"))
213
+ if add_prompt:
214
+ prompt += ", " + add_prompt
215
+ neg = NEG_PROMPT + (", " + add_neg if add_neg else "")
216
+
217
+ pipe.set_ip_adapter_scale(ip_scale)
218
+ img_in = Image.fromarray(face_np)
219
 
220
+ result = pipe(
221
+ prompt=prompt,
222
+ negative_prompt=neg,
223
+ ip_adapter_image=img_in,
224
+ image=img_in,
225
+ controlnet_conditioning_scale=0.9,
226
+ num_inference_steps=int(steps) + 5,
227
+ guidance_scale=cfg,
228
+ width=int(w),
229
+ height=int(h),
230
+ ).images[0]
231
+
232
+ if upscale:
233
+ if UPSCALE_OK:
234
+ up, _ = upsampler.enhance(
235
+ cv2.cvtColor(np.array(result), cv2.COLOR_RGB2BGR), outscale=up_factor
236
+ )
237
+ result = Image.fromarray(cv2.cvtColor(up, cv2.COLOR_BGR2RGB))
238
+ else:
239
+ result = result.resize(
240
+ (int(result.width * up_factor), int(result.height * up_factor)),
241
+ Image.LANCZOS,
242
+ )
243
+ return result
244
 
245
  ##############################################################################
246
+ # 5. Gradio UI
247
  ##############################################################################
248
+ with gr.Blocks() as demo:
249
+ gr.Markdown("# InstantID – Beautiful Realistic Asians v7")
250
+ with gr.Row():
251
+ with gr.Column():
252
+ face_in = gr.Image(label="顔写真", type="numpy")
253
+ subj_in = gr.Textbox(label="被写体説明", placeholder="e.g. woman in black suit, smiling")
254
+ add_in = gr.Textbox(label="追加プロンプト")
255
+ addneg_in = gr.Textbox(label="追加ネガティブ")
256
+ ip_sld = gr.Slider(0, 1.5, 0.65, step=0.05, label="IP-Adapter scale")
257
+ cfg_sld = gr.Slider(1, 15, 6, step=0.5, label="CFG")
258
+ step_sld = gr.Slider(10, 50, 20, step=1, label="Steps")
259
+ w_sld = gr.Slider(512, 1024, 512, step=64, label="幅")
260
+ h_sld = gr.Slider(512, 1024, 768, step=64, label="高さ")
261
+ up_ck = gr.Checkbox(label="アップスケール", value=True)
262
+ up_fac = gr.Slider(1, 8, 2, step=1, label="倍率")
263
+ btn = gr.Button("生成", variant="primary")
264
+ with gr.Column():
265
+ out_img = gr.Image(label="結果")
266
+
267
+ btn.click(
268
+ generate,
269
+ [face_in, subj_in, add_in, addneg_in, cfg_sld, ip_sld, step_sld, w_sld, h_sld, up_ck, up_fac],
270
+ out_img,
271
+ api_name="predict",
272
+ )
273
+
274
+ print("launching …")
275
+ demo.queue().launch(show_error=True)