File size: 2,182 Bytes
81b4246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""
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")