04-02-2009
11:54 AM
- last edited on
03-02-2026
11:26 AM
by
Content Cleaner
This producer/consumer architecture looks promising for my application where I'm needing to write every frame that is acquired from a Prosilica camera to disk without affecting my acquisition speed.
I modeled my code after this link: http://zone.ni.com/devzone/cda/epd/p/id/5859 but I do not have Vision (only Vision Acquisition) so I replicated the copy command for color images after reading this: http://forums.lavag.org/IMAQ-Copy-Equivalent-t10415.html and replaced the Inverse vi with the write 2 file vi and got rid of the threshold buffer that seemed irrelevant for what I'm doing.
My problem comes in the functionality when running this revised vi. What's coming into the recorded image display is the most recent frame acquired. As a result I am able to record but am skipping frames in the process. I would expect to see a delay in the 2 image indicators on the front panel but I am not. This is not good! I would like my vi to function more like this one: https://forums.ni.com/t5/Example-Code/Producer-Constumer-Events-With-No-Data-Loss-in-LabVIEW/ta-p/35... where all frames would be written to disk and the recording continues even when you hit the stop button until the buffer is completely written to disk. Let me know if you have any ideas on grabbing every frame instead of the most recent.
Thanks in advance,
Nick
04-02-2009 11:56 AM - edited 04-02-2009 11:57 AM
04-02-2009 01:18 PM
You made this way more complex than it needs to be. You already have a built in buffer in the acquisition that you didn't make use of.
Just use a single loop after you start your acquisition. Wire the loop index to the buffer number input when you retrieve an acquired image. You might need to tell it to use the buffer number input. Process the image in the same loop. As long as you never get 100 images behind the acquisition, you will process every image. If you get 100 images behind, it will suddenly skip 100 images and possibly give you an error message.
Bruce
04-02-2009 03:36 PM
Electramotive,
Bruce is correct that the biggest issue in your code is that you have the buffer mode set to "Next" instead of by specific buffer number. This means that your 100 buffer ring is essentially wasted since the Grab VI will always return the newest image. He is also correct that in some ways you are making this more complicated because the buffer ring IMAQdx uses internally gives you the same type of producer/consumer behavior by default.
However, there is potentially some benefit to doing this additional level of buffering. For one, it allows some parallelization of your file I/O and your image decoding (the Grab VI both extracts and decodes the image data from the ring). If the two are done in series then the decoding cannot be done in parallel while the file I/O is completing. Now, in theory your I/O is buffered by the OS and hardware, so it shouldn't block you too much anyways. Additionally, the second level of buffering you have is taking an extra image copy which can hurt your performance, and only uses a single buffer. If I were to write it myself I'd probably create a two queues of images, one for empty images and one for full ones. Your producer loop would pull from the empty queue and Grab into one of those buffers, then place it into the full queue. The consumer loop would pull from the full queue, save the image to disk, and put it back into the empty queue. This would eliminate the overhead of an extra copy. I'd also change to use the queues in a blocking fashion instead of looping while polling the queue status.
Now, I'm not sure if in the end this is necessary for your case, because as I said the file I/O tends to be very well buffered by the OS and hence completes "in the background" anyways. For super-high-performance uses (hundreds of MB/sec) oftentimes you'll disable I/O buffering because of the inherent copying it entails, but I don't think your application needs that.
Eric