feat: add control for multiple cameras
This commit is contained in:
parent
815f1ab00e
commit
72672e3dfe
65
main.py
65
main.py
@ -1,8 +1,3 @@
|
|||||||
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:
|
Here’s a detailed prompt you can use to generate the same GUI code anew using a language model:
|
||||||
@ -56,6 +51,12 @@ Please provide a fully functional `gui.py` implementation meeting these requirem
|
|||||||
|
|
||||||
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!
|
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!
|
||||||
"""
|
"""
|
||||||
|
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:
|
class OpenCVInterface:
|
||||||
def __init__(self, root):
|
def __init__(self, root):
|
||||||
self.root = root
|
self.root = root
|
||||||
@ -68,12 +69,12 @@ class OpenCVInterface:
|
|||||||
"param2": (0, 400, 25),
|
"param2": (0, 400, 25),
|
||||||
"minRadius": (0, 100, 5),
|
"minRadius": (0, 100, 5),
|
||||||
"maxRadius": (0, 1000, 1000),
|
"maxRadius": (0, 1000, 1000),
|
||||||
"color1_R_min": (0, 255, 0),
|
"color1_R_min": (0, 64, 5),
|
||||||
"color1_R_max": (0, 255, 0),
|
"color1_R_max": (0, 64, 5),
|
||||||
"color1_V_min": (0, 255, 0),
|
"color1_V_min": (0, 64, 5),
|
||||||
"color1_V_max": (0, 255, 0),
|
"color1_V_max": (0, 64, 5),
|
||||||
"color1_B_min": (0, 255, 0),
|
"color1_B_min": (0, 64, 5),
|
||||||
"color1_B_max": (0, 255, 0),
|
"color1_B_max": (0, 64, 5),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.variables = {
|
self.variables = {
|
||||||
@ -89,24 +90,44 @@ class OpenCVInterface:
|
|||||||
self.root.columnconfigure(0, weight=1)
|
self.root.columnconfigure(0, weight=1)
|
||||||
self.root.columnconfigure(1, weight=1)
|
self.root.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
|
# Dropdown for camera selection
|
||||||
|
camera_frame = ttk.Frame(self.root)
|
||||||
|
camera_frame.grid(row=0, column=0, sticky="nsew")
|
||||||
|
self.camera_selection = tk.StringVar()
|
||||||
|
self.camera_dropdown = ttk.Combobox(camera_frame, textvariable=self.camera_selection)
|
||||||
|
self.camera_dropdown.grid(row=0, column=0, padx=5, pady=5)
|
||||||
|
self.populate_camera_dropdown()
|
||||||
|
|
||||||
# Left Column: Sliders
|
# Left Column: Sliders
|
||||||
left_frame = ttk.Frame(self.root)
|
left_frame = ttk.Frame(self.root)
|
||||||
left_frame.grid(row=0, column=0, sticky="nswe")
|
left_frame.grid(row=1, column=0, sticky="nswe")
|
||||||
|
|
||||||
for var_name, var in self.variables.items():
|
for var_name, var in self.variables.items():
|
||||||
min_val, max_val, _ = self.variables_config[var_name]
|
min_val, max_val, _ = self.variables_config[var_name]
|
||||||
self.create_slider(left_frame, var_name, var, min_val, max_val)
|
self.create_slider(left_frame, var_name, var, min_val, max_val)
|
||||||
|
|
||||||
# Right Column: Image Placeholder
|
# Right Column: Image Placeholder
|
||||||
self.image_canvas = tk.Canvas(self.root, bg="gray", width=800, height=600)
|
self.image_canvas = tk.Canvas(self.root, bg="gray", width=1024, height=768)
|
||||||
self.image_canvas.grid(row=0, column=1, sticky="nswe")
|
self.image_canvas.grid(row=0, column=1, rowspan=2, sticky="nswe")
|
||||||
|
|
||||||
# Bottom Row: Run Button and Result
|
# Bottom Row: Run Button and Result
|
||||||
run_button = ttk.Button(self.root, text="Run", command=self.run_process)
|
run_button = ttk.Button(self.root, text="Run", command=self.run_process)
|
||||||
run_button.grid(row=1, column=0, sticky="we")
|
run_button.grid(row=2, column=0, sticky="we")
|
||||||
|
|
||||||
self.result_text = tk.Text(self.root, height=10, width=40)
|
self.result_text = tk.Text(self.root, height=5, width=40)
|
||||||
self.result_text.grid(row=1, column=1, sticky="nswe")
|
self.result_text.grid(row=2, column=1, sticky="nswe")
|
||||||
|
|
||||||
|
def populate_camera_dropdown(self):
|
||||||
|
# Detect connected cameras using OpenCV
|
||||||
|
cameras = []
|
||||||
|
for i in range(5): # Check first 5 indexes for cameras
|
||||||
|
cap = cv2.VideoCapture(i)
|
||||||
|
if cap.read()[0]:
|
||||||
|
cameras.append(f"Camera {i}")
|
||||||
|
cap.release()
|
||||||
|
self.camera_dropdown["values"] = cameras
|
||||||
|
if cameras:
|
||||||
|
self.camera_dropdown.current(0)
|
||||||
|
|
||||||
def create_slider(self, parent, name, variable, min_val, max_val):
|
def create_slider(self, parent, name, variable, min_val, max_val):
|
||||||
frame = ttk.Frame(parent)
|
frame = ttk.Frame(parent)
|
||||||
@ -118,7 +139,7 @@ class OpenCVInterface:
|
|||||||
|
|
||||||
def on_slide(value):
|
def on_slide(value):
|
||||||
# Round value to nearest multiple of 5
|
# Round value to nearest multiple of 5
|
||||||
rounded_value = round(float(value) / 2) * 2
|
rounded_value = round(float(value) / 5) * 5
|
||||||
variable.set(int(rounded_value)) # Update the variable with the rounded value
|
variable.set(int(rounded_value)) # Update the variable with the rounded value
|
||||||
|
|
||||||
# Slider
|
# Slider
|
||||||
@ -137,8 +158,11 @@ class OpenCVInterface:
|
|||||||
parameters = {key: var.get() for key, var in self.variables.items()}
|
parameters = {key: var.get() for key, var in self.variables.items()}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Get selected camera ID
|
||||||
|
cam_id = int(self.camera_selection.get().split()[-1])
|
||||||
|
|
||||||
# Call process function
|
# Call process function
|
||||||
image, result_text = process_frame(parameters)
|
image, result_text = process_frame(parameters, cam_id=cam_id)
|
||||||
|
|
||||||
# Convert OpenCV image (numpy array) to PIL Image for Tkinter display
|
# Convert OpenCV image (numpy array) to PIL Image for Tkinter display
|
||||||
if image is not None:
|
if image is not None:
|
||||||
@ -146,12 +170,13 @@ class OpenCVInterface:
|
|||||||
pil_image = Image.fromarray(image) # Convert numpy array to PIL Image
|
pil_image = Image.fromarray(image) # Convert numpy array to PIL Image
|
||||||
|
|
||||||
# Rescale image to fit within 1024x768 while preserving aspect ratio
|
# Rescale image to fit within 1024x768 while preserving aspect ratio
|
||||||
max_width, max_height = 800, 600
|
max_width, max_height = 1024, 768
|
||||||
original_width, original_height = pil_image.size
|
original_width, original_height = pil_image.size
|
||||||
aspect_ratio = min(max_width / original_width, max_height / original_height)
|
aspect_ratio = min(max_width / original_width, max_height / original_height)
|
||||||
new_width = int(original_width * aspect_ratio)
|
new_width = int(original_width * aspect_ratio)
|
||||||
new_height = int(original_height * aspect_ratio)
|
new_height = int(original_height * aspect_ratio)
|
||||||
pil_image = pil_image.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
pil_image = pil_image.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
||||||
|
|
||||||
tk_image = ImageTk.PhotoImage(pil_image) # Convert PIL Image to Tkinter Image
|
tk_image = ImageTk.PhotoImage(pil_image) # Convert PIL Image to Tkinter Image
|
||||||
|
|
||||||
# Clear canvas and display the image
|
# Clear canvas and display the image
|
||||||
|
@ -16,7 +16,7 @@ TYPE_2 = "___ ___"
|
|||||||
import cv2
|
import cv2
|
||||||
|
|
||||||
|
|
||||||
def capture_frame_from_webcam():
|
def capture_frame_from_webcam(cam_id):
|
||||||
"""
|
"""
|
||||||
Captures a single frame from the webcam.
|
Captures a single frame from the webcam.
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ def capture_frame_from_webcam():
|
|||||||
frame (numpy.ndarray): The captured frame as a NumPy array.
|
frame (numpy.ndarray): The captured frame as a NumPy array.
|
||||||
"""
|
"""
|
||||||
# Open a connection to the second webcam (index 0)
|
# Open a connection to the second webcam (index 0)
|
||||||
cap = cv2.VideoCapture(1)
|
cap = cv2.VideoCapture(cam_id)
|
||||||
|
|
||||||
if not cap.isOpened():
|
if not cap.isOpened():
|
||||||
raise Exception("Could not open webcam. Please check your webcam connection.")
|
raise Exception("Could not open webcam. Please check your webcam connection.")
|
||||||
@ -50,7 +50,7 @@ class Object:
|
|||||||
rayon: int
|
rayon: int
|
||||||
|
|
||||||
|
|
||||||
def process_frame(params):
|
def process_frame(params, cam_id):
|
||||||
"""
|
"""
|
||||||
Simulates OpenCV processing using parameters from the GUI.
|
Simulates OpenCV processing using parameters from the GUI.
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ def process_frame(params):
|
|||||||
# src = dir_path.joinpath('tests/images/balls-full-small.jpg')
|
# src = dir_path.joinpath('tests/images/balls-full-small.jpg')
|
||||||
# raw_image = cv2.imread(str(src))
|
# raw_image = cv2.imread(str(src))
|
||||||
|
|
||||||
raw_image = capture_frame_from_webcam()
|
raw_image = capture_frame_from_webcam(cam_id)
|
||||||
|
|
||||||
# 2. Boxing des objets via opencv
|
# 2. Boxing des objets via opencv
|
||||||
gray = cv2.cvtColor(raw_image, cv2.COLOR_BGR2GRAY)
|
gray = cv2.cvtColor(raw_image, cv2.COLOR_BGR2GRAY)
|
||||||
|
Loading…
Reference in New Issue
Block a user