Nad54 commited on
Commit
38fd38e
·
verified ·
1 Parent(s): b275d7f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -22
app.py CHANGED
@@ -166,14 +166,13 @@ def generate(face_image, style_image, prompt, negative_prompt,
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:
@@ -189,27 +188,21 @@ def generate(face_image, style_image, prompt, negative_prompt,
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),
@@ -217,24 +210,46 @@ def generate(face_image, style_image, prompt, negative_prompt,
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
 
232
  except torch.cuda.OutOfMemoryError:
233
  return None, "CUDA OOM: baisse la résolution ou les steps.", "\n".join(load_logs)
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"
 
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
+ from PIL import ImageOps
170
  face = ImageOps.exif_transpose(face_image).convert("RGB")
171
+ ms = min(face.size); x = (face.width - ms) // 2; y = (face.height - ms) // 2
 
 
172
  face_sq = face.crop((x, y, x + ms, y + ms)).resize((512, 512), Image.Resampling.LANCZOS)
173
 
174
  # InsightFace : embedding (torch [1,D]) + landmarks
175
+ face_emb, kps_img = extract_face_embed_and_kps(face_sq) # face_emb: torch.Tensor [1,D] on DEVICE/DTYPE
176
 
177
  # IP-Adapter scales
178
  try:
 
188
  if isinstance(cn, (list, tuple)):
189
  n_cn = len(cn)
190
  else:
191
+ try: n_cn = len(cn)
192
+ except Exception: n_cn = 1
 
 
193
 
194
+ image_arg = [kps_img] * n_cn if n_cn > 1 else ([kps_img] if isinstance(cn, (list, tuple)) else kps_img)
 
 
195
  scale_val = float(identity_strength)
196
+ scale_arg = [scale_val] * n_cn if n_cn > 1 else ([scale_val] if isinstance(cn, (list, tuple)) else scale_val)
 
 
197
 
198
+ # kwargs d’inférence (on met aussi ici pour compat)
199
  gen_kwargs = dict(
200
  prompt=(prompt or "").strip(),
201
  negative_prompt=(negative_prompt or "").strip(),
202
  image=image_arg,
203
+ image_embeds=face_emb, # compat pipeline
204
+ added_conditions={"image_embeds": face_emb}, # diffusers ≥ 0.30.x (si propagé)
205
+ added_cond_kwargs={"image_embeds": face_emb}, # diffusers 0.29.x (si propagé)
206
  controlnet_conditioning_scale=scale_arg,
207
  num_inference_steps=int(steps),
208
  guidance_scale=float(cfg),
 
210
  height=int(height),
211
  generator=gen,
212
  )
 
 
213
  if HAS_STYLE_ADAPTER and style_image is not None:
214
  try:
215
  gen_kwargs["ip_adapter_image"] = ImageOps.exif_transpose(style_image).convert("RGB")
216
  except Exception as e:
217
  print(f"ℹ️ ip_adapter_image ignoré: {e}")
218
 
219
+ # 🔧 MONKEY-PATCH: injecter image_embeds au niveau du UNet.forward
220
+ orig_forward = pipe.unet.forward
221
+
222
+ def forward_patch(*args, **kwargs):
223
+ # on fusionne proprement pour n’écraser rien
224
+ ac = kwargs.get("added_conditions")
225
+ if ac is None:
226
+ ac = {}
227
+ else:
228
+ ac = dict(ac)
229
+ ac["image_embeds"] = face_emb
230
+ kwargs["added_conditions"] = ac
231
+ # compat pour 0.29.x
232
+ kwargs["added_cond_kwargs"] = ac
233
+ return orig_forward(*args, **kwargs)
234
+
235
+ pipe.unet.forward = forward_patch
236
+
237
+ try:
238
+ images = pipe(**gen_kwargs).images
239
+ finally:
240
+ # toujours restaurer le forward d'origine
241
+ pipe.unet.forward = orig_forward
242
+
243
  return images[0], "", "\n".join(load_logs)
244
 
245
  except torch.cuda.OutOfMemoryError:
246
  return None, "CUDA OOM: baisse la résolution ou les steps.", "\n".join(load_logs)
247
  except Exception:
248
+ import traceback
249
  return None, "Erreur:\n" + traceback.format_exc(), "\n".join(load_logs)
250
 
251
 
252
+
253
  EX_PROMPT = (
254
  "one piece style, Eiichiro Oda style, anime portrait, upper body, pirate outfit, "
255
  "clean lineart, cel shading, vibrant colors, expressive eyes, dynamic composition, simple background"