The sigma filter is a "gentle smooth" filter found in Tony Collins' MBF
ImageJ. It's the best filter for processing confocal stacks before projection, but it's really really slow compared to the improved version of the ImageJ base filters (that are now a lot faster since 1.38u, thanks to Michael Schmid). I process a lot of stacks and I find myself waiting several minutes for each stack. Why is it so slow ? Is there a way to tweak it like the Gaussian/Mean/Median filters, in order to get multiprocessor support and to speed it ? The source of the filter can be found here if you want to take a look at the code : https://www.bio.espci.fr/upload/files/Sigma_Filter.java Thank you for your help and your support ! Christophe Leterrier |
Hi Christophe,
unfortunately the sigma filter code is not very short, so it is difficult for me to understand what exactly the filter does. I have no access to the 1983 article by J.S. Lee describing the filter. Anyhow, there are a few hints that I can give: Calculating the mean and sigma can be fast in ImageJ because these values are derived from sums over the pixel values and their squares. When moving from one pixel to the next, one can subtract the values that are not in the sum any more and add those that are new. This was the main trick for speeding up "mean" and "variance". This trick won't work with a procedure that needs to examine all the single pixel values, and the sigma filter contains such a loop. Nevertheless, you might do a few tricks to speed up the code significantly: - Convert it from a Plugin to a PlugInFilter (necessary for the following steps). You can also convert it to an ExtendedPlugInFilter, this will give you a the possibility to add preview. For an example, see http://imagejdocu.tudor.lu/Members/schmid/High_pass.java/view - Specify the PARALLELIZE_STACKS flag for running stack slices in parallel on multiprocessor machines. - You might use the CONVERT_TO_FLOAT flag of an (Extended)PlugInFilter. Then, the run(ip) method of your filter will be always called with a FloatProcessor (3 times for an RGB image, once for each color channel). This has the advantage that you can access the pixel values directly from the pixels array of the FloatProcessor, without the getPixelValue and putPixelValue methods. I guess that you can gain a factor between 3 and 10 by this. Another advantage is that RGB images won't be converted to grayscale as in the current code. The downside: The pixel values will be uncalibrated, in contrast to getPixelValue, which gives calibrated pixel values for 8-bit and 16-bit grayscale. As I understand the Sigma Filter, it won't matter whether you run it on calibrated or uncalibrated data. - Finally, you could salvage the code for copying the image data into a shorter cache array from the RankFilters.java in the ImageJ source code. Since the cache array will remain in the CPU cache, this will give you some speed gain again. [Using a cache would also work if you need the calibrated values obtained by getPixelValues since that method has to be called only once per pixel to read the data into the cache, not dozens of times.] For details, see comment "data handling" in RankFilters.java. Other advantages of using a cache: -- The data written into the output image do not modify the input any more. This is not properly done in the current Sigma Filter: when accessing the neighborhood of a pixel, the previously modified pixels are read. Thus, the filter is not strictly isotropic. -- Easier handling of edge pixels: The cache can be slightly larger than the input image and its values corresponding to out-of-image pixels can be set to the edge pixel. Then, when reading the cache, there are no "if-pixel-outside-image" conditionals that would make the code complicated and slow. It might be that the easiest way would be taking the RankFilters.java source http://rsb.info.nih.gov/ij/source/ij/plugin/filter/RankFilters.java There, delete the min/max/median code (except for the loop accessing the pixels one-by-one) and add the functionality required. Having a circle with radius r instead of a square neighborhood won't hurt. For a square, you might simply change all occurrences of lineRadius[...] to radius (whereby radius is 1 for a 3x3 neighborhood, 2 for 5x5, and so on). Hope this helps, Michael ________________________________________________________________ On 18 Oct 2007, at 19:11, Christophe Leterrier wrote: > The sigma filter is a "gentle smooth" filter found in Tony Collins' > MBF ImageJ. > > It's the best filter for processing confocal stacks before > projection, but it's really really slow compared to the improved > version of the ImageJ base filters (that are now a lot faster since > 1.38u, thanks to Michael Schmid). I process a lot of stacks and I > find myself waiting several minutes for each stack. > > Why is it so slow ? Is there a way to tweak it like the Gaussian/ > Mean/Median filters, in order to get multiprocessor support and to > speed it ? > > The source of the filter can be found here if you want to take a > look at the code : > https://www.bio.espci.fr/upload/files/Sigma_Filter.java > > Thank you for your help and your support ! > > Christophe Leterrier |
Dear Michael,
Thank you very much for your detailed reply. The plugin was written by Tony Collins. Concerning the definition of the Sigma filter, I found this definition on the web : http://www.geogr.ku.dk/CHIPS/Manual/f187.htm So the parameters are the kernel (window size, default 3x3), the sigma value (default 2), and the minimum number of pixels P (default 1). My understanding is that the filter can be modified ("Lee's modified" option in the plugin) by not taking the center pixel value into account in the average of the whole window, in case the thrershold number of pixels P is not reached. I'll try to see if it's easy to copy/paste the coding core from the Sigma plugin to the RankFilter, but I'm not Java skilled so if it involves more than a quick and dirty hack it will be difficult for me ! But hopefully someone more skilled can have a look and help me. Christophe Leterrier Michael Schmid a écrit : > Hi Christophe, > > unfortunately the sigma filter code is not very short, so it > is difficult for me to understand what exactly the filter does. > I have no access to the 1983 article by J.S. Lee describing > the filter. > > Anyhow, there are a few hints that I can give: > > Calculating the mean and sigma can be fast in ImageJ because > these values are derived from sums over the pixel values and > their squares. > When moving from one pixel to the next, one can subtract the > values that are not in the sum any more and add those that are > new. This was the main trick for speeding up "mean" and > "variance". > > This trick won't work with a procedure that needs to examine > all the single pixel values, and the sigma filter contains such > a loop. > > Nevertheless, you might do a few tricks to speed up the code > significantly: > > - Convert it from a Plugin to a PlugInFilter (necessary for the > following steps). You can also convert it to an > ExtendedPlugInFilter, this will give you a the possibility > to add preview. For an example, see > http://imagejdocu.tudor.lu/Members/schmid/High_pass.java/view > > - Specify the PARALLELIZE_STACKS flag for running stack slices > in parallel on multiprocessor machines. > > - You might use the CONVERT_TO_FLOAT flag of an > (Extended)PlugInFilter. Then, the run(ip) method of your > filter will be always called with a FloatProcessor (3 times > for an RGB image, once for each color channel). > This has the advantage that you can access the pixel values > directly from the pixels array of the FloatProcessor, without > the getPixelValue and putPixelValue methods. I guess that you > can gain a factor between 3 and 10 by this. > Another advantage is that RGB images won't be converted to > grayscale as in the current code. > The downside: The pixel values will be uncalibrated, in > contrast to getPixelValue, which gives calibrated pixel > values for 8-bit and 16-bit grayscale. As I understand the > Sigma Filter, it won't matter whether you run it on calibrated > or uncalibrated data. > > - Finally, you could salvage the code for copying the image data > into a shorter cache array from the RankFilters.java in the > ImageJ source code. Since the cache array will remain in the > CPU cache, this will give you some speed gain again. > [Using a cache would also work if you need the calibrated values > obtained by getPixelValues since that method has to be called > only once per pixel to read the data into the cache, not > dozens of times.] > For details, see comment "data handling" in RankFilters.java. > Other advantages of using a cache: > -- The data written into the output image do not modify the > input any more. This is not properly done in the current > Sigma Filter: when accessing the neighborhood of a pixel, > the previously modified pixels are read. Thus, the filter > is not strictly isotropic. > -- Easier handling of edge pixels: The cache can be slightly > larger than the input image and its values corresponding > to out-of-image pixels can be set to the edge pixel. > Then, when reading the cache, there are no > "if-pixel-outside-image" conditionals that would make the > code complicated and slow. > > It might be that the easiest way would be taking the > RankFilters.java source > http://rsb.info.nih.gov/ij/source/ij/plugin/filter/RankFilters.java > There, delete the min/max/median code (except for the loop > accessing the pixels one-by-one) and add the functionality > required. Having a circle with radius r instead of a square > neighborhood won't hurt. For a square, you might simply change > all occurrences of lineRadius[...] to radius (whereby radius is > 1 for a 3x3 neighborhood, 2 for 5x5, and so on). > > Hope this helps, > > Michael > ________________________________________________________________ > > On 18 Oct 2007, at 19:11, Christophe Leterrier wrote: > >> The sigma filter is a "gentle smooth" filter found in Tony Collins' >> MBF ImageJ. >> >> It's the best filter for processing confocal stacks before projection, >> but it's really really slow compared to the improved version of the >> ImageJ base filters (that are now a lot faster since 1.38u, thanks to >> Michael Schmid). I process a lot of stacks and I find myself waiting >> several minutes for each stack. >> >> Why is it so slow ? Is there a way to tweak it like the >> Gaussian/Mean/Median filters, in order to get multiprocessor support >> and to speed it ? >> >> The source of the filter can be found here if you want to take a look >> at the code : >> https://www.bio.espci.fr/upload/files/Sigma_Filter.java >> >> Thank you for your help and your support ! >> >> Christophe Leterrier > |
Free forum by Nabble | Edit this page |