""" Object Detection Engine using YOLO """ import cv2 import numpy as np from ultralytics import YOLO import os class ObjectDetector: def __init__(self, model_path='runs/detect/safety_detector/weights/best.pt'): """ Initialize the YOLO detector """ print(f"๐Ÿ” Loading model: {model_path}") # Check if model exists, use pretrained if not if not os.path.exists(model_path): print("โš ๏ธ Trained model not found. Using pretrained YOLO11...") model_path = 'yolo11n.pt' self.model = YOLO(model_path) # Class names (from Hard Hat Workers dataset) self.class_names = { 0: 'Helmet', 1: 'No-Helmet', 2: 'Vest', 3: 'Person' } # Colors for each class (BGR) self.colors = { 'Helmet': (0, 255, 0), # Green 'No-Helmet': (0, 0, 255), # Red 'Vest': (255, 200, 0), # Yellow 'Person': (255, 0, 0) # Blue } print(f"โœ… Detector initialized with {len(self.class_names)} classes") def detect_frame(self, frame): """ Detect objects in a single frame """ # Run inference results = self.model(frame, verbose=False) # Extract detections detections = [] for result in results: boxes = result.boxes if boxes is not None: for box in boxes: x1, y1, x2, y2 = box.xyxy[0].cpu().numpy().astype(int) cls = int(box.cls[0]) conf = float(box.conf[0]) # Only include confident detections if conf > 0.3: detections.append({ 'bbox': [x1, y1, x2, y2], 'class': self.class_names.get(cls, 'Unknown'), 'class_id': cls, 'confidence': conf }) return detections def draw_detections(self, frame, detections): """ Draw bounding boxes and labels on frame """ annotated_frame = frame.copy() for det in detections: x1, y1, x2, y2 = det['bbox'] cls_name = det['class'] conf = det['confidence'] color = self.colors.get(cls_name, (255, 255, 255)) # Draw rectangle cv2.rectangle(annotated_frame, (x1, y1), (x2, y2), color, 2) # Draw label with background label = f"{cls_name} {conf:.2f}" (label_w, label_h), _ = cv2.getTextSize( label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2 ) cv2.rectangle( annotated_frame, (x1, y1 - label_h - 8), (x1 + label_w + 8, y1), color, -1 ) cv2.putText( annotated_frame, label, (x1 + 4, y1 - 4), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2 ) return annotated_frame def process_image(self, image_path): """ Process an image file """ frame = cv2.imread(image_path) if frame is None: raise ValueError(f"Could not read image: {image_path}") detections = self.detect_frame(frame) annotated = self.draw_detections(frame, detections) return annotated, detections def get_stats(self, detections): """ Get statistics from detections """ stats = {} for det in detections: cls_name = det['class'] stats[cls_name] = stats.get(cls_name, 0) + 1 return stats # Test the detector if __name__ == "__main__": print("๐Ÿงช Testing ObjectDetector...") detector = ObjectDetector() print("โœ… ObjectDetector initialized successfully!")