175 lines
7.1 KiB
Python
175 lines
7.1 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
|
||
|
||
"""
|
||
Here’s a detailed prompt you can use to generate the same GUI code anew using a language model:
|
||
|
||
---
|
||
|
||
**Prompt:**
|
||
|
||
"I need a Python program to create a Tkinter-based GUI named 'Yiking'. The GUI will control parameters for an OpenCV image processing program. The program must be split into two files:
|
||
|
||
1. **`process.py`**: Contains a `process_frame` function that takes parameters as input, performs OpenCV operations (not implemented in this request), and returns an image as a NumPy array and a result string.
|
||
|
||
2. **`gui.py`**: Implements the GUI and integrates with `process.py`. Here are the detailed requirements:
|
||
|
||
### GUI Details:
|
||
- **Window Title**: 'Yiking'
|
||
- **Layout**:
|
||
- **Row 1**: Two columns
|
||
- Left column: Group of sliders for controlling parameters.
|
||
- Right column: A canvas for displaying a processed image (1024x768 pixels).
|
||
- **Row 2**: Two columns
|
||
- Left column: A "Run" button.
|
||
- Right column: A text box for displaying results or error messages.
|
||
- **Widgets**:
|
||
- Sliders with corresponding min, max, and default values:
|
||
- `minDist` = (0, 500, 100)
|
||
- `param1` = (0, 500, 30)
|
||
- `param2` = (0, 400, 25)
|
||
- `minRadius` = (0, 100, 5)
|
||
- `maxRadius` = (0, 1000, 1000)
|
||
- `color1_R_min` = (0, 64, 5)
|
||
- `color1_V_min` = (0, 64, 5)
|
||
- `color1_B_min` = (0, 64, 5)
|
||
- `color1_R_min` = (0, 64, 5)
|
||
- `color1_V_min` = (0, 64, 5)
|
||
- `color1_B_min` = (0, 64, 5)
|
||
- Sliders must snap to increments of 5 and synchronize with a text entry box.
|
||
- The image canvas must resize input images to fit within 1024x768 while maintaining aspect ratio.
|
||
- A "Run" button executes the `process_frame` function with the current slider values.
|
||
- If an exception occurs in `process_frame`, it should display the error in the result text box and clear the canvas.
|
||
|
||
### Key Features:
|
||
- Use the `Pillow` library (`PIL`) to handle image conversion and resizing.
|
||
- Catch exceptions in `run_process` to display error messages.
|
||
- Keep the GUI responsive and visually clean.
|
||
|
||
### Output:
|
||
Please provide a fully functional `gui.py` implementation meeting these requirements. Include imports, class structure, and the `__main__` block. Do not implement the OpenCV functionality within `process.py`—assume it exists for integration purposes."
|
||
|
||
---
|
||
|
||
This prompt is designed to give the LLM everything it needs to generate the desired `gui.py` code. Let me know if you'd like to adjust it further!
|
||
"""
|
||
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_min": (0, 255, 0),
|
||
"color1_R_max": (0, 255, 0),
|
||
"color1_V_min": (0, 255, 0),
|
||
"color1_V_max": (0, 255, 0),
|
||
"color1_B_min": (0, 255, 0),
|
||
"color1_B_max": (0, 255, 0),
|
||
}
|
||
|
||
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=800, height=600)
|
||
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) / 2) * 2
|
||
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 = 800, 600
|
||
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()
|