LogicGoInfotechSpaces commited on
Commit
91da7a0
·
1 Parent(s): 437b94f

feat(api): add /remove-pink endpoint - simple one-parameter endpoint that auto-detects pink segments and removes them

Browse files
Files changed (1) hide show
  1. api/main.py +88 -0
api/main.py CHANGED
@@ -57,6 +57,10 @@ class InpaintRequest(BaseModel):
57
  passthrough: bool = False # If True, return the original image unchanged
58
 
59
 
 
 
 
 
60
  @app.get("/")
61
  def root() -> Dict[str, object]:
62
  return {
@@ -359,6 +363,90 @@ def inpaint_multipart(
359
  return resp
360
 
361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  @app.get("/download/{filename}")
363
  def download_file(filename: str):
364
  path = os.path.join(OUTPUT_DIR, filename)
 
57
  passthrough: bool = False # If True, return the original image unchanged
58
 
59
 
60
+ class SimpleRemoveRequest(BaseModel):
61
+ image_id: str # Image with pink/magenta segments to remove
62
+
63
+
64
  @app.get("/")
65
  def root() -> Dict[str, object]:
66
  return {
 
363
  return resp
364
 
365
 
366
+ @app.post("/remove-pink")
367
+ def remove_pink_segments(
368
+ image: UploadFile = File(...),
369
+ request: Request = None,
370
+ _: None = Depends(bearer_auth),
371
+ ) -> Dict[str, str]:
372
+ """
373
+ Simple endpoint: just upload an image with pink/magenta segments you want to remove.
374
+ The API automatically detects pink areas and removes them, keeping everything else.
375
+ """
376
+ log.info(f"Simple remove-pink: processing image {image.filename}")
377
+
378
+ # Load the image (with pink paint on it)
379
+ img = Image.open(image.file).convert("RGBA")
380
+ img_rgb = cv2.cvtColor(np.array(img), cv2.COLOR_RGBA2RGB)
381
+
382
+ # Auto-detect pink/magenta segments
383
+ magenta_detected = (
384
+ (img_rgb[:, :, 0] > 240) & # Red: high
385
+ (img_rgb[:, :, 1] < 30) & # Green: low
386
+ (img_rgb[:, :, 2] > 240) # Blue: high
387
+ ).astype(np.uint8) * 255
388
+
389
+ # Clean up the mask
390
+ kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
391
+ binmask = cv2.morphologyEx(magenta_detected, cv2.MORPH_CLOSE, kernel, iterations=2)
392
+ binmask = cv2.morphologyEx(binmask, cv2.MORPH_OPEN, kernel, iterations=1)
393
+
394
+ nonzero = int((binmask > 0).sum())
395
+ log.info(f"Detected {nonzero} pink pixels to remove")
396
+
397
+ if nonzero < 50:
398
+ log.warning("Very few pink pixels detected! Trying strict magenta detection...")
399
+ magenta_strict = np.all(img_rgb == [255, 0, 255], axis=2).astype(np.uint8) * 255
400
+ binmask = cv2.morphologyEx(magenta_strict, cv2.MORPH_CLOSE, kernel, iterations=3)
401
+ nonzero = int((binmask > 0).sum())
402
+ log.info(f"Strict detection: {nonzero} pixels")
403
+
404
+ if nonzero < 50:
405
+ log.error("No pink segments detected! Returning original image.")
406
+ result = np.array(img.convert("RGB"))
407
+ result_name = f"output_{uuid.uuid4().hex}.png"
408
+ result_path = os.path.join(OUTPUT_DIR, result_name)
409
+ Image.fromarray(result).save(result_path)
410
+ return {
411
+ "result": result_name,
412
+ "error": "No pink/magenta segments detected. Please paint areas to remove with magenta/pink color (RGB 255,0,255)."
413
+ }
414
+
415
+ # Create mask: white = pink areas (remove), black = everything else (keep)
416
+ mask_rgba = np.zeros((binmask.shape[0], binmask.shape[1], 4), dtype=np.uint8)
417
+ mask_rgba[:, :, 0] = binmask # R
418
+ mask_rgba[:, :, 1] = binmask # G
419
+ mask_rgba[:, :, 2] = binmask # B
420
+ mask_rgba[:, :, 3] = 255 # Alpha
421
+
422
+ log.info(f"Created mask: {nonzero} white pixels (remove), {binmask.shape[0]*binmask.shape[1]-nonzero} black pixels (keep)")
423
+
424
+ # Process with invert_mask=False because white pixels = remove (standard)
425
+ result = process_inpaint(np.array(img), mask_rgba, invert_mask=False)
426
+ result_name = f"output_{uuid.uuid4().hex}.png"
427
+ result_path = os.path.join(OUTPUT_DIR, result_name)
428
+ Image.fromarray(result).save(result_path)
429
+
430
+ url: Optional[str] = None
431
+ try:
432
+ if request is not None:
433
+ url = str(request.url_for("download_file", filename=result_name))
434
+ except Exception:
435
+ url = None
436
+
437
+ logs.append({
438
+ "result": result_name,
439
+ "filename": image.filename,
440
+ "pink_pixels": nonzero,
441
+ "timestamp": datetime.utcnow().isoformat()
442
+ })
443
+
444
+ resp: Dict[str, str] = {"result": result_name, "pink_segments_detected": str(nonzero)}
445
+ if url:
446
+ resp["url"] = url
447
+ return resp
448
+
449
+
450
  @app.get("/download/{filename}")
451
  def download_file(filename: str):
452
  path = os.path.join(OUTPUT_DIR, filename)