I have a problem with my code. The purpose of this code is to select a camera, adjust the focus manually, save the image and go to the next camera in the drop-down menu.
The problem comes from the second camera, in fact, everything works perfectly for the first camera but when I select the second one I have no video return.
The two cameras are the same models (ethernet connection ) and I use the harvesters library and tkinter to make the code work.
the wierd part is when i click the quit button or the change camera button i have video feedback . but not after selected the right camera
import cv2
import os
import numpy as np
import cv2 as cv
import tkinter as tk
from tkinter import ttk
import tkinter.messagebox as messagebox
from PIL import Image, ImageTk
from harvesters.core import Harvester
from datetime import datetime
class CameraGUI:
"""
0
"""
def __init__(self, root):
"""ui inteface initialisation """
self.root = root
self.root.title("Focus adjuster")
self.video_frame = tk.Label(root)
self.video_frame.pack()
self.info_label = tk.Label(root,
text="Select the camera you want to adjust, then adjust the focus. \n "
"when you're done, click on 'quit' or press 'esc' ",
font=("Helvetica", 13))
self.info_label.pack()
self.instructions_label = tk.Label(root, text="Focus Adjustment Direction: OK", font=("Helvetica", 16))
# Create a dropdown menu to select cameras
self.camera_selection = ttk.Combobox(root, state="readonly", values=[], width=70) # Augmenter la largeur ici
self.camera_selection.pack()
self.camera_selection.bind("<<ComboboxSelected>>", self.on_camera_selected)
self.button_frame = tk.Frame(root)
self.button_frame.pack()
self.save_button = tk.Button(self.button_frame, text="Save Image", command=self.save_image, width=25)
self.save_button.pack(side="left") # Place the Save Image button on the left side of the button_frame
self.abort_button = tk.Button(self.button_frame, text="Change Camera", command=self.abort, width=25)
self.abort_button.pack(side="left") # Place the Abort button next to the Save Image button
self.root.bind("<Escape>", self.quit)
self.setup_camera()
self.max_var = 0
self.var_threshold = 0.010 # difference acceptable value in %
self.percentage_label = tk.Label(root, text="Percentage: 0%", font=("Helvetica", 14))
def setup_camera(self):
"""Setup of the camera and configuration harvester libraries"""
self.h = Harvester()
self.h.add_file(r"C:\Program Files\STEMMER IMAGING\Common Vision Blox\GenICam\bin\win64_x64\TLIs\GEVTL.cti")
self.h.update()
# Create an empty dictionary to store unique camera models with serial numbers
unique_cameras = {}
# Get a list of camera indices, names, and serial numbers
camera_info_list = [(i, camera_info.model, camera_info.serial_number) for i, camera_info in
enumerate(self.h.device_info_list)]
# Iterate through the camera_info_list to add unique cameras to the dictionary
for index, model, serial_number in camera_info_list:
unique_camera_identifier = f"{model} ({serial_number})"
unique_cameras[unique_camera_identifier] = index
# Extract the unique camera info list from the dictionary
unique_camera_info_list = [(index, identifier) for identifier, index in unique_cameras.items()]
# Populate the camera selection dropdown with unique camera models
self.camera_selection["values"] = [info[1] for info in unique_camera_info_list]
# Set the initial camera selection
self.camera_selection.current(0)
# Store the camera info list for later use
self.camera_info_list = unique_camera_info_list
# Create an empty camera instance
self.ia = None
def start_video_feed(self, selected_index):
"""Camera Properties setup """
# Destroy the existing camera instance
if self.ia is not None:
self.ia.destroy()
# Create a new camera instance based on the selected index
self.ia = self.h.create(selected_index)
# Rest of the camera setup code...
self.ia.keep_latest = True
self.ia.num_buffers = 8
self.ia.num_filled_buffers_to_hold = 1
self.ia.remote_device.node_map.AcquisitionMode.value = "Continuous"
self.ia.remote_device.node_map.AcquisitionFrameRateEnable.value = True
self.ia.remote_device.node_map.AcquisitionFrameRate.value = 24
self.ia.remote_device.node_map.GainAuto.value = "Once"
self.ia.remote_device.node_map.ExposureAuto.value = "Once"
# Set the resolution to 1080*1080
self.ia.remote_device.node_map.Height.value = 600
self.ia.remote_device.node_map.Width.value = 800
self.ia.remote_device.node_map.TriggerMode.value = "Off"
self.height = self.ia.remote_device.node_map.Height.value
self.width = self.ia.remote_device.node_map.Width.value
self.ia.start()
self.instructions_label.pack()
self.camera_selection.destroy()
self.info_label.destroy()
self.percentage_label.pack()
self.max_var = 0
# Start the video feed to adjust focus
self.update_frame()
def on_camera_selected(self, event):
# Get the selected camera index from the dropdown
selected_index = self.camera_info_list[self.camera_selection.current()][0]
# self.photo_label.destroy()
# Start the video feed for the selected camera to adjust focus
self.start_video_feed(selected_index)
def update_frame(self):
if self.ia is not None:
with self.ia.fetch(timeout=np.float32(1)) as buffer:
img_data = buffer.payload.components[0].data.reshape(self.height, self.width)
bgr_frame = cv.cvtColor(img_data, cv.COLOR_BAYER_BG2BGR)
self.last_frame = bgr_frame
# Check focus status (Example condition: mean pixel intensity)
var = cv2.Laplacian(bgr_frame, cv2.CV_64F).var()
self.max_var = max(self.max_var, var)
print("Current var value:", var)
print("Maximum var value:", self.max_var)
percentage_of_max = (var / self.max_var) * 100
print("Percentage of Max Value:", percentage_of_max)
# Calculate the percentage of how close the current focus value is to the maximum
# Check if the current variance is different from 0.05 of the maximum variance
is_focus_good = abs(var - self.max_var) <= self.var_threshold * self.max_var
# Set frame border color based on focus status
frame_with_border = self.set_frame_border_color(bgr_frame, is_focus_good)
focus_direction = "OK" # Default value if the focus is good
if var < self.max_var - self.var_threshold * self.max_var:
focus_direction = "Not ok , turn the lens"
# Convert the frame to PIL Image format
img = Image.fromarray(frame_with_border)
# Convert PIL Image to Tkinter-compatible image
img_tk = ImageTk.PhotoImage(image=img)
self.video_frame.config(image=img_tk)
self.video_frame.image = img_tk # Keep a reference to prevent garbage collection
print("Focus Adjustment Direction:", focus_direction)
self.percentage_label.config(text=f"Percentage: {percentage_of_max:.1f}%")
self.instructions_label.config(text="Focus Adjustment: " + focus_direction)
# Keep updating frames as long as the application is running
self.root.after(1, self.update_frame)
def set_frame_border_color(self, frame, is_focus_good):
"""Setting the border color to tell if focus is okay or not"""
if is_focus_good:
color = (0, 255, 0) # Green color for good focus
else:
color = (255, 0, 0) # Red color for bad focus
# Draw a colored border around the frame
frame_with_border = cv.copyMakeBorder(frame,3 ,3, 3, 3, cv.BORDER_CONSTANT, value=color)
return frame_with_border
def quit(self, event=None):
# Ask for confirmation before quitting
confirm_quit = messagebox.askyesno("Confirmation", "Are you sure you want to quit?")
if confirm_quit:
if hasattr(self, 'last_frame') and self.last_frame is not None:
# Get the current date and time
now = datetime.now()
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
file_name = os.path.join("log", f"last_frame_{date_time}.jpg")
cv.imwrite(file_name, self.last_frame)
if self.ia is not None:
self.ia.destroy()
self.h.reset()
self.root.quit()
def abort(self):
if self.ia is not None:
self.ia.destroy()
self.ia = None
# Create a new camera selection dropdown with updated values
self.camera_selection.destroy()
self.camera_selection = ttk.Combobox(
root, state="readonly",
values=[f"{info[1]} - {info[2]}" if len(info) > 2 else f"{info[1]}" for info in self.camera_info_list],
width=70
)
self.camera_selection.pack()
self.camera_selection.bind("<<ComboboxSelected>>", self.on_camera_selected)
self.camera_selection.current(0)
self.camera_selection.pack(side="top")
def save_image(self):
if hasattr(self, 'last_frame') and self.last_frame is not None:
# Ask for confirmation before saving the image
confirm_save = messagebox.askyesno("Save Image",
"Do you want to save the last displayed frame as an image?")
if confirm_save:
# Get the current date and time
now = datetime.now()
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
file_name = os.path.join("log", f"last_frame_{date_time}.jpg")
cv.imwrite(file_name, self.last_frame)
# Create the main Tkinter window
root = tk.Tk()
# Create an instance of the CameraGUI class
camera_gui = CameraGUI(root)
# Start the Tkinter event loop
root.mainloop()