Non-local means denoise filter in CLIJ

I would like to ask if there is any way to run non-local means denoise filter in CLIJ so it could speed up in GPU instead running in CPU.
I actually use it in ImageJ ( )
Thanks a lot for the assistance.

Hey @Murilo_Carvalho,

nice to see you here!

That’s a great idea. Thanks for suggesting. I just added the non-local mean filter and the bilateral filter (they are kind of related) to CLIJx - the experimental sibling of CLIJ2. By updating your Fiji while having the clij2 update site activated, you can give them a try. If you like it and if it does what it is supposed to do, please let me know and I can move the new filter(s) to CLIJ2 before release. If there is something wrong with them, I’m happy to fix it. They were just not part of CLIJ2 yet because I didn’t have a use-case.

Let me know what you think!


1 Like

Hi Robert.
Thanks a lot for that.
I have just tried and it is pretty impressive!
Also, I found a little bug in the function name (as I create a macro for the benchmark).
When creating a macro from the “record” in macro, it generates a code line where it calls the non-local means function (“Ext.CLIJx_nonLocalMean(…)”)
When try to run it returns an error as function not found…
It is due to the function name is spelled incorrectly as “Ext.CLIJx_nonLocalMaan(…)” (i.e. intead of “mean” it is spelled “maan”).
When “fixed” in macro code, it runs perfectly.

Well, for sake of curiosity I performed a simple benchmark.
Running a stitched brightfield microcopy image of 13816 x 19263 x 1 x 16-bit in a HP workstation (24 cores, 120 GB RAM, NVidia Quadro K4200 4GB RAM)
It took 372065 msec to run in CPU, parallelized in all cores (non-local means plugin, by biomedical imaging group) and impressive 10285 msec to run in GPU (CLIJ non-local means). It means a 36 times faster !!!

To finish, I wonder why it generates these two lines when recording a macro:

  • run(“Non-local mean on GPU (experimental)”, “cl_device=[Quadro K4200] input=image.tif radiusx=2 radiusy=2 radiusz=2 sigma=5”);
  • selectWindow(“local_mean”);
    It is supposed to be equivalent to the following lines (which are also created):
  • Ext.CLIJx_nonLocalMaan(image1, image2, radius_x, radius_y, radius_z, sigma);
  • Ext.CLIJ_pull(image2);

Now, I will compare the outputs and return as soon as I figure which are the best given a specific image.

Thanks a lot for such a nice work!

1 Like

Hi @Murilo_Carvalho,

thanks for testing and sorry for the typo in the name! :slight_smile:

I renamed the method to “CLIJx_nonLocalMeans” (note the s by the end). You may have noticed that two images popped up, that was an additional bug which also caused the recorder to record too much. It’s all fixed now if you update your Fiji. Please let me know if you confirm that it’s working now.

That’s amazing, but before partying too hard, I would carefully check that results are identical :wink: This depends on the entered parameters.

Thus, just a counter-question: What’s a typical sigma and radius values you enter? As usual, Wikipedia explains nicely the math behind but can’t tell us practical default values for parameters. What do you use?



Hi Robert.
It is working nicely.
I am , indeed, comparing the results in single image as well as in my workflows to segment cells in specific tissues.
As far as I can understand (I know almost nothing in Java programming) looking at the code of non-local means by biomedgroup, the radius is equivalent of 2 pixels, so, by changing sigma, we should compare both results.
The math implementation is far from simple, but let’s the workflow results (i.e. cell identification) tell the story.
Answering your question, I usually use sigma = 5 since we try to capture the images with best SNR. By using NLM filter, I try to avoid detection of small spots (noise) even though I also remove some “larger” small spots by morphological filter…
Anyway, as soon as I have more practical results, I reply to you

1 Like