Fast Math Operations on Images

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Fast Math Operations on Images

haider
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
Reply | Threaded
Open this post in threaded view
|

Re: Fast Math Operations on Images

Gabriel Landini
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
Reply | Threaded
Open this post in threaded view
|

Re: Fast Math Operations on Images

Michael Schmid
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
Reply | Threaded
Open this post in threaded view
|

Re: Fast Math Operations on Images

haider
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.