加入别人的代码
This commit is contained in:
parent
57441c2ab5
commit
7402dc775e
15
README.md
15
README.md
@ -6,3 +6,18 @@
|
|||||||
3.通过自己拍摄的图片把车位情况识别出来
|
3.通过自己拍摄的图片把车位情况识别出来
|
||||||
4.识别的是否有车信息传给地图,在地图上显示出来是否有车。
|
4.识别的是否有车信息传给地图,在地图上显示出来是否有车。
|
||||||
5.让用户选择个空车位,最后在地图上把导航路径画出来。
|
5.让用户选择个空车位,最后在地图上把导航路径画出来。
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- 看懂他的代码,把他的底图换成我们制定的数据结构。/ 或者自己重新写。
|
||||||
|
- 随机生成停车站状态,嵌入路径规划算法,实现交互。
|
||||||
|
|
||||||
|
## 导航算法
|
||||||
|
|
||||||
|
数据结构:
|
||||||
|
- 0:路
|
||||||
|
- 1:车位入口
|
||||||
|
- 2:
|
||||||
|
- 3:车位入口,有车了
|
||||||
|
- 4:
|
||||||
|
- -1:其他区域
|
||||||
|
38
cs.py
Normal file
38
cs.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
# 车位编号列表
|
||||||
|
left_side = list(range(119, 132))
|
||||||
|
right_side = list(range(99, 87, -1))
|
||||||
|
entry_left = [117, 115, 113]
|
||||||
|
entry_right = [108, 106, 104, 102, 101, 100]
|
||||||
|
p_row1 = [118, 116, 114, 112, 111, 110, None, 109, 107, 105, 103]
|
||||||
|
middle_bottom_row1 = [292, 290, 288, 286, 284, 282, 280, 278, 276, 274, 272]
|
||||||
|
middle_top_row2 = [293, 291, 289, 287, 285, 283, 281, 279, 277, 275, 273, 271]
|
||||||
|
middle_bottom_row2 = list(range(259, 271))
|
||||||
|
middle_top_row3 = [None] * 10 + [0] + [None]
|
||||||
|
middle_bottom_row3 = [258, 257, 256, None, None, None, None, None, None, 255, 254, None]
|
||||||
|
|
||||||
|
# 合并所有编号列表,去掉 None
|
||||||
|
all_spots = [
|
||||||
|
left_side, right_side, entry_left, entry_right, p_row1,
|
||||||
|
middle_bottom_row1, middle_top_row2, middle_bottom_row2,
|
||||||
|
middle_top_row3, middle_bottom_row3
|
||||||
|
]
|
||||||
|
|
||||||
|
all_numbers = [number for row in all_spots for number in row if number is not None]
|
||||||
|
|
||||||
|
# 指定存放文件夹的根目录
|
||||||
|
root_directory = "D:/car2/parking_folders"
|
||||||
|
|
||||||
|
# 创建根目录(如果不存在)
|
||||||
|
if not os.path.exists(root_directory):
|
||||||
|
os.makedirs(root_directory)
|
||||||
|
|
||||||
|
# 创建文件夹,确保文件夹名是三位数
|
||||||
|
for number in all_numbers:
|
||||||
|
folder_name = str(number).zfill(3) # 将编号转换为三位数
|
||||||
|
folder_path = os.path.join(root_directory, folder_name)
|
||||||
|
if not os.path.exists(folder_path):
|
||||||
|
os.makedirs(folder_path)
|
||||||
|
|
||||||
|
print(f"已成功创建 {len(all_numbers)} 个文件夹。")
|
52
data.py
Normal file
52
data.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import os
|
||||||
|
import random
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
# 车位编号列表
|
||||||
|
left_side = list(range(119, 132))
|
||||||
|
right_side = list(range(99, 87, -1))
|
||||||
|
entry_left = [117, 115, 113]
|
||||||
|
entry_right = [108, 106, 104, 102, 101, 100]
|
||||||
|
p_row1 = [118, 116, 114, 112, 111, 110, None, 109, 107, 105, 103]
|
||||||
|
middle_bottom_row1 = [292, 290, 288, 286, 284, 282, 280, 278, 276, 274, 272]
|
||||||
|
middle_top_row2 = [293, 291, 289, 287, 285, 283, 281, 279, 277, 275, 273, 271]
|
||||||
|
middle_bottom_row2 = list(range(259, 271))
|
||||||
|
middle_top_row3 = [None] * 10 + [0] + [None]
|
||||||
|
middle_bottom_row3 = [258, 257, 256, None, None, None, None, None, None, 255, 254, None]
|
||||||
|
|
||||||
|
# 合并所有编号列表,去掉 None
|
||||||
|
all_spots = [
|
||||||
|
left_side, right_side, entry_left, entry_right, p_row1,
|
||||||
|
middle_bottom_row1, middle_top_row2, middle_bottom_row2,
|
||||||
|
middle_top_row3, middle_bottom_row3
|
||||||
|
]
|
||||||
|
|
||||||
|
all_numbers = [number for row in all_spots for number in row if number is not None]
|
||||||
|
|
||||||
|
# 指定存放文件夹的根目录
|
||||||
|
root_directory = "D:/car2/parking_folders"
|
||||||
|
source_directory = "D:/car2/cs" # 图片文件夹
|
||||||
|
|
||||||
|
# 遍历所有车位编号
|
||||||
|
for number in all_numbers:
|
||||||
|
folder_name = str(number).zfill(3) # 将编号转换为三位数
|
||||||
|
folder_path = os.path.join(root_directory, folder_name)
|
||||||
|
|
||||||
|
# 检查车位编号文件夹是否存在
|
||||||
|
if os.path.exists(folder_path):
|
||||||
|
# 获取所有图片文件
|
||||||
|
image_files = [f for f in os.listdir(source_directory) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
|
||||||
|
|
||||||
|
if image_files:
|
||||||
|
# 随机选择一张图片
|
||||||
|
selected_image = random.choice(image_files)
|
||||||
|
image_path = os.path.join(source_directory, selected_image)
|
||||||
|
|
||||||
|
# 目标路径是车位编号对应的文件夹
|
||||||
|
destination_path = os.path.join(folder_path, selected_image)
|
||||||
|
|
||||||
|
# 将图片复制到对应的文件夹中
|
||||||
|
shutil.copy(image_path, destination_path)
|
||||||
|
print(f"已将图片 {selected_image} 复制到 {folder_path} 文件夹。")
|
||||||
|
|
||||||
|
print("图片已成功随机分配到车位文件夹。")
|
12
navigate.py
12
navigate.py
@ -52,14 +52,18 @@ def a_star(start, goal):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# 停车场状态矩阵
|
# 停车场状态矩阵
|
||||||
parking_lot = [
|
parking_lot = [
|
||||||
[1, 1, 1, 0, 1, 1, 1],
|
[1, 1, 1, 0, 3, 2, 1],
|
||||||
[1, 1, 1, 0, 1, 1, 1],
|
[1, 1, 1, 0, 3, 1, 1],
|
||||||
[0, 0, 0, 0, 0, 0, 0]
|
[0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0],
|
||||||
|
[0, 1, 1, 1, 1, 1, 0],
|
||||||
|
[0, 2, 2, 2, 2, 2, 0],
|
||||||
|
[0, 0, 0, 0, 0, 0, 0],
|
||||||
]
|
]
|
||||||
|
|
||||||
# 起点和终点(行, 列)
|
# 起点和终点(行, 列)
|
||||||
start = (0, 3)
|
start = (0, 3)
|
||||||
goal = (1, 1)
|
goal = (3, 5)
|
||||||
# 执行 A* 路径搜索
|
# 执行 A* 路径搜索
|
||||||
path = a_star(start, goal)
|
path = a_star(start, goal)
|
||||||
|
|
||||||
|
289
test.py
Normal file
289
test.py
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
import random
|
||||||
|
import heapq
|
||||||
|
import os
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# 停车场布局数据
|
||||||
|
left_side = list(range(119, 132))
|
||||||
|
right_side = list(range(99, 87, -1))
|
||||||
|
|
||||||
|
# 将右侧车位编号转换为三位数格式(例如:099, 098, ...)
|
||||||
|
right_side = [str(number).zfill(3) for number in right_side]
|
||||||
|
|
||||||
|
entry_left = [117, 115, 113]
|
||||||
|
entry_right = [108, 106, 104, 102, 101, 100]
|
||||||
|
p_row1 = [118, 116, 114, 112, 111, 110, None, 109, 107, 105, 103]
|
||||||
|
middle_bottom_row1 = [292, 290, 288, 286, 284, 282, 280, 278, 276, 274, 272]
|
||||||
|
middle_top_row2 = [293, 291, 289, 287, 285, 283, 281, 279, 277, 275, 273, 271]
|
||||||
|
middle_bottom_row2 = list(range(259, 271))
|
||||||
|
middle_top_row3 = [None] * 10 + [00] + [None]
|
||||||
|
middle_bottom_row3 = [258, 257, 256, None, None, None, None, None, None, 255, 254, None]
|
||||||
|
|
||||||
|
# 样式参数
|
||||||
|
car_space_width = 50
|
||||||
|
car_space_height = 80
|
||||||
|
road_width = 40
|
||||||
|
canvas_width = 1200
|
||||||
|
canvas_height = 900
|
||||||
|
middle_area_offset_y = 100 # 中间区域整体下移
|
||||||
|
|
||||||
|
# 车位状态对应颜色
|
||||||
|
status_color = {
|
||||||
|
'free': 'lightgreen',
|
||||||
|
'occupied': 'tomato',
|
||||||
|
}
|
||||||
|
|
||||||
|
default_color = 'white'
|
||||||
|
selected_color = 'cyan' # 搜索高亮颜色
|
||||||
|
|
||||||
|
# 设置 YOLO 检测结果路径
|
||||||
|
detection_folder = r"D:\car2\parking_folders"
|
||||||
|
|
||||||
|
|
||||||
|
# A*算法的启发式函数
|
||||||
|
def heuristic(a, b):
|
||||||
|
return abs(a[0] - b[0]) + abs(a[1] - b[1]) # 曼哈顿距离
|
||||||
|
|
||||||
|
|
||||||
|
class ParkingLot(tk.Tk):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.title("停车场平面图 🚗")
|
||||||
|
self.geometry(f"{canvas_width}x{canvas_height}")
|
||||||
|
self.canvas = tk.Canvas(self, width=canvas_width, height=canvas_height, bg='#CCCCCC')
|
||||||
|
self.canvas.pack()
|
||||||
|
|
||||||
|
# 搜索部分
|
||||||
|
self.search_entry = tk.Entry(self)
|
||||||
|
self.search_entry.pack(pady=5)
|
||||||
|
self.search_button = tk.Button(self, text="搜索车位", command=self.search_spot)
|
||||||
|
self.search_button.pack(pady=5)
|
||||||
|
|
||||||
|
self.spots = {} # 存储车位信息
|
||||||
|
self.path = [] # 存储路径
|
||||||
|
self.obstacles = [] # 存储障碍物坐标
|
||||||
|
self.draw_parking_lot()
|
||||||
|
|
||||||
|
def draw_parking_lot(self):
|
||||||
|
# 入口灰色路
|
||||||
|
self.canvas.create_rectangle(400, 0, 800, road_width, fill='gray')
|
||||||
|
self.canvas.create_text(750, 20, text="入口", fill="red", font=('Arial', 16))
|
||||||
|
|
||||||
|
# 入口两边车位
|
||||||
|
for idx, number in enumerate(entry_left):
|
||||||
|
x = 400 - (idx + 1) * (car_space_width + 5)
|
||||||
|
y = 0
|
||||||
|
self.draw_parking_spot(x, y, number, direction='down')
|
||||||
|
|
||||||
|
for idx, number in enumerate(entry_right):
|
||||||
|
x = 800 + idx * (car_space_width + 5)
|
||||||
|
y = 0
|
||||||
|
self.draw_parking_spot(x, y, number, direction='down')
|
||||||
|
|
||||||
|
# 左右两列
|
||||||
|
for idx, number in enumerate(left_side):
|
||||||
|
x = 0
|
||||||
|
y = road_width + idx * (car_space_height + 5)
|
||||||
|
self.draw_parking_spot(x, y, number, direction='right')
|
||||||
|
|
||||||
|
for idx, number in enumerate(right_side):
|
||||||
|
x = canvas_width - 50
|
||||||
|
y = road_width + idx * (car_space_height + 5)
|
||||||
|
self.draw_parking_spot(x, y, number, direction='left')
|
||||||
|
|
||||||
|
# 中间区域
|
||||||
|
start_y = road_width + 20 + middle_area_offset_y
|
||||||
|
self.draw_middle_row(start_y, p_row1, up=True)
|
||||||
|
self.draw_middle_row(start_y + car_space_height + 5, middle_bottom_row1, up=False)
|
||||||
|
|
||||||
|
start_y += (car_space_height + 5) * 2 + road_width
|
||||||
|
self.draw_middle_row(start_y, middle_top_row2, up=True)
|
||||||
|
self.draw_middle_row(start_y + car_space_height + 5, middle_bottom_row2, up=False)
|
||||||
|
|
||||||
|
start_y += (car_space_height + 5) * 2 + road_width
|
||||||
|
self.draw_middle_row(start_y, middle_top_row3, up=True)
|
||||||
|
self.draw_middle_row(start_y + car_space_height + 5, middle_bottom_row3, up=False)
|
||||||
|
|
||||||
|
def draw_middle_row(self, start_y, row_data, up=True):
|
||||||
|
total_spots = len(row_data)
|
||||||
|
row_width = total_spots * (car_space_width + 5) - 5
|
||||||
|
start_x = (canvas_width - row_width) / 2
|
||||||
|
|
||||||
|
current_x = start_x
|
||||||
|
for number in row_data:
|
||||||
|
rect = self.canvas.create_rectangle(
|
||||||
|
current_x, start_y,
|
||||||
|
current_x + car_space_width,
|
||||||
|
start_y + car_space_height,
|
||||||
|
fill=default_color,
|
||||||
|
outline='black'
|
||||||
|
)
|
||||||
|
|
||||||
|
if number is not None:
|
||||||
|
# 初始随机给状态
|
||||||
|
status = random.choice(['free', 'occupied'])
|
||||||
|
self.spots[rect] = {'number': number, 'status': status}
|
||||||
|
self.draw_arrow(current_x, start_y, 'up' if up else 'down')
|
||||||
|
self.canvas.create_text(current_x + car_space_width / 2, start_y + car_space_height / 2,
|
||||||
|
text=str(number), font=('Arial', 8))
|
||||||
|
self.canvas.tag_bind(rect, '<Button-1>', self.toggle_spot)
|
||||||
|
# 按状态上色
|
||||||
|
fill_color = status_color.get(status, default_color)
|
||||||
|
self.canvas.itemconfig(rect, fill=fill_color)
|
||||||
|
|
||||||
|
# 添加障碍物坐标
|
||||||
|
self.obstacles.append((current_x, start_y))
|
||||||
|
|
||||||
|
current_x += car_space_width + 5
|
||||||
|
|
||||||
|
def draw_arrow(self, x, y, direction):
|
||||||
|
if direction == 'up':
|
||||||
|
points = [x + car_space_width / 2, y + 10, x + 10, y + 30, x + car_space_width - 10, y + 30]
|
||||||
|
elif direction == 'down':
|
||||||
|
points = [x + car_space_width / 2, y + car_space_height - 10, x + 10, y + car_space_height - 30,
|
||||||
|
x + car_space_width - 10, y + car_space_height - 30]
|
||||||
|
elif direction == 'left':
|
||||||
|
points = [x + 10, y + car_space_height / 2, x + 30, y + 10, x + 30, y + car_space_height - 10]
|
||||||
|
else:
|
||||||
|
points = [x + car_space_width - 10, y + car_space_height / 2, x + car_space_width - 30, y + 10,
|
||||||
|
x + car_space_width - 30, y + car_space_height - 10]
|
||||||
|
self.canvas.create_polygon(points, fill='black')
|
||||||
|
|
||||||
|
def draw_parking_spot(self, x, y, number, direction='up'):
|
||||||
|
rect = self.canvas.create_rectangle(x, y, x + car_space_width, y + car_space_height, fill=default_color,
|
||||||
|
outline='black')
|
||||||
|
|
||||||
|
# 获取车位编号对应的YOLO检测结果图像路径
|
||||||
|
detection_image_path = os.path.join(detection_folder, f"{number}.jpg") # 假设图像以车位编号命名
|
||||||
|
|
||||||
|
# 检查文件是否存在
|
||||||
|
if os.path.exists(detection_image_path):
|
||||||
|
# 读取 YOLO 检测结果图像(假设是红绿图像,红色表示有车,绿色表示空位)
|
||||||
|
detection_image = cv2.imread(detection_image_path)
|
||||||
|
|
||||||
|
# 检查图片是否为空
|
||||||
|
if detection_image is not None:
|
||||||
|
# 假设检测图像中左上角是车位的检测状态,我们可以检查该区域的颜色
|
||||||
|
# 获取车位区域的颜色
|
||||||
|
region_color = detection_image[10, 10] # 假设检测图像左上角有车位状态信息
|
||||||
|
|
||||||
|
# 判断颜色,红色表示有车,绿色表示空位
|
||||||
|
if np.array_equal(region_color, [0, 0, 255]): # 红色
|
||||||
|
status = 'occupied'
|
||||||
|
elif np.array_equal(region_color, [0, 255, 0]): # 绿色
|
||||||
|
status = 'free'
|
||||||
|
else:
|
||||||
|
status = 'free' # 默认状态为免费
|
||||||
|
else:
|
||||||
|
status = 'free' # 默认状态为免费,如果读取失败
|
||||||
|
else:
|
||||||
|
status = 'free' # 默认状态为免费,如果没有检测结果
|
||||||
|
|
||||||
|
self.spots[rect] = {'number': number, 'status': status}
|
||||||
|
|
||||||
|
# 绘制箭头
|
||||||
|
self.draw_arrow(x, y, direction)
|
||||||
|
|
||||||
|
# 绘制车位编号
|
||||||
|
self.canvas.create_text(x + car_space_width / 2, y + car_space_height / 2, text=str(number), font=('Arial', 8))
|
||||||
|
|
||||||
|
# 绑定点击事件
|
||||||
|
self.canvas.tag_bind(rect, '<Button-1>', self.toggle_spot)
|
||||||
|
|
||||||
|
# 按状态设置颜色
|
||||||
|
fill_color = status_color.get(status, default_color)
|
||||||
|
self.canvas.itemconfig(rect, fill=fill_color)
|
||||||
|
|
||||||
|
def toggle_spot(self, event):
|
||||||
|
clicked = event.widget.find_withtag('current')[0]
|
||||||
|
spot = self.spots.get(clicked)
|
||||||
|
if spot:
|
||||||
|
messagebox.showinfo("车位信息", f"车位编号: {spot['number']}\n状态: {spot['status']}")
|
||||||
|
|
||||||
|
def search_spot(self):
|
||||||
|
query = self.search_entry.get()
|
||||||
|
found = False
|
||||||
|
for rect, spot in self.spots.items():
|
||||||
|
if str(spot['number']) == query:
|
||||||
|
self.canvas.itemconfig(rect, fill=selected_color)
|
||||||
|
self.find_path(rect)
|
||||||
|
found = True
|
||||||
|
else:
|
||||||
|
# 恢复成状态颜色
|
||||||
|
self.canvas.itemconfig(rect, fill=status_color.get(spot['status'], default_color))
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
messagebox.showwarning("提示", "未找到该车位编号!")
|
||||||
|
|
||||||
|
def find_path(self, target_rect):
|
||||||
|
target_coords = self.canvas.coords(target_rect)
|
||||||
|
start_coords = (canvas_width // 2, 0) # 入口位置
|
||||||
|
|
||||||
|
# A*路径规划的实现,避免车位区域
|
||||||
|
path = self.a_star(start_coords, target_coords)
|
||||||
|
|
||||||
|
# 绘制路径
|
||||||
|
for i in range(len(path) - 1):
|
||||||
|
self.canvas.create_line(path[i][0], path[i][1], path[i + 1][0], path[i + 1][1], fill="blue", width=4,
|
||||||
|
arrow=tk.LAST)
|
||||||
|
|
||||||
|
def a_star(self, start, end):
|
||||||
|
open_list = []
|
||||||
|
closed_list = set()
|
||||||
|
came_from = {}
|
||||||
|
|
||||||
|
start_node = (start[0], start[1])
|
||||||
|
end_node = (end[0], end[1])
|
||||||
|
|
||||||
|
# 计算G、H、F值
|
||||||
|
def g_cost(node):
|
||||||
|
return abs(node[0] - start[0]) + abs(node[1] - start[1])
|
||||||
|
|
||||||
|
def h_cost(node):
|
||||||
|
return heuristic(node, end_node)
|
||||||
|
|
||||||
|
def f_cost(node):
|
||||||
|
return g_cost(node) + h_cost(node)
|
||||||
|
|
||||||
|
heapq.heappush(open_list, (f_cost(start_node), start_node))
|
||||||
|
came_from[start_node] = None
|
||||||
|
|
||||||
|
while open_list:
|
||||||
|
current_f, current_node = heapq.heappop(open_list)
|
||||||
|
if current_node == end_node:
|
||||||
|
path = []
|
||||||
|
while current_node:
|
||||||
|
path.append(current_node)
|
||||||
|
current_node = came_from[current_node]
|
||||||
|
return path[::-1]
|
||||||
|
|
||||||
|
closed_list.add(current_node)
|
||||||
|
|
||||||
|
for direction in [(0, -car_space_height - 5), (0, car_space_height + 5), (-car_space_width - 5, 0),
|
||||||
|
(car_space_width + 5, 0)]:
|
||||||
|
neighbor = (current_node[0] + direction[0], current_node[1] + direction[1])
|
||||||
|
|
||||||
|
# Check if the neighbor is within bounds and not an obstacle
|
||||||
|
if 0 <= neighbor[0] < canvas_width and 0 <= neighbor[1] < canvas_height:
|
||||||
|
if self.is_obstacle(neighbor) or neighbor in closed_list:
|
||||||
|
continue
|
||||||
|
|
||||||
|
heapq.heappush(open_list, (f_cost(neighbor), neighbor))
|
||||||
|
came_from[neighbor] = current_node
|
||||||
|
|
||||||
|
return [] # No path found
|
||||||
|
|
||||||
|
def is_obstacle(self, coords):
|
||||||
|
# 判断当前位置是否为车位(障碍物)
|
||||||
|
for (x, y) in self.obstacles:
|
||||||
|
if x <= coords[0] <= x + car_space_width and y <= coords[1] <= y + car_space_height:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = ParkingLot()
|
||||||
|
app.mainloop()
|
223
test2.py
Normal file
223
test2.py
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
import os
|
||||||
|
from ultralytics import YOLO
|
||||||
|
|
||||||
|
# 停车场布局数据
|
||||||
|
left_side = list(range(119, 132))
|
||||||
|
right_side = list(range(99, 87, -1))
|
||||||
|
right_side = [str(number).zfill(3) for number in right_side]
|
||||||
|
|
||||||
|
entry_left = [117, 115, 113]
|
||||||
|
entry_right = [108, 106, 104, 102, 101, 100]
|
||||||
|
p_row1 = [118, 116, 114, 112, 111, 110, None, 109, 107, 105, 103]
|
||||||
|
middle_bottom_row1 = [292, 290, 288, 286, 284, 282, 280, 278, 276, 274, 272]
|
||||||
|
middle_top_row2 = [293, 291, 289, 287, 285, 283, 281, 279, 277, 275, 273, 271]
|
||||||
|
middle_bottom_row2 = list(range(259, 271))
|
||||||
|
middle_top_row3 = [None] * 10 + [0] + [None]
|
||||||
|
middle_bottom_row3 = [258, 257, 256, None, None, None, None, None, None, 255, 254, None]
|
||||||
|
|
||||||
|
# 样式参数
|
||||||
|
car_space_width = 50
|
||||||
|
car_space_height = 80
|
||||||
|
road_width = 40
|
||||||
|
canvas_width = 1200
|
||||||
|
canvas_height = 900
|
||||||
|
middle_area_offset_y = 100
|
||||||
|
|
||||||
|
status_color = {
|
||||||
|
'free': 'lightgreen',
|
||||||
|
'occupied': 'tomato',
|
||||||
|
}
|
||||||
|
|
||||||
|
default_color = 'white'
|
||||||
|
selected_color = 'cyan'
|
||||||
|
path_color = 'yellow'
|
||||||
|
|
||||||
|
MODEL_PATH = r"D:\\car2\\runs\\citrus_auto_detection_20250428-104743\\citrus_model\\weights\\best.pt"
|
||||||
|
PARKING_FOLDER = r"D:\\car2\\parking_folders"
|
||||||
|
|
||||||
|
model = YOLO(MODEL_PATH)
|
||||||
|
|
||||||
|
|
||||||
|
class ParkingLot(tk.Tk):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.title("停车场平面图 🚗")
|
||||||
|
self.geometry(f"{canvas_width}x{canvas_height}")
|
||||||
|
self.canvas = tk.Canvas(self, width=canvas_width, height=canvas_height, bg='#CCCCCC')
|
||||||
|
self.canvas.pack()
|
||||||
|
|
||||||
|
self.search_entry = tk.Entry(self)
|
||||||
|
self.search_entry.pack(pady=5)
|
||||||
|
|
||||||
|
self.search_button = tk.Button(self, text="搜索车位", command=self.search_spot)
|
||||||
|
self.search_button.pack(pady=5)
|
||||||
|
|
||||||
|
self.nav_button = tk.Button(self, text="导航到车位", command=self.navigate_to_spot)
|
||||||
|
self.nav_button.pack(pady=5)
|
||||||
|
|
||||||
|
self.refresh_button = tk.Button(self, text="刷新车位状态", command=self.refresh_all_status)
|
||||||
|
self.refresh_button.pack(pady=5)
|
||||||
|
|
||||||
|
self.spots = {}
|
||||||
|
self.draw_parking_lot()
|
||||||
|
|
||||||
|
# 绑定空格键刷新
|
||||||
|
self.bind('<space>', lambda event: self.refresh_all_status())
|
||||||
|
|
||||||
|
def draw_parking_lot(self):
|
||||||
|
self.canvas.create_rectangle(400, 0, 800, road_width, fill='gray')
|
||||||
|
self.canvas.create_text(750, 20, text="入口", fill="red", font=('Arial', 16))
|
||||||
|
|
||||||
|
for idx, number in enumerate(entry_left):
|
||||||
|
x = 400 - (idx + 1) * (car_space_width + 5)
|
||||||
|
y = 0
|
||||||
|
self.draw_parking_spot(x, y, number, direction='down')
|
||||||
|
|
||||||
|
for idx, number in enumerate(entry_right):
|
||||||
|
x = 800 + idx * (car_space_width + 5)
|
||||||
|
y = 0
|
||||||
|
self.draw_parking_spot(x, y, number, direction='down')
|
||||||
|
|
||||||
|
for idx, number in enumerate(left_side):
|
||||||
|
x = 0
|
||||||
|
y = road_width + idx * (car_space_height + 5)
|
||||||
|
self.draw_parking_spot(x, y, number, direction='right')
|
||||||
|
|
||||||
|
for idx, number in enumerate(right_side):
|
||||||
|
x = canvas_width - 50
|
||||||
|
y = road_width + idx * (car_space_height + 5)
|
||||||
|
self.draw_parking_spot(x, y, number, direction='left')
|
||||||
|
|
||||||
|
start_y = road_width + 20 + middle_area_offset_y
|
||||||
|
self.draw_middle_row(start_y, p_row1, up=True)
|
||||||
|
self.draw_middle_row(start_y + car_space_height + 5, middle_bottom_row1, up=False)
|
||||||
|
|
||||||
|
start_y += (car_space_height + 5) * 2 + road_width
|
||||||
|
self.draw_middle_row(start_y, middle_top_row2, up=True)
|
||||||
|
self.draw_middle_row(start_y + car_space_height + 5, middle_bottom_row2, up=False)
|
||||||
|
|
||||||
|
start_y += (car_space_height + 5) * 2 + road_width
|
||||||
|
self.draw_middle_row(start_y, middle_top_row3, up=True)
|
||||||
|
self.draw_middle_row(start_y + car_space_height + 5, middle_bottom_row3, up=False)
|
||||||
|
|
||||||
|
def draw_middle_row(self, start_y, row_data, up=True):
|
||||||
|
total_spots = len(row_data)
|
||||||
|
row_width = total_spots * (car_space_width + 5) - 5
|
||||||
|
start_x = (canvas_width - row_width) / 2
|
||||||
|
|
||||||
|
current_x = start_x
|
||||||
|
for number in row_data:
|
||||||
|
rect = self.canvas.create_rectangle(
|
||||||
|
current_x, start_y,
|
||||||
|
current_x + car_space_width,
|
||||||
|
start_y + car_space_height,
|
||||||
|
fill=default_color,
|
||||||
|
outline='black'
|
||||||
|
)
|
||||||
|
|
||||||
|
if number is not None:
|
||||||
|
self.spots[rect] = {'number': number, 'status': 'unknown'}
|
||||||
|
self.draw_arrow(current_x, start_y, 'up' if up else 'down')
|
||||||
|
self.canvas.create_text(current_x + car_space_width / 2, start_y + car_space_height / 2,
|
||||||
|
text=str(number).zfill(3), font=('Arial', 8))
|
||||||
|
self.canvas.tag_bind(rect, '<Button-1>', self.toggle_spot)
|
||||||
|
current_x += car_space_width + 5
|
||||||
|
|
||||||
|
def draw_arrow(self, x, y, direction):
|
||||||
|
if direction == 'up':
|
||||||
|
points = [x + car_space_width / 2, y + 10, x + 10, y + 30, x + car_space_width - 10, y + 30]
|
||||||
|
elif direction == 'down':
|
||||||
|
points = [x + car_space_width / 2, y + car_space_height - 10, x + 10, y + car_space_height - 30,
|
||||||
|
x + car_space_width - 10, y + car_space_height - 30]
|
||||||
|
elif direction == 'left':
|
||||||
|
points = [x + 10, y + car_space_height / 2, x + 30, y + 10, x + 30, y + car_space_height - 10]
|
||||||
|
else:
|
||||||
|
points = [x + car_space_width - 10, y + car_space_height / 2, x + car_space_width - 30, y + 10,
|
||||||
|
x + car_space_width - 30, y + car_space_height - 10]
|
||||||
|
self.canvas.create_polygon(points, fill='black')
|
||||||
|
|
||||||
|
def draw_parking_spot(self, x, y, number, direction='up'):
|
||||||
|
rect = self.canvas.create_rectangle(x, y, x + car_space_width, y + car_space_height, fill=default_color,
|
||||||
|
outline='black')
|
||||||
|
|
||||||
|
self.spots[rect] = {'number': number, 'status': 'unknown'}
|
||||||
|
self.draw_arrow(x, y, direction)
|
||||||
|
self.canvas.create_text(x + car_space_width / 2, y + car_space_height / 2,
|
||||||
|
text=str(number).zfill(3), font=('Arial', 8))
|
||||||
|
self.canvas.tag_bind(rect, '<Button-1>', self.toggle_spot)
|
||||||
|
|
||||||
|
def refresh_all_status(self):
|
||||||
|
for rect, spot in self.spots.items():
|
||||||
|
number = spot['number']
|
||||||
|
if number is None:
|
||||||
|
continue
|
||||||
|
new_status = self.detect_parking_status(number)
|
||||||
|
spot['status'] = new_status
|
||||||
|
self.canvas.itemconfig(rect, fill=status_color.get(new_status, default_color))
|
||||||
|
messagebox.showinfo("提示", "所有车位状态已刷新!")
|
||||||
|
|
||||||
|
def detect_parking_status(self, number):
|
||||||
|
folder_name = str(number).zfill(3)
|
||||||
|
folder_path = os.path.join(PARKING_FOLDER, folder_name)
|
||||||
|
if not os.path.isdir(folder_path):
|
||||||
|
return 'free'
|
||||||
|
|
||||||
|
images = [f for f in os.listdir(folder_path) if f.lower().endswith('.jpg')]
|
||||||
|
if not images:
|
||||||
|
return 'free'
|
||||||
|
|
||||||
|
image_path = os.path.join(folder_path, sorted(images)[-1])
|
||||||
|
|
||||||
|
try:
|
||||||
|
results = model(image_path)
|
||||||
|
for result in results:
|
||||||
|
if len(result.boxes) > 0:
|
||||||
|
return 'occupied'
|
||||||
|
except Exception as e:
|
||||||
|
print(f"检测{number}出错: {e}")
|
||||||
|
|
||||||
|
return 'free'
|
||||||
|
|
||||||
|
def toggle_spot(self, event):
|
||||||
|
clicked = event.widget.find_withtag('current')[0]
|
||||||
|
spot = self.spots.get(clicked)
|
||||||
|
if spot:
|
||||||
|
messagebox.showinfo("车位信息", f"车位编号: {str(spot['number']).zfill(3)}\n状态: {spot['status']}")
|
||||||
|
|
||||||
|
def search_spot(self):
|
||||||
|
query = self.search_entry.get().zfill(3)
|
||||||
|
found = False
|
||||||
|
for rect, spot in self.spots.items():
|
||||||
|
spot_number = str(spot['number']).zfill(3)
|
||||||
|
if spot_number == query:
|
||||||
|
self.canvas.itemconfig(rect, fill=selected_color)
|
||||||
|
found = True
|
||||||
|
else:
|
||||||
|
self.canvas.itemconfig(rect, fill=status_color.get(spot['status'], default_color))
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
messagebox.showwarning("提示", "未找到该车位编号!")
|
||||||
|
|
||||||
|
def navigate_to_spot(self):
|
||||||
|
query = self.search_entry.get().zfill(3)
|
||||||
|
found = False
|
||||||
|
for rect, spot in self.spots.items():
|
||||||
|
spot_number = str(spot['number']).zfill(3)
|
||||||
|
if spot_number == query:
|
||||||
|
self.canvas.itemconfig(rect, fill=selected_color)
|
||||||
|
found = True
|
||||||
|
else:
|
||||||
|
if spot['number'] is not None and spot_number[0] == query[0]:
|
||||||
|
self.canvas.itemconfig(rect, fill=path_color)
|
||||||
|
else:
|
||||||
|
self.canvas.itemconfig(rect, fill=status_color.get(spot['status'], default_color))
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
messagebox.showwarning("提示", "未找到该车位编号!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = ParkingLot()
|
||||||
|
app.mainloop()
|
Loading…
Reference in New Issue
Block a user