alliedvision / VimbaPython

Old Allied Vision Vimba Python API. The successor to this API is VmbPy
BSD 2-Clause "Simplified" License
93 stars 40 forks source link

multithreading with 3 camera #168

Open adri994 opened 1 year ago

adri994 commented 1 year ago

When I connect 3 camera at the time of the code I execute this line of code:

with self.producers_lock: for producer in self.producers.values(): producer.start()

tells me the following: camera with id XXXXX could not be found.

it should be noted that the camera is recognized and saved in the producer without any problem. this error only happens when I connect 3 or more cameras.

Teresa-AlliedVision commented 1 year ago

Can you stream all 3 cameras with the same settings in Vimba Viewer? If not, then this might be a bandwidth problem. To look into it further yu would need to provide more information about the camera and your setup and code. I would suggest you send a support request through our webform or post you full code here on Github. https://www.alliedvision.com/en/about-us/contact-us/technical-support-repair-/-rma/

adri994 commented 1 year ago

Right now seeing me it works but if I put a time.sleep at this point.

with self.producers_lock: for producer in self.producers.values(): producer.start() time.sleep(0.08)

the problem is that the thread system stops working because the frames are generated in a different order. without that it does not allow me to use the with cam

PD: I am using the same code as the example

adri994 commented 1 year ago

``class FrameProducer(threading.Thread): def init(self, cam: Camera, frame_queue: queue.Queue): threading.Thread.init(self)

    self.log = Log.get_instance()
    self.cam = cam
    self.frame_queue = frame_queue
    self.killswitch = threading.Event()
    self.lock = threading.Lock

def __call__(self, cam: Camera, stream: Stream, frame: Frame):

    logger.info('{} {}'.format(frame, self.cam.get_id()))
    if frame.get_status() == FrameStatus.Complete:

        if not self.frame_queue.full():
            frame_cpy = copy.deepcopy(frame)
            try_put_frame(self.frame_queue, cam, frame_cpy)  
    cam.queue_frame(frame)

def stop(self):
    self.killswitch.set()

def run(self):
    logger.info('Thread \'FrameProducer({})\' started.'.format(self.cam.get_id()))
    try:
        with self.cam:
            #self.setup_camera()

            try:   
                self.cam.start_streaming(self,buffer_count=5)
                self.killswitch.wait()
            finally:
                self.cam.stop_streaming()
    except VmbCameraError:
        pass

    finally:
        try_put_frame(self.frame_queue, self.cam, None)

    logger.info('Thread \'FrameProducer({})\' terminated.'.format(self.cam.get_id()))

class MainThread(threading.Thread): def init(self,configuration): threading.Thread.init(self)

    self.frame_queue = queue.Queue(maxsize=FRAME_QUEUE_SIZE)
    self.producers = {}
    self.producers_lock = threading.Lock()
    self.configuration = configuration

def __call__(self, cam: Camera, event: CameraEvent):
    if event == CameraEvent.Detected:
        with self.producers_lock:
            self.producers[cam.get_id()] = FrameProducer(cam, self.frame_queue)
            self.producers[cam.get_id()].start()

    elif event == CameraEvent.Missing:
        with self.producers_lock:
            producer = self.producers.pop(cam.get_id())
            producer.stop()
            producer.join()

def run(self):
    global count_cameras_used
    log = Log.get_instance()
    consumer = FrameConsumer(self.frame_queue, self.configuration['processing']['max-num-frame'])

    vmb = VmbSystem.get_instance()
    vmb.enable_log(LOG_CONFIG_INFO_CONSOLE_ONLY)

    log.info('Thread \'MainThread\' started.')

    with vmb:

        cams = vmb.get_all_cameras()

        logger.info('Creating configuration files')
        for cam in cams:
                try:
                    self.producers[cam.get_id()] = FrameProducer(cam, self.frame_queue)
                    #create_configuration_file(cam,self.configuration['processing']['xml-settings-path'], self.configuration['processing']['max-num-frame'])
                except:
                    logger.critical('Error!! could not configure the cameras')

        count_cameras_used = len(self.producers)    
        with self.producers_lock:
            for producer in self.producers.values():
                producer.start()

        # Start and wait for consumer to terminate
        vmb.register_camera_change_handler(self)
        consumer.start()
        consumer.join()
        vmb.unregister_camera_change_handler(self)

        # Stop all FrameProducer threads
        with self.producers_lock:
            # Initiate concurrent shutdown
            for producer in self.producers.values():
                producer.stop()

            # Wait for shutdown to complete
            for producer in self.producers.values():
                producer.join()

        logger.info('Thread \'MainThread\' terminated.')``

fails in the 'with' when there are more than 2 cameras, it does not recognize the cameras

Teresa-AlliedVision commented 1 year ago

Hi, pleasse check first of all, if all of the cameras can be accessed and stream in Vimba Viewer at the same time. This is to make sure that there is no problem with the setup or installation. Once that is clear, we can have a closer look at the code and specifically the Vimba Python setup.