Astridkraft commited on
Commit
c4ecf92
·
verified ·
1 Parent(s): fe8ed41

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -100
app.py CHANGED
@@ -235,151 +235,152 @@ def scale_image_and_mask_together(image, mask, target_size=512):
235
 
236
  return padded_image, padded_mask, padding_info
237
 
238
-
239
  # Composition Workflow nach Ausgabe ControlnetInpaint-Pipeline
240
  def composite_edited_region(original_image, inpaint_result, original_mask, padding_info, bbox_coords=None, mode="environment_change"):
241
  """
242
- KOMPLETT KORRIGIERTER COMPOSITING-WORKFLOW für alle 3 Modi:
243
-
244
- 1. 'environment_change': Original-Focus in bearbeitetes Bild integrieren
245
- 2. 'focus_change'/'face_only_change': Bearbeiteten Bereich in Originalbild integrieren
246
-
247
- Parameter:
248
- - original_image: Originalbild in Originalgröße
249
- - inpaint_result: 512x512 Inpaint-Ergebnis MIT PADDING
250
- - original_mask: Originalmaske (vor Skalierung)
251
- - padding_info: Skalierungsinformationen
252
- - bbox_coords: [x1, y1, x2, y2] oder None
253
- - mode: "environment_change", "focus_change", "face_only_change"
254
-
255
- Returns:
256
- - composited_image: Finales Bild mit korrekt integrierter Region
257
  """
258
  print(f"🎨 Starte Compositing für Modus: {mode}")
 
 
259
 
260
- # 1. PADDING ENTFERNEN (512x512 → herunterskaliertes Bild)
261
  x_offset = padding_info['x_offset']
262
  y_offset = padding_info['y_offset']
263
  scaled_width = padding_info['scaled_width']
264
  scaled_height = padding_info['scaled_height']
265
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  downscaled_result = inpaint_result.crop(
267
  (x_offset, y_offset, x_offset + scaled_width, y_offset + scaled_height)
268
  )
269
  print(f"✅ Padding entfernt: {inpaint_result.size} → {downscaled_result.size}")
270
 
271
- # Herunterskaliertes Originalbild für spätere Verwendung
272
- original_downscaled = original_image.resize(
273
- (scaled_width, scaled_height),
274
- Image.Resampling.LANCZOS
275
- )
276
 
277
- # 2. MODUS-SPEZIFISCHE VORBEREITUNG
278
  if mode == "environment_change":
279
  # ==============================================
280
  # MODUS: UMWELT ÄNDERN (Focus bleibt original)
281
  # ==============================================
282
- print("🔄 Modus: Umwelt ändern - Original-Focus in bearbeitetes Bild integrieren")
 
 
 
283
 
 
284
  if bbox_coords and all(c is not None for c in bbox_coords):
285
  x1, y1, x2, y2 = bbox_coords
286
 
287
- # BBox-Bereiche für herunterskalierte Bilder berechnen
288
- scale_factor = padding_info['scale_factor']
289
- bbox_downscaled = (
290
  int(x1 * scale_factor),
291
  int(y1 * scale_factor),
292
  int(x2 * scale_factor),
293
  int(y2 * scale_factor)
294
  )
295
 
296
- # Original-Focus-Bereich ausschneiden
297
- original_focus = original_downscaled.crop(bbox_downscaled)
 
 
 
 
298
 
299
- # Original-Focus in das bearbeitete Bild einfügen
300
- # (überschreibt den bearbeiteten BBox-Bereich mit dem Original)
301
- downscaled_result.paste(original_focus, bbox_downscaled[:2])
 
 
 
302
 
303
- print(f"✅ Original-Focus ({bbox_downscaled}) in bearbeitetes Bild integriert")
304
-
305
- # Für Compositing: Das gesamte bearbeitete Bild (jetzt mit Original-Focus) verwenden
306
- edited_region_downscaled = downscaled_result
307
- target_for_compositing = original_image # Wird später überschrieben
308
 
 
 
 
309
  else:
310
  # ==============================================
311
  # MODUS: FOCUS oder GESICHT ÄNDERN
312
  # ==============================================
313
  mode_name = "Focus" if mode == "focus_change" else "Gesicht"
314
- print(f"🔄 Modus: {mode_name} ändern - Bearbeiteten Bereich in Originalbild integrieren")
315
 
316
- if bbox_coords and all(c is not None for c in bbox_coords):
317
- x1, y1, x2, y2 = bbox_coords
318
-
319
- # BBox-Bereich für herunterskaliertes Bild berechnen
320
- scale_factor = padding_info['scale_factor']
321
- bbox_downscaled = (
322
- int(x1 * scale_factor),
323
- int(y1 * scale_factor),
324
- int(x2 * scale_factor),
325
- int(y2 * scale_factor)
326
- )
327
-
328
- # Bearbeiteten BBox-Bereich ausschneiden
329
- edited_region_downscaled = downscaled_result.crop(bbox_downscaled)
330
- print(f"✅ Bearbeiteten {mode_name}-Bereich ausgeschnitten: {bbox_downscaled}")
331
- else:
332
- # Fallback: gesamtes Bild verwenden
333
- edited_region_downscaled = downscaled_result
334
 
335
- target_for_compositing = original_image
336
-
337
- # 3. HOCHSKALIEREN auf Originalgröße
338
- original_size = (padding_info['original_width'], padding_info['original_height'])
339
-
340
- if mode == "environment_change":
341
- # Das gesamte bearbeitete Bild (mit Original-Focus) hochskalieren
342
- edited_region_fullsize = edited_region_downscaled.resize(
343
- original_size,
344
- Image.Resampling.LANCZOS
345
  )
346
- print(f"✅ Komplettes Bild auf Originalgröße skaliert: {edited_region_fullsize.size}")
347
 
348
- # Bei environment_change ist das Ergebnis bereits komplett
349
- return edited_region_fullsize.convert("RGB")
350
-
351
- else:
352
- # Nur den bearbeiteten BBox-Bereich hochskalieren
353
- edited_region_fullsize = edited_region_downscaled.resize(
354
- original_size,
 
355
  Image.Resampling.LANCZOS
356
  )
357
- print(f"✅ Bearbeiteter Bereich auf Originalgröße skaliert: {edited_region_fullsize.size}")
358
-
359
- # 4. COMPOSITING mit weicher Maske (nur für focus_change/face_only_change)
360
- # Weiche Maske erstellen für sanfte Übergänge
361
- from PIL import ImageFilter
362
-
363
- soft_mask = original_mask.copy()
364
- soft_mask = soft_mask.filter(ImageFilter.MaxFilter(5)) # Maske leicht erweitern
365
- soft_mask = soft_mask.filter(ImageFilter.GaussianBlur(3)) # Weiche Kanten
366
-
367
- # Alpha-Blending vorbereiten
368
- final_image = original_image.copy()
369
- edited_rgba = edited_region_fullsize.convert("RGBA")
370
- soft_mask_rgba = soft_mask.convert("L")
371
-
372
- # Temporäres Bild mit Alpha-Kanal
373
- temp_image = Image.new("RGBA", original_size, (0, 0, 0, 0))
374
- temp_image.paste(edited_rgba, (0, 0), soft_mask_rgba)
375
-
376
- # Finales Compositing
377
- final_image = Image.alpha_composite(final_image.convert("RGBA"), temp_image)
378
- final_image = final_image.convert("RGB")
379
 
380
- print(f"✅ Compositing abgeschlossen. Finale Größe: {final_image.size}")
381
- return final_image
382
-
383
 
384
  def auto_detect_face_area(image):
385
  """Optimierten Vorschlag für Gesichtsbereich ohne externe Bibliotheken"""
 
235
 
236
  return padded_image, padded_mask, padding_info
237
 
238
+
239
  # Composition Workflow nach Ausgabe ControlnetInpaint-Pipeline
240
  def composite_edited_region(original_image, inpaint_result, original_mask, padding_info, bbox_coords=None, mode="environment_change"):
241
  """
242
+ OPTIMIERTER COMPOSITING-WORKFLOW für alle Bildgrößen
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  """
244
  print(f"🎨 Starte Compositing für Modus: {mode}")
245
+ print(f"📏 Originalgröße: {original_image.size}")
246
+ print(f"📏 Inpaint-Result-Größe: {inpaint_result.size}")
247
 
248
+ # Extrahiere Padding-Info
249
  x_offset = padding_info['x_offset']
250
  y_offset = padding_info['y_offset']
251
  scaled_width = padding_info['scaled_width']
252
  scaled_height = padding_info['scaled_height']
253
+ scale_factor = padding_info['scale_factor']
254
+ original_width = padding_info['original_width']
255
+ original_height = padding_info['original_height']
256
+
257
+ print(f"📊 Skalierungsfaktor: {scale_factor:.4f}")
258
+ print(f"📊 Offsets: x={x_offset}, y={y_offset}")
259
+ print(f"📊 Skalierte Größe: {scaled_width}x{scaled_height}")
260
+
261
+ if bbox_coords:
262
+ print(f"🎯 BBox Original: {bbox_coords}")
263
+
264
+ # ==============================================
265
+ # FALL 1: Bild war bereits 512×512 (keine Skalierung, kein Padding)
266
+ # ControlNet-Inpaint hat bereits komplettes Bild bearbeitet
267
+ # ==============================================
268
+ if scale_factor == 1.0 and x_offset == 0 and y_offset == 0:
269
+ print(f"✅ FALL 1: Bild 512×512 - direktes ControlNet-Inpaint Result")
270
+ print(f" Kein Compositing nötig für {mode}")
271
+ return inpaint_result
272
+
273
+ # ==============================================
274
+ # FALL 2 & 3: Bild wurde skaliert (größer/kleiner als 512×512)
275
+ # ==============================================
276
+ print(f"🔄 FALL 2/3: Bild skaliert - Compositing Workflow")
277
+
278
+ # 1. PADDING ENTFERNEN von 512×512 Ergebnis
279
  downscaled_result = inpaint_result.crop(
280
  (x_offset, y_offset, x_offset + scaled_width, y_offset + scaled_height)
281
  )
282
  print(f"✅ Padding entfernt: {inpaint_result.size} → {downscaled_result.size}")
283
 
284
+ # 2. MODUS-SPEZIFISCHE LOGIK
285
+ original_size = (original_width, original_height)
 
 
 
286
 
 
287
  if mode == "environment_change":
288
  # ==============================================
289
  # MODUS: UMWELT ÄNDERN (Focus bleibt original)
290
  # ==============================================
291
+ print("🌳 Modus: Umwelt ändern")
292
+
293
+ # Gesamtes bearbeitetes Bild hochskalieren
294
+ final_image = downscaled_result.resize(original_size, Image.Resampling.LANCZOS)
295
 
296
+ # Original-Focus zurück einfügen
297
  if bbox_coords and all(c is not None for c in bbox_coords):
298
  x1, y1, x2, y2 = bbox_coords
299
 
300
+ # Skalierte BBox berechnen
301
+ bbox_scaled = (
 
302
  int(x1 * scale_factor),
303
  int(y1 * scale_factor),
304
  int(x2 * scale_factor),
305
  int(y2 * scale_factor)
306
  )
307
 
308
+ # Original-Focus ausschneiden (von original_downscaled)
309
+ original_downscaled = original_image.resize(
310
+ (scaled_width, scaled_height),
311
+ Image.Resampling.LANCZOS
312
+ )
313
+ original_focus = original_downscaled.crop(bbox_scaled)
314
 
315
+ # Focus auf Originalgröße skalieren
316
+ focus_original_size = (x2 - x1, y2 - y1)
317
+ original_focus_fullsize = original_focus.resize(
318
+ focus_original_size,
319
+ Image.Resampling.LANCZOS
320
+ )
321
 
322
+ # In finales Bild einfügen
323
+ final_image.paste(original_focus_fullsize, (x1, y1))
324
+ print(f"✅ Original-Focus eingefügt: {bbox_scaled} {x1},{y1}")
 
 
325
 
326
+ print(f"✅ Finales Bild: {final_image.size}")
327
+ return final_image.convert("RGB")
328
+
329
  else:
330
  # ==============================================
331
  # MODUS: FOCUS oder GESICHT ÄNDERN
332
  # ==============================================
333
  mode_name = "Focus" if mode == "focus_change" else "Gesicht"
334
+ print(f"👤 Modus: {mode_name} ändern")
335
 
336
+ if not bbox_coords or not all(c is not None for c in bbox_coords):
337
+ # Keine BBox: gesamtes Bild zurückgeben
338
+ final_image = downscaled_result.resize(original_size, Image.Resampling.LANCZOS)
339
+ print(f"⚠️ Keine BBox - gesamtes Bild skaliert")
340
+ return final_image.convert("RGB")
 
 
 
 
 
 
 
 
 
 
 
 
 
341
 
342
+ x1, y1, x2, y2 = bbox_coords
343
+
344
+ # Skalierte BBox für downscaled_result
345
+ bbox_scaled = (
346
+ int(x1 * scale_factor),
347
+ int(y1 * scale_factor),
348
+ int(x2 * scale_factor),
349
+ int(y2 * scale_factor)
 
 
350
  )
 
351
 
352
+ # Bearbeiteten Bereich ausschneiden
353
+ edited_region = downscaled_result.crop(bbox_scaled)
354
+ print(f"✅ Bearbeiteter Bereich: {bbox_scaled} → {edited_region.size}")
355
+
356
+ # Auf ORIGINAL-BBox-Größe skalieren (nicht Gesamtbild!)
357
+ original_bbox_size = (x2 - x1, y2 - y1)
358
+ edited_region_fullsize = edited_region.resize(
359
+ original_bbox_size,
360
  Image.Resampling.LANCZOS
361
  )
362
+ print(f"✅ Auf BBox-Größe skaliert: {edited_region.size} → {edited_region_fullsize.size}")
363
+
364
+ # 3. COMPOSITING mit weicher Maske
365
+ from PIL import ImageFilter
366
+
367
+ # Maske zuschneiden und weichzeichnen
368
+ mask_cropped = original_mask.crop((x1, y1, x2, y2))
369
+ soft_mask = mask_cropped.filter(ImageFilter.GaussianBlur(3))
370
+
371
+ # Alpha-Compositing
372
+ final_image = original_image.copy()
373
+ edited_rgba = edited_region_fullsize.convert("RGBA")
374
+ mask_rgba = soft_mask.convert("L")
375
+
376
+ temp_image = Image.new("RGBA", original_bbox_size, (0, 0, 0, 0))
377
+ temp_image.paste(edited_rgba, (0, 0), mask_rgba)
378
+
379
+ final_image.paste(temp_image, (x1, y1), temp_image)
380
+
381
+ print(f"✅ Compositing abgeschlossen. Finale Größe: {final_image.size}")
382
+ return final_image.convert("RGB")
 
383
 
 
 
 
384
 
385
  def auto_detect_face_area(image):
386
  """Optimierten Vorschlag für Gesichtsbereich ohne externe Bibliotheken"""