Astridkraft commited on
Commit
2c3a509
·
verified ·
1 Parent(s): 6769c24

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -33
app.py CHANGED
@@ -4,18 +4,26 @@ from diffusers import StableDiffusionInpaintPipeline, AutoencoderKL
4
  from diffusers import DPMSolverMultistepScheduler, PNDMScheduler
5
  from controlnet_module import controlnet_processor
6
  import torch
7
- from PIL import Image, ImageDraw
8
  import time
9
  import os
10
  import tempfile
11
  import random
12
  import re
13
 
14
- # === FACE-FIX IMPORT (automatisch nur bei Personen) ===
15
  try:
16
- from controlnet_facefix import apply_facefix
 
 
 
 
 
 
 
 
17
  FACEFIX_AVAILABLE = True
18
- print("Face-Fix (OpenPose_faceonly + Depth) erfolgreich geladen")
19
  except Exception as e:
20
  print(f"Face-Fix nicht verfügbar: {e}")
21
  FACEFIX_AVAILABLE = False
@@ -212,6 +220,61 @@ class ImageToImageProgressCallback:
212
  self.progress(progress_val, desc="Generierung läuft...")
213
  return callback_kwargs
214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  # === HAUPTFUNKTION: TEXT ZU BILD MIT AUTOMATISCHEM FACE-FIX ===
216
  def text_to_image(prompt, model_id, steps, guidance_scale, progress=gr.Progress()):
217
  try:
@@ -248,9 +311,13 @@ def text_to_image(prompt, model_id, steps, guidance_scale, progress=gr.Progress(
248
 
249
  # AUTOMATISCHER FACE-FIX NUR BEI PERSONEN
250
  if FACEFIX_AVAILABLE and is_person_prompt(enhanced_prompt):
251
- print("Person erkannt → Starte 20-Sekunden Face-Fix...")
252
  progress(0.92, desc="Perfektioniere Gesicht & Hände...")
253
  try:
 
 
 
 
254
  image = apply_facefix(
255
  image=image,
256
  prompt=enhanced_prompt,
@@ -258,13 +325,47 @@ def text_to_image(prompt, model_id, steps, guidance_scale, progress=gr.Progress(
258
  seed=seed,
259
  model_id=model_id
260
  )
 
261
  print("Face-Fix abgeschlossen!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  except Exception as e:
263
- print(f"Face-Fix fehlgeschlagen (ignoriert): {e}")
264
 
265
  duration = time.time() - start_time
266
  config = MODEL_CONFIGS.get(model_id, {"name": model_id})
267
  status_msg = f"Generiert mit {config.get('name', model_id)} in {duration:.1f}s"
 
 
 
 
 
268
  return image, status_msg
269
 
270
  except Exception as e:
@@ -273,7 +374,6 @@ def text_to_image(prompt, model_id, steps, guidance_scale, progress=gr.Progress(
273
  traceback.print_exc()
274
  return None, f"Fehler: {str(e)}"
275
 
276
-
277
  def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
278
  face_preserve, bbox_x1, bbox_y1, bbox_x2, bbox_y2,
279
  progress=gr.Progress()):
@@ -289,12 +389,11 @@ def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
289
  print(f"Negativ-Prompt: {neg_prompt}")
290
  print(f"Gesicht beibehalten: {face_preserve}")
291
 
292
-
293
- # ===== NEU: AUTOMATISCHEN NEGATIV-PROMPT GENERIEREN =====
294
  auto_negatives = auto_negative_prompt(prompt)
295
  print(f"🤖 Automatisch generierter Negativ-Prompt: {auto_negatives}")
296
 
297
- # ===== NEU: KOMBINIERE MANUELLEN UND AUTOMATISCHEN PROMPT =====
298
  combined_negative_prompt = ""
299
 
300
  if neg_prompt and neg_prompt.strip():
@@ -303,7 +402,6 @@ def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
303
  print(f"👤 Benutzer Negativ-Prompt: {user_neg}")
304
 
305
  # Entferne Duplikate zwischen automatischen und manuellen Prompts
306
- # Konvertiere beide in Sets für einfachen Duplikatvergleich
307
  user_words = [word.strip().lower() for word in user_neg.split(",")]
308
  auto_words = [word.strip().lower() for word in auto_negatives.split(",")]
309
 
@@ -315,7 +413,7 @@ def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
315
  if auto_word and auto_word not in user_words:
316
  combined_words.append(auto_word)
317
 
318
- # Zusammenfügen und Duplikate entfernen (für den Fall von Duplikaten innerhalb des gleichen Prompts)
319
  unique_words = []
320
  seen_words = set()
321
  for word in combined_words:
@@ -330,8 +428,6 @@ def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
330
  print(f"ℹ️ Kein manueller Negativ-Prompt, verwende nur automatischen: {combined_negative_prompt}")
331
 
332
  print(f"✅ Finaler kombinierter Negativ-Prompt: {combined_negative_prompt}")
333
- # ===== ENDE DER NEUEN LOGIK =====
334
-
335
 
336
  progress(0, desc="Starte Generierung mit ControlNet...")
337
 
@@ -415,6 +511,22 @@ def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
415
  print(f"🕒 Dauer: {end_time - start_time:.2f} Sekunden")
416
 
417
  generated_image = result.images[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  return generated_image
419
 
420
  except Exception as e:
@@ -423,24 +535,6 @@ def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
423
  traceback.print_exc()
424
  return None
425
 
426
- def update_bbox_from_image(image):
427
- """Aktualisiert die Bounding-Box-Koordinaten wenn ein Bild hochgeladen wird"""
428
- if image is None:
429
- return None, None, None, None
430
-
431
- bbox = auto_detect_face_area(image)
432
- return bbox[0], bbox[1], bbox[2], bbox[3]
433
-
434
- def update_model_settings(model_id):
435
- """Aktualisiert die empfohlenen Einstellungen basierend auf Modellauswahl"""
436
- config = MODEL_CONFIGS.get(model_id, MODEL_CONFIGS["runwayml/stable-diffusion-v1-5"])
437
-
438
- return (
439
- config["recommended_steps"], # steps
440
- config["recommended_cfg"], # guidance_scale
441
- f"📊 Empfohlene Einstellungen: {config['steps']} Steps, CFG {config['cfg']}"
442
- )
443
-
444
  def main_ui():
445
  with gr.Blocks(
446
  title="AI Image Generator",
@@ -535,6 +629,15 @@ def main_ui():
535
  color: #721c24;
536
  border: 1px solid #f5c6cb;
537
  }
 
 
 
 
 
 
 
 
 
538
  """
539
  ) as demo:
540
 
@@ -542,6 +645,16 @@ def main_ui():
542
  with gr.Tab("Text zu Bild"):
543
  gr.Markdown("## 🎨 Text zu Bild Generator")
544
 
 
 
 
 
 
 
 
 
 
 
545
  with gr.Row():
546
  with gr.Column(scale=2):
547
  # Modellauswahl Dropdown (NUR 2 MODELLE)
@@ -567,7 +680,7 @@ def main_ui():
567
 
568
  with gr.Column(scale=3):
569
  txt_input = gr.Textbox(
570
- placeholder="z.B. ultra realistic mountain landscape at sunrise, soft mist over the valley, detailed foliage, crisp textures, depth of field, sunlight rays through clouds, shot on medium format camera, 8k, HDR, hyper-detailed, natural lighting, masterpiece",
571
  lines=3,
572
  label="🎯 Prompt (Englisch)",
573
  info="Beschreibe detailliert, was du sehen möchtest. Negative Prompts werden automatisch generiert."
 
4
  from diffusers import DPMSolverMultistepScheduler, PNDMScheduler
5
  from controlnet_module import controlnet_processor
6
  import torch
7
+ from PIL import Image, ImageDraw, ImageFont
8
  import time
9
  import os
10
  import tempfile
11
  import random
12
  import re
13
 
14
+ # === FACE-FIX IMPORT (korrigierte Version) ===
15
  try:
16
+ # Versuche verschiedene Import-Möglichkeiten
17
+ try:
18
+ from controlnet_facefix import apply_facefix
19
+ except ImportError:
20
+ # Alternative Import-Methode
21
+ import sys
22
+ sys.path.append(".")
23
+ from controlnet_facefix import apply_facefix
24
+
25
  FACEFIX_AVAILABLE = True
26
+ print("Face-Fix erfolgreich geladen")
27
  except Exception as e:
28
  print(f"Face-Fix nicht verfügbar: {e}")
29
  FACEFIX_AVAILABLE = False
 
220
  self.progress(progress_val, desc="Generierung läuft...")
221
  return callback_kwargs
222
 
223
+ # === BILDVERARBEITUNGS-FUNKTIONEN FÜR BILD-TO-BILD TAB ===
224
+ def process_image_upload(image):
225
+ """Verarbeitet den Bild-Upload und aktualisiert die Koordinaten und Vorschau"""
226
+ if image is None:
227
+ return None, 100, 100, 300, 300
228
+
229
+ # Automatische Gesichtserkennung
230
+ bbox = auto_detect_face_area(image)
231
+
232
+ # Live-Vorschau erstellen
233
+ preview = update_live_preview(image, bbox[0], bbox[1], bbox[2], bbox[3], True)
234
+
235
+ return preview, bbox[0], bbox[1], bbox[2], bbox[3]
236
+
237
+ def update_live_preview(image, x1, y1, x2, y2, face_preserve):
238
+ """Erstellt eine Live-Vorschau mit farbigem Rahmen basierend auf dem Modus"""
239
+ if image is None:
240
+ return None
241
+
242
+ # Kopie des Bildes für Vorschau
243
+ preview = image.copy()
244
+
245
+ # Zeichne Rahmen basierend auf Modus
246
+ draw = ImageDraw.Draw(preview)
247
+
248
+ # Rahmenfarbe basierend auf Modus
249
+ if face_preserve:
250
+ # 🟢 GRÜN: Alles außerhalb des Rahmens wird verändert
251
+ outline_color = "green"
252
+ else:
253
+ # 🔴 ROT: Nur innerhalb des Rahmens wird verändert
254
+ outline_color = "red"
255
+
256
+ # Rahmen zeichnen
257
+ draw.rectangle([x1, y1, x2, y2], outline=outline_color, width=3)
258
+
259
+ # Hinweis-Text hinzufügen
260
+ try:
261
+ # Versuche, eine Schriftart zu laden (falls verfügbar)
262
+ try:
263
+ font = ImageFont.truetype("arial.ttf", 16)
264
+ except:
265
+ font = ImageFont.load_default()
266
+
267
+ text = f"{'🟢 Schutzmodus AN' if face_preserve else '🔴 Schutzmodus AUS'}"
268
+ # Text-Hintergrund
269
+ text_bbox = draw.textbbox((x1, y1 - 25), text, font=font)
270
+ draw.rectangle(text_bbox, fill="white")
271
+ # Text
272
+ draw.text((x1, y1 - 25), text, fill=outline_color, font=font)
273
+ except:
274
+ pass # Falls Schrift nicht geladen werden kann
275
+
276
+ return preview
277
+
278
  # === HAUPTFUNKTION: TEXT ZU BILD MIT AUTOMATISCHEM FACE-FIX ===
279
  def text_to_image(prompt, model_id, steps, guidance_scale, progress=gr.Progress()):
280
  try:
 
311
 
312
  # AUTOMATISCHER FACE-FIX NUR BEI PERSONEN
313
  if FACEFIX_AVAILABLE and is_person_prompt(enhanced_prompt):
314
+ print("Person erkannt → Starte Face-Fix für perfekte Gesichter...")
315
  progress(0.92, desc="Perfektioniere Gesicht & Hände...")
316
  try:
317
+ # Originalbild speichern für Vergleich
318
+ original_image = image.copy()
319
+
320
+ # Face-Fix anwenden
321
  image = apply_facefix(
322
  image=image,
323
  prompt=enhanced_prompt,
 
325
  seed=seed,
326
  model_id=model_id
327
  )
328
+
329
  print("Face-Fix abgeschlossen!")
330
+
331
+ # Optional: Vergleichsbild erstellen
332
+ try:
333
+ width, height = image.size
334
+ comparison = Image.new('RGB', (width * 2, height))
335
+ comparison.paste(original_image, (0, 0))
336
+ comparison.paste(image, (width, 0))
337
+
338
+ # Trennlinie
339
+ draw = ImageDraw.Draw(comparison)
340
+ draw.line([(width, 0), (width, height)], fill="white", width=2)
341
+
342
+ # Beschriftung hinzufügen
343
+ try:
344
+ font = ImageFont.truetype("arial.ttf", 20)
345
+ except:
346
+ font = ImageFont.load_default()
347
+
348
+ draw.text((10, 10), "Vor Face-Fix", fill="white", font=font)
349
+ draw.text((width + 10, 10), "Nach Face-Fix", fill="white", font=font)
350
+
351
+ # Vergleichsbild als Option zurückgeben
352
+ image = comparison
353
+
354
+ except Exception as e:
355
+ print(f"Vergleichsbild konnte nicht erstellt werden: {e}")
356
+ # Bei Fehler einfach das verbesserte Bild verwenden
357
+
358
  except Exception as e:
359
+ print(f"Face-Fix fehlgeschlagen (Original bleibt): {e}")
360
 
361
  duration = time.time() - start_time
362
  config = MODEL_CONFIGS.get(model_id, {"name": model_id})
363
  status_msg = f"Generiert mit {config.get('name', model_id)} in {duration:.1f}s"
364
+
365
+ # Face-Fix Info hinzufügen
366
+ if FACEFIX_AVAILABLE and is_person_prompt(enhanced_prompt):
367
+ status_msg += " + Face-Fix angewendet"
368
+
369
  return image, status_msg
370
 
371
  except Exception as e:
 
374
  traceback.print_exc()
375
  return None, f"Fehler: {str(e)}"
376
 
 
377
  def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
378
  face_preserve, bbox_x1, bbox_y1, bbox_x2, bbox_y2,
379
  progress=gr.Progress()):
 
389
  print(f"Negativ-Prompt: {neg_prompt}")
390
  print(f"Gesicht beibehalten: {face_preserve}")
391
 
392
+ # Automatischen Negativ-Prompt generieren
 
393
  auto_negatives = auto_negative_prompt(prompt)
394
  print(f"🤖 Automatisch generierter Negativ-Prompt: {auto_negatives}")
395
 
396
+ # Kombiniere manuellen und automatischen Prompt
397
  combined_negative_prompt = ""
398
 
399
  if neg_prompt and neg_prompt.strip():
 
402
  print(f"👤 Benutzer Negativ-Prompt: {user_neg}")
403
 
404
  # Entferne Duplikate zwischen automatischen und manuellen Prompts
 
405
  user_words = [word.strip().lower() for word in user_neg.split(",")]
406
  auto_words = [word.strip().lower() for word in auto_negatives.split(",")]
407
 
 
413
  if auto_word and auto_word not in user_words:
414
  combined_words.append(auto_word)
415
 
416
+ # Zusammenfügen und Duplikate entfernen
417
  unique_words = []
418
  seen_words = set()
419
  for word in combined_words:
 
428
  print(f"ℹ️ Kein manueller Negativ-Prompt, verwende nur automatischen: {combined_negative_prompt}")
429
 
430
  print(f"✅ Finaler kombinierter Negativ-Prompt: {combined_negative_prompt}")
 
 
431
 
432
  progress(0, desc="Starte Generierung mit ControlNet...")
433
 
 
511
  print(f"🕒 Dauer: {end_time - start_time:.2f} Sekunden")
512
 
513
  generated_image = result.images[0]
514
+
515
+ # Optional: Face-Fix auch auf das transformierte Bild anwenden
516
+ if FACEFIX_AVAILABLE and is_person_prompt(prompt):
517
+ print("Transformiertes Bild → Wende Face-Fix an...")
518
+ try:
519
+ generated_image = apply_facefix(
520
+ image=generated_image,
521
+ prompt=prompt,
522
+ negative_prompt=combined_negative_prompt,
523
+ seed=seed,
524
+ model_id="runwayml/stable-diffusion-v1-5"
525
+ )
526
+ print("Face-Fix auf transformiertem Bild abgeschlossen!")
527
+ except Exception as e:
528
+ print(f"Face-Fix auf transformiertem Bild fehlgeschlagen: {e}")
529
+
530
  return generated_image
531
 
532
  except Exception as e:
 
535
  traceback.print_exc()
536
  return None
537
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
538
  def main_ui():
539
  with gr.Blocks(
540
  title="AI Image Generator",
 
629
  color: #721c24;
630
  border: 1px solid #f5c6cb;
631
  }
632
+ .face-fix-badge {
633
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
634
+ color: white;
635
+ padding: 4px 8px;
636
+ border-radius: 12px;
637
+ font-size: 12px;
638
+ margin-left: 10px;
639
+ display: inline-block;
640
+ }
641
  """
642
  ) as demo:
643
 
 
645
  with gr.Tab("Text zu Bild"):
646
  gr.Markdown("## 🎨 Text zu Bild Generator")
647
 
648
+ # Face-Fix Info Badge
649
+ if FACEFIX_AVAILABLE:
650
+ gr.Markdown(
651
+ f"""
652
+ <div style="background: #e3f2fd; padding: 10px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #2196f3;">
653
+ 🎭 <strong>Face-Fix aktiviert!</strong> Gesichter werden automatisch verbessert.
654
+ </div>
655
+ """
656
+ )
657
+
658
  with gr.Row():
659
  with gr.Column(scale=2):
660
  # Modellauswahl Dropdown (NUR 2 MODELLE)
 
680
 
681
  with gr.Column(scale=3):
682
  txt_input = gr.Textbox(
683
+ placeholder="z.B. ultra realistic portrait of a beautiful woman with detailed skin, perfect eyes, sharp focus, cinematic lighting",
684
  lines=3,
685
  label="🎯 Prompt (Englisch)",
686
  info="Beschreibe detailliert, was du sehen möchtest. Negative Prompts werden automatisch generiert."