LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Median value of an image

How do you calculate memory efficiently the median value of image pixels? All IMAQ functions are providing MEAN only. I need median. I've tried several applications but everyone of them are memory eating monsters eventually causing the crash of my program after couple hundred times of function calls. I'm surprised none ever asked this before.

 

Here's the Desktop Excecution Trace Toolkit report of one ImgMedian.vi function call. http://pastebin.com/vadV4bN4

 

Link to code in description

0 Kudos
Message 1 of 15
(4,317 Views)

How big is the image?

 

Seems way too comvoluted. Growing an array inside a DVR seems odd. You can get the entire image and reshape it to a 1D array in one step, then get the median. What's the purpose of the sequence frames? They are not needed.

Message 2 of 15
(4,299 Views)

2400*1730px 16-bit. So 7.96mb.

 


@altenbach wrote:

 

You can get the entire image and reshape it to a 1D array in one step, then get the median.


That's what I thought also. When having image data pointed as data value reference you are actually able to delete the reference (and free memory? Correct me if I'm wrong).

 

I guess in this example sequence frames are only extra code for nothing as you pointed out. So please ignore them.

 

So your suggestion is that convert image to array using IMAQ ImageToArray then reshaping array  to 1D matching original image lenght*height then calcultaing median of result array? And it is memory efficient?

 

Cos now I'm struggling with LabVIEW VI stopping after a while and saying "Memory is full". Still LabVIEW.exe shows memory usage about 400 mb in task manager. Desktop Excecution Trace Toolkit reports massive write/erase occasions so I don't know if the memory gets fragmented or what...

0 Kudos
Message 3 of 15
(4,294 Views)

You still have not answered the question about the size of the image. Can you show your newest code?

0 Kudos
Message 4 of 15
(4,291 Views)

Size was before your quote on my post. In my original post is the newest code. It is a part of massive testing system. I'm trying to find a reason why it is stopping on "Memory is full". With help of Desktop Excecution Trace Toolkit and NI Support I found couple of subVI:s (one being this ImgMedian.vi) consuming lot of memory and I'm trying to re-write them more memory efficiently. My first attempt on calculating median was just like the description I wrote in my previous post. I thought that with DVR memory would be more efficiently used.

 

Do you prefer that method described in my prevoious post?

0 Kudos
Message 5 of 15
(4,286 Views)

Ah, I missed that. Maybe the "request deallocation" is not such a good idea, because now it needs to newly allocate the same amount of memory with every call over and over. Typically, it should hold onto the memory so no new allocations are needed.

Have you tried the "reshape"?

0 Kudos
Message 6 of 15
(4,283 Views)

"Request deallocation" is actually what NI Support told me to add on every subVI handling massive image data arrays. So who's right? I see my memory usage in task manager going up to LabVIEW 32-bit limit (around 2.5gb) if no allocation requests are called.

 

I tried the "reshape" at first. This application in my original post is my second attempt.

0 Kudos
Message 7 of 15
(4,278 Views)

"request deallocation" is fine if you plan on calling the VI only once and then never again.

Arrays of any dimension need to be contiguous in memory, so if you keep building a 1D array in a loop, the compiler may or may not be able to estimate the final size and thus requires incremental memory allocation. This can be very expensive, especially if you throw it all away a few microseconds later by requesting deallocation and need to redo it on the next call. The constant allocation/deallocation dance increases the probability that you will run out of sufficient contiguous memory space way before you run out ot memory.

 

Reshaping is an optimized procedure that has full knowledge about the final size, so only a single allocation is needed and if you don't request deallocation, that memory can be re-used on subsequent calls with the same size. (Use multiply array elements on the array size to the get 1D size).

Taking the median is also quite efficient (I assume that LabVIEW uses "quickselect" which can be done in place. Is the image really DBL or some integer with fewer bytes? You say it is 16bit and keeping that representation would use 4x less memory. Of course the stock "median" requires DBL, but you could easily implement an in-place quickselect that operates on other datatypes.

Message 8 of 15
(4,251 Views)

@altenbach wrote:

"request deallocation" is fine if you plan on calling the VI only once and then never again.

Arrays of any dimension need to be contiguous in memory, so if you keep building a 1D array in a loop, the compiler may or may not be able to estimate the final size and thus requires incremental memory allocation. This can be very expensive, especially if you throw it all away a few microseconds later by requesting deallocation and need to redo it on the next call. The constant allocation/deallocation dance increases the probability that you will run out of sufficient contiguous memory space way before you run out ot memory.

 

I took all "Request Deallocation" calls  away from all of my VIs and the result is that the memory usage of the program runs to 3gb (and causing "Memory is full") before the test sequence is even finished for the first time. So they are doing something to maintain application memory usage in reasonable level. Placing them back in allows me to run the test sequence ten times before running into "Memory is full".

 

In my test sequence I'm doing several array operations to image data (which i got to array using IMAQ ImageToArray). Is this done by best practises of LabVIEW image handling?

 

After every array opreation (add,subtract,multiply,divide,threshold and so on...) it appears that LabVIEW has to make a new memory allocation ie. LabVIEW is keepeing both original data and result data in memory. I tried to resolve this problem using DVR and modifying the actual one array in memory and not creating always new copies of original array. I guess that was not the right thing to do.


@altenbach wrote:

"Reshaping is an optimized procedure that has full knowledge about the final size, so only a single allocation is needed and if you don't request deallocation, that memory can be re-used on subsequent calls with the same size. (Use multiply array elements on the array size to the get 1D size).

Taking the median is also quite efficient (I assume that LabVIEW uses "quickselect" which can be done in place. Is the image really DBL or some integer with fewer bytes? You say it is 16bit and keeping that representation would use 4x less memory. Of course the stock "median" requires DBL, but you could easily implement an in-place quickselect that operates on other datatypes.





Image data being processed is in many test points mean of multiple images (to cancel noise). Thus double is only option to maintain the non-integer values.

0 Kudos
Message 9 of 15
(4,220 Views)

I think what you're doing in the in place structure is the leak. Here's two options that shouldn't go mem crazy. Try both.

median snip2.png

0 Kudos
Message 10 of 15
(4,211 Views)