|
|
|
@ -10,10 +10,44 @@ from ultralytics.utils.plotting import Annotator |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ParkingPtsSelection: |
|
|
|
|
"""Class for selecting and managing parking zone points on images using a Tkinter-based UI.""" |
|
|
|
|
""" |
|
|
|
|
A class for selecting and managing parking zone points on images using a Tkinter-based UI. |
|
|
|
|
|
|
|
|
|
This class provides functionality to upload an image, select points to define parking zones, and save the |
|
|
|
|
selected points to a JSON file. It uses Tkinter for the graphical user interface. |
|
|
|
|
|
|
|
|
|
Attributes: |
|
|
|
|
tk (module): The Tkinter module for GUI operations. |
|
|
|
|
filedialog (module): Tkinter's filedialog module for file selection operations. |
|
|
|
|
messagebox (module): Tkinter's messagebox module for displaying message boxes. |
|
|
|
|
master (tk.Tk): The main Tkinter window. |
|
|
|
|
canvas (tk.Canvas): The canvas widget for displaying the image and drawing bounding boxes. |
|
|
|
|
image (PIL.Image.Image): The uploaded image. |
|
|
|
|
canvas_image (ImageTk.PhotoImage): The image displayed on the canvas. |
|
|
|
|
rg_data (List[List[Tuple[int, int]]]): List of bounding boxes, each defined by 4 points. |
|
|
|
|
current_box (List[Tuple[int, int]]): Temporary storage for the points of the current bounding box. |
|
|
|
|
imgw (int): Original width of the uploaded image. |
|
|
|
|
imgh (int): Original height of the uploaded image. |
|
|
|
|
canvas_max_width (int): Maximum width of the canvas. |
|
|
|
|
canvas_max_height (int): Maximum height of the canvas. |
|
|
|
|
|
|
|
|
|
Methods: |
|
|
|
|
setup_ui: Sets up the Tkinter UI components. |
|
|
|
|
initialize_properties: Initializes the necessary properties. |
|
|
|
|
upload_image: Uploads an image, resizes it to fit the canvas, and displays it. |
|
|
|
|
on_canvas_click: Handles mouse clicks to add points for bounding boxes. |
|
|
|
|
draw_box: Draws a bounding box on the canvas. |
|
|
|
|
remove_last_bounding_box: Removes the last bounding box and redraws the canvas. |
|
|
|
|
redraw_canvas: Redraws the canvas with the image and all bounding boxes. |
|
|
|
|
save_to_json: Saves the bounding boxes to a JSON file. |
|
|
|
|
|
|
|
|
|
Examples: |
|
|
|
|
>>> parking_selector = ParkingPtsSelection() |
|
|
|
|
>>> # Use the GUI to upload an image, select parking zones, and save the data |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
|
"""Class initialization method.""" |
|
|
|
|
"""Initializes the ParkingPtsSelection class, setting up UI and properties for parking zone point selection.""" |
|
|
|
|
check_requirements("tkinter") |
|
|
|
|
import tkinter as tk |
|
|
|
|
from tkinter import filedialog, messagebox |
|
|
|
@ -24,7 +58,7 @@ class ParkingPtsSelection: |
|
|
|
|
self.master.mainloop() |
|
|
|
|
|
|
|
|
|
def setup_ui(self): |
|
|
|
|
"""Sets up the Tkinter UI components.""" |
|
|
|
|
"""Sets up the Tkinter UI components for the parking zone points selection interface.""" |
|
|
|
|
self.master = self.tk.Tk() |
|
|
|
|
self.master.title("Ultralytics Parking Zones Points Selector") |
|
|
|
|
self.master.resizable(False, False) |
|
|
|
@ -45,14 +79,14 @@ class ParkingPtsSelection: |
|
|
|
|
self.tk.Button(button_frame, text=text, command=cmd).pack(side=self.tk.LEFT) |
|
|
|
|
|
|
|
|
|
def initialize_properties(self): |
|
|
|
|
"""Initialize the necessary properties.""" |
|
|
|
|
"""Initialize properties for image, canvas, bounding boxes, and dimensions.""" |
|
|
|
|
self.image = self.canvas_image = None |
|
|
|
|
self.rg_data, self.current_box = [], [] |
|
|
|
|
self.imgw = self.imgh = 0 |
|
|
|
|
self.canvas_max_width, self.canvas_max_height = 1280, 720 |
|
|
|
|
|
|
|
|
|
def upload_image(self): |
|
|
|
|
"""Uploads an image, resizes it to fit the canvas, and displays it.""" |
|
|
|
|
"""Uploads and displays an image on the canvas, resizing it to fit within specified dimensions.""" |
|
|
|
|
from PIL import Image, ImageTk # scope because ImageTk requires tkinter package |
|
|
|
|
|
|
|
|
|
self.image = Image.open(self.filedialog.askopenfilename(filetypes=[("Image Files", "*.png;*.jpg;*.jpeg")])) |
|
|
|
@ -76,7 +110,7 @@ class ParkingPtsSelection: |
|
|
|
|
self.rg_data.clear(), self.current_box.clear() |
|
|
|
|
|
|
|
|
|
def on_canvas_click(self, event): |
|
|
|
|
"""Handles mouse clicks to add points for bounding boxes.""" |
|
|
|
|
"""Handles mouse clicks to add points for bounding boxes on the canvas.""" |
|
|
|
|
self.current_box.append((event.x, event.y)) |
|
|
|
|
self.canvas.create_oval(event.x - 3, event.y - 3, event.x + 3, event.y + 3, fill="red") |
|
|
|
|
if len(self.current_box) == 4: |
|
|
|
@ -85,12 +119,12 @@ class ParkingPtsSelection: |
|
|
|
|
self.current_box.clear() |
|
|
|
|
|
|
|
|
|
def draw_box(self, box): |
|
|
|
|
"""Draws a bounding box on the canvas.""" |
|
|
|
|
"""Draws a bounding box on the canvas using the provided coordinates.""" |
|
|
|
|
for i in range(4): |
|
|
|
|
self.canvas.create_line(box[i], box[(i + 1) % 4], fill="blue", width=2) |
|
|
|
|
|
|
|
|
|
def remove_last_bounding_box(self): |
|
|
|
|
"""Removes the last bounding box and redraws the canvas.""" |
|
|
|
|
"""Removes the last bounding box from the list and redraws the canvas.""" |
|
|
|
|
if not self.rg_data: |
|
|
|
|
self.messagebox.showwarning("Warning", "No bounding boxes to remove.") |
|
|
|
|
return |
|
|
|
@ -105,7 +139,7 @@ class ParkingPtsSelection: |
|
|
|
|
self.draw_box(box) |
|
|
|
|
|
|
|
|
|
def save_to_json(self): |
|
|
|
|
"""Saves the bounding boxes to a JSON file.""" |
|
|
|
|
"""Saves the selected parking zone points to a JSON file with scaled coordinates.""" |
|
|
|
|
scale_w, scale_h = self.imgw / self.canvas.winfo_width(), self.imgh / self.canvas.winfo_height() |
|
|
|
|
data = [{"points": [(int(x * scale_w), int(y * scale_h)) for x, y in box]} for box in self.rg_data] |
|
|
|
|
with open("bounding_boxes.json", "w") as f: |
|
|
|
@ -114,7 +148,30 @@ class ParkingPtsSelection: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ParkingManagement(BaseSolution): |
|
|
|
|
"""Manages parking occupancy and availability using YOLO model for real-time monitoring and visualization.""" |
|
|
|
|
""" |
|
|
|
|
Manages parking occupancy and availability using YOLO model for real-time monitoring and visualization. |
|
|
|
|
|
|
|
|
|
This class extends BaseSolution to provide functionality for parking lot management, including detection of |
|
|
|
|
occupied spaces, visualization of parking regions, and display of occupancy statistics. |
|
|
|
|
|
|
|
|
|
Attributes: |
|
|
|
|
json_file (str): Path to the JSON file containing parking region details. |
|
|
|
|
json (List[Dict]): Loaded JSON data containing parking region information. |
|
|
|
|
pr_info (Dict[str, int]): Dictionary storing parking information (Occupancy and Available spaces). |
|
|
|
|
arc (Tuple[int, int, int]): RGB color tuple for available region visualization. |
|
|
|
|
occ (Tuple[int, int, int]): RGB color tuple for occupied region visualization. |
|
|
|
|
dc (Tuple[int, int, int]): RGB color tuple for centroid visualization of detected objects. |
|
|
|
|
|
|
|
|
|
Methods: |
|
|
|
|
process_data: Processes model data for parking lot management and visualization. |
|
|
|
|
|
|
|
|
|
Examples: |
|
|
|
|
>>> from ultralytics.solutions import ParkingManagement |
|
|
|
|
>>> parking_manager = ParkingManagement(model="yolov8n.pt", json_file="parking_regions.json") |
|
|
|
|
>>> results = parking_manager(source="parking_lot_video.mp4") |
|
|
|
|
>>> print(f"Occupied spaces: {parking_manager.pr_info['Occupancy']}") |
|
|
|
|
>>> print(f"Available spaces: {parking_manager.pr_info['Available']}") |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
def __init__(self, **kwargs): |
|
|
|
|
"""Initializes the parking management system with a YOLO model and visualization settings.""" |
|
|
|
@ -136,10 +193,19 @@ class ParkingManagement(BaseSolution): |
|
|
|
|
|
|
|
|
|
def process_data(self, im0): |
|
|
|
|
""" |
|
|
|
|
Process the model data for parking lot management. |
|
|
|
|
Processes the model data for parking lot management. |
|
|
|
|
|
|
|
|
|
This function analyzes the input image, extracts tracks, and determines the occupancy status of parking |
|
|
|
|
regions defined in the JSON file. It annotates the image with occupied and available parking spots, |
|
|
|
|
and updates the parking information. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
im0 (ndarray): inference image. |
|
|
|
|
im0 (np.ndarray): The input inference image. |
|
|
|
|
|
|
|
|
|
Examples: |
|
|
|
|
>>> parking_manager = ParkingManagement(json_file="parking_regions.json") |
|
|
|
|
>>> image = cv2.imread("parking_lot.jpg") |
|
|
|
|
>>> parking_manager.process_data(image) |
|
|
|
|
""" |
|
|
|
|
self.extract_tracks(im0) # extract tracks from im0 |
|
|
|
|
es, fs = len(self.json), 0 # empty slots, filled slots |
|
|
|
|