Skip to content

Référence pour ultralytics/solutions/parking_management.py

Note

Ce fichier est disponible à l'adresse https://github.com/ultralytics/ ultralytics/blob/main/ ultralytics/solutions/parking_management .py. Si tu repères un problème, aide à le corriger en contribuant à une Pull Request 🛠️. Merci 🙏 !



ultralytics.solutions.parking_management.ParkingPtsSelection

Code source dans ultralytics/solutions/parking_management.py
class ParkingPtsSelection:
    def __init__(self, master):
        """
        Initializes the UI for selecting parking zone points in a tkinter window.

        Args:
            master (tk.Tk): The main tkinter window object.
        """
        check_requirements("tkinter")
        import tkinter as tk

        self.master = master
        master.title("Ultralytics Parking Zones Points Selector")

        # Disable window resizing
        master.resizable(False, False)

        # Setup canvas for image display
        self.canvas = tk.Canvas(master, bg="white")

        # Setup buttons
        button_frame = tk.Frame(master)
        button_frame.pack(side=tk.TOP)

        tk.Button(button_frame, text="Upload Image", command=self.upload_image).grid(row=0, column=0)
        tk.Button(button_frame, text="Remove Last BBox", command=self.remove_last_bounding_box).grid(row=0, column=1)
        tk.Button(button_frame, text="Save", command=self.save_to_json).grid(row=0, column=2)

        # Initialize properties
        self.image_path = None
        self.image = None
        self.canvas_image = None
        self.bounding_boxes = []
        self.current_box = []
        self.img_width = 0
        self.img_height = 0

        # Constants
        self.canvas_max_width = 1280
        self.canvas_max_height = 720

    def upload_image(self):
        """Upload an image and resize it to fit canvas."""
        self.image_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png;*.jpg;*.jpeg")])
        if not self.image_path:
            return

        self.image = Image.open(self.image_path)
        self.img_width, self.img_height = self.image.size

        # Calculate the aspect ratio and resize image
        aspect_ratio = self.img_width / self.img_height
        if aspect_ratio > 1:
            # Landscape orientation
            canvas_width = min(self.canvas_max_width, self.img_width)
            canvas_height = int(canvas_width / aspect_ratio)
        else:
            # Portrait orientation
            canvas_height = min(self.canvas_max_height, self.img_height)
            canvas_width = int(canvas_height * aspect_ratio)

        # Check if canvas is already initialized
        if self.canvas:
            self.canvas.destroy()  # Destroy previous canvas

        self.canvas = tk.Canvas(self.master, bg="white", width=canvas_width, height=canvas_height)
        resized_image = self.image.resize((canvas_width, canvas_height), Image.LANCZOS)
        self.canvas_image = ImageTk.PhotoImage(resized_image)
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.canvas_image)

        self.canvas.pack(side=tk.BOTTOM)
        self.canvas.bind("<Button-1>", self.on_canvas_click)

        # Reset bounding boxes and current box
        self.bounding_boxes = []
        self.current_box = []

    def on_canvas_click(self, event):
        """Handle mouse clicks on canvas to create points for bounding boxes."""
        self.current_box.append((event.x, event.y))
        x0, y0 = event.x - 3, event.y - 3
        x1, y1 = event.x + 3, event.y + 3
        self.canvas.create_oval(x0, y0, x1, y1, fill="red")

        if len(self.current_box) == 4:
            self.bounding_boxes.append(self.current_box)
            self.draw_bounding_box(self.current_box)
            self.current_box = []

    def draw_bounding_box(self, box):
        """
        Draw bounding box on canvas.

        Args:
            box (list): Bounding box data
        """
        for i in range(4):
            x1, y1 = box[i]
            x2, y2 = box[(i + 1) % 4]
            self.canvas.create_line(x1, y1, x2, y2, fill="blue", width=2)

    def remove_last_bounding_box(self):
        """Remove the last drawn bounding box from canvas."""
        if self.bounding_boxes:
            self.bounding_boxes.pop()  # Remove the last bounding box
            self.canvas.delete("all")  # Clear the canvas
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.canvas_image)  # Redraw the image

            # Redraw all bounding boxes
            for box in self.bounding_boxes:
                self.draw_bounding_box(box)

            messagebox.showinfo("Success", "Last bounding box removed.")
        else:
            messagebox.showwarning("Warning", "No bounding boxes to remove.")

    def save_to_json(self):
        """Saves rescaled bounding boxes to 'bounding_boxes.json' based on image-to-canvas size ratio."""
        canvas_width, canvas_height = self.canvas.winfo_width(), self.canvas.winfo_height()
        width_scaling_factor = self.img_width / canvas_width
        height_scaling_factor = self.img_height / canvas_height
        bounding_boxes_data = []
        for box in self.bounding_boxes:
            rescaled_box = []
            for x, y in box:
                rescaled_x = int(x * width_scaling_factor)
                rescaled_y = int(y * height_scaling_factor)
                rescaled_box.append((rescaled_x, rescaled_y))
            bounding_boxes_data.append({"points": rescaled_box})
        with open("bounding_boxes.json", "w") as json_file:
            json.dump(bounding_boxes_data, json_file, indent=4)

        messagebox.showinfo("Success", "Bounding boxes saved to bounding_boxes.json")

__init__(master)

Initialise l'interface utilisateur pour la sélection des points de la zone de stationnement dans une fenêtre tkinter.

Paramètres :

Nom Type Description DĂ©faut
master Tk

L'objet principal de la fenĂŞtre tkinter.

requis
Code source dans ultralytics/solutions/parking_management.py
def __init__(self, master):
    """
    Initializes the UI for selecting parking zone points in a tkinter window.

    Args:
        master (tk.Tk): The main tkinter window object.
    """
    check_requirements("tkinter")
    import tkinter as tk

    self.master = master
    master.title("Ultralytics Parking Zones Points Selector")

    # Disable window resizing
    master.resizable(False, False)

    # Setup canvas for image display
    self.canvas = tk.Canvas(master, bg="white")

    # Setup buttons
    button_frame = tk.Frame(master)
    button_frame.pack(side=tk.TOP)

    tk.Button(button_frame, text="Upload Image", command=self.upload_image).grid(row=0, column=0)
    tk.Button(button_frame, text="Remove Last BBox", command=self.remove_last_bounding_box).grid(row=0, column=1)
    tk.Button(button_frame, text="Save", command=self.save_to_json).grid(row=0, column=2)

    # Initialize properties
    self.image_path = None
    self.image = None
    self.canvas_image = None
    self.bounding_boxes = []
    self.current_box = []
    self.img_width = 0
    self.img_height = 0

    # Constants
    self.canvas_max_width = 1280
    self.canvas_max_height = 720

draw_bounding_box(box)

Dessine la boîte de délimitation sur la toile.

Paramètres :

Nom Type Description DĂ©faut
box list

Données de la boîte de délimitation

requis
Code source dans ultralytics/solutions/parking_management.py
def draw_bounding_box(self, box):
    """
    Draw bounding box on canvas.

    Args:
        box (list): Bounding box data
    """
    for i in range(4):
        x1, y1 = box[i]
        x2, y2 = box[(i + 1) % 4]
        self.canvas.create_line(x1, y1, x2, y2, fill="blue", width=2)

on_canvas_click(event)

Traite les clics de souris sur la toile pour créer des points pour les boîtes de délimitation.

Code source dans ultralytics/solutions/parking_management.py
def on_canvas_click(self, event):
    """Handle mouse clicks on canvas to create points for bounding boxes."""
    self.current_box.append((event.x, event.y))
    x0, y0 = event.x - 3, event.y - 3
    x1, y1 = event.x + 3, event.y + 3
    self.canvas.create_oval(x0, y0, x1, y1, fill="red")

    if len(self.current_box) == 4:
        self.bounding_boxes.append(self.current_box)
        self.draw_bounding_box(self.current_box)
        self.current_box = []

remove_last_bounding_box()

Retire la dernière boîte de délimitation dessinée du canevas.

Code source dans ultralytics/solutions/parking_management.py
def remove_last_bounding_box(self):
    """Remove the last drawn bounding box from canvas."""
    if self.bounding_boxes:
        self.bounding_boxes.pop()  # Remove the last bounding box
        self.canvas.delete("all")  # Clear the canvas
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.canvas_image)  # Redraw the image

        # Redraw all bounding boxes
        for box in self.bounding_boxes:
            self.draw_bounding_box(box)

        messagebox.showinfo("Success", "Last bounding box removed.")
    else:
        messagebox.showwarning("Warning", "No bounding boxes to remove.")

save_to_json()

Enregistre les boîtes de délimitation redimensionnées dans 'bounding_boxes.json' en fonction du rapport entre la taille de l'image et celle du canevas.

Code source dans ultralytics/solutions/parking_management.py
def save_to_json(self):
    """Saves rescaled bounding boxes to 'bounding_boxes.json' based on image-to-canvas size ratio."""
    canvas_width, canvas_height = self.canvas.winfo_width(), self.canvas.winfo_height()
    width_scaling_factor = self.img_width / canvas_width
    height_scaling_factor = self.img_height / canvas_height
    bounding_boxes_data = []
    for box in self.bounding_boxes:
        rescaled_box = []
        for x, y in box:
            rescaled_x = int(x * width_scaling_factor)
            rescaled_y = int(y * height_scaling_factor)
            rescaled_box.append((rescaled_x, rescaled_y))
        bounding_boxes_data.append({"points": rescaled_box})
    with open("bounding_boxes.json", "w") as json_file:
        json.dump(bounding_boxes_data, json_file, indent=4)

    messagebox.showinfo("Success", "Bounding boxes saved to bounding_boxes.json")

upload_image()

Télécharge une image et redimensionne-la pour qu'elle s'adapte à la toile.

Code source dans ultralytics/solutions/parking_management.py
def upload_image(self):
    """Upload an image and resize it to fit canvas."""
    self.image_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png;*.jpg;*.jpeg")])
    if not self.image_path:
        return

    self.image = Image.open(self.image_path)
    self.img_width, self.img_height = self.image.size

    # Calculate the aspect ratio and resize image
    aspect_ratio = self.img_width / self.img_height
    if aspect_ratio > 1:
        # Landscape orientation
        canvas_width = min(self.canvas_max_width, self.img_width)
        canvas_height = int(canvas_width / aspect_ratio)
    else:
        # Portrait orientation
        canvas_height = min(self.canvas_max_height, self.img_height)
        canvas_width = int(canvas_height * aspect_ratio)

    # Check if canvas is already initialized
    if self.canvas:
        self.canvas.destroy()  # Destroy previous canvas

    self.canvas = tk.Canvas(self.master, bg="white", width=canvas_width, height=canvas_height)
    resized_image = self.image.resize((canvas_width, canvas_height), Image.LANCZOS)
    self.canvas_image = ImageTk.PhotoImage(resized_image)
    self.canvas.create_image(0, 0, anchor=tk.NW, image=self.canvas_image)

    self.canvas.pack(side=tk.BOTTOM)
    self.canvas.bind("<Button-1>", self.on_canvas_click)

    # Reset bounding boxes and current box
    self.bounding_boxes = []
    self.current_box = []



ultralytics.solutions.parking_management.ParkingManagement

Code source dans ultralytics/solutions/parking_management.py
class ParkingManagement:
    def __init__(
        self,
        model_path,
        txt_color=(0, 0, 0),
        bg_color=(255, 255, 255),
        occupied_region_color=(0, 255, 0),
        available_region_color=(0, 0, 255),
        margin=10,
    ):
        """
        Initializes the parking management system with a YOLOv8 model and visualization settings.

        Args:
            model_path (str): Path to the YOLOv8 model.
            txt_color (tuple): RGB color tuple for text.
            bg_color (tuple): RGB color tuple for background.
            occupied_region_color (tuple): RGB color tuple for occupied regions.
            available_region_color (tuple): RGB color tuple for available regions.
            margin (int): Margin for text display.
        """
        # Model path and initialization
        self.model_path = model_path
        self.model = self.load_model()

        # Labels dictionary
        self.labels_dict = {"Occupancy": 0, "Available": 0}

        # Visualization details
        self.margin = margin
        self.bg_color = bg_color
        self.txt_color = txt_color
        self.occupied_region_color = occupied_region_color
        self.available_region_color = available_region_color

        self.window_name = "Ultralytics YOLOv8 Parking Management System"
        # Check if environment supports imshow
        self.env_check = check_imshow(warn=True)

    def load_model(self):
        """Load the Ultralytics YOLOv8 model for inference and analytics."""
        from ultralytics import YOLO

        self.model = YOLO(self.model_path)
        return self.model

    @staticmethod
    def parking_regions_extraction(json_file):
        """
        Extract parking regions from json file.

        Args:
            json_file (str): file that have all parking slot points
        """
        with open(json_file, "r") as json_file:
            return json.load(json_file)

    def process_data(self, json_data, im0, boxes, clss):
        """
        Process the model data for parking lot management.

        Args:
            json_data (str): json data for parking lot management
            im0 (ndarray): inference image
            boxes (list): bounding boxes data
            clss (list): bounding boxes classes list
        Returns:
            filled_slots (int): total slots that are filled in parking lot
            empty_slots (int): total slots that are available in parking lot
        """
        annotator = Annotator(im0)
        total_slots, filled_slots = len(json_data), 0
        empty_slots = total_slots

        for region in json_data:
            points = region["points"]
            points_array = np.array(points, dtype=np.int32).reshape((-1, 1, 2))
            region_occupied = False

            for box, cls in zip(boxes, clss):
                x_center = int((box[0] + box[2]) / 2)
                y_center = int((box[1] + box[3]) / 2)
                text = f"{self.model.names[int(cls)]}"

                annotator.display_objects_labels(
                    im0, text, self.txt_color, self.bg_color, x_center, y_center, self.margin
                )
                dist = cv2.pointPolygonTest(points_array, (x_center, y_center), False)
                if dist >= 0:
                    region_occupied = True
                    break

            color = self.occupied_region_color if region_occupied else self.available_region_color
            cv2.polylines(im0, [points_array], isClosed=True, color=color, thickness=2)
            if region_occupied:
                filled_slots += 1
                empty_slots -= 1

        self.labels_dict["Occupancy"] = filled_slots
        self.labels_dict["Available"] = empty_slots

        annotator.display_analytics(im0, self.labels_dict, self.txt_color, self.bg_color, self.margin)

    def display_frames(self, im0):
        """
        Display frame.

        Args:
            im0 (ndarray): inference image
        """
        if self.env_check:
            cv2.namedWindow(self.window_name)
            cv2.imshow(self.window_name, im0)
            # Break Window
            if cv2.waitKey(1) & 0xFF == ord("q"):
                return

__init__(model_path, txt_color=(0, 0, 0), bg_color=(255, 255, 255), occupied_region_color=(0, 255, 0), available_region_color=(0, 0, 255), margin=10)

Initialise le système de gestion du stationnement avec un modèle YOLOv8 et des paramètres de visualisation.

Paramètres :

Nom Type Description DĂ©faut
model_path str

Chemin d'accès au modèle YOLOv8 .

requis
txt_color tuple

Tuple de couleurs RVB pour le texte.

(0, 0, 0)
bg_color tuple

Tuple de couleurs RVB pour l'arrière-plan.

(255, 255, 255)
occupied_region_color tuple

Tuple de couleurs RVB pour les régions occupées.

(0, 255, 0)
available_region_color tuple

Tuple de couleurs RVB pour les régions disponibles.

(0, 0, 255)
margin int

Marge pour l'affichage du texte.

10
Code source dans ultralytics/solutions/parking_management.py
def __init__(
    self,
    model_path,
    txt_color=(0, 0, 0),
    bg_color=(255, 255, 255),
    occupied_region_color=(0, 255, 0),
    available_region_color=(0, 0, 255),
    margin=10,
):
    """
    Initializes the parking management system with a YOLOv8 model and visualization settings.

    Args:
        model_path (str): Path to the YOLOv8 model.
        txt_color (tuple): RGB color tuple for text.
        bg_color (tuple): RGB color tuple for background.
        occupied_region_color (tuple): RGB color tuple for occupied regions.
        available_region_color (tuple): RGB color tuple for available regions.
        margin (int): Margin for text display.
    """
    # Model path and initialization
    self.model_path = model_path
    self.model = self.load_model()

    # Labels dictionary
    self.labels_dict = {"Occupancy": 0, "Available": 0}

    # Visualization details
    self.margin = margin
    self.bg_color = bg_color
    self.txt_color = txt_color
    self.occupied_region_color = occupied_region_color
    self.available_region_color = available_region_color

    self.window_name = "Ultralytics YOLOv8 Parking Management System"
    # Check if environment supports imshow
    self.env_check = check_imshow(warn=True)

display_frames(im0)

Cadre d'affichage.

Paramètres :

Nom Type Description DĂ©faut
im0 ndarray

image d'inférence

requis
Code source dans ultralytics/solutions/parking_management.py
def display_frames(self, im0):
    """
    Display frame.

    Args:
        im0 (ndarray): inference image
    """
    if self.env_check:
        cv2.namedWindow(self.window_name)
        cv2.imshow(self.window_name, im0)
        # Break Window
        if cv2.waitKey(1) & 0xFF == ord("q"):
            return

load_model()

Charge le modèle Ultralytics YOLOv8 pour l'inférence et l'analyse.

Code source dans ultralytics/solutions/parking_management.py
def load_model(self):
    """Load the Ultralytics YOLOv8 model for inference and analytics."""
    from ultralytics import YOLO

    self.model = YOLO(self.model_path)
    return self.model

parking_regions_extraction(json_file) staticmethod

Extrait les régions de stationnement du fichier json.

Paramètres :

Nom Type Description DĂ©faut
json_file str

fichier qui a tous les points d'emplacement de stationnement

requis
Code source dans ultralytics/solutions/parking_management.py
@staticmethod
def parking_regions_extraction(json_file):
    """
    Extract parking regions from json file.

    Args:
        json_file (str): file that have all parking slot points
    """
    with open(json_file, "r") as json_file:
        return json.load(json_file)

process_data(json_data, im0, boxes, clss)

Traite les données du modèle pour la gestion des parkings.

Paramètres :

Nom Type Description DĂ©faut
json_data str

données json pour la gestion des parkings

requis
im0 ndarray

image d'inférence

requis
boxes list

Données sur les boîtes de délimitation

requis
clss list

liste des classes de boîtes de délimitation

requis

Retourne : filled_slots (int) : total des emplacements qui sont occupés dans le parking empty_slots (int) : nombre total d'emplacements disponibles dans le parking

Code source dans ultralytics/solutions/parking_management.py
def process_data(self, json_data, im0, boxes, clss):
    """
    Process the model data for parking lot management.

    Args:
        json_data (str): json data for parking lot management
        im0 (ndarray): inference image
        boxes (list): bounding boxes data
        clss (list): bounding boxes classes list
    Returns:
        filled_slots (int): total slots that are filled in parking lot
        empty_slots (int): total slots that are available in parking lot
    """
    annotator = Annotator(im0)
    total_slots, filled_slots = len(json_data), 0
    empty_slots = total_slots

    for region in json_data:
        points = region["points"]
        points_array = np.array(points, dtype=np.int32).reshape((-1, 1, 2))
        region_occupied = False

        for box, cls in zip(boxes, clss):
            x_center = int((box[0] + box[2]) / 2)
            y_center = int((box[1] + box[3]) / 2)
            text = f"{self.model.names[int(cls)]}"

            annotator.display_objects_labels(
                im0, text, self.txt_color, self.bg_color, x_center, y_center, self.margin
            )
            dist = cv2.pointPolygonTest(points_array, (x_center, y_center), False)
            if dist >= 0:
                region_occupied = True
                break

        color = self.occupied_region_color if region_occupied else self.available_region_color
        cv2.polylines(im0, [points_array], isClosed=True, color=color, thickness=2)
        if region_occupied:
            filled_slots += 1
            empty_slots -= 1

    self.labels_dict["Occupancy"] = filled_slots
    self.labels_dict["Available"] = empty_slots

    annotator.display_analytics(im0, self.labels_dict, self.txt_color, self.bg_color, self.margin)





Créé le 2024-04-29, Mis à jour le 2024-05-18
Auteurs : glenn-jocher (1), Burhan-Q (1), lakshanthad (1), RizwanMunawar (1)