import os import logging from PIL import Image, ImageDraw from huggingface_hub import hf_hub_download class ObjectDetector: def __init__(self, model_key="yolov8n", device="cpu"): self.device = device self.model = None self.model_key = model_key.lower().replace(".pt", "") hf_map = { "yolov8n": ("ultralytics/yolov8", "yolov8n.pt"), "yolov8s": ("ultralytics/yolov8", "yolov8s.pt"), "yolov8l": ("ultralytics/yolov8", "yolov8l.pt"), "yolov11b": ("Ultralytics/YOLO11", "yolov11b.pt"), } if self.model_key not in hf_map: raise ValueError(f"Unsupported model key: {self.model_key}") repo_id, filename = hf_map[self.model_key] self.weights_path = hf_hub_download( repo_id=repo_id, filename=filename, cache_dir="models/detection/weights", force_download=False ) def load_model(self): if self.model is None: import torch # Safe to import here from ultralytics import YOLO # Defer import # FORCE: Avoid triggering CUDA by setting env var os.environ["CUDA_VISIBLE_DEVICES"] = "-1" if self.device == "cpu" else "" # Initialize model self.model = YOLO(self.weights_path) # Move to CUDA only if necessary and safe if self.device == "cuda" and torch.cuda.is_available(): self.model.to("cuda") return self def predict(self, image: Image.Image, conf_threshold=0.25): self.load_model() results = self.model(image) detections = [] for r in results: for box in r.boxes: detections.append({ "class_name": r.names[int(box.cls)], "confidence": float(box.conf), "bbox": box.xyxy[0].tolist() }) return detections