Astridkraft commited on
Commit
c6c5a0f
·
verified ·
1 Parent(s): e640267

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -42
app.py CHANGED
@@ -56,7 +56,7 @@ def auto_negative_prompt(positive_prompt):
56
  if any(w in p for w in [
57
  "person", "man", "woman", "face", "portrait", "team", "employee",
58
  "people", "crowd", "character", "figure", "human", "child", "baby",
59
- "girl", "boy", "lady", "gentleman", "fairy", "elf", "dwarf", "santa claus"
60
  "mermaid", "angel", "demon", "witch", "wizard", "creature", "being",
61
  "model", "actor", "actress", "celebrity", "avatar", "group"]):
62
  negatives.append(
@@ -336,9 +336,10 @@ def load_txt2img(model_id):
336
  raise
337
 
338
  def load_img2img():
 
339
  global pipe_img2img
340
  if pipe_img2img is None:
341
- print("Loading Inpainting model...")
342
  try:
343
  pipe_img2img = StableDiffusionInpaintPipeline.from_pretrained(
344
  "runwayml/stable-diffusion-inpainting",
@@ -346,22 +347,26 @@ def load_img2img():
346
  allow_pickle=False,
347
  safety_checker=None,
348
  ).to(device)
 
 
 
 
 
 
 
 
 
 
 
349
  except Exception as e:
350
- print(f"Fehler beim Laden des Inpainting-Modells: {e}")
351
  raise
352
 
353
- from diffusers import DPMSolverMultistepScheduler
354
- pipe_img2img.scheduler = DPMSolverMultistepScheduler.from_config(
355
- pipe_img2img.scheduler.config,
356
- algorithm_type="sde-dpmsolver++",
357
- use_karras_sigmas=True,
358
- timestep_spacing="trailing"
359
- )
360
-
361
  pipe_img2img.enable_attention_slicing()
362
  pipe_img2img.enable_vae_tiling()
363
  if hasattr(pipe_img2img, 'vae_slicing'):
364
  pipe_img2img.vae_slicing = True
 
365
 
366
  return pipe_img2img
367
 
@@ -767,47 +772,36 @@ def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
767
 
768
  pipe = load_img2img()
769
 
770
- img_resized = inpaint_input.convert("RGB").resize((512, 512))
 
 
 
 
 
 
 
771
 
772
  adj_guidance = min(guidance_scale, 12.0)
773
  seed = random.randint(0, 2**32 - 1)
774
  generator = torch.Generator(device=device).manual_seed(seed)
775
  print(f"🌱 Inpaint Seed: {seed}")
776
 
777
- # ===== MASKE ERSTELLEN (BASIEREND AUF MODUS) =====
778
  mask = None
779
  if bbox_x1 is not None and bbox_y1 is not None and bbox_x2 is not None and bbox_y2 is not None:
780
- # Skaliere Slider-Werte (Original-Bildgröße) auf 512x512 für die Pipeline
781
- width, height = image.size
782
-
783
- # Skalierungsfaktoren berechnen
784
- scale_x = IMG_SIZE / width
785
- scale_y = IMG_SIZE / height
786
-
787
- # Skaliere Bounding-Box-Koordinaten auf 512x512
788
- pipeline_x1 = int(bbox_x1 * scale_x)
789
- pipeline_y1 = int(bbox_y1 * scale_y)
790
- pipeline_x2 = int(bbox_x2 * scale_x)
791
- pipeline_y2 = int(bbox_y2 * scale_y)
792
-
793
- # Sortiere und begrenze die Koordinaten
794
- pipeline_bbox = sort_coordinates(
795
- max(0, min(pipeline_x1, IMG_SIZE-1)),
796
- max(0, min(pipeline_y1, IMG_SIZE-1)),
797
- max(0, min(pipeline_x2, IMG_SIZE-1)),
798
- max(0, min(pipeline_y2, IMG_SIZE-1))
799
- )
800
 
801
- print(f"Original BBox: [{bbox_x1}, {bbox_y1}, {bbox_x2}, {bbox_y2}] -> Pipeline BBox: {pipeline_bbox}")
 
 
802
 
803
- # Erstelle Maske basierend auf skalierten Koordinaten
804
- mask = create_face_mask(img_resized, pipeline_bbox, mode)
805
- if mask:
806
- print(f"✅ Maske erstellt für Modus: {mode}")
807
 
808
- from diffusers import EulerAncestralDiscreteScheduler
809
- if not isinstance(pipe.scheduler, EulerAncestralDiscreteScheduler):
810
- pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
811
 
812
  callback = ImageToImageProgressCallback(progress, int(steps), adj_strength)
813
 
@@ -830,6 +824,7 @@ def img_to_image(image, prompt, neg_prompt, strength, steps, guidance_scale,
830
  print(f"✅ Transformation abgeschlossen in {duration:.2f} Sekunden")
831
  print(f"🎯 Verwendeter Modus: {mode}")
832
  print(f"⚙️ ControlNet: {'Depth+Canny' if keep_environment else 'OpenPose+Canny'}")
 
833
 
834
  generated_image = result.images[0]
835
  return generated_image
@@ -856,7 +851,7 @@ def update_model_settings(model_id):
856
  return (
857
  config["recommended_steps"], # steps
858
  config["recommended_cfg"], # guidance_scale
859
- f"📊 Empfohlene Einstellungen: {config['steps']} Steps, CFG {config['cfg']}"
860
  )
861
 
862
  def main_ui():
 
56
  if any(w in p for w in [
57
  "person", "man", "woman", "face", "portrait", "team", "employee",
58
  "people", "crowd", "character", "figure", "human", "child", "baby",
59
+ "girl", "boy", "lady", "gentleman", "fairy", "elf", "dwarf", "santa claus",
60
  "mermaid", "angel", "demon", "witch", "wizard", "creature", "being",
61
  "model", "actor", "actress", "celebrity", "avatar", "group"]):
62
  negatives.append(
 
336
  raise
337
 
338
  def load_img2img():
339
+ """Lädt das Inpainting-Modell mit DPMSolver++ Scheduler"""
340
  global pipe_img2img
341
  if pipe_img2img is None:
342
+ print("🔄 Lade Inpainting-Modell...")
343
  try:
344
  pipe_img2img = StableDiffusionInpaintPipeline.from_pretrained(
345
  "runwayml/stable-diffusion-inpainting",
 
347
  allow_pickle=False,
348
  safety_checker=None,
349
  ).to(device)
350
+
351
+ # WICHTIG: Behalte DPMSolver++ Scheduler bei (beste Qualität für Inpainting)
352
+ pipe_img2img.scheduler = DPMSolverMultistepScheduler.from_config(
353
+ pipe_img2img.scheduler.config,
354
+ algorithm_type="sde-dpmsolver++",
355
+ use_karras_sigmas=True,
356
+ timestep_spacing="trailing"
357
+ )
358
+
359
+ print("✅ DPMSolver++ Multistep Scheduler für Inpainting konfiguriert")
360
+
361
  except Exception as e:
362
+ print(f"Fehler beim Laden des Inpainting-Modells: {e}")
363
  raise
364
 
 
 
 
 
 
 
 
 
365
  pipe_img2img.enable_attention_slicing()
366
  pipe_img2img.enable_vae_tiling()
367
  if hasattr(pipe_img2img, 'vae_slicing'):
368
  pipe_img2img.vae_slicing = True
369
+ print("✅ Inpainting-Modell geladen und optimiert")
370
 
371
  return pipe_img2img
372
 
 
772
 
773
  pipe = load_img2img()
774
 
775
+ # ===== RICHTIGE BILD-SKALIERUNG =====
776
+ # Prüfe ob ControlNet schon 512×512 liefert
777
+ if inpaint_input.size != (512, 512):
778
+ img_resized = inpaint_input.convert("RGB").resize((512, 512), Image.Resampling.LANCZOS)
779
+ print("🔄 ControlNet Output von {} auf 512×512 skaliert".format(inpaint_input.size))
780
+ else:
781
+ img_resized = inpaint_input.convert("RGB")
782
+ print("✅ ControlNet Output ist bereits 512×512")
783
 
784
  adj_guidance = min(guidance_scale, 12.0)
785
  seed = random.randint(0, 2**32 - 1)
786
  generator = torch.Generator(device=device).manual_seed(seed)
787
  print(f"🌱 Inpaint Seed: {seed}")
788
 
789
+ # ===== RICHTIGE MASKEN-ERSTELLUNG (FIX: KEINE DOPPELTE SKALIERUNG) =====
790
  mask = None
791
  if bbox_x1 is not None and bbox_y1 is not None and bbox_x2 is not None and bbox_y2 is not None:
792
+ # 1. Maske AUF ORIGINAL-BILD erstellen (korrekte Proportionen)
793
+ original_mask = create_face_mask(image, (bbox_x1, bbox_y1, bbox_x2, bbox_y2), mode)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
794
 
795
+ # 2. Maske auf 512×512 skalieren (gleicher Algorithmus wie Bild)
796
+ # WICHTIG: NEAREST für scharfe Kanten, da Maske binär ist
797
+ mask = original_mask.resize((512, 512), Image.Resampling.NEAREST)
798
 
799
+ print(f"✅ Maske erstellt für Modus: {mode}")
800
+ print(f" Original BBox: [{bbox_x1}, {bbox_y1}, {bbox_x2}, {bbox_y2}]")
801
+ print(f" Maske skaliert von {original_mask.size} auf {mask.size}")
 
802
 
803
+ # WICHTIG: KEINE SCHEDULER-ÄNDERUNG MEHR - DPMSolver++ bleibt aktiv
804
+ print(f"✅ Verwende DPMSolver++ Scheduler: {type(pipe.scheduler).__name__}")
 
805
 
806
  callback = ImageToImageProgressCallback(progress, int(steps), adj_strength)
807
 
 
824
  print(f"✅ Transformation abgeschlossen in {duration:.2f} Sekunden")
825
  print(f"🎯 Verwendeter Modus: {mode}")
826
  print(f"⚙️ ControlNet: {'Depth+Canny' if keep_environment else 'OpenPose+Canny'}")
827
+ print(f"⚙️ Scheduler: DPMSolver++ (optimal für Inpainting)")
828
 
829
  generated_image = result.images[0]
830
  return generated_image
 
851
  return (
852
  config["recommended_steps"], # steps
853
  config["recommended_cfg"], # guidance_scale
854
+ f"📊 Empfohlene Einstellungen: {config['recommended_steps']} Steps, CFG {config['recommended_cfg']}"
855
  )
856
 
857
  def main_ui():