Issue using 2 cameras with harvester libraries

202 views Asked by At

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()
0

There are 0 answers