""" CarDentIQ — FastAPI backend Developer: Saksham Pathak (github.com/parthmax2) """ import base64 import io import json import numpy as np from fastapi import FastAPI, File, Form, UploadFile from fastapi.staticfiles import StaticFiles from PIL import Image from src.detector import CLASS_COLORS, CLASS_NAMES, DEFAULT_THRESHOLDS, detect app = FastAPI(title="CarDentIQ API") @app.get("/api/classes") def get_classes(): return { "classes": [ { "id": cid, "name": CLASS_NAMES[cid], "color": CLASS_COLORS[cid], "default_threshold": DEFAULT_THRESHOLDS[cid], } for cid in CLASS_NAMES ] } @app.post("/api/detect") async def api_detect( image: UploadFile = File(...), resize: bool = Form(False), thresholds: str = Form(...), ): thresholds_map = {int(k): float(v) for k, v in json.loads(thresholds).items()} raw = await image.read() img = np.array(Image.open(io.BytesIO(raw)).convert("RGB")) img_h, img_w = img.shape[:2] result = detect(img, resize, thresholds_map) def encode(arr) -> str: buf = io.BytesIO() Image.fromarray(arr).save(buf, format="PNG") return f"data:image/png;base64,{base64.b64encode(buf.getvalue()).decode()}" csv_lines = ["Class,Confidence,cx,cy,w,h"] yolo_lines = [] for d in result["detections"]: cx, cy, w, h = d["box_yolo"] csv_lines.append(f'{d["class_name"]},{d["confidence"]},{cx},{cy},{w},{h}') yolo_lines.append(f'{d["class_id"]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}') return { "annotated_image": encode(result["annotated"]), "detections": result["detections"], "summary": result["summary"], "image_info": { "width": img_w, "height": img_h, "size_bytes": len(raw), "filename": image.filename, }, "csv": "\n".join(csv_lines), "yolo_txt": "\n".join(yolo_lines), } # ── static frontend (must be mounted last — acts as a catch-all) ── app.mount("/", StaticFiles(directory="static", html=True), name="static")