|
|
""" |
|
|
detection.py - Dog Detection using YOLOv8 |
|
|
""" |
|
|
|
|
|
import cv2 |
|
|
import numpy as np |
|
|
import torch |
|
|
from ultralytics import YOLO |
|
|
from typing import List, Optional |
|
|
from dataclasses import dataclass |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class Detection: |
|
|
bbox: List[float] |
|
|
confidence: float |
|
|
image_crop: Optional[np.ndarray] = None |
|
|
|
|
|
|
|
|
class DogDetector: |
|
|
def __init__(self, confidence_threshold: float = 0.50, device: str = 'cuda'): |
|
|
self.confidence_threshold = confidence_threshold |
|
|
self.device = device if torch.cuda.is_available() else 'cpu' |
|
|
self.model = YOLO('yolov8m.pt') |
|
|
self.model.to(self.device) |
|
|
self.dog_class_id = 16 |
|
|
self.min_detection_area = 900 |
|
|
|
|
|
print(f"✅ Dog Detector initialized on {self.device}") |
|
|
print(f" Confidence threshold: {self.confidence_threshold:.2f}") |
|
|
|
|
|
def detect(self, frame: np.ndarray) -> List[Detection]: |
|
|
if frame is None or frame.size == 0: |
|
|
return [] |
|
|
|
|
|
results = self.model( |
|
|
frame, |
|
|
conf=self.confidence_threshold, |
|
|
classes=[self.dog_class_id], |
|
|
verbose=False |
|
|
) |
|
|
|
|
|
detections = [] |
|
|
|
|
|
if results and len(results) > 0: |
|
|
result = results[0] |
|
|
|
|
|
if result.boxes is not None: |
|
|
boxes = result.boxes |
|
|
|
|
|
for i in range(len(boxes)): |
|
|
x1, y1, x2, y2 = boxes.xyxy[i].cpu().numpy() |
|
|
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) |
|
|
|
|
|
h, w = frame.shape[:2] |
|
|
x1 = max(0, min(w-1, x1)) |
|
|
y1 = max(0, min(h-1, y1)) |
|
|
x2 = max(0, min(w, x2)) |
|
|
y2 = max(0, min(h, y2)) |
|
|
|
|
|
if x2 <= x1 or y2 <= y1: |
|
|
continue |
|
|
|
|
|
area = (x2 - x1) * (y2 - y1) |
|
|
if area < self.min_detection_area: |
|
|
continue |
|
|
|
|
|
confidence = float(boxes.conf[i]) |
|
|
dog_crop = frame[y1:y2, x1:x2].copy() |
|
|
|
|
|
detection = Detection( |
|
|
bbox=[x1, y1, x2, y2], |
|
|
confidence=confidence, |
|
|
image_crop=dog_crop |
|
|
) |
|
|
|
|
|
detections.append(detection) |
|
|
|
|
|
return detections |
|
|
|
|
|
def set_confidence(self, threshold: float): |
|
|
self.confidence_threshold = max(0.1, min(1.0, threshold)) |
|
|
print(f"Detection confidence updated: {self.confidence_threshold:.2f}") |
|
|
|
|
|
|
|
|
EnhancedDogDetector = DogDetector |