diff --git a/gui/GUICombiData.py b/gui/GUICombiData.py new file mode 100644 index 0000000..c2408f5 --- /dev/null +++ b/gui/GUICombiData.py @@ -0,0 +1,44 @@ +from gui.gui_yolo_class import GUIYoloClassData +from gui.gui_contour_extraction import GUIContourExtractionData +from gui.gui_alphabet import GUIAlphabetData +from gui.gui_outputmode import GUIOutputModeData +from gui.gui_sparsifier import GUISparsifierData + + +class GUICombiData: + def __init__(self) -> None: + self.yolo_class = GUIYoloClassData() + self.contour_extraction = GUIContourExtractionData() + self.alphabet = GUIAlphabetData() + self.output_mode = GUIOutputModeData() + self.sparsifier = GUISparsifierData() + + self.gui_running: bool = True + + def update(self, input) -> None: + self.yolo_class.update(input.yolo_class) + self.contour_extraction.update(input.contour_extraction) + self.alphabet.update(input.alphabet) + self.output_mode.update(input.output_mode) + self.sparsifier.update(input.sparsifier) + + def check_for_change(self) -> bool: + if self.yolo_class.data_changed is True: + return True + if self.contour_extraction.data_changed is True: + return True + if self.alphabet.data_changed is True: + return True + if self.output_mode.data_changed is True: + return True + if self.sparsifier.data_changed is True: + return True + + return False + + def reset_change_detector(self) -> None: + self.yolo_class.data_changed = False + self.contour_extraction.data_changed = False + self.alphabet.data_changed = False + self.output_mode.data_changed = False + self.sparsifier.data_changed = False diff --git a/gui/GUIEvents.py b/gui/GUIEvents.py new file mode 100644 index 0000000..270f30e --- /dev/null +++ b/gui/GUIEvents.py @@ -0,0 +1,113 @@ +import tkinter as tk +from tkinter import ttk + +from gui.gui_logo import GUILogoGUI +from gui.gui_yolo_class import GUIYoloClassGUI +from gui.gui_contour_extraction import GUIContourExtractionGUI +from gui.gui_alphabet import GUIAlphabetGUI +from gui.gui_outputmode import GUIOutputModeGUI +from gui.gui_sparsifier import GUISparsifierGUI +from gui.GUICombiData import GUICombiData + + +class GUIEvents: + tk_root: tk.Tk + exit_button: tk.ttk.Button + + def __init__(self, tk_root: tk.Tk, confdata: GUICombiData | None = None): + super().__init__() + assert confdata is not None + + width_element: int = 10 + width_label: int = 20 + width_button_extra: int = 5 + + self.tk_root = tk_root + self.tk_root.title("Percept Simulator 2023") + + self.confdata: GUICombiData = confdata + self.confdata.gui_running = True + + self.logo = GUILogoGUI(self.tk_root) + + # frame -> + self.frame = ttk.Frame(self.tk_root) + self.frame.pack() + # <- frame + + self.frame_left = ttk.Frame(self.frame) + self.frame_left.grid(row=0, column=0, sticky="nw") + + self.frame_right = ttk.Frame(self.frame) + self.frame_right.grid(row=0, column=1, sticky="nw") + + # gui_element_list -> + self.gui_element_list: list = [] + + self.gui_element_list.append( + GUIContourExtractionGUI( + self.frame_left, + name="Contour Extraction", + row_id=0, + column_id=0, + data_class=self.confdata.contour_extraction, + ) + ) + + self.gui_element_list.append( + GUIOutputModeGUI( + self.frame_left, + name="Display Options", + row_id=1, + column_id=0, + data_class=self.confdata.output_mode, + ) + ) + + self.gui_element_list.append( + GUISparsifierGUI( + self.frame_left, + name="Sparsifier Options", + row_id=2, + column_id=0, + data_class=self.confdata.sparsifier, + ) + ) + + self.gui_element_list.append( + GUIAlphabetGUI( + self.frame_right, + name="Alphabet", + row_id=0, + column_id=0, + data_class=self.confdata.alphabet, + ) + ) + + self.gui_element_list.append( + GUIYoloClassGUI( + self.frame_right, + name="Yolo", + row_id=1, + column_id=0, + data_class=self.confdata.yolo_class, + ) + ) + + # <- gui_element_list + + self.exit_button = ttk.Button( + self.frame, + text="--> EXIT <--", + command=self.exit_button_pressed, + width=2 * (width_label + width_element + width_button_extra), + ) + self.exit_button.grid(row=2, column=0, sticky="we", columnspan=2, pady=5) + + # windows close button -> + self.tk_root.protocol("WM_DELETE_WINDOW", self.exit_button_pressed) + # <- windows close button + + def exit_button_pressed(self) -> None: + self.confdata.gui_running = False + self.tk_root.destroy() diff --git a/gui/GUIMasterData.py b/gui/GUIMasterData.py new file mode 100644 index 0000000..07b7200 --- /dev/null +++ b/gui/GUIMasterData.py @@ -0,0 +1,26 @@ +class GUIMasterData: + data_changed: bool = False + data_type: str = "" + do_not_update: list[str] = ["do_not_update", "data_type"] + + def __init__(self) -> None: + self.data_type = str(type(self)).split(".")[-1][:-2] + + def update(self, input) -> None: + to_update: list[str] = [] + + something_todo = getattr(input, "data_changed", None) + if (something_todo is None) or (something_todo is False): + return + + for vars in dir(self): + if vars.startswith("__") is False: + if not callable(getattr(self, vars)): + if (vars in self.do_not_update) is False: + to_update.append(vars) + + input_name = getattr(input, "data_type", None) + if (input_name is not None) and (input_name == self.data_type): + for vars in to_update: + data_in = getattr(input, vars, None) + setattr(self, vars, data_in) diff --git a/gui/GUIMasterGUI.py b/gui/GUIMasterGUI.py new file mode 100644 index 0000000..96519b4 --- /dev/null +++ b/gui/GUIMasterGUI.py @@ -0,0 +1,25 @@ +import tkinter as tk +from tkinter import ttk + + +class GUIMasterGUI: + my_tk_root: tk.Tk | tk.ttk.Labelframe | tk.ttk.Frame + + verbose: bool = True + + def __init__( + self, + tk_root: tk.Tk | tk.ttk.Labelframe | tk.ttk.Frame, + name: str, + row_id: int, + column_id: int, + data_class=None, + ): + assert data_class is not None + super().__init__() + + self.my_tk_root = tk_root + self.data = data_class + + self.frame = ttk.LabelFrame(self.my_tk_root, text=name) + self.frame.grid(row=row_id, column=column_id, sticky="nw", pady=5) diff --git a/gui/gui_alphabet.py b/gui/gui_alphabet.py new file mode 100644 index 0000000..a96e9f1 --- /dev/null +++ b/gui/gui_alphabet.py @@ -0,0 +1,214 @@ +from gui.GUIMasterData import GUIMasterData +from gui.GUIMasterGUI import GUIMasterGUI +import tkinter as tk +from tkinter import ttk + + +class GUIAlphabetData(GUIMasterData): + phosphene_sigma_width: float + size_DVA: float + clocks_n_dir: int + clocks_pointer_width: float + clocks_pointer_length: float + selection: int = 0 + + tau_SEC: float = 0.3 + p_FEATperSECperPOS: float = 3.0 + + def __init__(self) -> None: + super().__init__() + + self.phosphene_sigma_width = 0.18 + self.size_DVA = 1.0 + + self.clocks_n_dir = 8 + self.clocks_pointer_width = 0.07 + self.clocks_pointer_length = 0.18 + + +class GUIAlphabetGUI(GUIMasterGUI): + def __init__( + self, + tk_root: tk.Tk | tk.ttk.Labelframe | tk.ttk.Frame, + name: str = "Alphabet", + row_id: int = 0, + column_id: int = 2, + data_class=None, + ) -> None: + super().__init__( + tk_root, + name=name, + row_id=row_id, + column_id=column_id, + data_class=data_class, + ) + width_element: int = 10 + width_label: int = 20 + width_button_extra: int = 5 + + # patch_size -> + self.label_size_DVA = ttk.Label( + self.frame, text="Patch size [DVA]", width=width_label + ) + self.label_size_DVA.grid(row=0, column=0, sticky="nw") + + self.entry_string_var_size_DVA = tk.StringVar( + value=f"{self.data.size_DVA}", + ) + + self.entry_size_DVA = ttk.Entry( + self.frame, + textvariable=self.entry_string_var_size_DVA, + width=width_element, + ) + self.entry_size_DVA.grid(row=0, column=1, sticky="nw") + # <- patch_size + + # tau_SEC -> + self.label_tau_SEC = ttk.Label( + self.frame, text="Patch decay [s]", width=width_label + ) + self.label_tau_SEC.grid(row=1, column=0, sticky="nw") + + self.entry_string_var_tau_SEC = tk.StringVar( + value=f"{self.data.tau_SEC}", + ) + + self.entry_tau_SEC = ttk.Entry( + self.frame, + textvariable=self.entry_string_var_tau_SEC, + width=width_element, + ) + self.entry_tau_SEC.grid(row=1, column=1, sticky="nw") + # <- tau_SEC + + # p_FEATperSECperPOS -> + self.label_p_FEATperSECperPOS = ttk.Label( + self.frame, text="Patch prob [1/s pos]", width=width_label + ) + self.label_p_FEATperSECperPOS.grid(row=2, column=0, sticky="nw", pady=[0, 15]) + + self.entry_string_var_p_FEATperSECperPOS = tk.StringVar( + value=f"{self.data.p_FEATperSECperPOS}", + ) + + self.entry_p_FEATperSECperPOS = ttk.Entry( + self.frame, + textvariable=self.entry_string_var_p_FEATperSECperPOS, + width=width_element, + ) + self.entry_p_FEATperSECperPOS.grid(row=2, column=1, sticky="nw", pady=[0, 15]) + # <- p_FEATperSECperPOS + + # Phosphene vs Clock -> + self.radio_selection_var = tk.IntVar() + self.radio_selection_var.set(self.data.selection) + + self.option0 = ttk.Radiobutton( + self.frame, + text="Phosphene", + variable=self.radio_selection_var, + value=0, + ) + self.option0.grid(row=3, column=0, sticky="w", pady=5) + + # sigma_width -> + self.label_sigma_width = ttk.Label( + self.frame, text="Sigma Width", width=width_label + ) + self.label_sigma_width.grid(row=4, column=0, sticky="w") + + self.entry_string_var_sigma_width = tk.StringVar( + value=f"{self.data.phosphene_sigma_width}", + ) + + self.entry_sigma_width = ttk.Entry( + self.frame, + textvariable=self.entry_string_var_sigma_width, + width=width_element, + ) + self.entry_sigma_width.grid(row=4, column=1, sticky="w") + # <- sigma_width + + self.option1 = ttk.Radiobutton( + self.frame, + text="Clock", + variable=self.radio_selection_var, + value=1, + ) + self.option1.grid(row=5, column=0, sticky="w", pady=[15, 0]) + # <- Phosphene vs Clock + + # clocks_n_dir -> + self.label_clocks_n_dir = ttk.Label( + self.frame, text="Number Orientations", width=width_label + ) + self.label_clocks_n_dir.grid(row=6, column=0, sticky="w") + + self.spinbox_clocks_n_dir = ttk.Spinbox( + self.frame, + values=list("{:d}".format(x) for x in range(1, 33)), + width=width_element, + ) + self.spinbox_clocks_n_dir.grid(row=6, column=1, sticky="w") + self.spinbox_clocks_n_dir.set(self.data.clocks_n_dir) + # <- clocks_n_dir + + # clocks_pointer_width -> + self.label_clocks_pointer_width = ttk.Label( + self.frame, text="Pointer Width", width=width_label + ) + self.label_clocks_pointer_width.grid(row=7, column=0, sticky="w") + + self.entry_string_var_clocks_pointer_width = tk.StringVar( + value=f"{self.data.clocks_pointer_width}" + ) + self.entry_clocks_pointer_width = ttk.Entry( + self.frame, + textvariable=self.entry_string_var_clocks_pointer_width, + width=width_element, + ) + self.entry_clocks_pointer_width.grid(row=7, column=1, sticky="w") + # <- clocks_pointer_width + + # clocks_pointer_length -> + self.label_clocks_pointer_length = ttk.Label( + self.frame, text="Pointer Length", width=width_label + ) + self.label_clocks_pointer_length.grid(row=8, column=0, sticky="w") + + self.entry_string_var_clocks_pointer_length = tk.StringVar( + value=f"{self.data.clocks_pointer_length}" + ) + self.entry_clocks_pointer_length = ttk.Entry( + self.frame, + textvariable=self.entry_string_var_clocks_pointer_length, + width=width_element, + ) + self.entry_clocks_pointer_length.grid(row=8, column=1, sticky="w") + # <- clocks_pointer_length + + # button_configure -> + self.button_configure = ttk.Button( + self.frame, + text="Configure", + command=self.button_configure_pressed, + width=(width_label + width_element + width_button_extra), + ) + self.button_configure.grid(row=9, column=0, sticky="w", columnspan=2, pady=5) + + # <- button_configure + + def button_configure_pressed(self) -> None: + self.data.phosphene_sigma_width = float(self.entry_sigma_width.get()) + + self.data.size_DVA = float(self.entry_size_DVA.get()) + self.data.tau_SEC = float(self.entry_tau_SEC.get()) + self.data.p_FEATperSECperPOS = float(self.entry_p_FEATperSECperPOS.get()) + + self.data.clocks_n_dir = int(self.spinbox_clocks_n_dir.get()) + self.data.clocks_pointer_width = float(self.entry_clocks_pointer_width.get()) + self.data.clocks_pointer_length = float(self.entry_clocks_pointer_length.get()) + + self.data.selection = int(self.radio_selection_var.get()) + self.data.data_changed = True diff --git a/gui/gui_contour_extraction.py b/gui/gui_contour_extraction.py new file mode 100644 index 0000000..ec6a095 --- /dev/null +++ b/gui/gui_contour_extraction.py @@ -0,0 +1,102 @@ +from gui.GUIMasterData import GUIMasterData +from gui.GUIMasterGUI import GUIMasterGUI +import tkinter as tk +from tkinter import ttk + +import torch +import torchvision as tv + + +class GUIContourExtractionData(GUIMasterData): + sigma_kernel_DVA: float = 0.06 + # sigma_kernel: float + # lambda_kernel: float + n_orientations: int = 8 + + # padding_x: int + # padding_y: int + # padding_fill: int + + def __init__(self) -> None: + super().__init__() + + # self.calculate_setting() + # self.padding_fill: int = int( + # tv.transforms.functional.rgb_to_grayscale( + # torch.full((3, 1, 1), 0) + # ).squeeze() + # ) + + # def calculate_setting(self) -> None: + # self.sigma_kernel = 1.0 * self.scale_kernel + # self.lambda_kernel = 2.0 * self.scale_kernel + # self.padding_x: int = int(3.0 * self.scale_kernel) + # self.padding_y: int = int(3.0 * self.scale_kernel) + + +class GUIContourExtractionGUI(GUIMasterGUI): + def __init__( + self, + tk_root: tk.Tk | tk.ttk.Labelframe | tk.ttk.Frame, + name: str = "Contour extraction", + row_id: int = 0, + column_id: int = 0, + data_class=None, + ): + super().__init__( + tk_root, + name=name, + row_id=row_id, + column_id=column_id, + data_class=data_class, + ) + width_element: int = 10 + width_label: int = 20 + width_button_extra: int = 5 + + # orientations -> + self.label_orientations = ttk.Label( + self.frame, text="Number orientations", width=width_label + ) + self.label_orientations.grid(row=0, column=0, sticky="w") + + self.spinbox_n_orientations = ttk.Spinbox( + self.frame, + values=list("{:d}".format(x) for x in range(1, 33)), + width=width_element, + ) + self.spinbox_n_orientations.grid(row=0, column=1, sticky="w") + self.spinbox_n_orientations.set(self.data.n_orientations) + # <- orientations + + # scale_kernel -> + self.label_scale_kernel = ttk.Label( + self.frame, text="Scale sigma [DVA]", width=width_label + ) + self.label_scale_kernel.grid(row=1, column=0, sticky="w") + + self.string_var_scale_kernel = tk.StringVar( + value=f"{self.data.sigma_kernel_DVA}" + ) + + self.entry_scale_kernel = ttk.Entry( + self.frame, textvariable=self.string_var_scale_kernel, width=width_element + ) + self.entry_scale_kernel.grid(row=1, column=1, sticky="w") + # <- scale_kernel + + # button_configure -> + self.button_configure = ttk.Button( + self.frame, + text="Configure", + command=self.button_configure_pressed, + width=(width_label + width_element + width_button_extra), + ) + self.button_configure.grid(row=2, column=0, sticky="w", columnspan=2, pady=5) + # <- button_configure + + def button_configure_pressed(self) -> None: + self.data.n_orientations = int(self.spinbox_n_orientations.get()) + self.data.sigma_kernel_DVA = float(self.entry_scale_kernel.get()) + # self.data.calculate_setting() + self.data.data_changed = True diff --git a/gui/gui_logo.py b/gui/gui_logo.py new file mode 100644 index 0000000..54089ce --- /dev/null +++ b/gui/gui_logo.py @@ -0,0 +1,31 @@ +import tkinter as tk + +from PIL import Image, ImageTk +import os + + +class GUILogoGUI: + logo: tk.Canvas + logo_image: int + my_tk_root: tk.Tk + + pic_path: str = os.path.join("gui", "logo") + + def __init__(self, tk_root: tk.Tk): + self.my_tk_root = tk_root + + logo_filename: str = os.path.join(self.pic_path, "ISee2.png") + pil_image = Image.open(logo_filename) + self.pil_imagetk = ImageTk.PhotoImage(pil_image) + canvas_width: int = pil_image.width + canvas_height: int = pil_image.height + + self.logo = tk.Canvas(self.my_tk_root, width=canvas_width, height=canvas_height) + self.logo.pack() + + self.logo_image = self.logo.create_image( + 0, + 0, + anchor=tk.NW, + image=self.pil_imagetk, + ) diff --git a/gui/gui_outputmode.py b/gui/gui_outputmode.py new file mode 100644 index 0000000..f842655 --- /dev/null +++ b/gui/gui_outputmode.py @@ -0,0 +1,102 @@ +from gui.GUIMasterData import GUIMasterData +from gui.GUIMasterGUI import GUIMasterGUI +import tkinter as tk +from tkinter import ttk + + +class GUIOutputModeData(GUIMasterData): + + enable_cam: bool = True + enable_yolo: bool = True + enable_contour: bool = True + enable_percept: bool = True + + +class GUIOutputModeGUI(GUIMasterGUI): + def __init__( + self, + tk_root: tk.Tk | tk.ttk.Labelframe | tk.ttk.Frame, + name: str = "Output Filter", + row_id: int = 0, + column_id: int = 3, + data_class=None, + ) -> None: + super().__init__( + tk_root, + name=name, + row_id=row_id, + column_id=column_id, + data_class=data_class, + ) + + width_element: int = 10 + width_label: int = 20 + width_button_extra: int = 5 + + # option0 -> + self.option0_var = tk.IntVar() + self.option0_var.set(int(self.data.enable_cam)) + self.option0 = ttk.Checkbutton( + self.frame, + text="CAM", + onvalue=1, + offvalue=0, + variable=self.option0_var, + command=self.selection_changed, + width=(width_label + width_element + width_button_extra), + ) + self.option0.pack(anchor=tk.W) + # <- option0 + + # option1 -> + self.option1_var = tk.IntVar() + self.option1_var.set(int(self.data.enable_yolo)) + self.option1 = ttk.Checkbutton( + self.frame, + text="YOLO", + onvalue=1, + offvalue=0, + variable=self.option1_var, + command=self.selection_changed, + width=(width_label + width_element + width_button_extra), + ) + self.option1.pack(anchor=tk.W) + # <- option1 + + # option2 ->bool(self.option0_var.get()) + self.option2_var = tk.IntVar() + self.option2_var.set(int(self.data.enable_contour)) + self.option2 = ttk.Checkbutton( + self.frame, + text="Contour", + onvalue=1, + offvalue=0, + variable=self.option2_var, + command=self.selection_changed, + width=(width_label + width_element + width_button_extra), + ) + self.option2.pack(anchor=tk.W) + # <- option2 + + # option3 -> + self.option3_var = tk.IntVar() + self.option3_var.set(int(self.data.enable_percept)) + self.option3 = ttk.Checkbutton( + self.frame, + text="Percept", + onvalue=1, + offvalue=0, + variable=self.option3_var, + command=self.selection_changed, + width=(width_label + width_element + width_button_extra), + ) + self.option3.pack(anchor=tk.W) + # <- option3 + + def selection_changed(self): + self.data.enable_cam = bool(self.option0_var.get()) + self.data.enable_yolo = bool(self.option1_var.get()) + self.data.enable_contour = bool(self.option2_var.get()) + self.data.enable_percept = bool(self.option3_var.get()) + + self.data.data_changed = True diff --git a/gui/gui_sparsifier.py b/gui/gui_sparsifier.py new file mode 100644 index 0000000..3872611 --- /dev/null +++ b/gui/gui_sparsifier.py @@ -0,0 +1,156 @@ +from gui.GUIMasterData import GUIMasterData +from gui.GUIMasterGUI import GUIMasterGUI +import tkinter as tk +from tkinter import ttk + + +class GUISparsifierData(GUIMasterData): + + number_of_patches: int = 10 + + use_exp_deadzone: bool = True + size_exp_deadzone_DVA: float = 1.0 + + use_cutout_deadzone: bool = True + size_cutout_deadzone_DVA: float = 1.0 + + +class GUISparsifierGUI(GUIMasterGUI): + def __init__( + self, + tk_root: tk.Tk | tk.ttk.Labelframe | tk.ttk.Frame, + name: str = "Sparsifier Options", + row_id: int = 0, + column_id: int = 4, + data_class=None, + ) -> None: + super().__init__( + tk_root, + name=name, + row_id=row_id, + column_id=column_id, + data_class=data_class, + ) + + width_element: int = 10 + width_label: int = 20 + width_button_extra: int = 5 + + # number_of_patches -> + self.label_number_of_patches = ttk.Label( + self.frame, text="Number Patches", width=width_label + ) + self.label_number_of_patches.grid(row=0, column=0, sticky="w") + + self.spinbox_number_of_patches = ttk.Spinbox( + self.frame, + values=list("{:d}".format(x) for x in range(1, 301)), + width=width_element, + ) + self.spinbox_number_of_patches.grid(row=0, column=1, sticky="w") + self.spinbox_number_of_patches.set(self.data.number_of_patches) + # <- number_of_patches + + self.label_forbidden_zone = ttk.Label( + self.frame, text="Forbidden Zone:", width=width_label + ) + self.label_forbidden_zone.grid(row=1, column=0, sticky="w", pady=[15, 0]) + # use_cutout_deadzone -> + + self.label_use_cutout_deadzone = ttk.Label( + self.frame, text="Hard Circle", width=width_label + ) + self.label_use_cutout_deadzone.grid(row=2, column=0, sticky="w") + + self.use_cutout_deadzone_var = tk.IntVar() + self.checkbox_use_cutout_deadzone = ttk.Checkbutton( + self.frame, + text="Enable", + onvalue=1, + offvalue=0, + variable=self.use_cutout_deadzone_var, + width=width_element, + ) + self.checkbox_use_cutout_deadzone.grid( + row=2, + column=1, + sticky="w", + ) + self.use_cutout_deadzone_var.set(int(self.data.use_cutout_deadzone)) + # <- use_cutout_deadzone + + # size_cutout_deadzone_DVA -> + self.label_size_cutout_deadzone_DVA = ttk.Label( + self.frame, text="Size Hard Circle", width=width_label + ) + self.label_size_cutout_deadzone_DVA.grid(row=3, column=0, sticky="w") + + self.entry_size_cutout_deadzone_DVA_var = tk.StringVar() + self.entry_size_cutout_deadzone_DVA_var.set( + str(self.data.size_cutout_deadzone_DVA) + ) + self.entry_size_cutout_deadzone_DVA = ttk.Entry( + self.frame, + textvariable=self.entry_size_cutout_deadzone_DVA_var, + width=width_element, + ) + self.entry_size_cutout_deadzone_DVA.grid(row=3, column=1, sticky="w") + # <- size_cutout_deadzone_DVA + + # use_exp_deadzone -> + + self.label_use_exp_deadzone = ttk.Label( + self.frame, text="Exponential Decay", width=width_label + ) + self.label_use_exp_deadzone.grid(row=4, column=0, sticky="w") + + self.checkbox_use_exp_deadzone_var = tk.IntVar() + self.checkbox_use_exp_deadzone = ttk.Checkbutton( + self.frame, + text="Enable", + onvalue=1, + offvalue=0, + variable=self.checkbox_use_exp_deadzone_var, + width=width_element, + ) + self.checkbox_use_exp_deadzone.grid(row=4, column=1, sticky="w") + self.checkbox_use_exp_deadzone_var.set(int(self.data.use_exp_deadzone)) + # <- use_exp_deadzone + + # size_exp_deadzone_DVA -> + self.label_size_exp_deadzone_DVA = ttk.Label( + self.frame, text="Size Exponential Decay", width=width_label + ) + self.label_size_exp_deadzone_DVA.grid(row=5, column=0, sticky="w") + + self.entry_size_exp_deadzone_DVA_var = tk.StringVar() + self.entry_size_exp_deadzone_DVA_var.set(str(self.data.size_exp_deadzone_DVA)) + self.entry_size_exp_deadzone_DVA = ttk.Entry( + self.frame, + textvariable=self.entry_size_exp_deadzone_DVA_var, + width=width_element, + ) + self.entry_size_exp_deadzone_DVA.grid(row=5, column=1, sticky="w") + # <- size_exp_deadzone_DVA + + # button_configure -> + self.button_configure = ttk.Button( + self.frame, + text="Configure", + command=self.button_configure_pressed, + width=(width_label + width_element + width_button_extra), + ) + self.button_configure.grid(row=6, column=0, sticky="w", columnspan=2, pady=5) + # <- button_configure + + def button_configure_pressed(self): + self.data.number_of_patches = int(self.spinbox_number_of_patches.get()) + self.data.use_cutout_deadzone = bool(self.use_cutout_deadzone_var.get()) + self.data.use_exp_deadzone = bool(self.checkbox_use_exp_deadzone_var.get()) + self.data.size_cutout_deadzone_DVA = float( + self.entry_size_cutout_deadzone_DVA_var.get() + ) + self.data.size_exp_deadzone_DVA = float( + self.entry_size_exp_deadzone_DVA_var.get() + ) + self.data.data_changed = True diff --git a/gui/gui_yolo_class.py b/gui/gui_yolo_class.py new file mode 100644 index 0000000..09f55ac --- /dev/null +++ b/gui/gui_yolo_class.py @@ -0,0 +1,143 @@ +from gui.GUIMasterData import GUIMasterData +from gui.GUIMasterGUI import GUIMasterGUI +import tkinter as tk +from tkinter import ttk + + +class GUIYoloClassData(GUIMasterData): + default_value: str = "--: None" + + available_classes: list[str] = [ + "--: None", + "00: person", + "01: bicycle", + "02: car", + "03: motorcycle", + "04: airplane", + "05: bus", + "06: train", + "07: truck", + "08: boat", + "09: traffic light", + "10: fire hydrant", + "11: stop sign", + "12: parking meter", + "13: bench", + "14: bird", + "15: cat", + "16: dog", + "17: horse", + "18: sheep", + "19: cow", + "20: elephant", + "21: bear", + "22: zebra", + "23: giraffe", + "24: backpack", + "25: umbrella", + "26: handbag", + "27: tie", + "28: suitcase", + "29: frisbee", + "30: skis", + "31: snowboard", + "32: sports ball", + "33: kite", + "34: baseball bat", + "35: baseball glove", + "36: skateboard", + "37: surfboard", + "38: tennis racket", + "39: bottle", + "40: wine glass", + "41: cup", + "42: fork", + "43: knife", + "44: spoon", + "45: bowl", + "46: banana", + "47: apple", + "48: sandwich", + "49: orange", + "50: broccoli", + "51: carrot", + "52: hot dog", + "53: pizza", + "54: donut", + "55: cake", + "56: chair", + "57: couch", + "58: potted plant", + "59: bed", + "60: dining table", + "61: toilet", + "62: tv", + "63: laptop", + "64: mouse", + "65: remote", + "66: keyboard", + "67: cell phone", + "68: microwave", + "69: oven", + "70: toaster", + "71: sink", + "72: refrigerator", + "73: book", + "74: clock", + "75: vase", + "76: scissors", + "77: teddy bear", + "78: hair drier", + "79: toothbrush", + ] + + value: list[int] | None = None + + def __init__(self) -> None: + super().__init__() + self.do_not_update.append(str("default_value")) + self.do_not_update.append(str("available_classes")) + + +class GUIYoloClassGUI(GUIMasterGUI): + def __init__( + self, + tk_root: tk.Tk | tk.ttk.Labelframe | tk.ttk.Frame, + name: str = "Yolo", + row_id: int = 1, + column_id: int = 0, + data_class=None, + ) -> None: + super().__init__( + tk_root, + name=name, + row_id=row_id, + column_id=column_id, + data_class=data_class, + ) + + width_element: int = 10 + width_label: int = 20 + width_button_extra: int = 5 + + self.selection: tk.ttk.Combobox = ttk.Combobox( + self.frame, width=(width_label + width_element + width_button_extra) + ) + self.selection["state"] = "readonly" + self.selection["values"] = self.data.available_classes + self.selection.pack() + self.selection.bind("<>", self.selection_changed) + self.selection.set(self.data.default_value) + self.selection_value = None + + def selection_changed(self, event) -> None: + temp: str = self.selection.get() + if temp[0] == "-": + self.data.value = None + else: + self.data.value = [int(temp[0:2])] + + if self.verbose is True: + print(f"Class changed to: {self.data.value}") + + self.data.data_changed = True diff --git a/gui/logo/ISee2.png b/gui/logo/ISee2.png new file mode 100644 index 0000000..1ac6b5c Binary files /dev/null and b/gui/logo/ISee2.png differ