File size: 2,555 Bytes
ea02dea
 
 
 
 
 
 
 
 
 
 
 
a79eae5
 
ea02dea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1cc8f67
 
ea02dea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import os
import time
from typing import Any, Dict, List

import cv2
import numpy as np
from fastapi import FastAPI, File, UploadFile, HTTPException
from huggingface_hub import hf_hub_download
from ultralytics import YOLO


MODEL_REPO_ID = os.getenv("MODEL_REPO_ID", "HudatersU/road_maintanance")
MODEL_FILENAME = os.getenv("MODEL_FILENAME", "pothole_best2.pt") #pothole_best2.pt
CONF_THRES = float(os.getenv("CONF_THRES", "0.45"))

app = FastAPI(title="Road Maintenance Detection API")

model = None


@app.on_event("startup")
def load_model():
    global model

    model_path = hf_hub_download(
        repo_id=MODEL_REPO_ID,
        filename=MODEL_FILENAME,
    )

    model = YOLO(model_path)


@app.get("/")
def root():
    return {
        "status": "ok",
        "model_repo": MODEL_REPO_ID,
        "model_file": MODEL_FILENAME,
        "endpoints": ["/health", "/predict"],
    }


@app.get("/health")
def health():
    return {
        "status": "ok",
        "model_loaded": model is not None,
    }


@app.post("/predict")
async def predict(file: UploadFile = File(...)) -> Dict[str, Any]:
    if model is None:
        raise HTTPException(status_code=503, detail="Model is not loaded yet")

    image_bytes = await file.read()

    np_arr = np.frombuffer(image_bytes, np.uint8)
    image = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)

    if image is None:
        raise HTTPException(status_code=400, detail="Invalid image")

    h, w = image.shape[:2]

    start = time.time()
    infer_image = cv2.resize(image, (640, 480))
    results = model.predict(infer_image, conf=CONF_THRES, imgsz=640, verbose=False)
    elapsed_ms = round((time.time() - start) * 1000, 2)

    detections: List[Dict[str, Any]] = []

    for r in results:
        if r.boxes is None:
            continue

        for i, box in enumerate(r.boxes):
            x1, y1, x2, y2 = box.xyxy[0].tolist()
            conf = float(box.conf[0])
            cls_id = int(box.cls[0])
            cls_name = model.names.get(cls_id, str(cls_id))

            det = {
                "class_id": cls_id,
                "class_name": cls_name,
                "confidence": conf,
                "box": [x1, y1, x2, y2],
            }

            if r.masks is not None and r.masks.xy is not None and i < len(r.masks.xy):
                det["polygon"] = r.masks.xy[i].tolist()

            detections.append(det)

    return {
        "image": {
            "width": w,
            "height": h,
        },
        "inference_ms": elapsed_ms,
        "detections": detections,
    }