Log in

View Full Version : xNLMeans


Pages : [1] 2

martin53
12th December 2015, 10:01
EDIT 03/24/2016: v0.03 - bugfixes & multiscale fingerprints

New Non-Local-Means denoiser plugin xNLMeans v0.03 (http://www.mediafire.com/download/4stpv24pvpfclzm/xNLMeans_0.03_20160324.zip)

Comments welcome

please see manual for details

needs Visual C++ Redistributable Package for Visual Studio 2015 Update 1 (https://www.microsoft.com/en-us/download/details.aspx?id=49984) (please check for more recent versions, link may be outdated)

~ VEGETA ~
12th December 2015, 11:44
so can I use it on a computer that doesn't have a GPU?

Groucho2004
12th December 2015, 15:07
so can I use it on a computer that doesn't have a GPU?
Yes, but it may be difficult to check if it's working since you can't connect a monitor to a computer without GPU. :rolleyes:

feisty2
12th December 2015, 16:13
which version of msvcr do I need to run this?

martin53
12th December 2015, 16:40
which version of msvcr do i need to run this?

msvcr 2015

Khanattila
13th December 2015, 16:56
I read the documentation to find some interesting innovations. I have not found it.

Mounir
13th December 2015, 17:43
LoadPlugin unable to load xNLMeans.dll module not found.
That's what i get what do i miss ?

StainlessS
13th December 2015, 18:23
@Mounir, looks like you may have missed posts #4 and #5.

Mounir
13th December 2015, 21:16
Okay, where can i get this "msvcr 2015"

StainlessS
13th December 2015, 21:19
All In One Installer (installs all runtimes), http://www.wincert.net/forum/topic/9790-aio-microsoft-visual-bcfj-redistributable-x86x64/

If problems, then see several posts from here:- http://forum.doom9.org/showthread.php?p=1749404#post1749404

martin53
14th December 2015, 16:46
Why not to compile it static?! It is just a few mouse clicks to change project settings...

http://forum.doom9.org/showthread.php?p=1746705#post1746705

martin53
14th December 2015, 17:06
I read the documentation to find some interesting innovations. I have not found it.

Really???

sdev because the filter impulse response resembles the geometrical weight function. I did not find an sdev equivalent in kNLMeansCL, but be happy to test - if there is one, please give me a hint
wmin to adjust the blend effect between the true filter output and unfiltered input
vcomp to fight high amplitude compression artefacts
center to fight mosquito noise

Groucho2004
14th December 2015, 21:41
OMG :D Users want your 10000 megabytes of unwanted stuff on PC because Groucho2004 love it...
I really tried but can't make sense of that sentence.

Khanattila
15th December 2015, 17:06
Really???

sdev because the filter impulse response resembles the geometrical weight function. I did not find an sdev equivalent in kNLMeansCL, but be happy to test - if there is one, please give me a hint
wmin to adjust the blend effect between the true filter output and unfiltered input
vcomp to fight high amplitude compression artefacts
center to fight mosquito noise

Although it was present in the original Non-local means paper I deliberately ignored the Gaussian distribution (sdev). Because it was not shown that brings benefits.

In my implementation wmin and center are equal to 1. Which it is also the situation recommended and more used. I do not think that it is interesting to allow users to modify this parameter.

Variance Compensation in fact is new. But I do not know how useful. Non-local means is designed to Gaussian noise and may not be effective.

Groucho2004
15th December 2015, 17:39
OMG :D Users want your 10000 megabytes of unwanted stuff on PC because Groucho2004 love it...I really tried but can't make sense of that sentence.

Hm, you may be referring to the space this runtime installer occupies on the user's hard drive. It's not quite 10000 megabytes, it's actually 75MB on a 32 Bit system and 135MB on a 64 Bit system, slightly less than your estimation.

StainlessS
15th December 2015, 18:21
And of course more than Avisynth will use all of the runtimes, so are more than likely necessary (sooner or later) anyway.

martin53
15th December 2015, 19:22
Although it was present in the original Non-local means paper I deliberately ignored the Gaussian distribution (sdev). Because it was not shown that brings benefits.

In my implementation wmin and center are equal to 1. Which it is also the situation recommended and more used. I do not think that it is interesting to allow users to modify this parameter.

Variance Compensation in fact is new. But I do not know how useful. Non-local means is designed to Gaussian noise and may not be effective.
Hi,
it is interesting that you could show that sdev brings no benefits. Does kNLMeansCL use any geometrical weighting, or are all pixels in the s range weighted same? I mainly used a digicam church indoor scene for my visual comparisons because it is blurry and noisy. The difference between original and denoised clip shows large and significant spots when higher s is used (or when sdev is >>1 with xNLMeans). I reason that large spots are not OK when the disturbance is expected to be independent between pixels, and I'm interested about more explanation from your side about this.

At the beginning, I observed that xNLMeans was unable to denoise pixels close to edges and generally in structured areas with low settings, while it blurred smooth areas with high settings. Because both the compressor will allow for more tolerance if there is more structure to compress, and (to my opinion) the eye is not aware of a bit more filtering of structures than smooth regions, I recommend the vcomp setting (or a better approach) as an extension to the controllers.

With center, I am unsure, too, about its general influence. When sdev is low, most of the total weight of a similarity neighborhood comes from the center pixel, which is illogical, looking at how the algorithm is justified. For this situation I recommend the control for the center pixel. When sdev is high or with a flat geometrical averaging, center should be unimportant.

And finally I feel that wmin might be the weakest point of the original paper itself. I never found a reason why the center pixel's weight should be so highly variable as to deliberately follow the weight of one of the other pixels. The whole thing looks to me like the paper didn't work first, and they needed no matter which solution but with attractive results - and voilà. Today we lack experience with this setting because all implementations strictly followed the paper, and I'm optimistic NLMeans can be a better remedy against not only gaussion noise but also artefacts with the additional controls.

But please don't take these explanations as a battle against kNLMeansCL. It's not meant like that! I just felt that I wanted more subtle control and programmed it, but I use kNLMeansCL for my movie clips, too :) Thanks for that great plugin btw!

Khanattila
15th December 2015, 21:31
Hi,
it is interesting that you could show that sdev brings no benefits. Does kNLMeansCL use any geometrical weighting, or are all pixels in the s range weighted same? I mainly used a digicam church indoor scene for my visual comparisons because it is blurry and noisy. The difference between original and denoised clip shows large and significant spots when higher s is used (or when sdev is >>1 with xNLMeans). I reason that large spots are not OK when the disturbance is expected to be independent between pixels, and I'm interested about more explanation from your side about this.

At the beginning, I observed that xNLMeans was unable to denoise pixels close to edges and generally in structured areas with low settings, while it blurred smooth areas with high settings. Because both the compressor will allow for more tolerance if there is more structure to compress, and (to my opinion) the eye is not aware of a bit more filtering of structures than smooth regions, I recommend the vcomp setting (or a better approach) as an extension to the controllers.

With center, I am unsure, too, about its general influence. When sdev is low, most of the total weight of a similarity neighborhood comes from the center pixel, which is illogical, looking at how the algorithm is justified. For this situation I recommend the control for the center pixel. When sdev is high or with a flat geometrical averaging, center should be unimportant.

And finally I feel that wmin might be the weakest point of the original paper itself. I never found a reason why the center pixel's weight should be so highly variable as to deliberately follow the weight of one of the other pixels. The whole thing looks to me like the paper didn't work first, and they needed no matter which solution but with attractive results - and voilà. Today we lack experience with this setting because all implementations strictly followed the paper, and I'm optimistic NLMeans can be a better remedy against not only gaussion noise but also artefacts with the additional controls.

But please don't take these explanations as a battle against kNLMeansCL. It's not meant like that! I just felt that I wanted more subtle control and programmed it, but I use kNLMeansCL for my movie clips, too :) Thanks for that great plugin btw!

Each innovation is welcome. I always try to improve it :)

When I compare two neighborhoods, S(p, s) and S(q, s), each pixel has the same weight.

feisty2
16th December 2015, 13:55
so I tried vcomp and center to destroy compression artifacts and it looks pretty cool
well, I could still get a tiny little bit better result with some kind of "abused" knlmeanscl (without vcomp and center)
source:
http://i.imgur.com/1DXJZbR.png


xnlmeans(a=4,h=2.2,vcomp=0.5,center=0,s=1)

http://i.imgur.com/Qm66uKC.png


import vapoursynth as vs
import Placebo as pb
core = vs.get_core()

clp = xxx
clp = core.std.ShufflePlanes(clp, planes=0, colorfamily=vs.GRAY)
clp = core.fmtc.bitdepth(clp, fulls=False, fulld=True, bits=32, flt=True)

cln = pb.reconstructor(clp,nrlevel=1)

cln.set_output ()

http://i.imgur.com/AvI7Tz9.png


import vapoursynth as vs
import Placebo as pb
core = vs.get_core()

clp = xxx
clp = core.std.ShufflePlanes(clp, planes=0, colorfamily=vs.GRAY)
clp = core.fmtc.bitdepth(clp, fulls=False, fulld=True, bits=32, flt=True)

cln = pb.reconstructor(clp,nrlevel=1)
cln = pb.halonr(cln)
cln = pb.generalnr(cln,clp,block_step=4)
vec = pb.getvectors(cln)
clp = pb.nrfinal(cln, core.std.MakeDiff(clp,cln), vec)

clp.set_output ()

http://i.imgur.com/T0lBGn5.png

vaporsynth stuff: https://github.com/IFeelBloated/VaporPlacebo/blob/master/Placebo.py

Khanattila
21st December 2015, 18:11
so I tried vcomp and center to destroy compression artifacts and it looks pretty cool
well, I could still get a tiny little bit better result with some kind of "abused" knlmeanscl (without vcomp and center)
source:
http://i.imgur.com/1DXJZbR.png


xnlmeans(a=4,h=2.2,vcomp=0.5,center=0,s=1)

http://i.imgur.com/Qm66uKC.png


import vapoursynth as vs
import Placebo as pb
core = vs.get_core()

clp = xxx
clp = core.std.ShufflePlanes(clp, planes=0, colorfamily=vs.GRAY)
clp = core.fmtc.bitdepth(clp, fulls=False, fulld=True, bits=32, flt=True)

cln = pb.reconstructor(clp,nrlevel=1)

cln.set_output ()

http://i.imgur.com/AvI7Tz9.png


import vapoursynth as vs
import Placebo as pb
core = vs.get_core()

clp = xxx
clp = core.std.ShufflePlanes(clp, planes=0, colorfamily=vs.GRAY)
clp = core.fmtc.bitdepth(clp, fulls=False, fulld=True, bits=32, flt=True)

cln = pb.reconstructor(clp,nrlevel=1)
cln = pb.halonr(cln)
cln = pb.generalnr(cln,clp,block_step=4)
vec = pb.getvectors(cln)
clp = pb.nrfinal(cln, core.std.MakeDiff(clp,cln), vec)

clp.set_output ()

http://i.imgur.com/T0lBGn5.png

vaporsynth stuff: https://github.com/IFeelBloated/VaporPlacebo/blob/master/Placebo.py

Better than I thought. I would try to do something similar.

BakaProxy
12th January 2016, 03:53
It's a nice plugin especially since it can be used server side where there is no OpenCL to (ab)use, the only downside is that there's no 16 bit support. So Martin53 could you add 16 bit support for this implementation of nlmeans?

martin53
12th January 2016, 19:56
Glad you like the alpha version.
Currently I finished a multithread version, will add 16 bit support after the topic I'm currently working on

martin53
15th February 2016, 21:08
only downside is that there's no 16 bit support

Now with 16 bit support, multitasking and more. Enjoy!

StainlessS
16th February 2016, 00:23
Hi M53, (have not forgotten about your PM, will get to it one day [same message to Jmac]).

You might want to post a link to this thread in your New Plugins & Utilites post.

Magik Mark
9th March 2016, 11:10
Martin,

Following our discssions. I'll be trying the ff parameters and compare it with KNLmeans:

KNLMeansCL | Spatio-Temporal Light = KNLMeansCL(D = 1, A = 1, h = 2)
KNLMeansCL | Spatio-Temporal Medium = KNLMeansCL(D = 1, A = 1, h = 4)
KNLMeansCL | Spatio-Temporal Strong = KNLMeansCL(D = 1, A = 1, h = 8)

xNLMeans | Light = xNLMeans(A = 1, D = 1, h = -0.9)
xNLMeans | Medium = xNLMeans(A = 1, D = 1, h = -1)
xNLMeans | Strong = xNLMeans(A = 1, D = 1, h = -1.1)

You have indicated that I just follow the A & D of the KNLmeans and play with the H

I think making this run in GPU would entice more users. My initial experiment took twice my regular encoding time and the file size is larger. I hope these new parameters would change everything.

Please provide more feedback on the parameters

Thanks you

burfadel
9th March 2016, 12:12
All In One Installer (installs all runtimes), http://www.wincert.net/forum/topic/9790-aio-microsoft-visual-bcfj-redistributable-x86x64/

A different installer with some newer runtimes can be found here:
http://1drv.ms/1pfkOEW

If the above link doesn't work, it's probably because a newer version was uploaded. The directory listing where you can download the latest one from is here:
http://1drv.ms/1oVTfju

martin53
9th March 2016, 20:43
I think making this run in GPU would entice more users
Maybe, maybe not (http://forum.doom9.org/showthread.php?p=1752862#post1752862) :)
I must set priorities, because I have a regular job and modifications of the algorithm do allure me more than to learn openCL at the moment. There are better experts in the world who might take this challenge, I hope...

I'll soon post some comparison images. Regarding different file sizes: although xNLMeans allows to set all parameters extremely close to those of kNLMeansCL and thus produce 'binary similar' results, I wouldn't recommend that with my some month's experience of the algorithm. The classical, static parameters tell the algorithm to blur details below a contrast threshold. In a real movie, the mixture of all kinds of scenes profits best from varying filtering.
Quite easily, one creates a 'plastic look' with the NLMeans algorithm. This will compress well, and if the user likes or prefers it (for file size reasons), this is OK.
Due to the 'flat' neighborhood window, and if I get that right, a bit different floating point arithmetic in the GPU compared to the CPU, kNLMeansCL preferredly irons areas with already quite constant luminance, while it lets pass through higher amplitude noise/contrast. This may be perfect for some footage - for structured content, it is less helpful.

Since the world does not need two plugins specialized on the same things, I also focus on still photography filtering ('enlarge' the sensor size by reducing pixel noise especially for low light) and highest quality possible :)

lisztfr9
9th March 2016, 22:47
Hi,

The filter exist for FFmpeg :

http://www.dirk-farin.net/projects/nlmeans/index.html

Can anyone explain the patch idea ? Ex :

http://www.ipol.im/pub/art/2011/bcm_nlm/

Thanks, L

Magik Mark
10th March 2016, 22:44
Martin,

Your documentation indicates that setting h=0 means automatic? Am I getting this right?

Will this work:

xNLMeans(A = 1, D = 1, h = 0)

Magik Mark
10th March 2016, 23:55
Martin

I'm trying to experiment with "removegrain" filter and xnlmeans and knlkmeans. I would like to see if they work together. However, there's "removegrainHD". Can you help me compile this to x64? I'm having trouble doing it.

Thanks

Izuchi
11th March 2016, 00:47
Removegrain and RemovegrainHD is obsolete. Use Rgtools.

Magik Mark
11th March 2016, 00:51
Removegrain is in rgtools. I thought the hd version is better


Sent from my iPhone using Tapatalk

martin53
11th March 2016, 21:53
setting h=0 means automatic?
I think I meant to say that h=-1 means automatic (the minus sign) with strength 1. But before you experiment with that and might be disappointed: I found two bugs these days. One slightly reduces the weighting quality at thread borders, and the other sets the weight of the input very low when filtering should be subtle (little absolute value of h); and also with a different coefficient training set of images, the automatic h setting seems not to be reliable enough for practical use.
So, until I can publish a fixed and improved version:
- please stay moderate with the number of threads, e.g. 4 or 6 might even be faster than too many (area of pixels per thread should be sufficiently large because tradeoff vs. thread mgmt), or set vcomp to a very small value like 0.00001
- set wmin to a value around 1
- set h manually about 1.5 times as high as with kNLMeansCL (although there is not a fixed factor between them)

(please use the original thread for a discussion about compiling another plugin, or start a new one, that's probably better than to change between topics in the posts here)

Here (http://www.mediafire.com/download/cwyi4439ylws6o5/ExampleImagesPreview_160311.zip) is an output preview of of the next version of xNLMeans. Please note the different residual noise in the sky around the trees.

lisztfr9
12th March 2016, 10:32
Hi,

Imho as i see it, nlmeans is suitable for high frequency noise so how does it work with halo, since it seems rather a large artifact ?

Thanks,

martin53
12th March 2016, 12:28
Can anyone explain the patch idea ?how does it work with halo?

There might be hundred ways to explain the idea, I'll try one: While before, most denoisers tried to distinguish the signal from the noise part of a pixel by its direct surrounding, the 'non local' aspect of the NLMeans algo thinks of the pixel and its neighbors as a 'fingerprint' (or 'patch'), and tries to find similar fingerprints anywhere else, not only directly adjacent to the patch center pixel.

This, however, is the mathematical idea. For practical use, 'anywhere' is restricted to an +-A pixels seek distance (and +-D frames).

(The fingerprint size balances between good cancellation of individual noise of the fingerprint pixels and taking too much irrelevant other image information into account for the center pixel. Its radius is the S parameter)

When similar fingerprints are found, the average values of their resp. center pixels are taken as the estimation for the correct original center pixel. How much they contribute to the average is determined by the difference between the original and the resp. patch. The H parameter controls how different they are allowed to be.

You are right that the filter efficacy founds on a few assumptions; among them:
pixels in the center of similar neighbors carry the same information
neighborhood similarity is still sufficiently measurable through the noise of the neighbors
good neighborhoods for enough pixels can be found
noise of all found pixels with similar neighborhood cancels out

I agree with your expectation that halos are a kind of noise that affects a goup of pixels, so it won't cancel out and the NLMeans algo will probably not be effective against them. I hope, though, that the once finished xNLMeans, probably together with a suitable edge mask, might be a good quality solution against mosquito noise (main challenge is the 2nd last assumption)

lisztfr9
13th March 2016, 10:35
Hi Martin,

There are numerous enhancements of this algorithm too... i don't understand them all. But i was thinking about a highly textured image, or maybe dithering. In this case, all fingerprints will be the same, inside the radius (In fact some calls it semi non local, not non local). In this case a simple kernel regression competes well to the NL means i think. The idea is nice, but the refinement complex. Hence an edge mask could work here also...

martin53
24th March 2016, 14:36
This (http://www.mediafire.com/download/arv4n9tof0l8ltc/examples.7z) is a selection of training images and the filtering results.

The original YV12 images (top left) luma planes were tainted with noise (top right) and fed to a recursive filter loop which varies h (bottom left) until the 'residual error' (bottom right) reaches its minimum.

Residual error definition: difference between pure original and output clip, where blurring (reduced output of input pixels brighter than their surrounding and vice versa) has a factor 3 penalty.
function ResidualError(clip reference, clip candidate) {
d1=mt_lutxy(candidate, reference, expr="x y - 128 +", chroma="-128") # diff of candidate to reference
d2=mt_luts(reference, reference, mode="avg", pixels="-1 -1 -1 0 -1 0 -1 1 0 -1 0 -1 0 1 0 1 1 -1 1 0 1 0 1 1", expr="x y - 128 + ", chroma="-128") # diff of reference pixel to its surrounding
err=mt_lutxy(d1, d2, expr="x 128 - y 128 - * 0 < 3 1 ? x 128 - 2 ^ *", chroma="-128") # weigh candidate diff high if it goes towards candidate average, i.e. if it blurs; weigh candidate diff lower if it enhances contrast
return err
}
...
.AverageLuma() #to get the figure.

The image triples are point resized to 200% for ease of difference viewing, exported with ImageWriter(), no post compression. They were made with
kNLMeansCL(a=6,s=4,h=...,cmode=false,wmode=1) as the reference (###_##_k.png),
kNLMeansCL(a=6,s=2,h=...,cmode=false,wmode=1) for comparison of noise halo and sky filtering (###_##_k2.png), and
xNLMeans(a=6,s=4,h=...) (###_##_x.png).

The _##_ filename part identifies the applied noise percentage.

martin53
24th March 2016, 14:42
New plugin version v0.03, including untested x64 build in 1st post.

Examples in above post were made during development of this version.

Unfortunately, I had to withdraw the automatic h estimation, since it is just too unreliable.

Any suggestion/algorithm to determine the amount of noise (uncorrelated amount of pixel brightness) in an image is highly appreciated.

Magik Mark
24th March 2016, 14:56
Martin

I thought your going to post different image comparison using different variables and comparison with knlmeans?

Can it support 28 threads?


Sent from my iPhone using Tapatalk

martin53
24th March 2016, 15:33
I thought your going to post different image comparison using different variables and comparison with knlmeans?

Can it support 28 threads?

Hi Mark,

except for h, where I can not provide a satisfying algorithm to determine it today, you can just leave all xNLMeans parameters to their defaults. This will provide best results until you get eager to optimize something specific.

When you watch the comparisons, you find the h settings there, which can give you a hint what amount of h is needed to eliminate how much noise. It differs with the image, I'm sorry, so it can only indicate the range.

For each picture, there are two kNLMeansCL comparisons, with s=2 and s=4, also h shown. I think that might be what you expected? Otherwise you might give ImageWriter() a try and produce some comparisons with your own images, it's easy. Just ask if you need assistance.

Yes, xNLMeans supports 'unlimited' threads!
However I'd suggest to stay moderate, because each thread creates a small penalty: it must be managed by the OS and close to the borders of the strip it processes, it must switch to single pixel calculation as not to overwrite its neighbor's memory (this fixes the inaccuracy of v0.02); while inside a distance of s pixels from each border, it can use all found fingerprint differences twice.

:)

Magik Mark
25th March 2016, 03:09
Martin

I think the challenge right now is to find the right h value. Do you have info on the parameter of h. What is the min & max strength ?


Sent from my iPhone using Tapatalk

martin53
26th March 2016, 21:15
I think the challenge right now is to find the right h value.
Exactly. Please think of h like this: You know that the filter looks around a to-be-denoised pixel if it finds other pixels with a similar environment, and if so, it averages these pixels values for the to-be-denoised one.
Now the term 'if so' is not a yes or no decision, but a variable amount between 1 and 0.
More precisely: the average of the difference between the fingerprints of the to-be-denoised pixel and possibly similar pixels is set into relation with h, and the amount is exp(-difference²/h²). Exp(-0) is one, so 'no difference' yields amount 1, and exp(-something) tends towards 0 as 'something' grows.

H is like a judge to assign a bigger or a smaller amount to a compared pixel. And as you increase h, the the filter gets more tolerant to include more diverging pixels into the output average, which creates blur.

As a first rule of thumb: h should be set to the average noise amplitude (in increments). From there it gets a bit more complicated because xNLMeans additionally takes the linear difference into account, because over-blurring of sky is not a problem etc. etc.

yup
28th March 2016, 07:06
Hi martin53!

For finding optimum h can use Cross validation approach.
This approach consume a lot of CPU time, can organize optimum value for some frames for example.

yup.

Magik Mark
13th April 2016, 01:09
Hi martin53!

For finding optimum h can use Cross validation approach.
This approach consume a lot of CPU time, can organize optimum value for some frames for example.

yup.

Yup

Can you assist on this? We need something like light, moderate and heavy settings.

Martin

Can we make this part of things to do?


This is something that looks promising

Thanks again

Magik Mark
29th April 2016, 23:48
I'm having problem testing. I'm already using Xeon processor and I'm only getting 0.5fps. Is there a way for us to make this faster? Tried changing threads from 4 to 16. No change

martin53
1st May 2016, 18:07
Which resolution does your clip have?

Magik Mark
1st May 2016, 23:58
1080p

martin53
6th May 2016, 15:11
With my i5-4670 (4 cores, 3.4GHz), xNLMeans(h=1.5), I also see ~0.435 FPS with 1080p footage (tested with AVSMeter).
12 threads yield 0.5 FPS, i.e. a ~14% speedup.
TfNLMeans(h=1.5) yields about 2 FPS,
xNLMeans(a=4,s=2,d=0,sdev=0,lcomp=0,vcomp=0,h=1.5,threads=12) yields 3 FPS.
This is a quite similar setting to kNLMeansCL(h=1.5), which yields ~4 FPS.

The up side for xNLMeans is that you have more options and no bother with GPU drivers. The down side is that it is slower.

(The XIMagic Denoiser photoshop plugin takes 124 seconds to process the Y plane with the NLMeans algorithm)

Khanattila
6th May 2016, 15:28
With my i5-4670 (4 cores, 3.4GHz), xNLMeans(h=1.5), I also see ~0.435 FPS with 1080p footage (tested with AVSMeter).
12 threads yield 0.5 FPS, i.e. a ~14% speedup.
TfNLMeans(h=1.5) yields about 2 FPS,
xNLMeans(a=4,s=2,d=0,sdev=0,lcomp=0,vcomp=0,h=1.5,threads=12) yields 3 FPS.
This is a quite similar setting to kNLMeansCL(h=1.5), which yields ~4 FPS.

The up side for xNLMeans is that you have more options and no bother with GPU drivers. The down side is that it is slower.

(The XIMagic Denoiser photoshop plugin takes 124 seconds to process the Y plane with the NLMeans algorithm)
If you think KNLMeansCL is not even well optimized for CPU it's not bad at all.

Reel.Deel
23rd May 2016, 14:19
Hi martin53,

The documentation says that xNLMeans is a MT_NICE_FILTER but when I tried it I got this error message (VDub and AVSMeter): "xNLMeans: thread 0 exited with code 103"

For some reason if I remove threads=1 then it works in AVSMeter. In VDub I can preview it (output looks corrupt) but after a few frames I get these errors: "xNLMeans: thread 145227180 exited with code 6e2356b1" and
"CAVIStreamSynth: System exception - Invalid Handle at 0x777b2b59"

I tried with MT mode 2, it works but you have to set threads=1 in order to disable xNLMeans' internal multi-threading. Would be nice if it detected when AviSynth MT is in use and disable internal multi-threading automatically.

LoadPlugin("xNLMeans.dll")

SetFilterMTMode("xNLMeans", 1)
SetFilterMTMode("AddGrainC", 2)

ColorBars(640, 480, "YV12")
Trim(0,1000)
AddGrainC(10000, 10000, seed=1)

xNLMeans(threads=1)

Prefetch(4)


Enviroment:

AviSynth+ 1849
AVSMeter 2.2.6
VDub 1.10.4

Only tried with 32-bit.