Update app.py
Browse files
app.py
CHANGED
|
@@ -244,7 +244,7 @@ def scale_image_and_mask_together(image, mask, target_size=512, bbox_coords=None
|
|
| 244 |
return padded_image, padded_mask, padding_info
|
| 245 |
|
| 246 |
|
| 247 |
-
|
| 248 |
def enhanced_composite_with_sam(original_image, inpaint_result, original_mask,
|
| 249 |
padding_info, bbox_coords, mode):
|
| 250 |
"""
|
|
@@ -437,139 +437,6 @@ def enhanced_composite_with_sam(original_image, inpaint_result, original_mask,
|
|
| 437 |
return final_image.convert("RGB")
|
| 438 |
|
| 439 |
|
| 440 |
-
# Composition Workflow nach Ausgabe ControlnetInpaint-Pipeline
|
| 441 |
-
def enhanced_composite_with_sam(original_image, inpaint_result, original_mask,
|
| 442 |
-
padding_info, bbox_coords, mode):
|
| 443 |
-
"""
|
| 444 |
-
COMPOSITING MIT SAM-MASKEN UND BBox-KOORDINATEN
|
| 445 |
-
Berücksichtigt die präzisen Kanten der SAM-Maske
|
| 446 |
-
"""
|
| 447 |
-
print(f"🎨 Verbessertes Compositing für Modus: {mode}")
|
| 448 |
-
|
| 449 |
-
# Extrahiere Padding-Info
|
| 450 |
-
x_offset = padding_info['x_offset']
|
| 451 |
-
y_offset = padding_info['y_offset']
|
| 452 |
-
scaled_width = padding_info['scaled_width']
|
| 453 |
-
scaled_height = padding_info['scaled_height']
|
| 454 |
-
scale_factor = padding_info['scale_factor']
|
| 455 |
-
original_width = padding_info['original_width']
|
| 456 |
-
original_height = padding_info['original_height']
|
| 457 |
-
|
| 458 |
-
# ==============================================
|
| 459 |
-
# FALL 1: Bild war bereits 512×512 (keine Skalierung)
|
| 460 |
-
# ==============================================
|
| 461 |
-
if scale_factor == 1.0 and x_offset == 0 and y_offset == 0:
|
| 462 |
-
print(f"✅ FALL 1: Bild 512×512 - kein Compositing nötig")
|
| 463 |
-
return inpaint_result
|
| 464 |
-
|
| 465 |
-
# ==============================================
|
| 466 |
-
# FALL 2 & 3: Bild wurde skaliert
|
| 467 |
-
# ==============================================
|
| 468 |
-
print(f"🔄 FALL 2/3: Bild skaliert - Compositing mit SAM-Maske")
|
| 469 |
-
|
| 470 |
-
# 1. PADDING ENTFERNEN von 512×512 Ergebnis
|
| 471 |
-
downscaled_result = inpaint_result.crop(
|
| 472 |
-
(x_offset, y_offset, x_offset + scaled_width, y_offset + scaled_height)
|
| 473 |
-
)
|
| 474 |
-
|
| 475 |
-
# 2. AUF ORIGINALGRÖßE SKALIEREN
|
| 476 |
-
final_image = original_image.copy()
|
| 477 |
-
|
| 478 |
-
if mode == "environment_change":
|
| 479 |
-
# ==============================================
|
| 480 |
-
# MODUS: UMWELT ÄNDERN (Objekt bleibt original)
|
| 481 |
-
# In dem Fall muß die BBox nicht berücksichtigt werden da Originalbild ausgeschnitten wird
|
| 482 |
-
# anhand der SAM-Maske
|
| 483 |
-
# ==============================================
|
| 484 |
-
print("🌳 Modus: Umwelt ändern mit SAM-Maske")
|
| 485 |
-
|
| 486 |
-
# Gesamtes bearbeitetes Bild hochskalieren
|
| 487 |
-
new_background = downscaled_result.resize(
|
| 488 |
-
(original_width, original_height),
|
| 489 |
-
Image.Resampling.LANCZOS
|
| 490 |
-
)
|
| 491 |
-
|
| 492 |
-
# Originalbild mit SAM-Maske einfügen
|
| 493 |
-
original_with_alpha = original_image.copy().convert("RGBA")
|
| 494 |
-
|
| 495 |
-
# Invertierte Maske für Objekterhalt
|
| 496 |
-
mask_inverted = Image.eval(original_mask, lambda x: 255 - x)
|
| 497 |
-
|
| 498 |
-
# Weiche Kanten für natürlichen Übergang
|
| 499 |
-
soft_mask = mask_inverted.filter(ImageFilter.GaussianBlur(3))
|
| 500 |
-
original_with_alpha.putalpha(soft_mask)
|
| 501 |
-
|
| 502 |
-
# Compositing
|
| 503 |
-
final_image = new_background.copy().convert("RGBA")
|
| 504 |
-
final_image.paste(original_with_alpha, (0, 0), original_with_alpha)
|
| 505 |
-
|
| 506 |
-
else:
|
| 507 |
-
# ==============================================
|
| 508 |
-
# MODUS: FOCUS oder GESICHT ÄNDERN
|
| 509 |
-
# Hier muß die BBox berücksichtigt werden da generiertes Bild ausgeschnitten wird
|
| 510 |
-
# ohne die BBox wird entlang der SAM-Maske geschnitten -> ungenau!
|
| 511 |
-
# ==============================================
|
| 512 |
-
mode_name = "Focus" if mode == "focus_change" else "Gesicht"
|
| 513 |
-
print(f"👤 Modus: {mode_name} ändern mit SAM-Maske")
|
| 514 |
-
|
| 515 |
-
if not bbox_coords or not all(c is not None for c in bbox_coords):
|
| 516 |
-
# Keine BBox: gesamtes Bild zurückgeben
|
| 517 |
-
final_image = downscaled_result.resize(
|
| 518 |
-
(original_width, original_height),
|
| 519 |
-
Image.Resampling.LANCZOS
|
| 520 |
-
)
|
| 521 |
-
return final_image.convert("RGB")
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
#BBox-Koordinaten korrekt transformieren
|
| 525 |
-
#Die BBox-Koordinaten müssen vom Originalbild nach 512x512 transformiert werden
|
| 526 |
-
bbox_scaled = (
|
| 527 |
-
int(bbox_coords[0] * scale_factor),
|
| 528 |
-
int(bbox_coords[1] * scale_factor),
|
| 529 |
-
int(bbox_coords[2] * scale_factor),
|
| 530 |
-
int(bbox_coords[3] * scale_factor)
|
| 531 |
-
)
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
#Mit den Padding-Offsets wird bei nicht quadratischen 512x512 Bildern
|
| 535 |
-
#das Padding hinzugefügt
|
| 536 |
-
bbox_in_512 = (
|
| 537 |
-
bbox_scaled[0] + x_offset,
|
| 538 |
-
bbox_scaled[1] + y_offset,
|
| 539 |
-
bbox_scaled[2] + x_offset,
|
| 540 |
-
bbox_scaled[3] + y_offset
|
| 541 |
-
)
|
| 542 |
-
|
| 543 |
-
if bbox_in_512[2] > bbox_in_512[0] and bbox_in_512[3] > bbox_in_512[1]:
|
| 544 |
-
# Bearbeiteten Bereich aus dem 512×512-Ergebnis ausschneiden
|
| 545 |
-
edited_region = inpaint_result.crop(bbox_in_512)
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
# Auf ORIGINAL-BBox-Größe skalieren
|
| 549 |
-
original_bbox_size = (bbox_coords[2] - bbox_coords[0],
|
| 550 |
-
bbox_coords[3] - bbox_coords[1])
|
| 551 |
-
edited_region_fullsize = edited_region.resize(
|
| 552 |
-
original_bbox_size,
|
| 553 |
-
Image.Resampling.LANCZOS
|
| 554 |
-
)
|
| 555 |
-
|
| 556 |
-
# SAM-Maske für den Bereich zuschneiden und weichzeichnen
|
| 557 |
-
mask_cropped = original_mask.crop(bbox_coords)
|
| 558 |
-
soft_mask = mask_cropped.filter(ImageFilter.GaussianBlur(3))
|
| 559 |
-
|
| 560 |
-
# Alpha-Compositing mit präziser SAM-Maske
|
| 561 |
-
edited_rgba = edited_region_fullsize.convert("RGBA")
|
| 562 |
-
mask_rgba = soft_mask.convert("L") # SAM-Maske als Alpha-Kanal
|
| 563 |
-
|
| 564 |
-
temp_image = Image.new("RGBA", original_bbox_size, (0, 0, 0, 0))
|
| 565 |
-
temp_image.paste(edited_rgba, (0, 0), mask_rgba)
|
| 566 |
-
|
| 567 |
-
final_image.paste(temp_image, (bbox_coords[0], bbox_coords[1]), temp_image)
|
| 568 |
-
|
| 569 |
-
print(f"✅ Korrektes Compositing abgeschlossen. Finale Größe: {final_image.size}")
|
| 570 |
-
|
| 571 |
-
return final_image.convert("RGB")
|
| 572 |
-
|
| 573 |
|
| 574 |
def auto_detect_face_area(image):
|
| 575 |
"""Optimierten Vorschlag für Gesichtsbereich ohne externe Bibliotheken"""
|
|
|
|
| 244 |
return padded_image, padded_mask, padding_info
|
| 245 |
|
| 246 |
|
| 247 |
+
# Composition Workflow nach Ausgabe ControlnetInpaint-Pipeline
|
| 248 |
def enhanced_composite_with_sam(original_image, inpaint_result, original_mask,
|
| 249 |
padding_info, bbox_coords, mode):
|
| 250 |
"""
|
|
|
|
| 437 |
return final_image.convert("RGB")
|
| 438 |
|
| 439 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 440 |
|
| 441 |
def auto_detect_face_area(image):
|
| 442 |
"""Optimierten Vorschlag für Gesichtsbereich ohne externe Bibliotheken"""
|