from fastapi import FastAPI, UploadFile, File from fastapi.responses import HTMLResponse, StreamingResponse, JSONResponse from fastapi.middleware.cors import CORSMiddleware from PIL import Image from simple_lama_inpainting import SimpleLama import io import numpy as np import cv2 import uvicorn app = FastAPI(title="LaMa Object Remover - Clean Removal") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Initialize LaMa with optimal settings lama = SimpleLama() def preprocess_mask(mask_pil, target_size=None): """Preprocess mask for better inpainting results""" # Convert to numpy array mask_np = np.array(mask_pil) # Ensure binary mask mask_np = (mask_np > 128).astype(np.uint8) * 255 # Apply morphological operations to clean mask kernel = np.ones((3,3), np.uint8) mask_np = cv2.morphologyEx(mask_np, cv2.MORPH_CLOSE, kernel) mask_np = cv2.morphologyEx(mask_np, cv2.MORPH_OPEN, kernel) # Dilate mask slightly for better edge detection kernel = np.ones((5,5), np.uint8) mask_np = cv2.dilate(mask_np, kernel, iterations=1) # Apply Gaussian blur to mask edges for smoother transitions mask_np = cv2.GaussianBlur(mask_np, (5,5), 0) mask_np = (mask_np > 128).astype(np.uint8) * 255 # Ensure same dimensions as target if specified if target_size: mask_pil_resized = Image.fromarray(mask_np) mask_pil_resized = mask_pil_resized.resize(target_size, Image.Resampling.LANCZOS) mask_np = np.array(mask_pil_resized) return Image.fromarray(mask_np) def resize_to_match(img1, img2): """Resize images to match dimensions""" # Get dimensions w1, h1 = img1.size w2, h2 = img2.size # If dimensions don't match, resize to smaller dimensions if w1 != w2 or h1 != h2: target_width = min(w1, w2) target_height = min(h1, h2) # Resize both images to same dimensions img1 = img1.resize((target_width, target_height), Image.Resampling.LANCZOS) img2 = img2.resize((target_width, target_height), Image.Resampling.LANCZOS) return img1, img2 def postprocess_result(result_pil, original_pil, mask_pil): """Post-process result for cleaner output""" # Ensure dimensions match result_pil, original_pil = resize_to_match(result_pil, original_pil) result_np = np.array(result_pil) original_np = np.array(original_pil) mask_np = np.array(mask_pil.convert('L')) # Ensure mask dimensions match if mask_np.shape[:2] != result_np.shape[:2]: mask_pil_resized = Image.fromarray(mask_np) mask_pil_resized = mask_pil_resized.resize((result_np.shape[1], result_np.shape[0]), Image.Resampling.LANCZOS) mask_np = np.array(mask_pil_resized) # Create a blending mask for edges mask_blur = cv2.GaussianBlur(mask_np, (15,15), 0) mask_blur = mask_blur / 255.0 # Extend mask to 3 channels if len(mask_blur.shape) == 2: mask_3ch = np.stack([mask_blur, mask_blur, mask_blur], axis=2) else: mask_3ch = mask_blur # Blend result with original at edges for smoother transitions blended = (result_np * mask_3ch + original_np * (1 - mask_3ch)).astype(np.uint8) return Image.fromarray(blended) HTML = """
Clean removal - No blur, No mess - Professional results
๐ค AI is removing objects with LaMa inpainting...
This may take 5-10 seconds for best quality