unwrap-clothes/app.py

115 lines
3.2 KiB
Python
Raw Normal View History

"""FastAPI backend for garment photo cleaning."""
import os
from pathlib import Path
from fastapi import FastAPI, File, Form, HTTPException, UploadFile, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from cleaner import (
DEFAULT_MODEL,
CleanerError,
_get_image_info,
build_prompt,
clean_garment,
encode_image_bytes,
)
DEFAULT_PROMPT = build_prompt("beige")
STATIC_DIR = Path(__file__).resolve().parent / "static"
STATIC_DIR.mkdir(parents=True, exist_ok=True)
app = FastAPI(title="unwrap-clothes")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/api/health")
def health_check():
return {"status": "ok"}
@app.get("/")
def read_root():
index_file = STATIC_DIR / "index.html"
if index_file.is_file():
return FileResponse(index_file)
return JSONResponse({"status": "ok", "message": "unwrap-clothes backend is running"})
@app.post("/api/clean")
async def clean_endpoint(
file: UploadFile = File(...),
prompt: str = Form(default=DEFAULT_PROMPT),
model: str = Form(default=DEFAULT_MODEL),
api_key: str | None = Form(default=None),
restore_res: bool = Form(default=True),
):
effective_api_key = (api_key.strip() if api_key and api_key.strip() else None) or os.environ.get(
"OPENROUTER_API_KEY"
)
if not effective_api_key:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="API key is required. Provide it in the form or set OPENROUTER_API_KEY.",
)
file_bytes = await file.read()
if not file_bytes:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Uploaded file is empty.",
)
orig_dims, _ = _get_image_info(file_bytes)
if orig_dims is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid image file. Could not decode image.",
)
try:
clean_result = clean_garment(
image_data=file_bytes,
prompt=prompt,
api_key=effective_api_key,
model=model,
restore_res=restore_res,
)
except CleanerError as exc:
raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail=str(exc),
)
return {
"image": encode_image_bytes(clean_result.image_bytes, mime=clean_result.media_type),
"cost": clean_result.cost,
"width": clean_result.width,
"height": clean_result.height,
"original_dimensions": list(clean_result.original_dimensions)
if clean_result.original_dimensions
else None,
"model_dimensions": list(clean_result.model_dimensions)
if clean_result.model_dimensions
else None,
"was_rescaled": clean_result.was_rescaled,
"media_type": clean_result.media_type,
}
if STATIC_DIR.is_dir():
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
if __name__ == "__main__":
import uvicorn
uvicorn.run("app:app", host="127.0.0.1", port=8000, reload=True)