| 13 | import time |
| 14 | |
| 15 | class MaskEditorGUI: |
| 16 | def __init__(self, root): |
| 17 | self.root = root |
| 18 | self.root.title("Mask Editor") |
| 19 | |
| 20 | # Video data |
| 21 | self.rgb_frames = [] |
| 22 | self.mask_frames = [] |
| 23 | self.current_frame = 0 |
| 24 | self.grid_rows = 0 |
| 25 | self.grid_cols = 0 |
| 26 | self.min_grid = 8 |
| 27 | |
| 28 | # Edit state |
| 29 | self.undo_stack = [] |
| 30 | self.redo_stack = [] |
| 31 | self.current_tool = "grid" # "grid" or "brush" |
| 32 | self.brush_size = 20 |
| 33 | self.brush_mode = "add" # "add" or "erase" |
| 34 | |
| 35 | # Display state |
| 36 | self.display_scale = 1.0 |
| 37 | self.rgb_photo = None |
| 38 | self.mask_photo = None |
| 39 | self.dragging = False |
| 40 | self.last_brush_pos = None |
| 41 | self.last_update_time = 0 |
| 42 | self.update_interval = 0.2 # Update every 200ms during dragging (5 FPS - less choppy) |
| 43 | self.cached_rgb_frame = None # Cache current RGB frame |
| 44 | self.cached_frame_idx = -1 # Track which frame is cached |
| 45 | self.pending_update = False # Track if update is needed after drag |
| 46 | self.brush_repeat_id = None # Timer for continuous brush application |
| 47 | |
| 48 | # Paths |
| 49 | self.folder_path = None |
| 50 | self.mask_path = None |
| 51 | self.rgb_path = None |
| 52 | |
| 53 | self.setup_ui() |
| 54 | |
| 55 | def setup_ui(self): |
| 56 | """Setup the GUI layout""" |
| 57 | # Menu bar |
| 58 | menubar = tk.Menu(self.root) |
| 59 | self.root.config(menu=menubar) |
| 60 | |
| 61 | file_menu = tk.Menu(menubar, tearoff=0) |
| 62 | menubar.add_cascade(label="File", menu=file_menu) |
| 63 | file_menu.add_command(label="Open Folder", command=self.load_folder) |
| 64 | file_menu.add_command(label="Save Mask", command=self.save_mask) |
| 65 | file_menu.add_separator() |
| 66 | file_menu.add_command(label="Exit", command=self.root.quit) |
| 67 | |
| 68 | edit_menu = tk.Menu(menubar, tearoff=0) |
| 69 | menubar.add_cascade(label="Edit", menu=edit_menu) |
| 70 | edit_menu.add_command(label="Undo", command=self.undo, accelerator="Ctrl+Z") |
| 71 | edit_menu.add_command(label="Redo", command=self.redo, accelerator="Ctrl+Y") |
| 72 | |