Label and Resize Functionality has been added
This commit is contained in:
parent
8510a48022
commit
8e7e65f04e
|
@ -0,0 +1,610 @@
|
|||
import customtkinter as Ctk
|
||||
import os
|
||||
from PIL import Image, ImageTk, ImageDraw
|
||||
import io
|
||||
from scripts.SaveData import SaveData
|
||||
import scripts.get_sys_info as system_code
|
||||
|
||||
|
||||
|
||||
class Labeling(Ctk.CTkFrame):
|
||||
def __init__(self,master,img_paths, output_path, callback, window_information, **kwargs):
|
||||
super().__init__(master, **kwargs)
|
||||
system_code.load_json_file()
|
||||
self.data_saver = SaveData()
|
||||
self.my_font = Ctk.CTkFont(family="Berlin Sans FB", size=22)
|
||||
self.image_btn_size = system_code.btn_img_size
|
||||
#callback
|
||||
self.callback = callback
|
||||
self.window_information = window_information
|
||||
# Image resources
|
||||
self.create_folder_image_path = r"./icons/create_folder.png"
|
||||
self.open_folder_image_path = r"./icons/open_folder.png"
|
||||
self.source_folder_image_path = r"./icons/source_folder.png"
|
||||
# Load and resize image as before
|
||||
self.create_folder_raw_image = Image.open(self.create_folder_image_path)
|
||||
self.open_folder_raw_image = Image.open(self.open_folder_image_path)
|
||||
self.source_folder_raw_image = Image.open(self.source_folder_image_path)
|
||||
self.load_button_images()
|
||||
# for the image show_process
|
||||
self.image_scale_init()
|
||||
# variables for the labeling itself
|
||||
self.index = 0 # when this gets opened we always want to start a 0.
|
||||
self.img_paths = img_paths
|
||||
self.active_output_path = output_path
|
||||
self.output_path = output_path
|
||||
|
||||
# bounding boxes
|
||||
self.labeling_boxes = []
|
||||
self.labeling_box_index = 0
|
||||
self.original_factor = None
|
||||
self.img_factor_x = None
|
||||
self.img_factor_y = None
|
||||
self.resolution = None
|
||||
self.labeled = False
|
||||
self.mpenn_data = self.data_saver.search_in_folder(self.active_output_path)
|
||||
self.save_index = self.data_saver.find_highest_image_number(self.mpenn_data[0])
|
||||
|
||||
self.bind("<n>", self.save_and_load)
|
||||
|
||||
self.start()
|
||||
|
||||
def update_active_output_path(self, output_path):
|
||||
self.active_output_path = output_path
|
||||
self.mpenn_data = self.data_saver.search_in_folder(self.active_output_path)
|
||||
self.save_index = self.data_saver.find_highest_image_number(self.mpenn_data[0])
|
||||
|
||||
def start(self):
|
||||
self.create_labeling()
|
||||
self.show_img(self.img_paths[self.index])
|
||||
|
||||
def open_new_folder(self):
|
||||
"""
|
||||
Callback for when a new folder is chosen.
|
||||
"""
|
||||
self.callback(self.output_path, 1) # Call the callback passing the current value
|
||||
|
||||
def create_new_folder(self):
|
||||
"""
|
||||
Callback for when a new folder is chosen.
|
||||
"""
|
||||
self.callback(self.output_path, 0) # Call the callback passing the current value
|
||||
|
||||
def return_image_information(self):
|
||||
# Extract the directory of the image file
|
||||
image_directory = os.path.dirname(self.img_paths[self.index])
|
||||
|
||||
# Now extract the folder name
|
||||
desired_folder = os.path.basename(image_directory)
|
||||
desired_name = os.path.basename(self.img_paths[self.index])
|
||||
|
||||
# Creating a tuple with the extracted information
|
||||
text_information = (desired_name, desired_folder, self.active_output_path)
|
||||
|
||||
# Presumed function to show or use the information
|
||||
self.window_information(text_information)
|
||||
|
||||
|
||||
def source_folder_dialog(self):
|
||||
self.callback(None, 2)
|
||||
|
||||
def image_scale_init(self):
|
||||
self.original_image = None
|
||||
self.displayed_image = None
|
||||
self.dragging = False
|
||||
self.resize_pending = False
|
||||
self.after_id = None
|
||||
self.tk_image = None
|
||||
self.rect = None # Keep track of the rectangle element
|
||||
self.start_x = None
|
||||
self.start_y = None
|
||||
self.end_x = None # Track the end position of the drag
|
||||
self.end_y = None
|
||||
self.image_position = (0, 0) # Initialize image position
|
||||
self.tk_cropped_image = None
|
||||
self.save_cropped = None
|
||||
|
||||
|
||||
# the Labeling part
|
||||
def create_labeling(self):
|
||||
"""adapt button size to window_size"""
|
||||
self.big_canvas = Ctk.CTkCanvas(self,background="#5f00c7", bd=0, highlightthickness=0)
|
||||
self.reset_btn = Ctk.CTkButton(self, text="reset Image", width=100, command=self.reset_rectangle, font=self.my_font)
|
||||
self.create_folder_btn = Ctk.CTkButton(self,image=self.create_folder_image, text="", width=100, command=self.create_new_folder, font=self.my_font)
|
||||
self.open_folder_btn = Ctk.CTkButton(self, image=self.open_folder_image,text="", width=100, command=self.open_new_folder, font=self.my_font)
|
||||
self.save_img_btn = Ctk.CTkButton(self, text="Save Image", width=100, command=self.save_and_load, font=self.my_font)
|
||||
self.delete_img_btn = Ctk.CTkButton(self, text="Delete Image", width=100, command=self.delete_img, font=self.my_font)
|
||||
self.skip_time_btn = Ctk.CTkButton(self, text="Jump", width=100, command=self.skip_time, font=self.my_font)
|
||||
self.new_source_btn = Ctk.CTkButton(self,image=self.source_folder_image, text="", width=100, command=self.source_folder_dialog, font=self.my_font)
|
||||
self.preview_canvas = Ctk.CTkCanvas(self,background="#5f00c7", bd=0, highlightthickness=0)
|
||||
self.start_mode = Ctk.StringVar(value=system_code.data_mode)
|
||||
self.choose_mode = Ctk.CTkSegmentedButton(self, values= system_code.data_modes,
|
||||
variable=self.start_mode,
|
||||
command=self.set_data_mode,width=64,font=self.my_font)
|
||||
|
||||
# big_canvas
|
||||
self.big_canvas.bind("<ButtonPress-1>", self.on_press)
|
||||
self.big_canvas.bind("<B1-Motion>", self.on_drag)
|
||||
self.big_canvas.bind("<ButtonRelease-1>", self.on_release)
|
||||
self.after_idle(self.adjust_image_sizes_for_buttons)
|
||||
self.bind("<Configure>", self.on_resize)
|
||||
self.place_labeling()
|
||||
|
||||
def set_data_mode(self, value):
|
||||
system_code.data_mode = value
|
||||
print(system_code.data_mode)
|
||||
if system_code.data_mode == "Resize":
|
||||
self.reset_rectangle()
|
||||
else:
|
||||
if self.tk_cropped_image is not None:
|
||||
self.show_img(self.save_cropped)
|
||||
else:
|
||||
self.show_img(self.img_paths[self.index])
|
||||
|
||||
|
||||
def adjust_image_sizes_for_buttons(self):
|
||||
"""Adjust the image sizes based on the current height of the buttons and update them accordingly."""
|
||||
self.update_idletasks() # Force Tkinter to finalize the window layout
|
||||
|
||||
example_button_height = self.create_folder_btn.winfo_height()
|
||||
example_button_width = self.create_folder_btn.winfo_width()
|
||||
|
||||
# Assuming buttons' height as a basis for square image size
|
||||
orientation_value = min(example_button_height, example_button_width) - 25
|
||||
|
||||
# Ensure the orientation_value does not drop below a minimum size threshold
|
||||
orientation_value = max(orientation_value, 1) # Prevents size from being 0 or negative
|
||||
|
||||
# Your existing logic to resize and apply the images
|
||||
self.image_btn_size = (orientation_value, orientation_value)
|
||||
self.load_button_images()
|
||||
|
||||
self.create_folder_btn.configure(image=self.create_folder_image)
|
||||
self.open_folder_btn.configure(image=self.open_folder_image)
|
||||
self.new_source_btn.configure(image=self.source_folder_image)
|
||||
|
||||
self.create_folder_btn.image = self.create_folder_image
|
||||
self.open_folder_btn.image = self.open_folder_image
|
||||
self.new_source_btn.image = self.source_folder_image
|
||||
|
||||
|
||||
def load_button_images(self):
|
||||
"""
|
||||
Load, resize button images to the specified size and convert them into a Tkinter-compatible format.
|
||||
"""
|
||||
# Convert PIL images to Ctk.CTkImage objects for compatibility with Tkinter/customtkinter
|
||||
self.create_folder_image = Ctk.CTkImage(self.create_folder_raw_image , size =self.image_btn_size)
|
||||
self.open_folder_image = Ctk.CTkImage(self.open_folder_raw_image, size =self.image_btn_size)
|
||||
self.source_folder_image = Ctk.CTkImage(self.source_folder_raw_image, size =self.image_btn_size)
|
||||
|
||||
def reset_rectangle(self):
|
||||
# Check if there is a rectangle to delete
|
||||
if self.rect:
|
||||
self.delete_current_rectangle(self.rect)
|
||||
for rect in self.labeling_boxes:
|
||||
self.delete_current_rectangle(rect[0])
|
||||
self.labeling_boxes = []
|
||||
self.labeling_box_index = 0
|
||||
self.rect = None
|
||||
self.draw = None
|
||||
self.preview_canvas.delete("all")
|
||||
|
||||
def save_and_load(self):
|
||||
save_path = f"{self.active_output_path}/{self.save_index:03d}{system_code.img_format}"
|
||||
if system_code.data_mode == "Labeling":
|
||||
if len(self.labeling_boxes) == 0:
|
||||
self.labeled = False
|
||||
else:
|
||||
image = self.draw_rects(self.original_image)
|
||||
image.save(save_path)
|
||||
self.resolution = image.size
|
||||
elif self.tk_cropped_image is not None:
|
||||
self.save_cropped.save(save_path)
|
||||
self.resolution = self.save_cropped.size
|
||||
|
||||
|
||||
print( self.labeling_boxes)
|
||||
self.data_saver.append_to_json_file(save_path, self.resolution, self.labeled, self.labeling_boxes, self.mpenn_data[0])
|
||||
self.reset_rectangle()
|
||||
os.remove(self.img_paths[self.index])
|
||||
self.index += 1
|
||||
self.save_index += 1
|
||||
self.show_img(self.img_paths[self.index])
|
||||
|
||||
def draw_rects(self, image):
|
||||
self.draw = ImageDraw.Draw(image)
|
||||
|
||||
for rect in self.labeling_boxes:
|
||||
# Each 'rect' in 'self.labeling_boxes' is expected to be a list with 2 elements:
|
||||
# The first element could be a rectangle object or identifier (we will not use it here)
|
||||
# The second element is a list of coordinates in the format [start_x, start_y, end_x, end_y]
|
||||
coordinates = rect[1] # Getting the coordinates list
|
||||
|
||||
color = rect[2]
|
||||
thickness = rect[3]
|
||||
if thickness <= 0:
|
||||
thickness = 1
|
||||
self.draw.rectangle(coordinates, outline=color, width=thickness)
|
||||
self.labeled = True
|
||||
return image
|
||||
|
||||
def delete_img(self):
|
||||
os.remove(self.img_paths[self.index])
|
||||
self.index += 1
|
||||
self.show_img(self.img_paths[self.index])
|
||||
|
||||
def skip_time(self):
|
||||
for i in range(system_code.skipable_frames):
|
||||
os.remove(self.img_paths[self.index + i])
|
||||
self.index = self.index + system_code.skipable_frames
|
||||
self.show_img(self.img_paths[self.index])
|
||||
|
||||
def show_img(self, to_displayed):
|
||||
self.preview_canvas.delete("all")
|
||||
self.tk_cropped_image = None
|
||||
# Check if 'to_displayed' is a PIL Image object
|
||||
if isinstance(to_displayed, Image.Image):
|
||||
self.original_image = to_displayed # 'to_displayed' is already an image object, use it directly
|
||||
else:
|
||||
# It's assumed to be a file path, try to open as an image file
|
||||
try:
|
||||
self.original_image = Image.open(to_displayed)
|
||||
except Exception as e:
|
||||
print(f"Error opening image: {e}")
|
||||
return
|
||||
|
||||
self.return_image_information()
|
||||
self.resize_image()
|
||||
self.display_image()
|
||||
|
||||
def resize_image(self):
|
||||
"""
|
||||
Resize the image to fit within the panel dimensions while maintaining aspect ratio.
|
||||
Note: This function should be called after the window is visible and has been updated, to ensure
|
||||
accurate dimensions are retrieved from 'big_canvas'.
|
||||
"""
|
||||
|
||||
self.big_canvas.update_idletasks()
|
||||
|
||||
if self.original_image is None or self.big_canvas.winfo_width() <= 1 or self.big_canvas.winfo_height() <= 1:
|
||||
return
|
||||
# Update idletasks to ensure the window's layout is processed and accurate dimensions are retrieved
|
||||
self.big_canvas.update_idletasks()
|
||||
|
||||
panel_width, panel_height = self.big_canvas.winfo_width(), self.big_canvas.winfo_height()
|
||||
|
||||
print("resized:", panel_width, panel_height)
|
||||
original_width, original_height = self.original_image.size
|
||||
aspect_ratio = original_width / original_height
|
||||
|
||||
# Determine the best fit size for keeping the aspect ratio
|
||||
if panel_width / aspect_ratio <= panel_height:
|
||||
new_width, new_height = int(panel_width), int(panel_width / aspect_ratio)
|
||||
else:
|
||||
new_width, new_height = int(panel_height * aspect_ratio), int(panel_height)
|
||||
|
||||
# Inside the resize_image method, after computing new_width and new_height
|
||||
if new_width <= 0 or new_height <= 0:
|
||||
return # Consider logging this case or handling it appropriately
|
||||
|
||||
self.displayed_image = self.original_image.resize((new_width, new_height), Image.LANCZOS)
|
||||
|
||||
# Calculate and print the size_factor
|
||||
size_factor_width = original_width / new_width
|
||||
size_factor_height = original_height / new_height
|
||||
|
||||
self.img_factor_x = size_factor_width
|
||||
self.img_factor_y = size_factor_height
|
||||
print(f"Size Factor: {self.img_factor_x}, {self.img_factor_y}")
|
||||
|
||||
def display_image(self):
|
||||
"""Display the image centered in the canvas."""
|
||||
if self.displayed_image is None:
|
||||
return
|
||||
|
||||
if self.tk_image:
|
||||
self.delete_current_rectangle("all") # Clear the canvas before displaying a new image
|
||||
|
||||
self.tk_image = ImageTk.PhotoImage(self.displayed_image)
|
||||
# Force an update to ensure current dimensions are fetched
|
||||
self.big_canvas.update_idletasks()
|
||||
canvas_width, canvas_height = self.big_canvas.winfo_width(), self.big_canvas.winfo_height()
|
||||
image_width, image_height = self.tk_image.width(), self.tk_image.height()
|
||||
|
||||
# Calculate the center position
|
||||
x_offset = int((canvas_width - image_width) // 2)
|
||||
y_offset = int((canvas_height - image_height) // 2)
|
||||
|
||||
self.big_canvas.create_image(x_offset, y_offset, anchor=Ctk.NW, image=self.tk_image)
|
||||
self.image_position = (x_offset, y_offset) # Save the centered image position
|
||||
|
||||
def on_press(self, event):
|
||||
self.start_x = event.x
|
||||
self.start_y = event.y
|
||||
# If there's an existing rectangle, remove it
|
||||
if self.rect and (system_code.data_mode == "Resize"):
|
||||
self.delete_current_rectangle(self.rect)
|
||||
# Create an initial 1x1 rectangle that will be adjusted in `on_drag`
|
||||
self.rect = self.big_canvas.create_rectangle(self.start_x, self.start_y, self.start_x+1, self.start_y+1,
|
||||
outline=system_code.color if system_code.data_mode != "Resize" else "#5f00c7",
|
||||
width=system_code.thickness // self.img_factor_x if system_code.data_mode != "Resize" else 1)
|
||||
|
||||
def on_resize(self, event):
|
||||
"""Handle window resize events with throttling."""
|
||||
if not self.resize_pending:
|
||||
self.resize_pending = True
|
||||
|
||||
if self.after_id:
|
||||
self.after_cancel(self.after_id)
|
||||
self.adjust_image_sizes_for_buttons()
|
||||
self.after_id = self.after(100, self.perform_resize)
|
||||
|
||||
def on_drag(self, event):
|
||||
if not self.dragging:
|
||||
# This marks the start of actual dragging, so we do the rectangle creation here
|
||||
self.dragging = True # Set dragging flag to True to indicate dragging has started
|
||||
# If there's an existing rectangle from a previous operation, remove it
|
||||
if self.rect:
|
||||
self.delete_current_rectangle(self.rect)
|
||||
# Start a new rectangle
|
||||
self.rect = self.big_canvas.create_rectangle(self.start_x, self.start_y, self.start_x+1, self.start_y+1,
|
||||
outline=system_code.color if system_code.data_mode == "Labeling" else "#5f00c7",
|
||||
width=system_code.thickness // self.img_factor_x if system_code.data_mode == "Labeling" else 1)
|
||||
|
||||
self.end_x, self.end_y = event.x, event.y
|
||||
|
||||
if system_code.data_mode == "Resize":
|
||||
# Maintain 1:1 aspect ratio for resize mode
|
||||
delta_x = self.end_x - self.start_x
|
||||
delta_y = self.end_y - self.start_y
|
||||
delta = min(abs(delta_x), abs(delta_y))
|
||||
delta_x = delta if delta_x > 0 else -delta
|
||||
delta_y = delta if delta_y > 0 else -delta
|
||||
|
||||
self.end_x, self.end_y = self.start_x + delta_x, self.start_y + delta_y
|
||||
# For other modes, the rectangle adjusts to current coordinates directly
|
||||
|
||||
# Update rectangle size during drag
|
||||
self.big_canvas.coords(self.rect, self.start_x, self.start_y, self.end_x, self.end_y)
|
||||
|
||||
def on_release(self, event):
|
||||
# Only proceed if dragging actually occurred
|
||||
if self.dragging:
|
||||
self.big_canvas.coords(self.rect, self.start_x, self.start_y, self.end_x, self.end_y)
|
||||
if self.start_x > self.end_x:
|
||||
temp = self.start_x
|
||||
self.start_x = self.end_x
|
||||
self.end_x = temp
|
||||
if self.start_y > self.end_y:
|
||||
temp = self.start_y
|
||||
self.start_y = self.end_y
|
||||
self.end_y = temp
|
||||
self.big_canvas.coords(self.rect, self.start_x, self.start_y, self.end_x, self.end_y)
|
||||
print(f"Rectangle coordinates: Start({self.start_x}, {self.start_y}) End({self.end_x}, {self.end_y})")
|
||||
self.display_cropped_part() # New line to display the cropped area
|
||||
self.dragging = False # Reset dragging flag
|
||||
if system_code.data_mode == "Labeling" and self.rect is not None:
|
||||
coordinates = [self.start_x, self.start_y, self.end_x, self.end_y]
|
||||
coordinates = self.subtract_image_from_canvas(coordinates)
|
||||
coordinates = self.multiply_array(coordinates, self.img_factor_x, self.img_factor_y)
|
||||
temp_array = [self.labeling_box_index,coordinates, system_code.color, system_code.thickness]
|
||||
self.labeling_boxes.append(temp_array)
|
||||
self.labeling_box_index += 1
|
||||
else:
|
||||
# Handle the case where a rectangle shouldn't have been started
|
||||
if self.rect:
|
||||
self.delete_current_rectangle(self.rect)
|
||||
self.rect = None
|
||||
|
||||
def multiply_array(self, arr, num1, num2):
|
||||
"""
|
||||
Multiplies each element of the array 'arr' by 'num'.
|
||||
|
||||
Parameters:
|
||||
arr (list): The input list whose elements are to be multiplied.
|
||||
num (int): The number by which each element of the list is multiplied.
|
||||
|
||||
Returns:
|
||||
list: A new list with each element of 'arr' multiplied by 'num'.
|
||||
"""
|
||||
# Use list comprehension to multiply each element by num
|
||||
return arr[0] * num1, arr[1]* num2, arr[2]* num1, arr[3] * num2
|
||||
|
||||
def subtract_image_from_canvas(self, arr):
|
||||
|
||||
width = self.image_position[0]
|
||||
height = self.image_position[1]
|
||||
|
||||
return arr[0] - width, arr[1] - height, arr[2] - width, arr[3] - height
|
||||
|
||||
|
||||
def display_cropped_part(self):
|
||||
if not self.validate_image_and_rectangle():
|
||||
return
|
||||
|
||||
adj_coordinates = self.adjust_coordinates_for_border()
|
||||
if not self.validate_adjusted_coordinates(adj_coordinates):
|
||||
self.delete_current_rectangle(self.rect)
|
||||
return
|
||||
|
||||
crop_coordinates = self.calculate_crop_coordinates(adj_coordinates)
|
||||
self.cropped_image = self.original_image.crop(crop_coordinates)
|
||||
self.display_resized_cropped_image(self.cropped_image)
|
||||
|
||||
def adjust_coordinates_for_border(self):
|
||||
"""Adjust rectangle's position by considering the image's position and border width."""
|
||||
adj_start_x = self.start_x - self.image_position[0] + (system_code.thickness / 2)
|
||||
adj_start_y = self.start_y - self.image_position[1] + (system_code.thickness / 2)
|
||||
adj_end_x = self.end_x - self.image_position[0] - (system_code.thickness / 2)
|
||||
adj_end_y = self.end_y - self.image_position[1] - (system_code.thickness / 2)
|
||||
return adj_start_x, adj_start_y, adj_end_x, adj_end_y
|
||||
|
||||
def validate_adjusted_coordinates(self, coordinates):
|
||||
"""Ensure logical and boundary adherence of adjusted coordinates."""
|
||||
adj_start_x, adj_start_y, adj_end_x, adj_end_y = coordinates
|
||||
if (adj_end_x <= adj_start_x) or (adj_end_y <= adj_start_y):
|
||||
# Negative width or height indicates a coordinate error
|
||||
return False
|
||||
|
||||
if (adj_start_x < 0 or adj_start_y < 0 or
|
||||
adj_end_x > self.displayed_image.width or
|
||||
adj_end_y > self.displayed_image.height):
|
||||
# Coordinates exceed displayed image bounds
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def calculate_crop_coordinates(self, adj_coordinates):
|
||||
"""Calculate crop coordinates on the original image, considering display scaling."""
|
||||
adj_start_x, adj_start_y, adj_end_x, adj_end_y = adj_coordinates
|
||||
|
||||
# Scaling ratios, considering the displayed image might be scaled down/up to fit into the canvas
|
||||
x_scale = self.original_image.size[0] / self.displayed_image.width
|
||||
y_scale = self.original_image.size[1] / self.displayed_image.height
|
||||
|
||||
# Apply scaling to adjust coordinates to match the original image size
|
||||
crop_start_x = max(0, int(adj_start_x * x_scale))
|
||||
crop_start_y = max(0, int(adj_start_y * y_scale))
|
||||
crop_end_x = min(self.original_image.size[0], int(adj_end_x * x_scale))
|
||||
crop_end_y = min(self.original_image.size[1], int(adj_end_y * y_scale))
|
||||
|
||||
return crop_start_x, crop_start_y, crop_end_x, crop_end_y
|
||||
|
||||
def display_resized_cropped_image(self, cropped_image):
|
||||
"""Resize and display the cropped image on the preview canvas."""
|
||||
cropped_image_aspect_ratio = (cropped_image.width / cropped_image.height)
|
||||
|
||||
preview_canvas_width = self.preview_canvas.winfo_width()
|
||||
preview_canvas_height = self.preview_canvas.winfo_height()
|
||||
if cropped_image_aspect_ratio > (preview_canvas_width / preview_canvas_height):
|
||||
new_width = preview_canvas_width
|
||||
new_height = int(preview_canvas_width / cropped_image_aspect_ratio)
|
||||
else:
|
||||
new_height = preview_canvas_height
|
||||
new_width = int(preview_canvas_height * cropped_image_aspect_ratio)
|
||||
|
||||
resized_cropped_image = cropped_image.resize((new_width, new_height), Image.LANCZOS)
|
||||
self.save_cropped = resized_cropped_image
|
||||
self.tk_cropped_image = ImageTk.PhotoImage(resized_cropped_image)
|
||||
self.preview_canvas.delete("all")
|
||||
centered_x = (preview_canvas_width - new_width) / 2
|
||||
centered_y = (preview_canvas_height - new_height) / 2
|
||||
self.preview_canvas.create_image(centered_x, centered_y, anchor='nw', image=self.tk_cropped_image)
|
||||
self.preview_canvas.image = self.tk_cropped_image
|
||||
|
||||
def perform_resize(self):
|
||||
"""Perform the resize operation and clear cropped image and rectangle."""
|
||||
if self.resize_pending:
|
||||
self.resize_image()
|
||||
self.display_image()
|
||||
|
||||
# Clear the rectangle on the main canvas if it exists
|
||||
self.reset_rectangle()
|
||||
|
||||
# Reset rectangle coordinates
|
||||
self.start_x, self.start_y, self.end_x, self.end_y = None, None, None, None
|
||||
|
||||
# Optionally, if desired, clear the dragging states
|
||||
self.dragging = False
|
||||
|
||||
# Now print the image position and size if an image is displayed, else, print "No image displayed."
|
||||
if self.displayed_image:
|
||||
image_width, image_height = self.displayed_image.size
|
||||
print(f"Image position: {self.image_position}, Size: {image_width}x{image_height}")
|
||||
|
||||
|
||||
|
||||
def delete_current_rectangle(self, obj):
|
||||
"""Remove the rectangle object if coordinates are invalid."""
|
||||
self.big_canvas.delete(obj)
|
||||
self.rect = None
|
||||
|
||||
def validate_image_and_rectangle(self):
|
||||
if not self.displayed_image or not self.rect:
|
||||
return False
|
||||
return True
|
||||
|
||||
def place_labeling(self):
|
||||
self.big_canvas.place(
|
||||
relx=0.025,
|
||||
rely=0.5,
|
||||
relwidth=0.775,
|
||||
relheight=0.95,
|
||||
anchor="w"
|
||||
)
|
||||
self.reset_btn.place(
|
||||
relx=0.975,
|
||||
rely=0.1,
|
||||
relwidth=0.15,
|
||||
relheight=0.06,
|
||||
anchor="e",
|
||||
)
|
||||
self.create_folder_btn.place(
|
||||
relx=0.975,
|
||||
rely=0.2,
|
||||
relwidth=0.06,
|
||||
relheight=0.06,
|
||||
anchor="e",
|
||||
)
|
||||
self.open_folder_btn.place(
|
||||
relx=0.825,
|
||||
rely=0.2,
|
||||
relwidth=0.06,
|
||||
relheight=0.06,
|
||||
anchor="w",
|
||||
)
|
||||
self.save_img_btn.place(
|
||||
relx=0.975,
|
||||
rely=0.3,
|
||||
relwidth=0.15,
|
||||
relheight=0.06,
|
||||
anchor="e",
|
||||
)
|
||||
self.delete_img_btn.place(
|
||||
relx=0.975,
|
||||
rely=0.4,
|
||||
relwidth=0.15,
|
||||
relheight=0.06,
|
||||
anchor="e",
|
||||
)
|
||||
self.skip_time_btn.place(
|
||||
relx=0.975,
|
||||
rely=0.5,
|
||||
relwidth=0.06,
|
||||
relheight=0.06,
|
||||
anchor="e",
|
||||
)
|
||||
self.new_source_btn.place(
|
||||
relx=0.825,
|
||||
rely=0.5,
|
||||
relwidth=0.06,
|
||||
relheight=0.06,
|
||||
anchor="w",
|
||||
)
|
||||
self.preview_canvas.place(
|
||||
relx=0.975,
|
||||
rely=0.7,
|
||||
relwidth=0.15,
|
||||
relheight=0.25,
|
||||
anchor="e",
|
||||
)
|
||||
self.choose_mode.place(
|
||||
relx=0.975,
|
||||
rely=0.9,
|
||||
relwidth=0.15,
|
||||
relheight=0.06,
|
||||
anchor="e",
|
||||
)
|
||||
|
||||
def hide_labeling(self):
|
||||
self.big_canvas.place_forget()
|
||||
self.reset_btn.place_forget()
|
||||
self.create_folder_btn.place_forget()
|
||||
self.open_folder_btn.place_forget()
|
||||
self.save_img_btn.place_forget()
|
||||
self.delete_img_btn.place_forget()
|
||||
self.skip_time_btn.place_forget()
|
||||
self.new_source_btn.place_forget()
|
||||
self.preview_canvas.place_forget()
|
||||
self.choose_mode.place_forget()
|
||||
|
Loading…
Reference in New Issue