yiking/main.py
2024-12-10 23:14:39 +01:00

124 lines
4.6 KiB
Python

import tkinter as tk
from tkinter import ttk
from process import process_frame
from PIL import Image, ImageTk # Required for displaying images
import cv2 # OpenCV for numpy array to image conversion
class OpenCVInterface:
def __init__(self, root):
self.root = root
self.root.title("Yiking")
# Variables for sliders with min, max, and default values
self.variables_config = {
"minDist": (0, 500, 100),
"param1": (0, 500, 30),
"param2": (0, 400, 25),
"minRadius": (0, 100, 5),
"maxRadius": (0, 1000, 1000),
"color1_R": (0, 64, 5),
"color1_V": (0, 64, 5),
"color1_B": (0, 64, 5),
"color2_R": (0, 64, 5),
"color2_V": (0, 64, 5),
"color2_B": (0, 64, 5),
}
self.variables = {
name: tk.IntVar(value=config[2]) for name, config in self.variables_config.items()
}
# GUI Layout
self.setup_gui()
def setup_gui(self):
# Root grid layout
self.root.rowconfigure(1, weight=1)
self.root.columnconfigure(0, weight=1)
self.root.columnconfigure(1, weight=1)
# Left Column: Sliders
left_frame = ttk.Frame(self.root)
left_frame.grid(row=0, column=0, sticky="nswe")
for var_name, var in self.variables.items():
min_val, max_val, _ = self.variables_config[var_name]
self.create_slider(left_frame, var_name, var, min_val, max_val)
# Right Column: Image Placeholder
self.image_canvas = tk.Canvas(self.root, bg="gray", width=1024, height=768)
self.image_canvas.grid(row=0, column=1, sticky="nswe")
# Bottom Row: Run Button and Result
run_button = ttk.Button(self.root, text="Run", command=self.run_process)
run_button.grid(row=1, column=0, sticky="we")
self.result_text = tk.Text(self.root, height=10, width=40)
self.result_text.grid(row=1, column=1, sticky="nswe")
def create_slider(self, parent, name, variable, min_val, max_val):
frame = ttk.Frame(parent)
frame.pack(fill="x", padx=5, pady=2)
# Label
label = ttk.Label(frame, text=name)
label.pack(side="left")
def on_slide(value):
# Round value to nearest multiple of 5
rounded_value = round(float(value) / 5) * 5
variable.set(int(rounded_value)) # Update the variable with the rounded value
# Slider
slider = ttk.Scale(
frame, from_=min_val, to=max_val,
variable=variable, orient="horizontal", command=on_slide
)
slider.pack(side="left", fill="x", expand=True, padx=5)
# Entry box
entry = ttk.Entry(frame, textvariable=variable, width=5)
entry.pack(side="left")
def run_process(self):
# Collect slider values
parameters = {key: var.get() for key, var in self.variables.items()}
try:
# Call process function
image, result_text = process_frame(parameters)
# Convert OpenCV image (numpy array) to PIL Image for Tkinter display
if image is not None:
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Convert BGR to RGB
pil_image = Image.fromarray(image) # Convert numpy array to PIL Image
# Rescale image to fit within 1024x768 while preserving aspect ratio
max_width, max_height = 1024, 768
original_width, original_height = pil_image.size
aspect_ratio = min(max_width / original_width, max_height / original_height)
new_width = int(original_width * aspect_ratio)
new_height = int(original_height * aspect_ratio)
pil_image = pil_image.resize((new_width, new_height), Image.Resampling.LANCZOS)
tk_image = ImageTk.PhotoImage(pil_image) # Convert PIL Image to Tkinter Image
# Clear canvas and display the image
self.image_canvas.delete("all")
self.image_canvas.create_image(512, 384, image=tk_image, anchor="center")
self.image_canvas.image = tk_image # Keep a reference to prevent garbage collection
# Update result text
self.result_text.delete(1.0, tk.END)
self.result_text.insert(tk.END, result_text)
except Exception as exc:
# Handle and display exceptions
self.result_text.delete(1.0, tk.END)
self.result_text.insert(tk.END, str(exc))
self.image_canvas.delete("all")
if __name__ == "__main__":
root = tk.Tk()
app = OpenCVInterface(root)
root.mainloop()