traffic-density-backend / video_api.py
Dhanush606's picture
Update video_api.py
6f1f0f2 verified
Raw
History Blame Contribute Delete
3.54 kB
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import torch
from transformers import AutoImageProcessor, SiglipForImageClassification
from PIL import Image
import io
import base64
import numpy as np
import os
app = FastAPI()
# Enable CORS for the Next.js frontend
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "https://dhanush-bt.github.io"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Load Model
MODEL_PATH = "./Traffic-Density-Classification"
if not os.path.exists(MODEL_PATH):
MODEL_PATH = "prithivMLmods/Traffic-Density-Classification"
try:
print(f"Loading density model from {MODEL_PATH}...")
device = "cuda" if torch.cuda.is_available() else "cpu"
processor = AutoImageProcessor.from_pretrained(MODEL_PATH)
model = SiglipForImageClassification.from_pretrained(MODEL_PATH).to(device)
id2label = model.config.id2label
print(f"Model loaded successfully on {device}")
except Exception as e:
print(f"Error loading model: {e}")
# Fallback or exit if model is critical
processor, model, device, id2label = None, None, None, {}
@app.post("/analyze-frame")
async def analyze_frame(data: dict):
if not model:
raise HTTPException(status_code=500, detail="Model not loaded")
try:
# Decode base64 image
image_data = data.get("image")
if not image_data:
raise HTTPException(status_code=400, detail="No image data provided")
# Remove header if present (e.g., "data:image/jpeg;base64,")
if "," in image_data:
image_data = image_data.split(",")[1]
image_bytes = base64.b64decode(image_data)
image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
# Preprocess and Inference
inputs = processor(images=image, return_tensors="pt").to(device)
with torch.no_grad():
outputs = model(**inputs)
probs = torch.nn.functional.softmax(outputs.logits, dim=1)
# Get all probabilities
all_probs = probs[0].tolist()
top_class = torch.argmax(probs, dim=1).item()
# Helper to get label safely
def get_label(idx):
if idx in id2label: return id2label[idx]
if str(idx) in id2label: return id2label[str(idx)]
return f"class_{idx}"
label = get_label(top_class)
confidence = all_probs[top_class]
# Logic for Signal
signal = "GREEN"
if "high-traffic" in label:
signal = "RED"
elif "medium-traffic" in label:
signal = "YELLOW"
return {
"label": label,
"confidence": confidence,
"signal": signal,
"probabilities": {get_label(i): p for i, p in enumerate(all_probs)}
}
except Exception as e:
print(f"Inference error: {e}")
raise HTTPException(status_code=500, detail=str(e))
@app.get("/")
async def root():
return {"message": "HELIOS Traffic Controller API is running. Check /health for status."}
@app.get("/health")
async def health():
return {"status": "ok", "model_loaded": model is not None}
if __name__ == "__main__":
import uvicorn
port = int(os.environ.get("PORT", 7860))
uvicorn.run(app, host="0.0.0.0", port=port)