File size: 2,559 Bytes
b23251f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import numpy as np
from PIL import Image, ImageDraw
import logging
from ultralytics import YOLO
from utils.model_downloader import download_model_if_needed

logger = logging.getLogger(__name__)

class ObjectDetector:
    """

    Generalized Object Detection Wrapper for YOLOv5, YOLOv8, and future variants.

    """

    def __init__(self, model_key="yolov5n-seg", weights_dir="models/detection/weights", device="cpu"):
        """

        Initialize the Object Detection model.



        Args:

            model_key (str): Model identifier as defined in model_downloader.py.

            weights_dir (str): Directory to store/download model weights.

            device (str): Inference device ("cpu" or "cuda").

        """
        weights_path = os.path.join(weights_dir, f"{model_key}.pt")
        download_model_if_needed(model_key, weights_path)

        logger.info(f"Loading Object Detection model '{model_key}' from {weights_path}")
        self.device = device
        self.model = YOLO(weights_path)

    def predict(self, image: Image.Image):
        """

        Run object detection.



        Args:

            image (PIL.Image.Image): Input image.



        Returns:

            List[Dict]: List of detected objects with class name, confidence, and bbox.

        """
        logger.info("Running object detection")
        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()
                })
        logger.info(f"Detected {len(detections)} objects")
        return detections

    def draw(self, image: Image.Image, detections, alpha=0.5):
        """

        Draw bounding boxes on image.



        Args:

            image (PIL.Image.Image): Input image.

            detections (List[Dict]): Detection results.

            alpha (float): Blend strength.



        Returns:

            PIL.Image.Image: Image with bounding boxes drawn.

        """
        overlay = image.copy()
        draw = ImageDraw.Draw(overlay)
        for det in detections:
            bbox = det["bbox"]
            label = f'{det["class_name"]} {det["confidence"]:.2f}'
            draw.rectangle(bbox, outline="red", width=2)
            draw.text((bbox[0], bbox[1]), label, fill="red")
        return Image.blend(image, overlay, alpha)