Update api/main.py
Browse files- api/main.py +89 -20
api/main.py
CHANGED
|
@@ -13,6 +13,9 @@ from PIL import Image
|
|
| 13 |
import cv2
|
| 14 |
import logging
|
| 15 |
|
|
|
|
|
|
|
|
|
|
| 16 |
logging.basicConfig(level=logging.INFO)
|
| 17 |
log = logging.getLogger("api")
|
| 18 |
|
|
@@ -39,6 +42,10 @@ app = FastAPI(title="Photo Object Removal API", version="1.0.0")
|
|
| 39 |
file_store: Dict[str, Dict[str, str]] = {}
|
| 40 |
logs: List[Dict[str, str]] = []
|
| 41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
def bearer_auth(authorization: Optional[str] = Header(default=None)) -> None:
|
| 44 |
if not ENV_TOKEN:
|
|
@@ -182,32 +189,94 @@ def _load_rgba_mask_from_image(img: Image.Image) -> np.ndarray:
|
|
| 182 |
log.info(f"Loaded RGBA mask (alpha-based): {int((mask_bw > 0).sum())} white pixels (to remove)")
|
| 183 |
return rgba
|
| 184 |
|
| 185 |
-
|
| 186 |
@app.post("/inpaint")
|
| 187 |
def inpaint(req: InpaintRequest, _: None = Depends(bearer_auth)) -> Dict[str, str]:
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
log.info(f"Inpaint request: mask has {white_pixels} white pixels, invert_mask={req.invert_mask}")
|
| 200 |
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
result = process_inpaint(np.array(img_rgba), mask_rgba, invert_mask=req.invert_mask)
|
| 205 |
-
result_name = f"output_{uuid.uuid4().hex}.png"
|
| 206 |
-
result_path = os.path.join(OUTPUT_DIR, result_name)
|
| 207 |
-
Image.fromarray(result).save(result_path, "PNG", optimize=False, compress_level=1)
|
| 208 |
|
| 209 |
-
|
| 210 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
|
| 212 |
|
| 213 |
@app.post("/inpaint-url")
|
|
|
|
| 13 |
import cv2
|
| 14 |
import logging
|
| 15 |
|
| 16 |
+
from pymongo import MongoClient
|
| 17 |
+
import time
|
| 18 |
+
|
| 19 |
logging.basicConfig(level=logging.INFO)
|
| 20 |
log = logging.getLogger("api")
|
| 21 |
|
|
|
|
| 42 |
file_store: Dict[str, Dict[str, str]] = {}
|
| 43 |
logs: List[Dict[str, str]] = []
|
| 44 |
|
| 45 |
+
MONGO_URI = "mongodb+srv://harilogicgo_db_user:pdnh6UCMsWvuTCoi@kiddoimages.k2a4nuv.mongodb.net/?appName=KiddoImages"
|
| 46 |
+
mongo_client = MongoClient(MONGO_URI)
|
| 47 |
+
mongo_db = mongo_client["object_remover"]
|
| 48 |
+
mongo_logs = mongo_db["api_logs"]
|
| 49 |
|
| 50 |
def bearer_auth(authorization: Optional[str] = Header(default=None)) -> None:
|
| 51 |
if not ENV_TOKEN:
|
|
|
|
| 189 |
log.info(f"Loaded RGBA mask (alpha-based): {int((mask_bw > 0).sum())} white pixels (to remove)")
|
| 190 |
return rgba
|
| 191 |
|
|
|
|
| 192 |
@app.post("/inpaint")
|
| 193 |
def inpaint(req: InpaintRequest, _: None = Depends(bearer_auth)) -> Dict[str, str]:
|
| 194 |
+
start_time = time.time()
|
| 195 |
+
status = "success"
|
| 196 |
+
error_msg = None
|
| 197 |
+
output_name = None
|
| 198 |
|
| 199 |
+
try:
|
| 200 |
+
if req.image_id not in file_store or file_store[req.image_id]["type"] != "image":
|
| 201 |
+
raise HTTPException(status_code=404, detail="image_id not found")
|
| 202 |
|
| 203 |
+
if req.mask_id not in file_store or file_store[req.mask_id]["type"] != "mask":
|
| 204 |
+
raise HTTPException(status_code=404, detail="mask_id not found")
|
|
|
|
| 205 |
|
| 206 |
+
img_rgba = _load_rgba_image(file_store[req.image_id]["path"])
|
| 207 |
+
mask_img = Image.open(file_store[req.mask_id]["path"])
|
| 208 |
+
mask_rgba = _load_rgba_mask_from_image(mask_img)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
|
| 210 |
+
if req.passthrough:
|
| 211 |
+
result = np.array(img_rgba.convert("RGB"))
|
| 212 |
+
else:
|
| 213 |
+
result = process_inpaint(
|
| 214 |
+
np.array(img_rgba),
|
| 215 |
+
mask_rgba,
|
| 216 |
+
invert_mask=req.invert_mask
|
| 217 |
+
)
|
| 218 |
+
|
| 219 |
+
output_name = f"output_{uuid.uuid4().hex}.png"
|
| 220 |
+
output_path = os.path.join(OUTPUT_DIR, output_name)
|
| 221 |
+
|
| 222 |
+
Image.fromarray(result).save(
|
| 223 |
+
output_path, "PNG", optimize=False, compress_level=1
|
| 224 |
+
)
|
| 225 |
+
|
| 226 |
+
return {"result": output_name}
|
| 227 |
+
|
| 228 |
+
except Exception as e:
|
| 229 |
+
status = "fail"
|
| 230 |
+
error_msg = str(e)
|
| 231 |
+
raise
|
| 232 |
+
|
| 233 |
+
finally:
|
| 234 |
+
end_time = time.time()
|
| 235 |
+
response_time_ms = (end_time - start_time) * 1000
|
| 236 |
+
|
| 237 |
+
log_doc = {
|
| 238 |
+
"input_image_id": req.image_id,
|
| 239 |
+
"input_mask_id": req.mask_id,
|
| 240 |
+
"output_id": output_name,
|
| 241 |
+
"status": status,
|
| 242 |
+
"timestamp": datetime.utcnow(),
|
| 243 |
+
"ts": int(time.time()),
|
| 244 |
+
"response_time_ms": response_time_ms
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
if error_msg:
|
| 248 |
+
log_doc["error"] = error_msg
|
| 249 |
+
|
| 250 |
+
try:
|
| 251 |
+
mongo_logs.insert_one(log_doc)
|
| 252 |
+
except Exception as mongo_err:
|
| 253 |
+
log.error(f"Mongo log insert failed: {mongo_err}")
|
| 254 |
+
|
| 255 |
+
# @app.post("/inpaint")
|
| 256 |
+
# def inpaint(req: InpaintRequest, _: None = Depends(bearer_auth)) -> Dict[str, str]:
|
| 257 |
+
# if req.image_id not in file_store or file_store[req.image_id]["type"] != "image":
|
| 258 |
+
# raise HTTPException(status_code=404, detail="image_id not found")
|
| 259 |
+
# if req.mask_id not in file_store or file_store[req.mask_id]["type"] != "mask":
|
| 260 |
+
# raise HTTPException(status_code=404, detail="mask_id not found")
|
| 261 |
+
|
| 262 |
+
# img_rgba = _load_rgba_image(file_store[req.image_id]["path"])
|
| 263 |
+
# mask_img = Image.open(file_store[req.mask_id]["path"]) # may be RGB/gray/RGBA
|
| 264 |
+
# mask_rgba = _load_rgba_mask_from_image(mask_img)
|
| 265 |
+
|
| 266 |
+
# # Debug: check mask before processing
|
| 267 |
+
# white_pixels = int((mask_rgba[:,:,0] > 128).sum())
|
| 268 |
+
# log.info(f"Inpaint request: mask has {white_pixels} white pixels, invert_mask={req.invert_mask}")
|
| 269 |
+
|
| 270 |
+
# if req.passthrough:
|
| 271 |
+
# result = np.array(img_rgba.convert("RGB"))
|
| 272 |
+
# else:
|
| 273 |
+
# result = process_inpaint(np.array(img_rgba), mask_rgba, invert_mask=req.invert_mask)
|
| 274 |
+
# result_name = f"output_{uuid.uuid4().hex}.png"
|
| 275 |
+
# result_path = os.path.join(OUTPUT_DIR, result_name)
|
| 276 |
+
# Image.fromarray(result).save(result_path, "PNG", optimize=False, compress_level=1)
|
| 277 |
+
|
| 278 |
+
# logs.append({"result": result_name, "timestamp": datetime.utcnow().isoformat()})
|
| 279 |
+
# return {"result": result_name}
|
| 280 |
|
| 281 |
|
| 282 |
@app.post("/inpaint-url")
|