Python: Add a pointer to image data in memory to acquisition queue, not the retrieved image data

Question:

I have a multithreaded image processing Python SW where:

  • One thread does image acquisition and appends metadata from other sensors (accelerometer ++) and pushes it all to a queue
  • Another thread pops from the queue and does a computation on the images + metadata

My issue is that the pypylon command
cam.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException) takes ~100ms pr. camera and that is when images are already in the buffer (external trigger signal has happened).

Here is a pseudo code of how I do it today:

Acquicition thread:

queu_element = type('queue_element', (object,), {})()
images = [None] * 3
for i, cam in enumerate(cameras):
  grab_result = cam.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)
  images[i] = grab_result.GetArray().copy()
  grab_result.Release()
queu_element.images = images
queu_element.metadate = get_metadata()
queue.append(queu_element)

Processing thread:

queue_element = queue.pop()
do_awsome_processing(queue_element.images, queue_element.metadata)

My Idea of speeding up my image acquisition is to move the RetriveResult command from my acquisition thread to my processing thread.
I am thinking that my Acquisition queue should contain pointers to the memory address and not the retrieved result itself. The processing thread should retrieve the result.
Here is some pseudocode of my idea:

Acquiction thread:

queu_element = type('queue_element', (object,), {})()
pointers = [None]*len(cameras)
while cameras[0].no_new_image_in_buffer():
  sleep(0.01)
for i, cam in enumerate(cameras):
  pointers[i] = cam.PointerToNewestBufferedImage()
queue_element.pointers = pointers
queue_element.metadata = get_metadata()
queue. Push(queue_element)

Processing thread:

queue_element = queue.pop()
images = [None] * len(queue_element.pointers)
for i, pointer in enumerate(queue_element.pointers)
  images[i] = RetrieveResultFromMemoryAddess(pointer, pylon.TimeoutHandling_ThrowException)
do_awsome_processing(images, queue_element.metadata)

I hope someone knows a way to guide me towards this solution

I have functional code based on pypylon example code. However, I want to optimize where acquisition and adding new data to queue takes as little time as possible.

Asked By: Joachim Spange

||

Answers:

The answer to this python problem is something else than pointers. After learning about pointers in python Real Python, this became clear to me.

When it comes to streaming images from cameras the pypylon command has the same response time as the Pylon Viewer Software. If you can steam a certain fps there, then you should be able to see the same data response time running cam.RetrieveResult()

However, two settings might need to be edited

  1. USB Steam Maximum Transfer Size
  2. cam.GetStreamGrabberNodeMap().GetNode("MaxTransferSize").Value

Thanks to @ChristophRackwitz and @ArtiomKozyrev for initiating me onto this great learning path.

P.S.
This issue was also discussed at the pypylon community on GitHub

Answered By: Joachim Spange