Hello everyone
I have been looking at ways to do mathematical operations on an ImageStack in the most optimized way in ImageJ possible. The first method is to simply iterate through every pixel of every slice of the image (two for loops). I perform three operations on the pixels of two identical size image stacks: add (3/8) , square root , multiply by 2 . There are 8388608 x 2 elements and it takes like 11 seconds to modify the two image stacks simultaneously. The next thing I tried using was the internal ImageJ commands: IJ.run( ing, "Add...", "value= 0.4" ) IJ.run( img, "Square Root", "") IJ.run( img, "Multiply...", "value=2") This seems much faster but the problem is that only the square root operation is performed on the whole image stack (I get a prompt where I conform that the square root should be performed on the whole stack). The other two operations only get performed on the first slice of the stack. The other issue with this approach is that I can not add (3/8) to each pixel because the pixels are stores as int . And adding (3/8) has no effect. Is there a way to perform adding and multiplying with the internal ImageJ commands such that they get performed on the whole stack. Also, how would I get floating point precision using these internal commands. Thanks Haider |
On Monday 01 Sep 2014 16:47:30 you wrote:
> Hello everyone > > I have been looking at ways to do mathematical operations on an ImageStack > in the most optimized way in ImageJ possible. The first method is to simply > iterate through every pixel of every slice of the image (two for loops). I > perform three operations on the pixels of two identical size image stacks: > add (3/8) , square root , multiply by 2 . There are 8388608 x 2 elements > and it takes like 11 seconds to modify the two image stacks simultaneously. > The next thing I tried using was the internal ImageJ commands: > > IJ.run( ing, "Add...", "value= 0.4" ) > IJ.run( img, "Square Root", "") > IJ.run( img, "Multiply...", "value=2") > > This seems much faster but the problem is that only the square root > operation is performed on the whole image stack (I get a prompt where I > conform that the square root should be performed on the whole stack). The > other two operations only get performed on the first slice of the stack. The > other issue with this approach is that I can not add (3/8) to each pixel > because the pixels are stores as int . And adding (3/8) has no effect. Is > there a way to perform adding and multiplying with the internal ImageJ > commands such that they get performed on the whole stack. Also, how would I > get floating point precision using these internal commands. To generate code it is easier to use the Macro Recorder. For example this was generated that way and resolves the problems: IJ.run(imp, "32-bit", ""); IJ.run(imp, "Add...", "value=0.4 stack"); IJ.run(imp, "Square Root", "stack"); IJ.run(imp, "Multiply...", "value=2 stack"); But you might be able to do this faster if you loaded all the image into an array, perform the operations and then put the result back. There might be faster ways of doing this, like loading your image data into a 1D array and perform the computation on the array, then finally put the result back into the image. Several plugins do this, so you will have to look at the sources to see examples. Regards Gabriel -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by haider
Hi Haider,
if this is the only operation or everything else you want to do can be done in a PlugInFilter, probably the fastest and easiest option would be writing a PlugInFilter with the following flags: CONVERT_TO_FLOAT: Concert all data types from/to float, so you can do everything with 32-bit float data irrespective of the original data type. DOES_STACKS: process all stack slices PARALLELIZE_STACKS: use parallel threads (multiple CPU cores) for different slices PARALLELIZE_IMAGES (maybe): use this flag only if you have fewer stack slices than CPUs: It calls the plugin with different ROIs that will be handled in parallel. Then you can loop through the pixels and do everything by accessing each pixel just once. Compared to three separate loops, this will speed up the process since reading and writing large amounts of data from/to memory takes time. By the way, adding 3/8 = 0.375 or 0.4 to integer data (8-bit, 16-bit, RGB images) does nothing unless you do all three operations at once with floating point data. Michael ________________________________________________________________ On Sep 2, 2014, at 01:47, haider wrote: > Hello everyone > > I have been looking at ways to do mathematical operations on an ImageStack > in the most optimized way in ImageJ possible. The first method is to simply > iterate through every pixel of every slice of the image (two for loops). I > perform three operations on the pixels of two identical size image stacks: > add (3/8) , square root , multiply by 2 . There are 8388608 x 2 elements > and it takes like 11 seconds to modify the two image stacks simultaneously. > The next thing I tried using was the internal ImageJ commands: > > IJ.run( ing, "Add...", "value= 0.4" ) > IJ.run( img, "Square Root", "") > IJ.run( img, "Multiply...", "value=2") > > This seems much faster but the problem is that only the square root > operation is performed on the whole image stack (I get a prompt where I > conform that the square root should be performed on the whole stack). The > other two operations only get performed on the first slice of the stack. The > other issue with this approach is that I can not add (3/8) to each pixel > because the pixels are stores as int . And adding (3/8) has no effect. Is > there a way to perform adding and multiplying with the internal ImageJ > commands such that they get performed on the whole stack. Also, how would I > get floating point precision using these internal commands. > > Thanks > Haider -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by Gabriel Landini
@Gabriel
Thank you for the code. It works as expected and it takes about .1 seconds (much much faster). I did try loading the image into a 1D array and then performing the operations. But doing such operations on a python array was still very slow. I used list comprehension and it brought the operation time from 10 seconds to 6 seconds, but this was still not good enough. I think I will stick with the Internal ImageJ commands now that the problems have been resolved. @Michael Gabriel's solution works well, but I will still look into doing these operations by writing a PlugInFilter. Thanks for telling me about it. |
Free forum by Nabble | Edit this page |