Update app.py
Browse files
app.py
CHANGED
|
@@ -165,12 +165,17 @@ def generate(face_image, style_image, prompt, negative_prompt,
|
|
| 165 |
|
| 166 |
gen = None if seed is None or int(seed) < 0 else torch.Generator(device=DEVICE).manual_seed(int(seed))
|
| 167 |
|
|
|
|
| 168 |
face = ImageOps.exif_transpose(face_image).convert("RGB")
|
| 169 |
-
ms = min(face.size)
|
|
|
|
|
|
|
| 170 |
face_sq = face.crop((x, y, x + ms, y + ms)).resize((512, 512), Image.Resampling.LANCZOS)
|
| 171 |
|
|
|
|
| 172 |
face_emb, kps_img = extract_face_embed_and_kps(face_sq)
|
| 173 |
|
|
|
|
| 174 |
try:
|
| 175 |
if HAS_STYLE_ADAPTER and style_image is not None:
|
| 176 |
pipe.set_ip_adapter_scale({"instantid": float(adapter_strength), "style": float(style_strength)})
|
|
@@ -179,41 +184,48 @@ def generate(face_image, style_image, prompt, negative_prompt,
|
|
| 179 |
except Exception as e:
|
| 180 |
print(f"ℹ️ set_ip_adapter_scale ignoré: {e}")
|
| 181 |
|
|
|
|
| 182 |
cn = getattr(pipe, "controlnet", None)
|
| 183 |
if isinstance(cn, (list, tuple)):
|
| 184 |
n_cn = len(cn)
|
| 185 |
else:
|
| 186 |
-
try:
|
| 187 |
-
|
|
|
|
|
|
|
| 188 |
|
| 189 |
-
image_arg = [kps_img] * n_cn if n_cn > 1 else (
|
|
|
|
|
|
|
| 190 |
scale_val = float(identity_strength)
|
| 191 |
-
scale_arg = [scale_val] * n_cn if n_cn > 1 else (
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
gen_kwargs = dict(
|
| 195 |
-
prompt=(prompt or "").strip(),
|
| 196 |
-
negative_prompt=(negative_prompt or "").strip(),
|
| 197 |
-
image=image_arg, # IdentityNet (landmarks)
|
| 198 |
-
image_embeds=face_emb, # compat pipeline
|
| 199 |
-
# --- CLÉ : passer aux deux noms pour couvrir 0.29 (added_cond_kwargs) et 0.30 (added_conditions)
|
| 200 |
-
added_conditions={"image_embeds": face_emb}, # ← diffusers >= 0.30.0
|
| 201 |
-
added_cond_kwargs={"image_embeds": face_emb}, # ← diffusers 0.29.x (safe no-op si ignoré)
|
| 202 |
-
controlnet_conditioning_scale=scale_arg,
|
| 203 |
-
num_inference_steps=int(steps),
|
| 204 |
-
guidance_scale=float(cfg),
|
| 205 |
-
width=int(width),
|
| 206 |
-
height=int(height),
|
| 207 |
-
generator=gen,
|
| 208 |
-
)
|
| 209 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
|
|
|
|
| 211 |
if HAS_STYLE_ADAPTER and style_image is not None:
|
| 212 |
try:
|
| 213 |
gen_kwargs["ip_adapter_image"] = ImageOps.exif_transpose(style_image).convert("RGB")
|
| 214 |
except Exception as e:
|
| 215 |
print(f"ℹ️ ip_adapter_image ignoré: {e}")
|
| 216 |
|
|
|
|
| 217 |
images = pipe(**gen_kwargs).images
|
| 218 |
return images[0], "", "\n".join(load_logs)
|
| 219 |
|
|
@@ -222,6 +234,7 @@ gen_kwargs = dict(
|
|
| 222 |
except Exception:
|
| 223 |
return None, "Erreur:\n" + traceback.format_exc(), "\n".join(load_logs)
|
| 224 |
|
|
|
|
| 225 |
EX_PROMPT = (
|
| 226 |
"one piece style, Eiichiro Oda style, anime portrait, upper body, pirate outfit, "
|
| 227 |
"clean lineart, cel shading, vibrant colors, expressive eyes, dynamic composition, simple background"
|
|
|
|
| 165 |
|
| 166 |
gen = None if seed is None or int(seed) < 0 else torch.Generator(device=DEVICE).manual_seed(int(seed))
|
| 167 |
|
| 168 |
+
# visage → carré 512 pour détection stable
|
| 169 |
face = ImageOps.exif_transpose(face_image).convert("RGB")
|
| 170 |
+
ms = min(face.size)
|
| 171 |
+
x = (face.width - ms) // 2
|
| 172 |
+
y = (face.height - ms) // 2
|
| 173 |
face_sq = face.crop((x, y, x + ms, y + ms)).resize((512, 512), Image.Resampling.LANCZOS)
|
| 174 |
|
| 175 |
+
# InsightFace : embedding (torch [1,D]) + landmarks
|
| 176 |
face_emb, kps_img = extract_face_embed_and_kps(face_sq)
|
| 177 |
|
| 178 |
+
# IP-Adapter scales
|
| 179 |
try:
|
| 180 |
if HAS_STYLE_ADAPTER and style_image is not None:
|
| 181 |
pipe.set_ip_adapter_scale({"instantid": float(adapter_strength), "style": float(style_strength)})
|
|
|
|
| 184 |
except Exception as e:
|
| 185 |
print(f"ℹ️ set_ip_adapter_scale ignoré: {e}")
|
| 186 |
|
| 187 |
+
# compat multi-ControlNet (même si on en a qu’un)
|
| 188 |
cn = getattr(pipe, "controlnet", None)
|
| 189 |
if isinstance(cn, (list, tuple)):
|
| 190 |
n_cn = len(cn)
|
| 191 |
else:
|
| 192 |
+
try:
|
| 193 |
+
n_cn = len(cn)
|
| 194 |
+
except Exception:
|
| 195 |
+
n_cn = 1
|
| 196 |
|
| 197 |
+
image_arg = [kps_img] * n_cn if n_cn > 1 else (
|
| 198 |
+
[kps_img] if isinstance(cn, (list, tuple)) else kps_img
|
| 199 |
+
)
|
| 200 |
scale_val = float(identity_strength)
|
| 201 |
+
scale_arg = [scale_val] * n_cn if n_cn > 1 else (
|
| 202 |
+
[scale_val] if isinstance(cn, (list, tuple)) else scale_val
|
| 203 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
+
# ✅ Correctif clé : double passage pour compatibilité 0.29 / 0.30
|
| 206 |
+
gen_kwargs = dict(
|
| 207 |
+
prompt=(prompt or "").strip(),
|
| 208 |
+
negative_prompt=(negative_prompt or "").strip(),
|
| 209 |
+
image=image_arg,
|
| 210 |
+
image_embeds=face_emb,
|
| 211 |
+
added_conditions={"image_embeds": face_emb}, # diffusers ≥ 0.30.0
|
| 212 |
+
added_cond_kwargs={"image_embeds": face_emb}, # diffusers 0.29.x
|
| 213 |
+
controlnet_conditioning_scale=scale_arg,
|
| 214 |
+
num_inference_steps=int(steps),
|
| 215 |
+
guidance_scale=float(cfg),
|
| 216 |
+
width=int(width),
|
| 217 |
+
height=int(height),
|
| 218 |
+
generator=gen,
|
| 219 |
+
)
|
| 220 |
|
| 221 |
+
# Si un style est fourni
|
| 222 |
if HAS_STYLE_ADAPTER and style_image is not None:
|
| 223 |
try:
|
| 224 |
gen_kwargs["ip_adapter_image"] = ImageOps.exif_transpose(style_image).convert("RGB")
|
| 225 |
except Exception as e:
|
| 226 |
print(f"ℹ️ ip_adapter_image ignoré: {e}")
|
| 227 |
|
| 228 |
+
# Appel pipeline
|
| 229 |
images = pipe(**gen_kwargs).images
|
| 230 |
return images[0], "", "\n".join(load_logs)
|
| 231 |
|
|
|
|
| 234 |
except Exception:
|
| 235 |
return None, "Erreur:\n" + traceback.format_exc(), "\n".join(load_logs)
|
| 236 |
|
| 237 |
+
|
| 238 |
EX_PROMPT = (
|
| 239 |
"one piece style, Eiichiro Oda style, anime portrait, upper body, pirate outfit, "
|
| 240 |
"clean lineart, cel shading, vibrant colors, expressive eyes, dynamic composition, simple background"
|