Update app.py
Browse files
app.py
CHANGED
|
@@ -21,7 +21,9 @@ from insightface.app import FaceAnalysis
|
|
| 21 |
# Config globale
|
| 22 |
# ---------------------------
|
| 23 |
|
| 24 |
-
|
|
|
|
|
|
|
| 25 |
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 26 |
DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
|
| 27 |
|
|
@@ -33,20 +35,26 @@ CHECKPOINT_DIR = "./checkpoints"
|
|
| 33 |
# ---------------------------
|
| 34 |
|
| 35 |
def download_checkpoints():
|
|
|
|
| 36 |
hf_hub_download(
|
| 37 |
repo_id="InstantX/InstantID",
|
| 38 |
filename="ControlNetModel/config.json",
|
| 39 |
local_dir=CHECKPOINT_DIR,
|
|
|
|
| 40 |
)
|
| 41 |
hf_hub_download(
|
| 42 |
repo_id="InstantX/InstantID",
|
| 43 |
filename="ControlNetModel/diffusion_pytorch_model.safetensors",
|
| 44 |
local_dir=CHECKPOINT_DIR,
|
|
|
|
| 45 |
)
|
|
|
|
|
|
|
| 46 |
hf_hub_download(
|
| 47 |
repo_id="InstantX/InstantID",
|
| 48 |
filename="ip-adapter.bin",
|
| 49 |
local_dir=CHECKPOINT_DIR,
|
|
|
|
| 50 |
)
|
| 51 |
|
| 52 |
|
|
@@ -86,13 +94,14 @@ def get_face_info(image: Image.Image):
|
|
| 86 |
reverse=True,
|
| 87 |
)[0]
|
| 88 |
|
| 89 |
-
#
|
| 90 |
emb = getattr(face, "normed_embedding", None)
|
| 91 |
if emb is None and isinstance(face, dict):
|
| 92 |
emb = face.get("embedding", None)
|
| 93 |
if emb is None:
|
| 94 |
raise RuntimeError("Impossible de récupérer l'embedding du visage.")
|
| 95 |
|
|
|
|
| 96 |
kps = getattr(face, "kps", None)
|
| 97 |
if kps is None and isinstance(face, dict):
|
| 98 |
kps = face.get("kps", None)
|
|
@@ -103,15 +112,17 @@ def get_face_info(image: Image.Image):
|
|
| 103 |
|
| 104 |
|
| 105 |
# ---------------------------
|
| 106 |
-
# Chargement du pipeline InstantID SDXL
|
| 107 |
# ---------------------------
|
| 108 |
|
| 109 |
def load_pipeline():
|
|
|
|
| 110 |
controlnet = ControlNetModel.from_pretrained(
|
| 111 |
CONTROLNET_PATH,
|
| 112 |
torch_dtype=DTYPE,
|
| 113 |
)
|
| 114 |
|
|
|
|
| 115 |
pipe = StableDiffusionXLInstantIDPipeline.from_pretrained(
|
| 116 |
BASE_MODEL_ID,
|
| 117 |
controlnet=controlnet,
|
|
@@ -120,7 +131,10 @@ def load_pipeline():
|
|
| 120 |
|
| 121 |
if DEVICE == "cuda":
|
| 122 |
pipe.to("cuda")
|
|
|
|
|
|
|
| 123 |
|
|
|
|
| 124 |
pipe.load_ip_adapter_instantid(IP_ADAPTER_PATH)
|
| 125 |
pipe.set_ip_adapter_scale(0.6)
|
| 126 |
|
|
@@ -145,7 +159,7 @@ def generate(face_image, prompt, negative_prompt="", steps=30, guidance_scale=5,
|
|
| 145 |
if face_image is None:
|
| 146 |
raise gr.Error("Merci de fournir une image de visage.")
|
| 147 |
|
| 148 |
-
#
|
| 149 |
if DEVICE == "cuda":
|
| 150 |
pipe.to("cuda")
|
| 151 |
else:
|
|
@@ -159,7 +173,6 @@ def generate(face_image, prompt, negative_prompt="", steps=30, guidance_scale=5,
|
|
| 159 |
kps_image = draw_kps(face_image, face_kps) # PIL.Image, comme dans l'exemple officiel
|
| 160 |
|
| 161 |
# 3) Appel du pipeline InstantID SDXL
|
| 162 |
-
# Note : image_embeds = face_emb, image = kps_image (comme dans l'exemple)
|
| 163 |
out = pipe(
|
| 164 |
prompt=prompt,
|
| 165 |
negative_prompt=negative_prompt,
|
|
@@ -185,7 +198,7 @@ def generate(face_image, prompt, negative_prompt="", steps=30, guidance_scale=5,
|
|
| 185 |
# ---------------------------
|
| 186 |
|
| 187 |
with gr.Blocks() as demo:
|
| 188 |
-
gr.Markdown("## InstantID +
|
| 189 |
|
| 190 |
with gr.Row():
|
| 191 |
with gr.Column():
|
|
@@ -195,8 +208,9 @@ with gr.Blocks() as demo:
|
|
| 195 |
label="Prompt",
|
| 196 |
lines=3,
|
| 197 |
value=(
|
| 198 |
-
"photorealistic full body portrait,
|
| 199 |
-
"
|
|
|
|
| 200 |
),
|
| 201 |
)
|
| 202 |
|
|
|
|
| 21 |
# Config globale
|
| 22 |
# ---------------------------
|
| 23 |
|
| 24 |
+
# ⚠️ Mets ici TON repo diffusers ArtFusion (après conversion + push_to_hub)
|
| 25 |
+
BASE_MODEL_ID = "leteint/artfusion-xl-real-v16-diffusers"
|
| 26 |
+
|
| 27 |
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 28 |
DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
|
| 29 |
|
|
|
|
| 35 |
# ---------------------------
|
| 36 |
|
| 37 |
def download_checkpoints():
|
| 38 |
+
# ControlNet InstantID (dossier ControlNetModel complet)
|
| 39 |
hf_hub_download(
|
| 40 |
repo_id="InstantX/InstantID",
|
| 41 |
filename="ControlNetModel/config.json",
|
| 42 |
local_dir=CHECKPOINT_DIR,
|
| 43 |
+
local_dir_use_symlinks=False,
|
| 44 |
)
|
| 45 |
hf_hub_download(
|
| 46 |
repo_id="InstantX/InstantID",
|
| 47 |
filename="ControlNetModel/diffusion_pytorch_model.safetensors",
|
| 48 |
local_dir=CHECKPOINT_DIR,
|
| 49 |
+
local_dir_use_symlinks=False,
|
| 50 |
)
|
| 51 |
+
|
| 52 |
+
# IP-Adapter InstantID
|
| 53 |
hf_hub_download(
|
| 54 |
repo_id="InstantX/InstantID",
|
| 55 |
filename="ip-adapter.bin",
|
| 56 |
local_dir=CHECKPOINT_DIR,
|
| 57 |
+
local_dir_use_symlinks=False,
|
| 58 |
)
|
| 59 |
|
| 60 |
|
|
|
|
| 94 |
reverse=True,
|
| 95 |
)[0]
|
| 96 |
|
| 97 |
+
# Embedding
|
| 98 |
emb = getattr(face, "normed_embedding", None)
|
| 99 |
if emb is None and isinstance(face, dict):
|
| 100 |
emb = face.get("embedding", None)
|
| 101 |
if emb is None:
|
| 102 |
raise RuntimeError("Impossible de récupérer l'embedding du visage.")
|
| 103 |
|
| 104 |
+
# Keypoints
|
| 105 |
kps = getattr(face, "kps", None)
|
| 106 |
if kps is None and isinstance(face, dict):
|
| 107 |
kps = face.get("kps", None)
|
|
|
|
| 112 |
|
| 113 |
|
| 114 |
# ---------------------------
|
| 115 |
+
# Chargement du pipeline InstantID SDXL + ArtFusion
|
| 116 |
# ---------------------------
|
| 117 |
|
| 118 |
def load_pipeline():
|
| 119 |
+
# ControlNet InstantID
|
| 120 |
controlnet = ControlNetModel.from_pretrained(
|
| 121 |
CONTROLNET_PATH,
|
| 122 |
torch_dtype=DTYPE,
|
| 123 |
)
|
| 124 |
|
| 125 |
+
# Pipeline InstantID SDXL avec ArtFusion comme base
|
| 126 |
pipe = StableDiffusionXLInstantIDPipeline.from_pretrained(
|
| 127 |
BASE_MODEL_ID,
|
| 128 |
controlnet=controlnet,
|
|
|
|
| 131 |
|
| 132 |
if DEVICE == "cuda":
|
| 133 |
pipe.to("cuda")
|
| 134 |
+
else:
|
| 135 |
+
pipe.to("cpu")
|
| 136 |
|
| 137 |
+
# IP-Adapter InstantID
|
| 138 |
pipe.load_ip_adapter_instantid(IP_ADAPTER_PATH)
|
| 139 |
pipe.set_ip_adapter_scale(0.6)
|
| 140 |
|
|
|
|
| 159 |
if face_image is None:
|
| 160 |
raise gr.Error("Merci de fournir une image de visage.")
|
| 161 |
|
| 162 |
+
# On s'assure que le pipe est bien sur le bon device
|
| 163 |
if DEVICE == "cuda":
|
| 164 |
pipe.to("cuda")
|
| 165 |
else:
|
|
|
|
| 173 |
kps_image = draw_kps(face_image, face_kps) # PIL.Image, comme dans l'exemple officiel
|
| 174 |
|
| 175 |
# 3) Appel du pipeline InstantID SDXL
|
|
|
|
| 176 |
out = pipe(
|
| 177 |
prompt=prompt,
|
| 178 |
negative_prompt=negative_prompt,
|
|
|
|
| 198 |
# ---------------------------
|
| 199 |
|
| 200 |
with gr.Blocks() as demo:
|
| 201 |
+
gr.Markdown("## InstantID + ArtFusion XL Real (SDXL) – Visage → corps généré (ZeroGPU)")
|
| 202 |
|
| 203 |
with gr.Row():
|
| 204 |
with gr.Column():
|
|
|
|
| 208 |
label="Prompt",
|
| 209 |
lines=3,
|
| 210 |
value=(
|
| 211 |
+
"photorealistic full body portrait, white European man, realistic skin texture, "
|
| 212 |
+
"firefighter uniform with detailed fabric, realistic studio lighting, 35mm DSLR, "
|
| 213 |
+
"sharp focus on face, clean background, high resolution"
|
| 214 |
),
|
| 215 |
)
|
| 216 |
|