Fourier_face / app.py
Pastaaaaa2003's picture
yay app ready?
dc43ffb
Raw
History Blame Contribute Delete
2.66 kB
import os
import uuid
import tempfile
from pathlib import Path
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from src.model.pipeline import pipeline
ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp", ".bmp"}
MAX_FILE_SIZE_MB = 5
MAX_N_CIRCLES = 500
MIN_N_CIRCLES = 1
app = FastAPI(title="Fourier Epicycle API")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=False,
allow_methods=["POST", "GET"],
allow_headers=["*"],
)
@app.post("/api/fourier-data")
async def get_fourier_data(
file: UploadFile = File(...),
n_circles: int = Form(...)
):
# Validate n_circles
if not (MIN_N_CIRCLES <= n_circles <= MAX_N_CIRCLES):
raise HTTPException(
status_code=400,
detail=f"n_circles must be between {MIN_N_CIRCLES} and {MAX_N_CIRCLES}"
)
# Validate file extension
original_ext = Path(file.filename).suffix.lower() if file.filename else ""
if original_ext not in ALLOWED_EXTENSIONS:
raise HTTPException(
status_code=400,
detail=f"Unsupported file type. Allowed: {', '.join(ALLOWED_EXTENSIONS)}"
)
# Read and validate file size
contents = await file.read()
if len(contents) > MAX_FILE_SIZE_MB * 1024 * 1024:
raise HTTPException(
status_code=413,
detail=f"File too large. Maximum size is {MAX_FILE_SIZE_MB} MB"
)
# Write to a safe temp file with a random name
tmp_dir = tempfile.gettempdir()
temp_path = os.path.join(tmp_dir, f"{uuid.uuid4().hex}{original_ext}")
try:
with open(temp_path, "wb") as f:
f.write(contents)
result = pipeline(image_path=temp_path, n_circles=n_circles)
circles = [
[
float(result['magnitude'][i]),
float(result['frequencies'][i]),
float(result['phases'][i])
]
for i in range(len(result['frequencies']))
]
return {"circles": circles, "success": True}
except HTTPException:
raise
except Exception:
return JSONResponse(
status_code=500,
content={"error": "Image processing failed. Try a different image or fewer circles.", "success": False}
)
finally:
if os.path.exists(temp_path):
os.remove(temp_path)
# Serve the frontend — must be mounted AFTER API routes
app.mount("/", StaticFiles(directory=".", html=True), name="static")