VimbaPython icon indicating copy to clipboard operation
VimbaPython copied to clipboard

How to use asynchronous capture with multiple cameras?

Open OvervCW opened this issue 3 years ago • 2 comments

I'm trying to stream frames from two cameras at the same time (Allied Vision 1800 U-2050c, Allied Vision 1800 U-2460c) using the following code:

from vimba import Camera, Frame, FrameStatus, PixelFormat, Vimba
import time
import threading


def setup_camera(cam: Camera) -> None:
    cam.set_pixel_format(PixelFormat.Mono8)

    cam.AcquisitionMode.set("Continuous")
    cam.BinningVertical.set(1)
    cam.BinningHorizontal.set(1)

    cam.Width.set(5328)
    cam.Height.set(3672)

    cam.ExposureAutoMin.set(1000.0)
    cam.ExposureAutoMax.set(20000.0)
    cam.ExposureTime.set(20000.0)
    cam.Gain.set(10.0)

    cam.AcquisitionFrameRateEnable.set(True)
    cam.AcquisitionFrameRate.set(1)


class Handler:
    def __init__(self, idx: int):
        self._idx = idx

    def __call__(self, camera: Camera, frame: Frame) -> None:
        if frame.get_status() == FrameStatus.Complete:
            print(f"{time.monotonic()} - cam #{self._idx}: complete frame")
        else:
            print(f"{time.monotonic()} - cam #{self._idx}: failed frame: {frame}")

        camera.queue_frame(frame)


stop_running = False


def capture_thread(idx, cam):
    global stop_running

    setup_camera(cam)

    handler = Handler(idx)

    cam.start_streaming(handler=handler, buffer_count=2)

    while not stop_running:
        time.sleep(1.0)

    cam.stop_streaming()


with Vimba.get_instance() as vimba:
    cameras = vimba.get_all_cameras()

    with cameras[0] as cam0:
        with cameras[1] as cam1:
            t0 = threading.Thread(target=capture_thread, args=(0, cam0))
            t1 = threading.Thread(target=capture_thread, args=(1, cam1))

            t0.start()
            t1.start()

            input("press enter to stop\n")
            stop_running = True

            t0.join()
            t1.join()

I would expect the handlers in both threads to be regularly called using a frame from the associated camera, but in practice only the handler for the first camera (with index 0) is actually called.

Sample output:

press enter to stop
1213137.914160055 - cam #0: complete frame
1213138.914284494 - cam #0: complete frame
1213141.914462255 - cam #0: complete frame
1213144.914603388 - cam #0: complete frame
1213145.91475032 - cam #0: complete frame
1213148.914914694 - cam #0: complete frame
...

If I change the two binning values to 2 then it does work:

press enter to stop
1213817.792815084 - cam #1: complete frame
1213818.743061794 - cam #0: complete frame
1213818.792745757 - cam #1: complete frame
1213819.74312082 - cam #0: complete frame
1213819.792785887 - cam #1: complete frame
...

The change in behavior based on the binning value would suggest a problem with bandwidth, but I find it hard to believe that I would be running into bandwidth problems at a frame rate of 1 with monochrome images.

What am I doing wrong? How do I capture full resolution frames from both cameras?

OvervCW avatar Mar 09 '22 14:03 OvervCW

Thank you for generating this issue. We recommend our Multithreading example for mutli cameras. Please find them in the example folder.

arunprakash-avt avatar Mar 09 '22 16:03 arunprakash-avt

For future reference, my colleague @OvervCW got this to work by:

  • Increasing usb-fs buffer size by a lot (see https://china.alliedvision.com/fileadmin/content/documents/products/cameras/various/appnote/USB/USB-Camera-Handling-Linux-Application-Note.pdf)
  • Making sure that the frame handler function returns as quickly as possible. So by putting the image onto a queue to be processed by another process, without blocking when the queue is full.

kriskorrel-cw avatar Mar 11 '22 07:03 kriskorrel-cw