07-26-2009 02:01 AM
Hello,
I'm copying a video stream at 30Hz from a non-NI acquisition device to a CWIMAQViewer. Every new frame triggers the ImageAvailable event and is available from the framegrabber either as a .NET Bitmap or a pointer to a byte[]. It appears that the fastest way to copy the frames to the viewer is via the ArrayToImage function. If there is a better way, please let me know.
Please see the following post for more details:
http://forums.ni.com/ni/board/message?board.id=200&thread.id=23850
The challenge is that the ArrayToImage function takes 30-50ms to process the data which means that there is a substantial video lag when running at 30Hz. I noticed that if I set Viewer.NonTearingDisplay to false that the time drops to about 12ms. However, I really need to leave this option set to true because the display quality is unacceptable (lots of "tears") without it enabled.
What can be done (now or in future releases of the VDM) to improve the speed of the ArrayToImage function?
Thanks,
Neville
07-26-2009 02:34 AM
Hi,
Are you sure that you lost most time in MainBufferImage.ArrayToImage(ImageBuffer2D);
and not in Buffer.BlockCopy(ImageBuffer1D, 0, ImageBuffer2D, 0, ImageBuffer1D.Length * sizeof(byte));?
How big your image?
Andrey.
07-27-2009 12:56 AM
Hi Neville ,
What is your application? What is your image size? Can you extract (and shrink) the data in other words can extracting only the needed area reduce your time further? Do you need the entire image?
07-27-2009 12:09 PM
Hello Andrey and muks,
Andrey, I'm sure it's not in the BlockCopy. The BlockCopy takes about 0.5ms.
muks: I need to display full screen live video for an imaging application (moving a camera on a stage with a joystick). The image size is 1024x768, but we're about to upgrade to a 3MP camera (2048x1536), which will make it all even worse, I'm sure.
Hopefully there's a way to speed it up.
Neville
07-27-2009 12:20 PM
Hi,
If your BlockCopy so fast and IMAQArrayToImage so slow, then you can avoid such conversion: Get pointer to the memory where pixels located with IMAQ GetImagePixelPtr function and perform BlockCopy directly to the IMAQ Image.
IMPORTANT: your image should be created without Border! (Border=0). And this will work for images where line width the same with image width (as in your case for 1024 pixels).
Andrey.
07-27-2009 12:27 PM
Hello Andrey,
Very clever! I'll look into it. For the part where you talk about line width, I didn't fully understand what you were getting at. Do you mean that the zoom factor should be 1:1 with my screen resolution (i.e., 1 image pixel to 1 screen pixel)? Or did you mean something else? I will need to have the ability for the user to zoom the live video stream somehow.
Thanks,
Neville
07-27-2009 12:37 PM
No, I mean if you will using direct access to the pixels, you shouls understand, how IMAQ Image placed in memory:
So, if you have width=1024 and Border=0, then LineWidth equal to Image width. Otherwise (for example image width = 1024, but border = 3, then you will get boder and gap between lines). Gap is necessary for alignment.
Andrey.
07-27-2009 12:50 PM
Hi Andrey,
Thanks so much for explaining and for the image. It was really helpful. I have the border set to 0, so I think I'm good.
I tried finding IMAQ GetImagePixelPtr, but I couldn't find it. Can you please provide the full .NET funciton name? What NI dlls do I need to include as references?
Thanks,
Neville