Vai al contenuto

Riferimento per ultralytics/solutions/parking_management.py

Nota

Questo file è disponibile all'indirizzo https://github.com/ultralytics/ ultralytics/blob/main/ ultralytics/solutions/parking_management .py. Se riscontri un problema, contribuisci a risolverlo inviando una Pull Request 🛠️. Grazie 🙏!



ultralytics.solutions.parking_management.ParkingPtsSelection

Codice sorgente in ultralytics/solutions/parking_management.py
class ParkingPtsSelection:
    def __init__(self, master):
        """Initializes the UI for selecting parking zone points in a tkinter window."""
        self.master = master
        master.title("Ultralytics Parking Zones Points Selector")

        # Resizable false
        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.canvas = 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)

Inizializza l'interfaccia utente per la selezione dei punti di parcheggio in una finestra tkinter.

Codice sorgente in ultralytics/solutions/parking_management.py
def __init__(self, master):
    """Initializes the UI for selecting parking zone points in a tkinter window."""
    self.master = master
    master.title("Ultralytics Parking Zones Points Selector")

    # Resizable false
    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.canvas = 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)

Disegna il rettangolo di selezione sulla tela.

Parametri:

Nome Tipo Descrizione Predefinito
box list

Dati del rettangolo di selezione

richiesto
Codice sorgente in 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)

Gestisce i clic del mouse sulla tela per creare punti per i riquadri di delimitazione.

Codice sorgente in 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()

Rimuove l'ultimo rettangolo di selezione disegnato dalla tela.

Codice sorgente in 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()

Salva i riquadri di delimitazione ridimensionati in 'bounding_boxes.json' in base al rapporto tra le dimensioni dell'immagine e della tela.

Codice sorgente in 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()

Carica un'immagine e ridimensionala per adattarla alla tela.

Codice sorgente in 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

Codice sorgente in 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,
    ):
        # 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 support 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

display_frames(im0)

Cornice del display.

Parametri:

Nome Tipo Descrizione Predefinito
im0 ndarray

immagine di inferenza

richiesto
Codice sorgente in 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()

Carica il modello Ultralytics YOLOv8 per l'inferenza e l'analisi.

Codice sorgente in 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

Estrai le regioni di parcheggio dal file json.

Parametri:

Nome Tipo Descrizione Predefinito
json_file str

file con tutti i punti di parcheggio

richiesto
Codice sorgente in 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)

Elaborare i dati del modello per la gestione dei parcheggi.

Parametri:

Nome Tipo Descrizione Predefinito
json_data str

dati json per la gestione dei parcheggi

richiesto
im0 ndarray

immagine di inferenza

richiesto
boxes list

Dati delle caselle di delimitazione

richiesto
clss list

Elenco delle classi di rettangoli di selezione

richiesto

Restituisce: filled_slots (int): totale di slot occupati nel parcheggio empty_slots (int): totale di slot disponibili nel parcheggio

Codice sorgente in 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)





Creato 2024-04-29, Aggiornato 2024-05-08
Autori: Burhan-Q (1), lakshanthad (1), RizwanMunawar (1)