LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Fastest way to log IMAQ images to Disk

Haven't done vision related stuff for a while but you might want to look into using "IMAQ ImageToEDVR" in conjunction with "TDMS Advanced Asynchronous Write (Date Ref)". The IMAQ ImageToArray function takes a non-trivial amount of time to execute as it has to copy all in-memory pixel values. I believe using the data reference functions avoids this unnecessary copy which should save you some time.

 

Before you go this route I would probably benchmark how long IMAQ ImageToArray takes to execute on an "average" image for you and multiply that by your camera's frame rate to see how much time you are devoting to this operation. 

Matt J | National Instruments | CLA
0 Kudos
Message 11 of 20
(1,880 Views)
I can't help with the IMAQ part, but I wanted to mention that if SSD speed is a problem you can use a RAID0 array to increase speeds. If you go this way, don't store anything on that disk long-term. RAID0 doubles your risk of failure for doubling of write speeds (theoretically); if one disk goes, they both go. Use it as a buffer only. I had a case once where I used a pair of SSD's in RAID0 and the cord on one bumped loose while I was working on something else (with the power off). When I booted up the computer, it could only see one disk and corrupted the array. There might've been a way to save it but "just plug it back in" didn't work.
0 Kudos
Message 12 of 20
(1,865 Views)

Thanks a lot, Bob-Schor for your time and worthy suggestions.

 

I am adding a few more details about the requirement,

 

1. Images are acquired in a PC (server) and streamed to other PC(clients) through 10 Gb Ethernet.

2. The clients would parse the TCP stream and display it in Image control and the user can enable recording of image streams in client PC.

 

Using a Circular Buffer:

I can still use the circular buffer as you suggest on the client-side but I need to write the circular buffer logic, whereas in case image acquisition IMAQ driver handles the ring acquisition, based on the buffers configured.

 

Avoiding Image Display:

The requirement is such that the images need to be displayed and logged only when the user enables logging. (Final code will have 2 queues one for logging and displaying but the reference will be same) 

 

Destroy image:

I profiled the IMAQ dispose image API (4k *4k U16) and it took 0.5 ms on average. But will try if there is any way to avoid this in the consumer loop.

 

The other main observation from the time profiling is TDMS write (both sync & async) is better than any other formats but not fast enough(500 MB/S) to stream image without memory building though the SSD drive is capable of high write speed (3500 MB/S) as per spec. I have written to NI to get their thoughts on this behavior.

 

Thanks,

Mani.

 

 

0 Kudos
Message 13 of 20
(1,853 Views)

Hi Jacobson, 

 

I am using the NI examples - Stream to TDMS for profiling. As you suggested this example uses "IMAQ ImageToEDVR" in case of asynchronous TDMS write. This API is pretty fast (0.5 ms) when compared to the IMAQ image to array (30 ms).

 

Thanks,

Mani

0 Kudos
Message 14 of 20
(1,851 Views)

Wow.  Now a lot more details are coming out, showing that there is a lot of I/O traffic going on, multiple computers, multiple passing of megabytes of data (actual images) through multiple TCP/IP 10 Gb connections.

 

Wherever you have Images, you need Image Buffers, one per Image.  However, if Images are "transient" (as in "Acquire in Camera and immediately show once and write to disk"), then you can reuse the Buffers (which are pointers to large areas in memory where you temporatily store pixel data, in your case megabytes of data) -- you only need to be sure you have enough that when you are filling a Buffer, its "old" data have already been used and or saved and are no longer needed.

 

If all you are doing is capturing images in the Camera, displaying them once, and immediately saving them, all on the same machine, you need sufficient Buffers to hold all the images to do the "Capture-Show-Save" cycle, which should be driven by the expected lag time between Capture and Saved.  If you are, instead, doing "Capture and Send to Consumer", then you need to configure a separate Ring Buffer for the Consumer Loop, again keeping all the Buffers intact and rotating the data through them.  Configure them all before using any of them, and dispose of them all as part of your shut-down routine (or you can be "sloppy" and just exit the program).

 

Bob Schor

0 Kudos
Message 15 of 20
(1,834 Views)

You should be able to make an array in the producer that cycles it's active element (remainder (counter, buffer size)), and send the updated element to the consumer, over a queue or user event. The elements are pointers.

 

It's a bit tricky, as the producer can overwrite the element before the consumer used it. That would be a buffer overflow in all scenario's. The design would be simpler, but the overflow might be harder to detect.

0 Kudos
Message 16 of 20
(1,829 Views)

Bob_Schor & wiebe@CARYA, Maintaining a circular image buffer will ensure there is no memory shoot up since it is one-time allocation and deallocation but will cannot achieve lossless recording (logging all the frames). I suspect there is an additional overhead in TDMS write API which is the main bottleneck in achieving the write speed.

 

Thanks,

Mani.

0 Kudos
Message 17 of 20
(1,796 Views)

@manig wrote:

Bob_Schor & wiebe@CARYA, Maintaining a circular image buffer will ensure there is no memory shoot up since it is one-time allocation and deallocation but will cannot achieve lossless recording (logging all the frames). I suspect there is an additional overhead in TDMS write API which is the main bottleneck in achieving the write speed.


At the end of the line storage must be faster or as fast as the creation. If in>out, you will get an out of memory, or data loss.

 

A circular buffer will smoothen the logging, buffering images when the storage is slow for a while. 

0 Kudos
Message 18 of 20
(1,784 Views)

Concerning avoiding the display of images:

We have run a couple of time into issues with displaying images slowing things down. As normal people can only register 25 to 30 images per second may be you can cut down the number of images actually brought to display. I usually use "Quotient and Remainder" to only show every n-th image.

 

TDMS for saving images as of this study:

https://forums.ni.com/t5/Example-Code/Storing-Images-in-TDMS-Files-Benchmarks-and-Example-Code/ta-p/...

seems to be the fastest as you may be able to get with LabVIEW.

 

Also my experience with IMAQ functions is to be VERY careful to not open (and close) too many IMAQ image instances within a short period of time. Best practise seems to be to plan carefully, how many image buffers you'll need at the same time for different operations and then create them before doing anything else and disposing of them when everything else is done. Disposing image buffers with IMAQ Dispose also can be very cumbersome with respect to time.

0 Kudos
Message 19 of 20
(1,771 Views)

Yes Comrade, it doesn't make sense to display at a faster rate and I will implement slowing down image display.

 

As you mentioned, TDMS is the fastest way so far and have tried multiple options consolidating that in order of fast to slow,

 

1. TDMS Asynchronous

2. TDMS Synchronous - with reserving file size before logging to avoid allocation for each image log (this requires the application to be run as admin)

3. TDMS Synchronous

4. Binary File

5. File Streams - using mscorlib.dll

 

We are able to log images to TDMS asynchronous mode at required rate when the application is run as executable with admin privileges.

 

Thanks,

Mani.

 

Thanks,

Mani.

0 Kudos
Message 20 of 20
(1,740 Views)