genicam / harvesters

Image Acquisition Library for GenICam-based Machine Vision System
Apache License 2.0
502 stars 86 forks source link

Unable to get two cameras to asynchronously read frames #466

Open y2k0999 opened 1 week ago

y2k0999 commented 1 week ago

Describe the Issue When I run the tutorial code in two instances concurrently, each connecting to a separate camera, the recording is not done asynchronously, ie one camera finishing recording before the other starts.

To Reproduce Steps to reproduce the behavior:

  1. Connect two genicam cameras via a switch to an Nvidia Jetson.
  2. Run the tutorial code in two different tty's at the same time, each connecting to a unique camera.
  3. Print out the filename of the frame when saving it
  4. See that the print order is synchronous

Sample Code I mostly just used the tutorial code for this.

Sample output:

connected to cam 1 connected to cam 2 saving image: cam1/0.png saving image: cam1/1.png ... saving image: cam1/10.png saving image: cam2/0.png ... exiting cam1 saving image: cam2/10.pong exiting cam2

Expected Behavior I expected the frames to be taken asynchronously, ie the print out would look as follows:

connected to cam 1 connected to cam 2 saving image: cam1/0.png saving image: cam2/0.png saving image: cam1/1.png saving image: cam2/1.png ... exiting cam1 exiting cam2

Configuration

Reproducibility

This phenomenon can be stably reproduced:

This happens every time.

Actions You Have Taken

y2k0999 commented 1 week ago

Sorry about the code formatting issue. I don't know what the problem causing it is.

I found this issue and copy pasted his code with threading and multiprocessing, both of which presented different issues. Threading still is reading the frames sequentially, multiprocessing hangs on the call to ia.start() for the second camera.

`

def camera_stream(camera_name): print(camera_name, 'entered fork') camera_name.start() print(camera_name, 'started_cam') for frame in range(20): time.sleep(1) print('iterating over frame', frame) buffer = camera_name.fetch() print(camera_name, datetime.now()) component = buffer.payload.components[0] w, h = component.width, component.height buffer.queue() if name == "main": h = Harvester() h.add_file('/opt/ImpactAcquire/lib/arm64/mvGenTLProducer.cti') h.update() device_found = h.device_info_list ia = h.create(0) ib = h.create(1) device_found = [ia, ib] procs = [] for name in device_found: print('about to fork')

proc = Process(target=camera_stream, args=(name,))

    proc = threading.Thread(target=camera_stream, args=(name,))
    print('finished forking')
    procs.append(proc)
    proc.start()
    print('procs started')
for proc in procs:
    proc.join()
    print('finished join')

ia.stop()
ia.destroy()
ib.stop()
ib.destroy()
h.reset()

` jet@ubuntu:~/harv_test$ python3 italian_main.py about to fork finished forking <harvesters.core.ImageAcquirer object at 0xffff61ca1900>procs started entered forkabout to fork

finished forking <harvesters.core.ImageAcquirer object at 0xffff61ca1900><harvesters.core.ImageAcquirer object at 0xffff61ca2920> started_camprocs started

entered fork <harvesters.core.ImageAcquirer object at 0xffff61ca2920> started_cam iterating over frame 0 <harvesters.core.ImageAcquirer object at 0xffff61ca1900> 2024-06-28 17:02:51.845528 iterating over frame 0 iterating over frame 1 <harvesters.core.ImageAcquirer object at 0xffff61ca1900> 2024-06-28 17:02:52.875362 iterating over frame 2 <harvesters.core.ImageAcquirer object at 0xffff61ca1900> 2024-06-28 17:02:53.916362 iterating over frame 3 <harvesters.core.ImageAcquirer object at 0xffff61ca1900> 2024-06-28 17:02:54.940115 iterating over frame 4 <harvesters.core.ImageAcquirer object at 0xffff61ca1900> 2024-06-28 17:02:55.992438