Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from tkinter import messagebox, filedialog
- import tkinter.ttk as ttk
- from PIL import Image, ImageTk
- import json
- class MarkupApp(tk.Tk):
- def __init__(self):
- tk.Tk.__init__(self)
- self.canvas = None
- self.done_btn = None
- self.zone_label = None
- self.clear_btn = None
- self.load_btn = None
- self.cnt_zones = None
- self.tk_img = None
- self.img_name = "preview_img.png"
- self.colors = ["black", "red", "green", "blue", "cyan", "yellow", "magenta"]
- self.curr_colors = ["black", "red", "green", "blue", "cyan", "yellow", "magenta"]
- self.height = None
- self.width = None
- self.click_num = 0
- self.x1 = self.y1 = None
- self.start_x = self.start_y = None
- self.zones = []
- self.curr_zone = []
- self.init_gui()
- def init_gui(self):
- self.create_canvas()
- self.load_btn = ttk.Button(self, text="Загрузить", command=self.load_image)
- self.load_btn.grid(row=0, column=0)
- self.zone_label = ttk.Label(self, text="Текущее количество зон:")
- self.zone_label.grid(row=1, column=0)
- self.cnt_zones = ttk.Label(self, text='0')
- self.cnt_zones.grid(row=2, column=0)
- self.done_btn = ttk.Button(self, text="Завершить", command=self.save_zone)
- self.done_btn.grid(row=3, column=0)
- def load_image(self):
- filetypes = (
- ('Изображения', '*.jpg; *.jpeg; *.png'),
- ('Все файлы', '*.*')
- )
- self.img_name = filedialog.askopenfilename(title="Выбор изображения для разметки", filetypes=filetypes)
- if self.img_name:
- img = Image.open(self.img_name)
- self.canvas.delete("all")
- self.zones = []
- self.curr_zone = []
- self.x1 = None
- self.y1 = None
- self.click_num = 0
- self.tk_img = ImageTk.PhotoImage(img)
- self.height = self.tk_img.height()
- self.width = self.tk_img.width()
- self.canvas.config(width=self.width, height=self.height)
- self.canvas.create_image(0, 0, anchor="nw", image=self.tk_img)
- def save_zone(self):
- if len(self.zones) != 0:
- messagebox.showinfo("Завершение!", "Разметка успешно завершена. Вы можете закрыть приложение.")
- res_zones = {f"zone_{i}": coords for i, coords in enumerate(self.zones)}
- with open('markup_data.json', 'w') as f:
- json.dump(res_zones, f)
- else:
- messagebox.showwarning("Предупреждение!", "Для начала выделите хотя бы одну зону.")
- def count_zones(self):
- self.cnt_zones.config(text='{}'.format(len(self.zones)))
- def create_canvas(self):
- self.canvas = tk.Canvas(self, width=self.width, height=self.height, background="white")
- self.canvas.grid(row=0, column=1)
- self.canvas.bind('<Button-1>', self.draw_line)
- img = Image.open(self.img_name)
- self.tk_img = ImageTk.PhotoImage(img)
- self.height = self.tk_img.height()
- self.width = self.tk_img.width()
- self.canvas.create_image(0, 0, anchor="nw", image=self.tk_img)
- def clear_zone(self):
- pass
- def draw_line(self, event):
- if self.click_num == 0:
- self.curr_zone = []
- self.x1 = event.x
- self.y1 = event.y
- self.start_x = self.x1
- self.start_y = self.y1
- if len(self.curr_colors) == 0:
- self.curr_colors = self.colors
- self.canvas.create_oval(self.x1 - 2, self.y1 - 2, self.x1 + 2, self.y1 + 2, width=0, fill=self.curr_colors[-1])
- self.click_num = 1
- self.curr_zone.append({"x": self.x1, "y": self.y1})
- else:
- x2 = event.x
- y2 = event.y
- self.curr_zone.append({"x": x2, "y": y2})
- self.canvas.create_oval(x2 - 2, y2 - 2, x2 + 2, y2 + 2, width=0, fill=self.curr_colors[-1])
- self.canvas.create_line(self.x1, self.y1, x2, y2, fill=self.curr_colors[-1], width=2)
- self.x1 = x2
- self.y1 = y2
- self.click_num += 1
- if self.click_num == 4:
- x2 = self.start_x
- y2 = self.start_y
- self.curr_zone.append({"x": self.x1, "y": self.y1})
- self.canvas.create_line(self.x1, self.y1, x2, y2, fill=self.curr_colors[-1], width=2)
- num_zone_x = (self.curr_zone[0]['x'] + self.curr_zone[2]['x']) // 2
- num_zone_y = (self.curr_zone[0]['y'] + self.curr_zone[2]['y']) // 2
- self.canvas.create_text(num_zone_x,
- num_zone_y,
- text=str(len(self.zones) + 1),
- fill=self.curr_colors[-1],
- font=('Helvetica 18 bold'))
- self.click_num = 0
- self.curr_colors.pop()
- self.zones.append(self.curr_zone)
- self.count_zones()
- if __name__ == '__main__':
- app = MarkupApp()
- app.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement