# 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" }