2024-12-10 22:14:39 +00:00
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
2024-12-15 13:28:27 +00:00
"""
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 ( 1024 x768 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 1024 x768 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!
"""
2024-12-10 22:14:39 +00:00
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 ) ,
2024-12-15 13:28:27 +00:00
" 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 ) ,
2024-12-10 22:14:39 +00:00
}
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
2024-12-15 13:28:27 +00:00
rounded_value = round ( float ( value ) / 2 ) * 2
2024-12-10 22:14:39 +00:00
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 ( )