View Full Version : Plugin for noise detection?


SlowDelivery
23rd May 2020, 02:39
I'm wondering if there exists an avisynth plugin that detects noise in a video.
I could easily find one for scene change detection but not noise detection, which was a bit surprising to be honest.

johnmeyer
23rd May 2020, 04:06
I'm wondering if there exists an avisynth plugin that detects noise in a video.
I could easily find one for scene change detection but not noise detection, which was a bit surprising to be honest.What is "noise detection?" Do you want to have the plugin sense some noise threshold and then perform some operation only when that threshold is exceeded?

While not an AVISynth plugin, I think Neat Video does something like this during its analysis pass.

I assume you have Googled this, but if not, a simple Google search turns up this:

https://www.compression.ru/video/noise_estimation/index_en.html

It is a VirtualDub filter, not an AVISynth plugin, but appears to do what you ask.

SlowDelivery
23rd May 2020, 14:20
What is "noise detection?" Do you want to have the plugin sense some noise threshold and then perform some operation only when that threshold is exceeded?
That's exactly what I meant by noise detection, sorry for the vagueness.
I did come across softwares like neat video and virtualdub while searching but I wanted to stick to only avisynth for now because I'm a video editing newbie and my head is already exploding with just avisynth.

johnmeyer
23rd May 2020, 16:36
That's exactly what I meant by noise detection, sorry for the vagueness.
I did come across softwares like neat video and virtualdub while searching but I wanted to stick to only avisynth for now because I'm a video editing newbie and my head is already exploding with just avisynth.VirtualDub is easier than AVISynth.

Also, many VirtualDub plugins can be used inside of AVISynth.

SlowDelivery
24th May 2020, 06:46
VirtualDub is easier than AVISynth.

Also, many VirtualDub plugins can be used inside of AVISynth.

I didn't know that, I will give it a try then. Though looking at it a bit more closely, the feature might even be an overkill for me, as I wanted something more quick and dirty.:p

SlowDelivery
30th May 2020, 09:04
I found using virtualdub filters a bit inconvenient so I decided to write my own script. It's a very simple script but it does the job for me.:)
# DenoiseSelective by SlowDelivery
# Uses a test denoiser on a small window at the frame centre to measure the luma noise level for each frame.
# Applies a chosen denoiser only if the measured noise level is above the threshold.
# Check the noise level by setting 'showValue=true' and choose a suitable threshold.
# The script requires SMDegrain.
#
Function DenoiseSelective(clip c, float "thr", string "denoiser", string "denoiserTest", bool "showValue")
{
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
showValue = Default(showValue, false)

w = c.Width()
h = c.Height()
x0 = Round(w/4)
y0 = Round(h/4)

global original = c
global window = c.Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
global threshold = thr
global show = showValue
global tested = window.Eval(denoiserTest)
global denoised = c.Eval(denoiser)

ScriptClip(c,"""
noise = LumaDifference(window,tested)
(noise>threshold) ? denoised : original
(show==false) ? Last : Subtitle( "Noise Level: "+String(noise) )
""")
}
You can change the SMDegrain settings or use denoisers other than SMDegrain.
For example, the script below uses FFT3DGPU(sigma=1) to measure the noise level and applies MCTemporalDenoise(settings="high") only if the noise level is above 1.
DenoiseSelective(thr=1, denoiser="""MCTemporalDenoise(settings="high")""", denoiserTest="FFT3DGPU(sigma=1)")
Hopefully some will find this useful.

gispos
30th May 2020, 12:36
For sources with scene dependent noise, this could be of interest.
I changed the hard transition a bit. Check it out.

It results in a completely different behavior.
Thershold values above 1.0 are interesting for me.
I'm just not sure if that's useful, but the first tests were positive.

I replaced the bool showValue with show (I am used to it):)

/*
DenoiseSelective by SlowDelivery
Uses a test denoiser on a small window at the frame centre to measure the luma noise level for each frame.
Applies a chosen denoiser only if the measured noise level is above the threshold.
Check the noise level by setting 'showValue=true' and choose a suitable threshold.
The script requires SMDegrain.

You can change the SMDegrain settings or use denoisers other than SMDegrain.
For example, the script below uses FFT3DGPU(sigma=1) to measure the noise level and applies MCTemporalDenoise(settings="high") only if the noise level is above 1.
Code:
DenoiseSelective(thr=1, denoiser="""MCTemporalDenoise(settings="high")""", denoiserTest="FFT3DGPU(sigma=1)")
*/

Function DenoiseSelective(clip c, float "thr", string "denoiser", string "denoiserTest", bool "show")
{
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
show = Default(show, false)

w = c.Width()
h = c.Height()
x0 = Round(w/4)
y0 = Round(h/4)

global original = c
global window = c.Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
global threshold = thr
global showValue = show
global tested = window.Eval(denoiserTest)
global denoised = c.Eval(denoiser)

ScriptClip(c,"""
noise = LumaDifference(window,tested)
#(noise>threshold) ? denoised : original
weight = Min(noise/threshold,1)
weight = weight > 0.01 ? weight : 0
weight > 0 ? merge(original, denoised, weight=weight) : original
(showValue==false) ? Last : Subtitle("Noise Level: "+ String(noise) + " - Denoise Level: " + String(weight) )
""")
}

StainlessS
30th May 2020, 12:53
I too have had a little bit play, I noticed that x0 and y0 could be odd.

Anyway, maybe you want to make combination of gispos mod and this, or not. [EDIT: I also did not like ShowValue]


# DenoiseSelective by SlowDelivery
# Uses a test denoiser on a small window at the frame centre to measure the luma noise level for each frame.
# Applies a chosen denoiser only if the measured noise level is above the threshold.
# Check the noise level by setting 'show=true' and choose a suitable threshold.
# The script requires SMDegrain.
#
Function DenoiseSelective(clip c, float "thr", string "denoiser", string "denoiserTest", bool "show") {
c
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
show = Default(show, false)
x0 = (Width +4)/8*2 # Round(w/8)*2 ## Ensure x0 is mod 2 and x0*2 is Mod 4
y0 = (Height+4)/8*2 # Round(h/8)*2 ## Ditto
window = Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
tested = window.Eval(denoiserTest)
denoised = Eval(denoiser)
sss = """
noise = LumaDifference(window,tested)
T = (noise>thr)
(T) ? denoised : Last
"""
sss = (show) ? sss + """Subtitle( "Noise Level: "+String(noise) + (T ? " T" : " F") )""" : sss
ScriptClip(sss,Args="window,tested,denoised,Thr") # Req Grunt for Args (get rid of Globals).
}

AviSource("D:\Parade.avi")

SHOW=True

# Below, still needs mod 4 input clip for else error for "denoised = Eval(denoiser)" where eg denoiser="MCTemporalDenoise()" # MCTemporalDenoise req mod 4
DenoiseSelective(thr=0.6, denoiser="""MCTemporalDenoise(settings="high")""", denoiserTest="FFT3DFilter(sigma=1)",Show=SHOW)


EDIT:

Dont use this type of arrangement (compare with false, requires access to Global var "false", Global vars slow to find)

(show==false) ? Last : Subtitle( "Noise Level: "+String(noise) )


Better

(!show) ? Last : Subtitle( "Noise Level: "+String(noise) )


Or [EDIT: using (show) or (!show) is processed via Script Parser, much faster than access Global vars "true" or "false"]

(show) ? Subtitle( "Noise Level: "+String(noise) ) : Last


EDIT: Forgot, I also got rid of Globals, but needs Grunt plugin.

gispos
30th May 2020, 13:36
I get an error: "I don't know what window means"
Where is my mistake?

Import("D:\Tools\AviSynth\plugins64+\DenoiseSelective.avs")
LoadPlugin("D:\Tools\AviSynth\plugins64+\Diverse\grunt_x64.dll")

Function DenoiseSelective3(clip c, float "thr", string "denoiser", string "denoiserTest", bool "show") {
c
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
show = Default(show, false)
x0 = (Width +4)/8*2 # Round(w/8)*2 ## Ensure x0 is mod 2 and x0*2 is Mod 4
y0 = (Height+4)/8*2 # Round(h/8)*2 ## Ditto
window = Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
tested = window.Eval(denoiserTest)
denoised = Eval(denoiser)
sss = """
noise = LumaDifference(window,tested)
T = (noise>thr)
(T) ? denoised : Last
"""
sss = (show) ? sss + """Subtitle( "Noise Level: "+String(noise) + (T ? " T" : " F") )""" : sss
ScriptClip(sss,Args="window,tested,denoised,Thr") # Req Grunt for Args (get rid of Globals).
}

SHOW=True
DenoiseSelective3(thr=0.8, denoiser="""MCTemporalDenoise(settings="low")""", denoiserTest="FFT3DGPU(sigma=1)", show=SHOW)

StainlessS
30th May 2020, 13:39
# Req Grunt for Args (get rid of Globals).
Need Grunt for Args arg.

EDIT: Arh, missed your usage of Grunt plug, dont know what is wrong, I'll test on x64, but it should work if grunt x64 working proper.

EDIT: If you change Scriptclip to GScriptclip, will prove if Grunt is installed.

gispos
30th May 2020, 13:42
Need Grunt for Args arg.

EDIT: Arh, mnissed your usage of Grunt, dont know what is wrong, I'll test on x64, but it should work if grunt x64 working proper.
So another one?

LoadPlugin("D:\Tools\AviSynth\plugins64+\Diverse\grunt_x64.dll")


Edit:
Seen your edit too late. I'll see how old my dll is.

StainlessS
30th May 2020, 13:45
See Edit.

There was recently some problem with grunt not working proper, maybe see Groucho2004 stuff, think he fixed it.

StainlessS
30th May 2020, 13:52
I dont have all plugins for x64, I'll have to find them.

gispos
30th May 2020, 13:52
See Edit.

There was recently some problem with grunt not working proper, maybe see Groucho2004 stuff, think he fixed it.

Got this here. And everything is good:)
https://github.com/pinterf/GRunT/releases

StainlessS
30th May 2020, 14:10
Yep thats the one, bit of a bum steer thinking it was Grouchy, of course was Pinterf ( always get them two mixed up, one as handsome as the other :) )

gispos
30th May 2020, 14:23
Thanks StainlessSSSS

Whether it was worth the effort, I changed it again.:)


Function DenoiseSelective2(clip c, float "thr", string "denoiser", string "denoiserTest", bool "show") {
c
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
show = Default(show, false)
x0 = (Width +4)/8*2 # Round(w/8)*2 ## Ensure x0 is mod 2 and x0*2 is Mod 4
y0 = (Height+4)/8*2 # Round(h/8)*2 ## Ditto
window = Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
tested = window.Eval(denoiserTest)
denoised = Eval(denoiser)
sss = """
noise = LumaDifference(window,tested)
weight = Min(noise/thr,1)
weight = weight > 0.01 ? weight : 0
weight > 0 ? merge(last, denoised, weight=weight) : last
"""
sss = (show) ? sss + """Subtitle( "Noise Level: "+String(noise) + " - Denoise Level: " + String(weight))""" : sss
ScriptClip(sss,Args="window,tested,denoised,Thr") # Req Grunt for Args (get rid of Globals).
}

StainlessS
30th May 2020, 14:27
Gispos, can you post link to gradfun2db_3-29-2010.rar (x64 by JoshyD) somewhere please, my ISP seems to be blocking Archive.org

StainlessS
30th May 2020, 14:30
Scrub that request, I found it here, in JoshyD x64 archive:- https://code.google.com/archive/p/avisynth64/wikis/PluginLinks.wiki

gispos
30th May 2020, 14:30
Found this here.
Upload it to a hoster. OK?
http://avisynth.nl/index.php/GradFun2db

StainlessS
30th May 2020, 14:32
Thanks GP, I found it as prev posted. Sorry for the trouble :(

EDIT: The x64 version via Gispos link is still on Archive.org and still blocked by my ISP.
ISP seems to be generally blocking Archive.org, not that particular file.

gispos
30th May 2020, 14:35
Now I've already uploaded it, so then the link. :)
https://www.file-upload.net/download-14111224/gradfun2db_3-29-2010.rar.html

StainlessS
30th May 2020, 14:45
Thanks for all your trouble, nice mod.

gispos
30th May 2020, 16:32
I get good results.
MCTD is very good to preserving details, but I still notice a difference.
I can use sigma=6 or 8 instead of 4 and have a higher filter effect with higher noise, and more detail maintenance with less noise. (like with sigma=4).

DenoiseSelective2(thr=1.0, denoiser="""MCTemporalDenoise(settings="low", sigma=6)""", denoiserTest="FFT3DGPU(sigma=1)", show=SHOW)

StainlessS
30th May 2020, 16:55
GP, you dont feel there is any need for an Optional hard switch ? [as per original function]
Just asking, not suggesting that it would improve anything [I'm happy with your mod, but considered adding a hard switch option].

gispos
30th May 2020, 17:27
GP, you dont feel there is any need for an Optional hard switch ? [as per original function]
Just asking, not suggesting that it would improve anything [I'm happy with your mod, but considered adding a hard switch option].
;) Was rewriting before you posted it, just didn't know if I should introduce it.


# DenoiseSelective by SlowDelivery, mod by StainlessS and GPo
# soft=True : Applies a chosen denoiser with smooth transition dependent on the noise level and threshold.
# soft=False: Applies a chosen denoiser only if the measured noise level is above the threshold.
# The script requires SMDegrain and Grunt for Args.
#
# You can change the SMDegrain settings or use denoisers other than SMDegrain.
# Exemple:
# DenoiseSelective(thr=1.0, denoiser="""MCTemporalDenoise(settings="high")""", denoiserTest="FFT3DGPU(sigma=1)")
#
Function DenoiseSelective(clip c, float "thr", string "denoiser", string "denoiserTest", bool "soft", bool "show") {
c
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
soft = Default(soft, True)
show = Default(show, false)
x0 = (Width +4)/8*2
y0 = (Height+4)/8*2
window = Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
tested = window.Eval(denoiserTest)
denoised = Eval(denoiser)
if (soft){
sss = """
noise = LumaDifference(window,tested)
weight = Min(noise/thr,1)
weight = weight > 0.2 ? weight : 0
weight > 0 ? merge(last, denoised, weight=weight) : last
"""
sss = (show) ? sss + """Subtitle( "Noise Level: "+String(noise) + " - Denoise Level: " + String(weight))""" : sss
}
else{
sss = """
noise = LumaDifference(window,tested)
T = (noise>thr)
(T) ? denoised : Last
"""
sss = (show) ? sss + """Subtitle( "Noise Level: "+String(noise) + (T ? " T" : " F") )""" : sss
}
ScriptClip(sss,Args="window,tested,denoised,Thr")
return last
}

StainlessS
30th May 2020, 18:43
Allows usage under Avs Standard without GScript. [Grunt still required though]

# DenoiseSelective by SlowDelivery
# Uses a test denoiser on a small window at the frame centre to measure the luma noise level for each frame.
# Applies a chosen denoiser only if the measured noise level is above the threshold.
# Check the noise level by setting 'show=true' and choose a suitable threshold.
# The script requires SMDegrain.
#
Function DenoiseSelective(clip c, float "thr", string "denoiser", string "denoiserTest",bool "soft", bool "show") {
c
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
soft = Default(soft, True)
show = Default(show, false)
x0 = (Width +4)/8*2 # Round(w/8)*2 ## Ensure x0 is mod 2 and x0*2 is Mod 4
y0 = (Height+4)/8*2 # Round(h/8)*2 ## Ditto
window = Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
tested = window.Eval(denoiserTest)
denoised = Eval(denoiser)
sss = (!soft) ? """
noise = LumaDifference(window,tested)
T = (noise>thr)
(T) ? denoised : Last
""" : """
noise = LumaDifference(window,tested)
weight = Min(noise/thr,1) # weight Limited to at most 1.0
weight = weight > 0.2 ? weight : 0
weight > 0 ? merge(last, denoised, weight=weight) : last
"""
sss = sss + (
\ (!show)
\ ? ""
\ : (!soft)
\ ? """Subtitle( "Noise Level: "+String(noise) + (T ? " T" : " F") )"""
\ : """Subtitle( "Noise Level: "+String(noise) + " - Denoise Level: " + String(weight))"""
\ )
Return ScriptClip(sss,Args="window,tested,denoised,Thr") # Req Grunt for Args (get rid of Globals).
}



AviSource("D:\Parade.avi")

THR = 1.0
SOFT = True
SHOW = True

DenoiseSelective(thr = THR, denoiser="""MCTemporalDenoise(settings="high")""", denoiserTest="FFT3DFilter(sigma=1)",soft=SOFT,Show=SHOW)

gispos
30th May 2020, 20:04
Ok, I accept. v1.0.1 :)


# DenoiseSelective by SlowDelivery, mod by StainlessS and GPo (v1.0.1)
# soft=True : Applies a chosen denoiser with smooth transition dependent on the noise level and threshold.
# soft=False: Applies a chosen denoiser only if the measured noise level is above the threshold.
# soft_min: If soft=True, "Denoise Level" must be greater than soft_min, otherwise no filtering.
# The script requires SMDegrain and Grunt for Args.
#
# You can change the SMDegrain settings or use denoisers other than SMDegrain.
# Exemple:
# DenoiseSelective(thr=1.0, denoiser="""MCTemporalDenoise(settings="high")""", denoiserTest="FFT3DGPU(sigma=1)")
#
Function DenoiseSelective(clip c, float "thr", string "denoiser", string "denoiserTest", bool "soft", float "soft_min", bool "show") {
c
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
soft = Default(soft, True)
soft_min = Default(soft_min, 0.2)
show = Default(show, false)
!soft ? nop : Assert(thr>0, "DenoiseSelective: Threshold must be greater then 0")

x0 = (Width +4)/8*2
y0 = (Height+4)/8*2
window = Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
tested = window.Eval(denoiserTest)
denoised = Eval(denoiser)
sss = (soft) ? """
noise = LumaDifference(window,tested)
weight = Min(noise/thr,1) # weight Limited to at most 1.0
weight = weight > soft_min ? weight : 0
weight > 0 ? merge(last, denoised, weight=weight) : last
""" : """
noise = LumaDifference(window,tested)
T = (noise>thr)
(T) ? denoised : Last
"""
sss = sss + (
\ (!show)
\ ? ""
\ : (!soft)
\ ? """Subtitle( "Noise Level: "+String(noise) + (T ? " T" : " F") )"""
\ : """Subtitle( "Noise Level: "+String(noise) + " - Denoise Level: " + String(weight))"""
\ )
Return ScriptClip(sss,Args="window,tested,denoised,Thr,soft_min") # Req Grunt for Args (get rid of Globals).
}


Edit:
Avisynth code question? (! soft) or also works (soft)
changed Assert

StainlessS
30th May 2020, 20:36
EDIT:
Avisynth code question? (! soft) or also works (soft)
Generally either ok.
End EDIT

Not sure what you were asking there, but maybe for the assert

# DenoiseSelective by SlowDelivery, mod by StainlessS and GPo (v1.0.1) # https://forum.doom9.org/showthread.php?p=1914252#post1914252
# soft=True : Applies a chosen denoiser with smooth transition dependent on the noise level and threshold.
# soft=False: Applies a chosen denoiser only if the measured noise level is above the threshold.
# soft_min: If soft=True, "Denoise Level" must be greater than soft_min, otherwise no filtering.
# The script requires SMDegrain and Grunt for Args.
#
# You can change the SMDegrain settings or use denoisers other than SMDegrain.
# Example:
# DenoiseSelective(thr=1.0, denoiser="""MCTemporalDenoise(settings="high")""", denoiserTest="FFT3DGPU(sigma=1)")
#
Function DenoiseSelective(clip c, float "thr", string "denoiser", string "denoiserTest", bool "soft", float "soft_min", bool "show") {
c
thr = Default(thr, 2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
soft = Default(soft, True)
soft_min = Default(soft_min, 0.2)
show = Default(show, false)
Assert(!soft || thr>0, "DenoiseSelective: Threshold must be greater then 0")

x0 = (Width +4)/8*2
y0 = (Height+4)/8*2
window = Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
tested = window.Eval(denoiserTest)
denoised = Eval(denoiser)
sss = (soft) ? """
noise = LumaDifference(window,tested)
weight = Min(noise/thr,1) # weight Limited to at most 1.0
weight = weight > soft_min ? weight : 0
weight > 0 ? merge(last, denoised, weight=weight) : last
""" : """
noise = LumaDifference(window,tested)
T = (noise>thr)
(T) ? denoised : Last
"""
sss = sss + (
\ (!show)
\ ? ""
\ : (!soft)
\ ? """Subtitle( "Noise Level: "+String(noise) + (T ? " T" : " F") )"""
\ : """Subtitle( "Noise Level: "+String(noise) + " - Denoise Level: " + String(weight))"""
\ )
Return ScriptClip(sss,Args="window,tested,denoised,Thr,soft_min") # Req Grunt for Args (get rid of Globals).
}



AviSource("D:\Parade.avi")

THR = 1.0
SOFT = True
SHOW = True

# Below, still needs mod 4 input clip for else error for "denoised = Eval(denoiser)" where eg denoiser="MCTemporalDenoise()" # MCTemporalDenoise req mod 4
DenoiseSelective(thr = THR, denoiser="""MCTemporalDenoise(settings="high")""", denoiserTest="FFT3DFilter(sigma=1)",soft=SOFT,Show=SHOW)


EDIT: Added link to current post, the intro.

Reel.Deel
30th May 2020, 21:36
Thanks GP, I found it as prev posted. Sorry for the trouble :(

EDIT: The x64 version via Gispos link is still on Archive.org and still blocked by my ISP.
ISP seems to be generally blocking Archive.org, not that particular file.

Most plugins that have a dedicated wiki page have an 'archived downloads' section. There was an alternate link there: http://avisynth.nl/index.php/GradFun2db#Archived_Downloads

StainlessS
30th May 2020, 21:41
Thanks RD, I already have it. Also, I found a copy in my overflowing inbox.

EDIT: Hurray, have just finished shelling and eating bout 1/4 pound of roasted sunflower seeds, takes forever.

SlowDelivery
31st May 2020, 04:27
I wake up to see a brand new script! Thanks for the improvement guys.:D
I love the soft threshold feature, I was thinking of implementing it but was unsure how to.
So far I don't have any trouble running the script.

Drmsy
31st May 2020, 13:12
Very nice

gispos
21st June 2020, 19:52
I'm not always satisfied with the result with soft = True, so I expanded the soft = False code.
There is now a second Denoiser so 3 filter results in total (denoiser, denoiser2, last), I am now satisfied with the result.:)

If thr_min is not set too high, it is now always filtered, depending on the threshold. This results in a much more homogeneous result than switching between filtered / unfiltered.

See the example.

Edit: next post

gispos
21st June 2020, 23:44
That kept me awake. Some corrections.:o

# DenoiseSelective by SlowDelivery, mod by StainlessS and GPo (v1.0.3) # https://forum.doom9.org/showthread.php?p=1916341#post1916341
# thr : Noise level threshold
# thr_min : Noise or Denoise Level must be greater than thr_min, otherwise no filtering.
# soft=True : Applies a chosen denoiser with smooth transition dependent on the noise level and threshold.
# soft=False: Applies chosen denoiser (denoiser, denoiser2) dependent on the noise level and threshold.
# If an empty string is specified for denoiser2 (""), only denoiser is used.


# The script requires SMDegrain and Grunt for Args.
#
# You can change the SMDegrain settings or use denoisers other than SMDegrain.
# Example:
# DenoiseSelective(thr=0.7, denoiser="""MCTemporalDenoise(settings="low", sigma=2, strength=100, tovershoot=1, GPU=True)""",
# \denoiser2="""MCTemporalDenoise(settings="low", sigma=4, strength=120, tovershoot=1, GPU=True)""",
# \denoiserTest="FFT3DGPU(sigma=1)", soft=False, thr_min=0.2, show=True)
#
Function DenoiseSelective(clip c, float "thr", string "denoiser", string "denoiser2", string "denoiserTest", bool "soft", float "thr_min", bool "show") {
c
thr = Default(thr, 1.0)
thr_min = Default(thr_min, 0.2)
denoiser = Default(denoiser, "SMDegrain(tr=3,thSAD=200)")
denoiser2 = Default(denoiser2, "SMDegrain(tr=3,thSAD=400)")
denoiserTest = Default(denoiserTest, "SMDegrain(tr=1,thSAD=400,chroma=false)")
soft = Default(soft, False)
show = Default(show, False)
Assert(!soft || thr>0, "DenoiseSelective: Threshold must be greater then 0")

x0 = (Width +4)/8*2
y0 = (Height+4)/8*2
window = Spline36Resize(x0*2,y0*2,x0,y0,-x0,-y0)
tested = window.Eval(denoiserTest)
useD2 = (denoiser2 != "")
denoised = Eval(denoiser)
denoised2 = !soft ? useD2 ? Eval(denoiser2) : denoised : last

sss = (soft) ? """
noise = LumaDifference(window,tested)
weight = Min(noise/thr,1)
weight = weight > thr_min ? weight : 0
weight > 0 ? merge(last, denoised, weight=weight) : last
""" : """
noise = LumaDifference(window,tested)
T = (noise>thr)
noise > thr_min ? (T) ? denoised2 : useD2 ? denoised : last : last
"""
sss = sss + (
\ (!show)
\ ? ""
\ : (!soft)
\ ? """Subtitle( "Noise Level: "+String(noise) + (noise > thr_min ? T ? useD2 ? " D2" : " D1" : useD2 ? " D1" : " F" : " F"))"""
\ : """Subtitle( "Noise Level: "+String(noise) + " - Denoise Level: " + String(weight))"""
\ )
Return ScriptClip(sss,Args="window,tested,denoised,denoised2,thr,thr_min,useD2") # Req Grunt for Args (get rid of Globals).
}

StainlessS
22nd June 2020, 09:30
Oooo, busy again.
Gispos, update link on first line to point at your last post.

EDIT: Thank you.