Spaces:
Running
on
T4
Running
on
T4
Commit
·
782a2a8
1
Parent(s):
0e28031
feat: use fixed pink RGB bounds (lower=[150,0,100], upper=[255,120,255]) for /remove-pink and mask_is_painted in /inpaint-multipart; keep white=remove logic
Browse files- api/main.py +19 -35
api/main.py
CHANGED
|
@@ -193,7 +193,7 @@ def inpaint(req: InpaintRequest, _: None = Depends(bearer_auth)) -> Dict[str, st
|
|
| 193 |
img_rgba = _load_rgba_image(file_store[req.image_id]["path"])
|
| 194 |
mask_img = Image.open(file_store[req.mask_id]["path"]) # may be RGB/gray/RGBA
|
| 195 |
mask_rgba = _load_rgba_mask_from_image(mask_img)
|
| 196 |
-
|
| 197 |
# Debug: check mask before processing
|
| 198 |
white_pixels = int((mask_rgba[:,:,0] > 128).sum())
|
| 199 |
log.info(f"Inpaint request: mask has {white_pixels} white pixels, invert_mask={req.invert_mask}")
|
|
@@ -279,12 +279,13 @@ def inpaint_multipart(
|
|
| 279 |
|
| 280 |
m_rgb = cv2.cvtColor(np.array(m), cv2.COLOR_RGBA2RGB)
|
| 281 |
|
| 282 |
-
#
|
| 283 |
-
|
|
|
|
| 284 |
magenta_detected = (
|
| 285 |
-
(m_rgb[:, :, 0]
|
| 286 |
-
(m_rgb[:, :, 1]
|
| 287 |
-
(m_rgb[:, :, 2]
|
| 288 |
).astype(np.uint8) * 255
|
| 289 |
|
| 290 |
# Method 2: Also check if original image was provided to find differences
|
|
@@ -313,13 +314,8 @@ def inpaint_multipart(
|
|
| 313 |
nonzero = int((binmask > 0).sum())
|
| 314 |
log.info("Pink/magenta paint detected: %d pixels marked for removal (white)", nonzero)
|
| 315 |
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
# Try more strict magenta detection (exact match)
|
| 319 |
-
magenta_strict = np.all(m_rgb == [255, 0, 255], axis=2).astype(np.uint8) * 255
|
| 320 |
-
binmask = cv2.morphologyEx(magenta_strict, cv2.MORPH_CLOSE, kernel, iterations=3)
|
| 321 |
-
nonzero = int((binmask > 0).sum())
|
| 322 |
-
log.info("Strict magenta detection: %d pixels", nonzero)
|
| 323 |
|
| 324 |
if nonzero < 50:
|
| 325 |
log.error("CRITICAL: Could not detect pink/magenta paint! Returning original image.")
|
|
@@ -344,7 +340,7 @@ def inpaint_multipart(
|
|
| 344 |
log.info("Successfully created binary mask: %d pink pixels → white (255), %d pixels → black (0)",
|
| 345 |
nonzero, binmask.shape[0] * binmask.shape[1] - nonzero)
|
| 346 |
else:
|
| 347 |
-
|
| 348 |
|
| 349 |
# When mask_is_painted=true, we encode pink as alpha=0, so process_inpaint's default invert_mask=True works correctly
|
| 350 |
actual_invert = invert_mask # Use default True for painted masks
|
|
@@ -394,27 +390,15 @@ def remove_pink_segments(
|
|
| 394 |
# Pink/Magenta → white in mask (remove)
|
| 395 |
# Everything else (natural image colors, including dark areas) → black in mask (keep)
|
| 396 |
|
| 397 |
-
#
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
(img_rgb[:, :,
|
| 402 |
-
(img_rgb[:, :,
|
|
|
|
| 403 |
).astype(np.uint8) * 255
|
| 404 |
|
| 405 |
-
# Method 2: Detect exact magenta (255, 0, 255)
|
| 406 |
-
magenta_strict = np.all(img_rgb == [255, 0, 255], axis=2).astype(np.uint8) * 255
|
| 407 |
-
|
| 408 |
-
# Method 3: Detect pink-ish colors (high red+blue, low green)
|
| 409 |
-
pink_detected = (
|
| 410 |
-
(img_rgb[:, :, 0] > 220) & # Red: very high
|
| 411 |
-
(img_rgb[:, :, 1] < 100) & # Green: low
|
| 412 |
-
(img_rgb[:, :, 2] > 220) # Blue: very high
|
| 413 |
-
).astype(np.uint8) * 255
|
| 414 |
-
|
| 415 |
-
# Combine all detection methods
|
| 416 |
-
binmask = np.maximum.reduce([magenta_detected_loose, magenta_strict, pink_detected])
|
| 417 |
-
|
| 418 |
# Clean up the pink mask
|
| 419 |
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
|
| 420 |
binmask = cv2.morphologyEx(binmask, cv2.MORPH_CLOSE, kernel, iterations=2)
|
|
@@ -424,8 +408,8 @@ def remove_pink_segments(
|
|
| 424 |
total_pixels = binmask.shape[0] * binmask.shape[1]
|
| 425 |
log.info(f"Detected {nonzero} pink pixels ({100*nonzero/total_pixels:.2f}% of image) to remove")
|
| 426 |
|
| 427 |
-
# Debug:
|
| 428 |
-
log.info(
|
| 429 |
|
| 430 |
if nonzero < 50:
|
| 431 |
log.error("No pink segments detected! Returning original image.")
|
|
|
|
| 193 |
img_rgba = _load_rgba_image(file_store[req.image_id]["path"])
|
| 194 |
mask_img = Image.open(file_store[req.mask_id]["path"]) # may be RGB/gray/RGBA
|
| 195 |
mask_rgba = _load_rgba_mask_from_image(mask_img)
|
| 196 |
+
|
| 197 |
# Debug: check mask before processing
|
| 198 |
white_pixels = int((mask_rgba[:,:,0] > 128).sum())
|
| 199 |
log.info(f"Inpaint request: mask has {white_pixels} white pixels, invert_mask={req.invert_mask}")
|
|
|
|
| 279 |
|
| 280 |
m_rgb = cv2.cvtColor(np.array(m), cv2.COLOR_RGBA2RGB)
|
| 281 |
|
| 282 |
+
# Detect pink/magenta using fixed RGB bounds (same as /remove-pink)
|
| 283 |
+
lower = np.array([150, 0, 100], dtype=np.uint8)
|
| 284 |
+
upper = np.array([255, 120, 255], dtype=np.uint8)
|
| 285 |
magenta_detected = (
|
| 286 |
+
(m_rgb[:, :, 0] >= lower[0]) & (m_rgb[:, :, 0] <= upper[0]) &
|
| 287 |
+
(m_rgb[:, :, 1] >= lower[1]) & (m_rgb[:, :, 1] <= upper[1]) &
|
| 288 |
+
(m_rgb[:, :, 2] >= lower[2]) & (m_rgb[:, :, 2] <= upper[2])
|
| 289 |
).astype(np.uint8) * 255
|
| 290 |
|
| 291 |
# Method 2: Also check if original image was provided to find differences
|
|
|
|
| 314 |
nonzero = int((binmask > 0).sum())
|
| 315 |
log.info("Pink/magenta paint detected: %d pixels marked for removal (white)", nonzero)
|
| 316 |
|
| 317 |
+
# If very few pixels detected, assume the user may already be providing a BW mask
|
| 318 |
+
# and proceed without forcing strict detection
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 319 |
|
| 320 |
if nonzero < 50:
|
| 321 |
log.error("CRITICAL: Could not detect pink/magenta paint! Returning original image.")
|
|
|
|
| 340 |
log.info("Successfully created binary mask: %d pink pixels → white (255), %d pixels → black (0)",
|
| 341 |
nonzero, binmask.shape[0] * binmask.shape[1] - nonzero)
|
| 342 |
else:
|
| 343 |
+
mask_rgba = _load_rgba_mask_from_image(m)
|
| 344 |
|
| 345 |
# When mask_is_painted=true, we encode pink as alpha=0, so process_inpaint's default invert_mask=True works correctly
|
| 346 |
actual_invert = invert_mask # Use default True for painted masks
|
|
|
|
| 390 |
# Pink/Magenta → white in mask (remove)
|
| 391 |
# Everything else (natural image colors, including dark areas) → black in mask (keep)
|
| 392 |
|
| 393 |
+
# Detect pink/magenta using fixed RGB bounds per requested logic
|
| 394 |
+
lower = np.array([150, 0, 100], dtype=np.uint8)
|
| 395 |
+
upper = np.array([255, 120, 255], dtype=np.uint8)
|
| 396 |
+
binmask = (
|
| 397 |
+
(img_rgb[:, :, 0] >= lower[0]) & (img_rgb[:, :, 0] <= upper[0]) &
|
| 398 |
+
(img_rgb[:, :, 1] >= lower[1]) & (img_rgb[:, :, 1] <= upper[1]) &
|
| 399 |
+
(img_rgb[:, :, 2] >= lower[2]) & (img_rgb[:, :, 2] <= upper[2])
|
| 400 |
).astype(np.uint8) * 255
|
| 401 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 402 |
# Clean up the pink mask
|
| 403 |
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
|
| 404 |
binmask = cv2.morphologyEx(binmask, cv2.MORPH_CLOSE, kernel, iterations=2)
|
|
|
|
| 408 |
total_pixels = binmask.shape[0] * binmask.shape[1]
|
| 409 |
log.info(f"Detected {nonzero} pink pixels ({100*nonzero/total_pixels:.2f}% of image) to remove")
|
| 410 |
|
| 411 |
+
# Debug: log bounds used
|
| 412 |
+
log.info("Pink detection bounds used: lower=[150,0,100], upper=[255,120,255]")
|
| 413 |
|
| 414 |
if nonzero < 50:
|
| 415 |
log.error("No pink segments detected! Returning original image.")
|