File size: 4,548 Bytes
44f7c73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# 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"
    }