from ultralytics import YOLO import numpy as np from typing import List, Dict, Any, Union from pathlib import Path class PotholeDetector: _instance = None _model = None def __new__(cls, model_path: Union[str, Path]): if cls._instance is None: cls._instance = super(PotholeDetector, cls).__new__(cls) # Only preload once safely enforcing Singleton configuration cls._instance._model = YOLO(str(model_path)) return cls._instance @classmethod def get_instance(cls, model_path: Union[str, Path] = "yolov8n.pt"): if cls._instance is None: return cls(model_path) return cls._instance def predict(self, image: Union[np.ndarray, str, Path], conf_thresh: float = 0.25) -> List[Dict[str, Any]]: """ Runs YOLOv8 object detection inference. Inputs: image: Image payload represented as absolute Path string or physical BGR matrix natively. conf_thresh: Decimal threshold constraint evaluating bounding strictness minimums. Outputs: Rigorous dictionary format: {'xyxy': [x1, y1, x2, y2], 'confidence': float, 'class_id': int} """ # Model strictly anticipates physical images natively results = self._model.predict(source=image, conf=conf_thresh, verbose=False) detections = [] for r in results: boxes = r.boxes if boxes is None or len(boxes) == 0: continue for box in boxes: xyxy = box.xyxy[0].cpu().numpy().tolist() conf = float(box.conf[0].cpu().numpy()) cls_id = int(box.cls[0].cpu().numpy()) detections.append({'xyxy': xyxy, 'confidence': conf, 'class_id': cls_id}) return detections