yusef
Initial commit - V5.1 API
df64c50
"""
Building Detection API β€” FastAPI Backend for Hugging Face Spaces.
Endpoints:
GET / β†’ Health check + model info
GET /health β†’ Health check
POST /detect β†’ Detect buildings in a polygon area
"""
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from typing import List, Optional
import uvicorn
from model_manager import load_model, get_model_info
from inference import detect_buildings
# ==========================================
# === App Setup ===
# ==========================================
app = FastAPI(
title="πŸ—οΈ Building Detection API",
description="Detect buildings from satellite imagery using Mask R-CNN V5",
version="1.0.0",
)
# Allow CORS for Vercel frontend
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # In production, restrict to your Vercel domain
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ==========================================
# === Request / Response Models ===
# ==========================================
class DetectRequest(BaseModel):
coordinates: List[List[float]] = Field(
...,
description="Polygon coordinates as [[lng, lat], ...] in GeoJSON format",
example=[[31.24, 30.04], [31.25, 30.04], [31.25, 30.05], [31.24, 30.05]],
)
threshold: Optional[float] = Field(
default=0.5,
ge=0.1,
le=0.95,
description="Detection confidence threshold",
)
use_v51: Optional[bool] = Field(
default=True,
description="Enable V5.1 pipeline (MobileSAM + SigLIP) for better accuracy",
)
class DetectResponse(BaseModel):
geojson: dict
stats: dict
class HealthResponse(BaseModel):
status: str
model: dict
# ==========================================
# === Startup Event ===
# ==========================================
@app.on_event("startup")
async def startup():
"""Load model when the server starts."""
print("πŸš€ Starting Building Detection API...")
load_model()
print("βœ… API ready!")
# ==========================================
# === Endpoints ===
# ==========================================
@app.get("/", response_model=HealthResponse)
async def root():
"""Health check and model info."""
return {
"status": "🟒 online",
"model": get_model_info(),
}
@app.get("/health", response_model=HealthResponse)
async def health():
"""Health check endpoint."""
return {
"status": "🟒 online",
"model": get_model_info(),
}
@app.post("/detect", response_model=DetectResponse)
async def detect(request: DetectRequest):
"""
Detect buildings in the specified polygon area.
Send polygon coordinates in GeoJSON format [[lng, lat], ...].
Returns a GeoJSON FeatureCollection with detected building polygons.
"""
try:
result = detect_buildings(
coordinates=request.coordinates,
threshold=request.threshold,
use_v51=request.use_v51,
)
if "error" in result:
raise HTTPException(status_code=400, detail=result["error"])
return result
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Processing error: {str(e)}")
# ==========================================
# === Run ===
# ==========================================
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860)