Neil Pate Posted January 20, 2017 Report Share Posted January 20, 2017 (edited) Hi gang, Simple question, can I treat a Vision Images ref just like any other U32 ref with all the rules applicable like forking wires etc? It seems to me that there is some kind of special stuff going on with Vision Image refs. Another related question, in my particular use case I have a piece of code generating a user event with an image as the data at some arbitrary fast rate. The act of Generating the user event creates the a copy, right? Some other code wants to process some of these frames (at a slower rate) and then I use IMAQ Copy to make a local copy, is this IMAQ Copy necessary or could I just hold onto the "Image" reference coming in from the user event? In the code below Images is just a local buffer I plan on using. The reason I ask is I am getting some weird behaviour whereby destroying my Images refs as shown in Capture3.jpg kills my acquisition code as well. (I presume because I am forcing all images to be destroyed, but I am surprised this is happening) Edited January 20, 2017 by Neil Pate Quote Link to comment
Neil Pate Posted January 20, 2017 Author Report Share Posted January 20, 2017 More strangeness (probably just me not getting something). Why are all four Image references the same? Quote Link to comment
drjdpowell Posted January 20, 2017 Report Share Posted January 20, 2017 Cast it to a U64 instead of an I32; then the numbers are different. 1 Quote Link to comment
Neil Pate Posted January 20, 2017 Author Report Share Posted January 20, 2017 2 minutes ago, drjdpowell said: Cast it to a U64 instead of an I32; then the numbers are different. Bingo! Thanks James. So Image refs are just plain old normal U64 size refs? I sometimes wish there was a way to see refs as native "pointers" in a probe rather than the special type (i.e. the image). I suppose I could create a custom probe and just display the U64... Quote Link to comment
drjdpowell Posted January 20, 2017 Report Share Posted January 20, 2017 1 hour ago, Neil Pate said: Another related question, in my particular use case I have a piece of code generating a user event with an image as the data at some arbitrary fast rate. The act of Generating the user event creates the a copy, right? I always find images annoying because the are by-ref. You send a copy of the reference to the image, not a copy of the image. Quote Link to comment
Neil Pate Posted January 20, 2017 Author Report Share Posted January 20, 2017 2 minutes ago, drjdpowell said: I always find images annoying because the are by-ref. You send a copy of the reference to the image, not a copy of the image. But they are kinda ByVal as you wire into an indicator to actually display the image. You cannot just make that association once and then assume it will automatically get updated. Quote Link to comment
drjdpowell Posted January 20, 2017 Report Share Posted January 20, 2017 Well, to dequeue from a Queue, you have to provide the Queue reference every time. You can't call dequeue once and have it automatically keep happening. The confusing thing is that it is we write the Image Ref to a Control Terminal, rather than a VI. That's what fools us into thinking of passing images by-value. Quote Link to comment
smithd Posted January 20, 2017 Report Share Posted January 20, 2017 (edited) Images are bizarre. My experience using them lately is that I basically don't trust anything that they do without testing. In the first case, I don't think you need to copy the image into a local reference unless you want to do several processing steps on it (where the source reference could be updated between steps). If you just want to display the image I think the image display makes a copy of the image data pointed to by the refnum. Usually. I also could swear I've seen it automatically update sometimes, but in the code I was working on last week, it didn't. See below. That having been said, unless there is a performance concern I'd just make the copy. I've personally found that its easier and less painful to re-create dataflow manually through several data copies than it is to deal with the references -- copying a sequential chunk of memory is not expensive. Its worth mentioning my biggest problem with images -- the references are named in a global namespace. I had several months of issues related to flattening and unflattening images at runtime and causing camera A to be mixed up with camera B, or the display suddenly getting populated with week-old data because I read from a file where the flattened images had the same name. Anyway this experience taught me to be super aggressive with copies, and all my images use GUIDs for names. Copy, copy, copy. Where performance is less of a concern I started using ImageToArray and passing around the 2D pixel array dataflow-style. Because seriously screw globally named references. Quote The reason I ask is I am getting some weird behaviour whereby destroying my Images refs as shown in Capture3.jpg kills my acquisition code as well. (I presume because I am forcing all images to be destroyed, but I am surprised this is happening) This seems more straightforward. If you dispose of all images, acquisition should fail since there is no memory space to put new images into. Am I misunderstanding? Edited January 20, 2017 by smithd Quote Link to comment
smithd Posted January 20, 2017 Report Share Posted January 20, 2017 Hrm... http://digital.ni.com/public.nsf/allkb/70C818F9E5CFCFDB8625703E007EEAAD This explains how I've seen it sometimes update. Maybe the older code I was looking at had "snapshot" turned off. Quote Link to comment
drjdpowell Posted January 20, 2017 Report Share Posted January 20, 2017 (edited) Yes. With snapshot off, the image redraws from the buffer whenever it refreshes. Writing to a terminal triggers a refresh**, but you can also do it by the "Refresh Image" Method. ** Note: LabVIEW controls are running in the UI thread and are asynchronous to their terminal, so writing an Image ref to a terminal only schedules an update for possibly several milliseconds in the future, by which time the image may have been overwritten. I think this may also be a big source of confusion, as with by-value data the delay is never a problem, but with by reference data it is. Edited January 20, 2017 by drjdpowell Quote Link to comment
Rolf Kalbermatter Posted April 3, 2017 Report Share Posted April 3, 2017 (edited) The IMAQ datatype is a special thing. It is in fact a refnum that "refers" to a memory location that holds the entire image information, and that is not just the pixeldata itself but also additional information such as ROI, scaling, calibration, etc. Just as passing a file refnum to a file function does not pass a copy of the file to the function to operate on, so does passing an IMAQ refnum not create a copy of the data. It at most creates a copy of the refnum (and increments an internal refcount in the actual image data structure). The IMAQ control does the same. It increases the refcount so the image stays in memory, and decreases the refcount for the previous image when another IMAQ refnum is written into the control. And there is a good reason that NI decided to use a refnum type for images. If it would operate on them by value just as with other wire data, you would be pretty hard pressured to process even moderately sized images on a normal computer. And it would get terribly slow too, if at every wire branching, LabIEW would start to create a new by value image and copy all the potentially 100MB and more data from the original image into that copy. And if you wire a true constant to the destroy all? input on the IMAQ Destroy function this simply tells IMAQ to actually destroy any and every image that is currently allocated by IMAQ. And if you do that you can in fact save yourself the trouble of calling this function in a loop multiple times to destroy each IMAQ refnum individually. But yes, it will basically destroy any and every IMAQ refnum currently in memory, so there is no surprise that your IMAQ control suddenly turns blank as the image it displays is yanked out of memory under its feet. And why would they have added this option to the IMAQ Destroy? Well, it's pretty usual to create temporary images during image analysis functions and give them a specific name. If they don't exist they will be created and once they are in memory they will be looked up by their name and reused. So you don't typically want to destroy them after every image analysis round but just let them hang around in memory to be reused in the next execution of the analysis routine. But then to properly destroy them at the end of the application, you would have to store them in some queue or buffer somewhere to refer to them just before exiting and pass that refnum explicitly to the IMAQ Destroy function. Instead you can simply call IMAQ Destroy with that boolean set to true, to destroy any IMAQ refnums that were left lingering around. Edited April 3, 2017 by rolfk Quote Link to comment
infinitenothing Posted April 3, 2017 Report Share Posted April 3, 2017 On 1/20/2017 at 1:21 AM, Neil Pate said: Bingo! Thanks James. So Image refs are just plain old normal U64 size refs? I sometimes wish there was a way to see refs as native "pointers" in a probe rather than the special type (i.e. the image). I suppose I could create a custom probe and just display the U64... On 1/20/2017 at 0:20 AM, Neil Pate said: More strangeness (probably just me not getting something). Why are all four Image references the same? Your reference id: 0x496d6167 is hex ascii for "Imag". That is, it's the first four bytes of your image name. Images are string references a bit like a named queue. It's too bad Image Refs came before DVRs. It would have been much simpler to understand if you knew the DVR syntax. 1 Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.