Showing results for 
Search instead for 
Did you mean: 

Vision acquisition - resolution problem

@RiffLord wrote:

I have tried experimenting in NI MAX and the camera works fine (...) The only problem is when I'm using vision acquisition and it doesn't save resolution.


At this stage I assume what you mean by 'resolution' is (implied by) the Video Mode parameter you've encircled in photo_2 in your first post.

It says 640x360 YUY2 30.00fps. If you set the Video Mode this way in NI MAX once, the setting should carry over to your VI- meaning you don't need to configure it anymore.


However, it may very well be you do have the right 'resolution' when using your VI: in your first post photo_3 seems to be a zoomed-in version of photo_2. To correct this, right-click on the Image Out panel and select Zoom to Fit. That should give you the entire view. Have you tried that?



@RiffLord wrote:


I tried using normal blocks from IMAQdx and without my full program it works too, but when I'm using it in my full program camera slows down, have like 2-3FPS (...)


If you're able to get the imaging working with the basic building blocks of IMAQdx, you're already well on your way.


You may want to look at the NI Example Finder to learn more about setting up a robust imaging session and image processing. 

On the Front Panel, select Help >> Find Examples...). This opens the Example Finder. Select Directory Structure below the Browse according to: option and then look for Vision and Vision Acquisition examples.


The reason why you only get a grab rate of 2 to 3 fps is because the image (i.e. the Image Out control) is updated after each iteration of the while loop - but this happens when all the other (non-imaging) functions in your loop have executed.

To solve this, your set up requires parallel processing. See below.



@RiffLord wrote:

Do you mean to use a separate loop for camera streaming with filters and pattern matching? And it can be done in the same VI? or do I need to do it in a separate VI? Any tips how to separate it in different loops?


Yes (separate loops) and yes (same VI). A decent first choice for separating loops is the Producer/Consumer architecture mentionded by Bob_Schor above: I'd try to set this up so the top loop is dedicated to image streaming and the lower loop does the image processing (and other stuff).

0 Kudos
Message 11 of 28

I'm sorry that i have to ask this many times, but i need to be sure. One loop is dedicated to image streaming, that means with filters like brightness, contrast, pattern matching or without? I'm not sure if there is supposed to be blocks like pattern maching or move them to another loop as you called image processing and other stuff. 

And I tried to set the Video Mode in NI MAX, but that doesn't save resolution to my VI's, so i had to set this parameter in VI.

So I have to use Queue Operations, when using two loops? Or can I use two loops, connected without this Queue Operations? I've never seen these operations before. 

And last question (I hope) in two loop system I can use webcam in real time? I mean is whether the camera will provide a real-time preview?

Thank you so much again!

0 Kudos
Message 12 of 28

Thank you so much for your response, the Queue system seems complicated 😕 

I have a question about it, in my program, I'm using a bundle, unbundle, and blocks like pattern matching, where should it be, in the loop with a camera or in the consumer loop? I don't understand where should things be 😞 

So before the producer loop I have to get the Camera completely set up right? and in a Producer loop will be blocks like Grab, Extract Single Color Plane, Patter Maching? or put these blocks in Consumer loop, so the producer loop will only have grab?

And  IMAQ Start Acquisition has to be before or in the loop?

I'm sorry that I have to ask these probably easy questions, I hope this doesn't irritate you. I've never used Queue operations, and I'm not sure what blocks have to be in the producer/consumer loop.

Thanks for your time again!

0 Kudos
Message 13 of 28

Hi, RiffLord.


     Am I correct that you are trying to use LabVIEW Vision before you've experienced the "traditional" Data Acquisition functions in LabVIEW called DAQmx?  And you haven't read "Learn 10 Functions in NI-DAQmx and Solve 80 Percent of your Data Acquisition Applications"?


     If so, I recommend you do a Web search, find this White Paper, and read it.  It shows that "continuous data acquisition" using NI hardware (and video, using Webcams) generally have "Configure" functions, a "Start" function, a While Loop with (basically) a Read (into a buffer, multiple points) and "use the data" code, and a "Stop/Close" set of functions when the While loop exits.  There is no explicit timing (no Wait function or timed loop) inside the While -- that's all set up before the Start.


     IMAQdx is the same.  You configure it first, start the Camera, enter a While Loop, acquire a Frame, process it, and keep going until you exit the While Loop.


     The Acquisition as a "natural" clock rate, once per "Read" (or "Grab"), after which you have "until the next Read/Grab needs to dump data".  The point is that dumping data is fast, whereas processing the data might be slow (you might do an FFT, for example, or drive a display).  To prevent data processing from slowing down the acquisition, you use Producer/Consumer -- the Producer (the Grab) "gets the data" (the "image", which is really a pointer to a buffer) and "exports it" out of the Loop via a Queue or a Stream Channel Wire to another parallel loop, the "Consumer", which does the processing.  It doesn't worry about "camera", only deals with "image".


Bob Schor

Message 14 of 28

Thank you for your response and thanks for the tips, I haven't read this "Learn 10 Functions...", I was thrown in at the deep end with this Vision thing 😞 I had a program done before but with a sensor, not a webcam. My job was to change it from sensor to webcam, but it is challenge for me, I thought, that Im gonna only remove blocks that used sensor data and change it to vision acquisition and that's it. But in observation in real time, and using PID to tune a real element which is a levitating ball in a tube with fans, I couldn't have had that much delay from the webcam... That's my story.

I'm trying to find information about "Obtain Queue" block, but I still don't understand what should I put into an element data type from my program. Could you maybe explain it to me, I was thinking about connecting date there from IMAQ create? or maybe I don't need to connect anything to it?

In attachement I will show you how i think the producer loop should look like.(producer_loop)

Edit. I moved some elements to another loop, it seems to be fine??? but still don't know how to use "obtain queue" (attachement prod_cons_loop)

Download All
0 Kudos
Message 15 of 28

Sigh.  How many times do we have to say "Always attach VIs, preferably in a LabVIEW Version we can read" (which means, for many of us, "Save for Previous Version" in LabVIEW 2019).


When you do a IMAQdx Grab, what you get is an "image" (which is not pixels, but a pointer to a buffer in your PC where all the pixels are stored).  You could wire this "image" to a (oops, I momentarily forgot the name of the indicator that shows the Image, is it a "Window"?) "thing", and you see your most recent frame.  Well, if you enqueue this "image", and in a separate free-running Loop dequeue it into the "thing that shows the image", you'll see the image!  Because you are basically passing a "pointer to memory" that LabVIEW "knows" contains an image, and pointers are very small (a dozen bytes?), this operation takes virtually no time at all!


Bob Schor


P.S. -- if you attach real code, I might show you how to do the Producer/Consumer bit using a Stream Channel Wire, which is so much more mnemonic, hence easier to create and much easier to understand, than a Queue.

Message 16 of 28

I wrote that earlier, that I don't have new LabView, we're using LabView2015, that's the problem. I read that they added Stream Channel Wire in LabView 2016 😞 My school is lincesed for the LabView 2015, that's why i asked you about block named "Obtain Queue". Tomorrow I will ask my teachers if there's maybe a newer version somewhere, if the "queue" is too dificult for me to do...

I will attach the file, but i don't know if you will be able to open it, if it is from Labview 2015.

I think I connected the rest of the blocks correctly, but I don't know what to do with "Obtain Queue", what to connect to "element data type".

Thank you for your help, patience and I'm sorry that I am a slow learner.

0 Kudos
Message 17 of 28

Here's a partial fix.  When you create a Queue, you need to specify what is in the Queue, which you do at "Create Queue".  The "picture" below (I don't have LabVIEW 2015 on this machine, so I'm showing you a picture, sorry) shows the single wire I added that "defined the Queue" and made all the Queue errors vanish.


But I wasn't sure (and still am not 100% certain) that the rest of the code was OK.  To understand the Producer loop (shown here), I "improved the Style" by straightening out the Error Line and trying to keep wires as straight as possible and relatively short, so you can "see the forest for the trees".  I left the other loop alone, so I didn't include it in the picture.

RiffLord Fix (partial).png

Bob Schor 

Message 18 of 28

Thank you so much, you probably saved my life 😄 It works! (I think...) On my home computer camera works on like 20FPS, which is enough for the project, not 30FPS as I imagined, but it doesn't look like the camera has any delay. I'll have to check it out at school now, with all the equipment. 

One thing that worries me, is this error. (Attachment) It shows up when I stop the program. It has a problem with the dequeue element, but I think when the program is working I can be calm.

If you know the solution, this will be my last request to you (unless in school more errors will occur :P)

If there are any errors, can I ask further?


Thank you so much again!

0 Kudos
Message 19 of 28

That's a "feature" that NI build into their Queue implementation which occurs when you try to close a Producer/Consumer loop.  I've not re-examined your code to be sure I'm 100% accurate, so bear with me if I get a detail wrong.


The problem comes in asking "How do you stop a Producer/Consumer pattern that uses Queues to synchronize the two?".  Generally, you run a Producer, it "produces" data that gets "asynchronously" sent to a Consumer, who "consumes" it.  What happens when you want to stop these two processes?  One "almost always" tells the Producer to stop, typically by wiring the Stop button button to the Stop indicator in the While Loop.  So it exits, and (obviously) stops sending packets to the Consumer. 


At this point, the Producer "knows" it won't put any more data into the Queue, so as far as the Producer is concerned, the Queue can be closed.  But the Consumer doesn't "know" this.  Most Consumers (politely) wait for more data from the Producer, but if the Producer has released the Queue, the Consumer will "Error Out".


There are two Better Ways (well, they're the "same" way, implemented differently).  Both rely on the Producer sending the Consumer a signal that it is done.  Traditionally, this is called a "sentinel".  So instead of releasing the Queue when the Producer exits, have it send "one last packet", something "unique", to the Consumer.  Since all other packets were "Arrays of Data", send an "empty" Array of Data, and let the Producer Loop exit.


Now the Consumer dequeues its packet, an "Array of Data".  If it is an empty Array, you want the Consumer to exit (so wire it to the Stop Indicator) and to release the Queue, which you can do inside the "True" limb of the "Is Empty Array?" Case Statement you added, or when the Consumer exits.


The other method, one that I've used since Asynchronous Channel Wires were first introduced as a "Hidden Feature" of LabVIEW 2015, is to use a Stream Channel, which is a "Queue for Producer/Consumer purposes" done right.  It has a Writer (similar to Create Queue/Enqueue) and a Reader (similar to Dequeue), with additional controls on the Writer for "Last Element?" and "Valid?", and indicators on the Reader.  Best of all, the "Channel Wire" (which looks like a Pipe) "flows" from left to right, so the output from the Writer in on the right (unlike a Queue, where the data "appear to flow backwards").  Streams are only for transferring data from one place to another -- you aren't supposed to "branch" them.


Bob Schor


Message 20 of 28