Feature #1123
Support #1098: Coding Thread
Feature #1112: GUI for the Code
Example Code Needs to fixed
Start date:
10/24/2024
Due date:
10/31/2024 (about 12 months late)
% Done:
100%
Estimated time:
2.00 h
Spent time:
Description
class ImageProcessingApp:
def __init__(self, root):
self.root = root
self.root.title("Image Processing Application")
# Initialize variables
self.left_image_path = ""
self.right_image_path = ""
self.left_params = {}
self.right_params = {}
self.processed_images = {}
# Create notebook (tabs)
self.notebook = ttk.Notebook(root)
self.notebook.pack(expand=True, fill='both')
# Create frames for each tab
self.tab_left = ttk.Frame(self.notebook)
self.tab_right = ttk.Frame(self.notebook)
self.tab_settings = ttk.Frame(self.notebook)
self.tab_preview = ttk.Frame(self.notebook)
self.notebook.add(self.tab_left, text='Left Image')
self.notebook.add(self.tab_right, text='Right Image')
self.notebook.add(self.tab_settings, text='Settings')
self.notebook.add(self.tab_preview, text='Preview')
# Setup each tab
self.setup_left_tab()
self.setup_right_tab()
self.setup_settings_tab()
self.setup_preview_tab()
# Process and Save Button
self.process_button = tk.Button(root, text="Process and Save Images", command=self.process_and_save)
self.process_button.pack(pady=10)
# Progress Bar
self.progress_bar = ttk.Progressbar(root, orient="horizontal", length=400, mode="determinate")
self.progress_bar.pack(pady=10)
def setup_left_tab(self):
frame = self.tab_left
# Select Image Button
btn_select = tk.Button(frame, text="Select Left Image", command=self.select_left_image)
btn_select.pack(pady=5)
# Display selected image path
self.left_image_label = tk.Label(frame, text="No image selected", wraplength=300, anchor="w", justify="left")
self.left_image_label.pack(padx=10, pady=5)
# Parameters for left image
params_frame = tk.LabelFrame(frame, text="Left Image Parameters", padx=10, pady=10)
params_frame.pack(padx=10, pady=10, fill="x")
# Projected Image Width
tk.Label(params_frame, text="Projected Image Width:").grid(row=0, column=0, sticky="e")
self.left_projected_image_width = tk.Entry(params_frame)
self.left_projected_image_width.insert(0, "800")
self.left_projected_image_width.grid(row=0, column=1, pady=2, sticky="w")
# Projected Overlap Width
tk.Label(params_frame, text="Projected Overlap Width:").grid(row=1, column=0, sticky="e")
self.left_projected_overlap_width = tk.Entry(params_frame)
self.left_projected_overlap_width.insert(0, "100")
self.left_projected_overlap_width.grid(row=1, column=1, pady=2, sticky="w")
# Gamma
tk.Label(params_frame, text="Gamma:").grid(row=2, column=0, sticky="e")
self.left_gamma = tk.Entry(params_frame)
self.left_gamma.insert(0, "1.0")
self.left_gamma.grid(row=2, column=1, pady=2, sticky="w")
# Image Side
tk.Label(params_frame, text="Image Side:").grid(row=3, column=0, sticky="e")
self.left_image_side = tk.IntVar(value=0) # Default to left
tk.Radiobutton(params_frame, text="Left", variable=self.left_image_side, value=0).grid(row=3, column=1, sticky="w")
tk.Radiobutton(params_frame, text="Right", variable=self.left_image_side, value=1).grid(row=3, column=1, padx=60, sticky="w")
# Transparency Factor
tk.Label(params_frame, text="Transparency Factor:").grid(row=4, column=0, sticky="e")
self.left_transparency_factor = tk.Entry(params_frame)
self.left_transparency_factor.insert(0, "1.0")
self.left_transparency_factor.grid(row=4, column=1, pady=2, sticky="w")
def setup_right_tab(self):
frame = self.tab_right
# Select Image Button
btn_select = tk.Button(frame, text="Select Right Image", command=self.select_right_image)
btn_select.pack(pady=5)
# Display selected image path
self.right_image_label = tk.Label(frame, text="No image selected", wraplength=300, anchor="w", justify="left")
self.right_image_label.pack(padx=10, pady=5)
# Parameters for right image
params_frame = tk.LabelFrame(frame, text="Right Image Parameters", padx=10, pady=10)
params_frame.pack(padx=10, pady=10, fill="x")
# Projected Image Width
tk.Label(params_frame, text="Projected Image Width:").grid(row=0, column=0, sticky="e")
self.right_projected_image_width = tk.Entry(params_frame)
self.right_projected_image_width.insert(0, "800")
self.right_projected_image_width.grid(row=0, column=1, pady=2, sticky="w")
# Projected Overlap Width
tk.Label(params_frame, text="Projected Overlap Width:").grid(row=1, column=0, sticky="e")
self.right_projected_overlap_width = tk.Entry(params_frame)
self.right_projected_overlap_width.insert(0, "100")
self.right_projected_overlap_width.grid(row=1, column=1, pady=2, sticky="w")
# Gamma
tk.Label(params_frame, text="Gamma:").grid(row=2, column=0, sticky="e")
self.right_gamma = tk.Entry(params_frame)
self.right_gamma.insert(0, "1.0")
self.right_gamma.grid(row=2, column=1, pady=2, sticky="w")
# Image Side
tk.Label(params_frame, text="Image Side:").grid(row=3, column=0, sticky="e")
self.right_image_side = tk.IntVar(value=1) # Default to right
tk.Radiobutton(params_frame, text="Left", variable=self.right_image_side, value=0).grid(row=3, column=1, sticky="w")
tk.Radiobutton(params_frame, text="Right", variable=self.right_image_side, value=1).grid(row=3, column=1, padx=60, sticky="w")
# Transparency Factor
tk.Label(params_frame, text="Transparency Factor:").grid(row=4, column=0, sticky="e")
self.right_transparency_factor = tk.Entry(params_frame)
self.right_transparency_factor.insert(0, "1.0")
self.right_transparency_factor.grid(row=4, column=1, pady=2, sticky="w")
def setup_settings_tab(self):
frame = self.tab_settings
# Configurations can be saved or loaded here
save_config_btn = tk.Button(frame, text="Save Configuration", command=self.save_configuration)
save_config_btn.pack(pady=10)
load_config_btn = tk.Button(frame, text="Load Configuration", command=self.load_configuration)
load_config_btn.pack(pady=10)
def setup_preview_tab(self):
frame = self.tab_preview
# Labels to display images
self.original_image_label = tk.Label(frame, text="Original Image")
self.original_image_label.pack(side="left", padx=10, pady=10)
self.processed_image_label = tk.Label(frame, text="Processed Image")
self.processed_image_label.pack(side="right", padx=10, pady=10)
def select_left_image(self):
path = filedialog.askopenfilename(title="Select Left Image",
filetypes=[("Image files", "*.png *.jpg *.jpeg *.bmp")])
if path:
self.left_image_path = path
self.left_image_label.config(text=os.path.basename(path))
logging.info(f"Selected left image: {path}")
def select_right_image(self):
path = filedialog.askopenfilename(title="Select Right Image",
filetypes=[("Image files", "*.png *.jpg *.jpeg *.bmp")])
if path:
self.right_image_path = path
self.right_image_label.config(text=os.path.basename(path))
logging.info(f"Selected right image: {path}")
def save_configuration(self):
config = ConfigReader()
# Left Image Parameters
if self.left_image_path:
config.setParameters({
'image_name': self.left_image_path,
'projected_image_width': self.left_projected_image_width.get(),
'projected_overlap_width': self.left_projected_overlap_width.get(),
'gamma': self.left_gamma.get(),
'image_side': self.left_image_side.get(),
'transparency_factor': self.left_transparency_factor.get()
})
# Right Image Parameters
if self.right_image_path:
config.setParameters({
'image_name': self.right_image_path,
'projected_image_width': self.right_projected_image_width.get(),
'projected_overlap_width': self.right_projected_overlap_width.get(),
'gamma': self.right_gamma.get(),
'image_side': self.right_image_side.get(),
'transparency_factor': self.right_transparency_factor.get()
})
# Save to file
save_path = filedialog.asksaveasfilename(title="Save Configuration",
defaultextension=".ini",
filetypes=[("INI files", "*.ini")])
if save_path:
config.save_config(save_path)
messagebox.showinfo("Success", f"Configuration saved to {save_path}")
logging.info(f"Configuration saved to {save_path}")
def load_configuration(self):
load_path = filedialog.askopenfilename(title="Load Configuration",
filetypes=[("INI files", "*.ini")])
if load_path and os.path.exists(load_path):
config = ConfigReader(load_path)
# Load left image parameters
self.left_image_path = config.getImageName()
if self.left_image_path and os.path.exists(self.left_image_path):
self.left_image_label.config(text=os.path.basename(self.left_image_path))
self.left_projected_image_width.delete(0, tk.END)
self.left_projected_image_width.insert(0, config.getProjectedImageWidth())
self.left_projected_overlap_width.delete(0, tk.END)
self.left_projected_overlap_width.insert(0, config.getProjectedOverlapWidth())
self.left_gamma.delete(0, tk.END)
self.left_gamma.insert(0, config.getGamma())
self.left_image_side.set(config.getImageSide())
self.left_transparency_factor.delete(0, tk.END)
self.left_transparency_factor.insert(0, config.getTransparencyFactor())
# Load right image parameters
self.right_image_path = config.getImageName()
if self.right_image_path and os.path.exists(self.right_image_path):
self.right_image_label.config(text=os.path.basename(self.right_image_path))
self.right_projected_image_width.delete(0, tk.END)
self.right_projected_image_width.insert(0, config.getProjectedImageWidth())
self.right_projected_overlap_width.delete(0, tk.END)
self.right_projected_overlap_width.insert(0, config.getProjectedOverlapWidth())
self.right_gamma.delete(0, tk.END)
self.right_gamma.insert(0, config.getGamma())
self.right_image_side.set(config.getImageSide())
self.right_transparency_factor.delete(0, tk.END)
self.right_transparency_factor.insert(0, config.getTransparencyFactor())
messagebox.showinfo("Success", f"Configuration loaded from {load_path}")
logging.info(f"Configuration loaded from {load_path}")
else:
messagebox.showerror("Error", "Failed to load configuration.")
def process_and_save(self):
# Validate inputs
if not self.left_image_path or not self.right_image_path:
messagebox.showerror("Error", "Please select both left and right images.")
return
# Collect parameters for left image
left_params = {
'image_name': self.left_image_path,
'projected_image_width': int(self.left_projected_image_width.get()),
'projected_overlap_width': int(self.left_projected_overlap_width.get()),
'gamma': float(self.left_gamma.get()),
'image_side': self.left_image_side.get(),
'transparency_factor': float(self.left_transparency_factor.get())
}
# Collect parameters for right image
right_params = {
'image_name': self.right_image_path,
'projected_image_width': int(self.right_projected_image_width.get()),
'projected_overlap_width': int(self.right_projected_overlap_width.get()),
'gamma': float(self.right_gamma.get()),
'image_side': self.right_image_side.get(),
'transparency_factor': float(self.right_transparency_factor.get())
}
# Initialize main display
main_display = MainDisplay()
# Process left image
self.progress_bar["value"] = 0
self.root.update_idletasks()
left_processed, left_name = process_image(self.left_image_path, left_params, main_display)
if left_processed is not None and left_name is not None:
self.processed_images[left_name] = left_processed
save_image(left_processed, left_name)
self.progress_bar["value"] += 50
self.root.update_idletasks()
# Process right image
right_processed, right_name = process_image(self.right_image_path, right_params, main_display)
if right_processed is not None and right_name is not None:
self.processed_images[right_name] = right_processed
save_image(right_processed, right_name)
self.progress_bar["value"] += 50
self.root.update_idletasks()
# Display images
self.display_preview()
# Finalize progress
self.progress_bar["value"] = 100
self.root.update_idletasks()
messagebox.showinfo("Processing Complete", "Images processed and saved successfully.")
def display_preview(self):
# Display the first processed image as preview
if self.processed_images:
# For simplicity, display the first image
name, img = next(iter(self.processed_images.items()))
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(img_rgb)
pil_img = pil_img.resize((400, 300), Image.ANTIALIAS)
img_tk = ImageTk.PhotoImage(pil_img)
self.processed_image_label.config(image=img_tk)
self.processed_image_label.image = img_tk
# Load and display original image
original_img = cv2.imread(self.left_image_path if name == 'left' else self.right_image_path, cv2.IMREAD_COLOR)
if original_img is not None:
original_rgb = cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB)
pil_original = Image.fromarray(original_rgb)
pil_original = pil_original.resize((400, 300), Image.ANTIALIAS)
original_tk = ImageTk.PhotoImage(pil_original)
self.original_image_label.config(image=original_tk)
self.original_image_label.image = original_tk
def display_image(self, processed_images):
# This method can be expanded to display multiple images if needed
pass
Files