When writing vision-applications in LabVIEW, I never know what the best way, or the difference is, between
the 2 following methods to pass a reference of an image to a parallel VI.
So suppose I have a producer loop that produces an image with a unique name ("IMAQ Create"-name).
Then I have a consumer loop that should process this image.
I typically use string-type queues to send a message from a producer to consumer loop.
So in the producer loop, I want to put the reference of this image in a string, and send this string (via queues) to the consumer loop.
There, the string must be converted back to an actual image.
I have used 2 ways of coding this in the past. Please tell me which one is best
1 : use coersion :
- just wire the image control to a string, so you get the image name in your string control. Send the string-value to the other loop via a queue.
There I do the reverse : wire the string control to an image.
2. Use flatten to string :
- I use the "IMAQ flatten image to string" (by reference!), so I also get a string. I send this string to the other loop.
and there I unflatten the string back to an image.
Or do both methods actually do exactly the same?
Thanks for your advice!
Solved! Go to Solution.
Our queues have default type definitions : it is a cluster with 2 elements :
- an enum, called 'Command' (e.g. this can be : "Trigger", "Reload", "Start calibration", "New image", ...)
- and a string called 'Data' : herein we put the parameters that comes with the 'command'. This can be anything, so we flatten it to string.
In this case, I would like to send a "New image"-message. The data-string in the message should hold the reference to the image itself.
The optimal way (as pointed out) is to queue the reference itself. This is just passing a pointer to the image around.
Passing just the string name of the image is possible because LabVIEW can look up the reference name in its table and get access to the pointer. This involves additional traversal through a map structure. If you have a lot of images in use, this can add some overhead.
Flattening the image to a string is the worst of all, because it is basically copying the image data out to a string, then copying it back into an image on the other side.
I am not agreeing with your point that flattening the image is basically copying image data out to a string.
I mentioned that I use the 'flatten to string' function with the "Reference to image" option.
This only puts a reference to the image in the string, so no image or pixel data.
So if I have an image that is created with the name "Test Image", and I apply both methods to this image, I get this result :
- Method 1 (coerse image to string) => String = "Test Image"
- Method 2 (flatten to string - by reference) => String = " Test Image nivissvc.* □LVImageDTClassinfo □ □ □ üwS"
So in the 2nd method the string is only a little longer. Some binary data seems to be added.
Also I am not sure that there is a difference between the image reference itself and the image name. As the image reference can just coerse to a string, I think the image reference and image name are the same.
Maybe you could have a look to the attached vi. I used the IMAQ Flatten Image to string vi to convert the image reference to a string.
The returned string is 127 bytes long regardless the image size.
The image you get out of the notifier I used is the original one.
One surprising thing however, is that the name of the image (and so the image reference) remains the same regardless the value of the Flatten with Process-Unique Name parameter in IMAQ Flatten Image to string vi. When setting this parameter to true I would have expected a new image name (and thus a new image) to be generated.
Hope this helps,
This is basically how I am passing image references.
However my initial question remains : should I just send the image name, or the flattened image reference (by ref)?
I can't think about another way to use the image name only except calling IMAQ Create vi again.
As far as I remember, many years ago, calling this vi and putting an image name you already used in a previous IMAQ Create call would have returned you the initial image.
But for sure today, this is not the case anymore as you can test with the attached vi.
So except if you know a way to get the reference of an image from its name, I would strongly suggest you flatten the image reference.
Another way if it is not too late, could be to consider using variants in your queue data instead of strings.
The coersing (image to string and back) just works.
To explain everthing : I've created a small VI that shows the 2 (working) methods to pass the image reference over a string-type queue.
I hope it will make things clearer.
Ah, I didn't realize you were only flattening the reference and not the whole image data.
Personally I'd avoid going through the flatten/unflatten infrastructure if there's no good reason to use it. Just converting the refnum to its string name and back again is pretty simple compared to the path internally for flatten/unflatten.
However, what are your goals here? Performance? Why not just benchmark the two paths and see for yourself? Note that the performance might be dramatically different if there are a large number of vision images allocated, because most of these operations do some sort of lookup of the names, and not all of those lookups might be implemented the same way.