Advertisement
Prin_Di

MarkupApp

Apr 27th, 2022 (edited)
1,245
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.36 KB | None | 0 0
  1. import tkinter as tk
  2. from tkinter import messagebox, filedialog
  3. import tkinter.ttk as ttk
  4. from PIL import Image, ImageTk
  5. import json
  6.  
  7.  
  8. class MarkupApp(tk.Tk):
  9.     def __init__(self):
  10.         tk.Tk.__init__(self)
  11.         self.canvas = None
  12.         self.done_btn = None
  13.         self.zone_label = None
  14.         self.clear_btn = None
  15.         self.load_btn = None
  16.         self.cnt_zones = None
  17.  
  18.         self.tk_img = None
  19.         self.img_name = "preview_img.png"
  20.         self.colors = ["black", "red", "green", "blue", "cyan", "yellow", "magenta"]
  21.         self.curr_colors = ["black", "red", "green", "blue", "cyan", "yellow", "magenta"]
  22.  
  23.         self.height = None
  24.         self.width = None
  25.  
  26.         self.click_num = 0
  27.         self.x1 = self.y1 = None
  28.         self.start_x = self.start_y = None
  29.  
  30.         self.zones = []
  31.         self.curr_zone = []
  32.  
  33.         self.init_gui()
  34.  
  35.     def init_gui(self):
  36.         self.create_canvas()
  37.         self.load_btn = ttk.Button(self, text="Загрузить", command=self.load_image)
  38.         self.load_btn.grid(row=0, column=0)
  39.  
  40.         self.zone_label = ttk.Label(self, text="Текущее количество зон:")
  41.         self.zone_label.grid(row=1, column=0)
  42.  
  43.         self.cnt_zones = ttk.Label(self, text='0')
  44.         self.cnt_zones.grid(row=2, column=0)
  45.  
  46.         self.done_btn = ttk.Button(self, text="Завершить", command=self.save_zone)
  47.         self.done_btn.grid(row=3, column=0)
  48.  
  49.     def load_image(self):
  50.         filetypes = (
  51.             ('Изображения', '*.jpg; *.jpeg; *.png'),
  52.             ('Все файлы', '*.*')
  53.         )
  54.         self.img_name = filedialog.askopenfilename(title="Выбор изображения для разметки", filetypes=filetypes)
  55.         if self.img_name:
  56.             img = Image.open(self.img_name)
  57.             self.canvas.delete("all")
  58.             self.zones = []
  59.             self.curr_zone = []
  60.             self.x1 = None
  61.             self.y1 = None
  62.             self.click_num = 0
  63.             self.tk_img = ImageTk.PhotoImage(img)
  64.             self.height = self.tk_img.height()
  65.             self.width = self.tk_img.width()
  66.             self.canvas.config(width=self.width, height=self.height)
  67.             self.canvas.create_image(0, 0, anchor="nw", image=self.tk_img)
  68.  
  69.     def save_zone(self):
  70.         if len(self.zones) != 0:
  71.             messagebox.showinfo("Завершение!", "Разметка успешно завершена. Вы можете закрыть приложение.")
  72.             res_zones = {f"zone_{i}": coords for i, coords in enumerate(self.zones)}
  73.             with open('markup_data.json', 'w') as f:
  74.                 json.dump(res_zones, f)
  75.         else:
  76.             messagebox.showwarning("Предупреждение!", "Для начала выделите хотя бы одну зону.")
  77.  
  78.     def count_zones(self):
  79.         self.cnt_zones.config(text='{}'.format(len(self.zones)))
  80.  
  81.     def create_canvas(self):
  82.         self.canvas = tk.Canvas(self, width=self.width, height=self.height, background="white")
  83.         self.canvas.grid(row=0, column=1)
  84.         self.canvas.bind('<Button-1>', self.draw_line)
  85.         img = Image.open(self.img_name)
  86.         self.tk_img = ImageTk.PhotoImage(img)
  87.         self.height = self.tk_img.height()
  88.         self.width = self.tk_img.width()
  89.         self.canvas.create_image(0, 0, anchor="nw", image=self.tk_img)
  90.  
  91.     def clear_zone(self):
  92.         pass
  93.  
  94.     def draw_line(self, event):
  95.         if self.click_num == 0:
  96.             self.curr_zone = []
  97.             self.x1 = event.x
  98.             self.y1 = event.y
  99.             self.start_x = self.x1
  100.             self.start_y = self.y1
  101.             if len(self.curr_colors) == 0:
  102.                 self.curr_colors = self.colors
  103.             self.canvas.create_oval(self.x1 - 2, self.y1 - 2, self.x1 + 2, self.y1 + 2, width=0, fill=self.curr_colors[-1])
  104.             self.click_num = 1
  105.             self.curr_zone.append({"x": self.x1, "y": self.y1})
  106.         else:
  107.             x2 = event.x
  108.             y2 = event.y
  109.             self.curr_zone.append({"x": x2, "y": y2})
  110.             self.canvas.create_oval(x2 - 2, y2 - 2, x2 + 2, y2 + 2, width=0, fill=self.curr_colors[-1])
  111.             self.canvas.create_line(self.x1, self.y1, x2, y2, fill=self.curr_colors[-1], width=2)
  112.             self.x1 = x2
  113.             self.y1 = y2
  114.             self.click_num += 1
  115.             if self.click_num == 4:
  116.                 x2 = self.start_x
  117.                 y2 = self.start_y
  118.                 self.curr_zone.append({"x": self.x1, "y": self.y1})
  119.                 self.canvas.create_line(self.x1, self.y1, x2, y2, fill=self.curr_colors[-1], width=2)
  120.                 num_zone_x = (self.curr_zone[0]['x'] + self.curr_zone[2]['x']) // 2
  121.                 num_zone_y = (self.curr_zone[0]['y'] + self.curr_zone[2]['y']) // 2
  122.                 self.canvas.create_text(num_zone_x,
  123.                                         num_zone_y,
  124.                                         text=str(len(self.zones) + 1),
  125.                                         fill=self.curr_colors[-1],
  126.                                         font=('Helvetica 18 bold'))
  127.                 self.click_num = 0
  128.                 self.curr_colors.pop()
  129.                 self.zones.append(self.curr_zone)
  130.                 self.count_zones()
  131.  
  132.  
  133. if __name__ == '__main__':
  134.     app = MarkupApp()
  135.     app.mainloop()
  136.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement