road-damage / src /api /config.py
Zok213's picture
Add Road Damage Detection API with YOLO model
44f7c73
# backend/src/api/config.py
"""
Configuration for Road Damage Detection Backend Orchestrator
Architecture:
- Local YOLO11 model (active, weight=1.0)
- Future HuggingFace Spaces for YOLO12 and SAHI (pending, weight=0.0)
When additional models are trained and deployed:
1. Update MODEL_WEIGHTS to enable them
2. Add HF_SPACES URLs
3. Set MIN_ENSEMBLE_VOTES to require agreement
"""
import os
from pydantic_settings import BaseSettings
from typing import Dict, List
class Settings(BaseSettings):
"""Global configuration for the backend orchestrator"""
# API Settings
API_TITLE: str = "Road Damage Detection - Backend Orchestrator"
API_VERSION: str = "2.0.0"
API_HOST: str = "0.0.0.0"
API_PORT: int = 8001
# ===========================================
# MODEL CONFIGURATION
# ===========================================
# Model weights for ensemble voting
# Currently: only yolo11 is active (local model)
# Future: yolo12 and sahi on HuggingFace Spaces
MODEL_WEIGHTS: Dict[str, float] = {
"yolo11": 1.0, # Active - local model (models/yolo11base.pt)
"yolo12": 0.0, # Pending - training in progress
"sahi": 0.0 # Pending - training in progress
}
# Local model path (relative to backend directory)
YOLO11_MODEL_PATH: str = "../models/yolo11base.pt"
# HuggingFace Spaces URLs (for future use)
HF_SPACES: Dict[str, str] = {
"yolo12": "https://YOUR_USERNAME-road-damage-yolo12.hf.space",
"sahi": "https://YOUR_USERNAME-road-damage-sahi.hf.space"
}
# ===========================================
# INFERENCE SETTINGS
# ===========================================
# Confidence threshold for detections
CONFIDENCE_THRESHOLD: float = 0.25
# NMS IoU threshold for merging overlapping boxes
NMS_IOU_THRESHOLD: float = 0.45
# Minimum models that must agree (for future ensemble)
# Currently set to 1 since only yolo11 is active
MIN_ENSEMBLE_VOTES: int = 1
# Image size for inference
INFERENCE_IMG_SIZE: int = 640
# ===========================================
# GPS FALLBACK - NEAR DJI SAMPLE LOCATION
# ===========================================
# Based on DJI_202511261727_006 sample data GPS
# Original: 16.009719, 108.258302 (Da Nang area)
# Fallback: 50 meters to the right (East)
DEFAULT_LATITUDE: float = 16.009719
DEFAULT_LONGITUDE: float = 108.258852
DEFAULT_ALTITUDE: float = 68.5
# ===========================================
# DAMAGE CLASS MAPPING
# ===========================================
# Standard RDD2022 classes
CLASS_NAMES: Dict[int, str] = {
0: "D00", # Longitudinal Crack
1: "D10", # Transverse Crack
2: "D20", # Alligator Crack
3: "D40", # Pothole
}
CLASS_DISPLAY_NAMES: Dict[str, str] = {
"D00": "Longitudinal Crack",
"D10": "Transverse Crack",
"D20": "Alligator Crack",
"D40": "Pothole",
}
# ===========================================
# SEVERITY THRESHOLDS
# ===========================================
# Based on damage area relative to image
SEVERITY_THRESHOLDS: Dict[str, float] = {
"light": 0.05, # < 5% of image
"medium": 0.15, # 5-15% of image
# > 15% = heavy
}
# ===========================================
# FILE SETTINGS
# ===========================================
MAX_IMAGE_SIZE_MB: int = 50
SUPPORTED_FORMATS: List[str] = ["jpg", "jpeg", "png", "bmp", "tiff"]
UPLOAD_DIR: str = "data/uploads"
# ===========================================
# CORS
# ===========================================
ALLOWED_ORIGINS: List[str] = [
"http://localhost:3000",
"http://localhost:3001",
"http://localhost:8001",
"http://127.0.0.1:3000",
"http://127.0.0.1:3001",
]
class Config:
env_file = ".env"
case_sensitive = True
# Global settings instance
settings = Settings()
# Update model path based on environment
if os.getenv("YOLO11_MODEL_PATH"):
settings.YOLO11_MODEL_PATH = os.getenv("YOLO11_MODEL_PATH")
# Update HF username if provided
if os.getenv("HF_USERNAME"):
username = os.getenv("HF_USERNAME")
settings.HF_SPACES = {
"yolo12": f"https://{username}-road-damage-yolo12.hf.space",
"sahi": f"https://{username}-road-damage-sahi.hf.space"
}