Log in

View Full Version : ScriptClip AverageLuma Value in Function


anton_foy
9th February 2022, 22:14
Im trying to make a function that will detect an average luma of the image and use the resulting number into levels approximately like this:
(but without printing the result with Subtitle)
ScriptClip(Last, """
threshold = 55
luma = AverageLuma ## gives the average luma of the current frame
luma < threshold
\ ? Levels(0, 1.0+0.5*(threshold-luma)/threshold, 255, 0, 255)
\ : last
Subtitle("luma=" + String(luma), align=2)
""")

function AutoL(clip c)
{
c.ex_levels((luma/340),(luma/6100),237,0,170)
return last
}
Okay I don't have a clue how to get ScriptClip to work inside a function also and I would also know if there is possible to make rounding: luma/6100<---here, inside of the "ex_levels"-line.
Thanks!

EDIT: Thought I figured out the "rounding" thing ex_levels((luma/340%.0f),(luma/6100%.2f),237,0,170) but I didn't.
Anyway I got it to work sort of but its really slow:

function AutoL(clip c)
{
current_frame = 0
luma=Averageluma(c)
c.ex_levels((luma/340),(luma/6100),237,0,170)
return last
}

So could this be restricted so that AverageLuma only grabs the value from the first frame of the clip instead of every frames during the whole clip? Wouldn't that be faster?

EDIT2:
Changing to:

function AutoL(clip c)
{
current_frame = -1
luma=Averageluma(c)
c.ex_levels((luma/340),(luma/6100),237,0,170)
return last
} made it faster :D

Dogway
10th February 2022, 00:52
What about this:

function AutoL(clip c, int "thr") {
thr = Default(thr, 55)
ScriptClip(c,function[thr] () {
luma = AverageLuma() ## gives the average luma of the current frame
luma < thr
\ ? ex_levels((luma/340),1.0+0.5*(thr-luma)/thr,237,0,170)
\ : last
} ) }

I'm working on SceneStats so you can get AverageLuma of the entire scene to do some filtering based on that.

anton_foy
10th February 2022, 01:06
What about this:

function AutoL(clip c, int "thr") {
thr = Default(thr, 55)
ScriptClip(c,function[thr] () {
luma = AverageLuma() ## gives the average luma of the current frame
luma < thr
\ ? ex_levels((luma/340),1.0+0.5*(thr-luma)/thr,237,0,170)
\ : last
} ) }

I'm working on SceneStats so you can get AverageLuma of the entire scene to do some filtering based on that.

Thank you Dogway! Fast and nice. What if I want to extend my function adding more lines before and after ex_levels, is that tricky? Im not too familiar with this runtime-stuff :)
BTW looking forward to SceneStats!

Dogway
10th February 2022, 01:43
You can use Eval() or use a pointer, I prefer the second.

function AutoL(clip c, int "thr") {
thr = Default(thr, 55)
ScriptClip(c,function[thr] () {
luma = AverageLuma()
orig = last
ex_levels((luma/340),1.0+0.5*(thr-luma)/thr,237,0,170)
blabla()
luma < thr : last : orig
} ) }

Maybe by March I have SceneStats, first I'm making SceneChange() for robust SC detection with lookahead.

anton_foy
10th February 2022, 10:20
You can use Eval() or use a pointer, I prefer the second.

function AutoL(clip c, int "thr") {
thr = Default(thr, 55)
ScriptClip(c,function[thr] () {
luma = AverageLuma()
orig = last
ex_levels((luma/340),1.0+0.5*(thr-luma)/thr,237,0,170)
blabla()
luma < thr : last : orig
} ) }

Maybe by March I have SceneStats, first I'm making SceneChange() for robust SC detection with lookahead.

Thanks! Although when I try to fit this code into it I run into problems:
function AutoNR(clip c, string "Preset", int "TR", int "BLK", int "THSAD", float "SHARP",
\ int "WARP")
{

# Select presets:
Preset = default( Preset, "Medium" )
pNum = (Preset == "Low" ) ? 0 : \
(Preset == "Medium" ) ? 1 : \
(Preset == "High" ) ? 2 : \
Assert( FALSE , "'Preset' choice is invalid" )


# Preset defaults: Low Medium High
TR = default( TR, Select( pNum, 1 , 3 , 4 ) )
BLK = default( BLK, Select( pNum, 16, 16, 16 ) )
THSAD = default( THSAD, Select( pNum, 220, 340, 470 ) )
SHARP = default( SHARP, Select( pNum, 0.16, 0.20, 0.24 ) )
WARP = default( WARP, Select( pNum, 4 , 6 , 7 ) )

### Temporal color NR
v=c.vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false).vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)

### Spatial NR
s=v.fft3dgpu(sigma=0.3,sigma2=0.4,sigma3=1.4,sigma4=1,plane=3,bt=3).
\ fft3dgpu(sigma=0.3,sigma2=0.4,sigma3=1.6,sigma4=2.7,plane=0,bt=3).ex_vibrance(1.2)

### Dynamic NR mask
emask=v.ex_levels((luma/340),(luma/6100),237,0,170)
m=mt_merge(v,s,emask.mt_invert().mt_inpand(),Y=3,U=3,V=3, luma=true)

### Dynamic prefilter
p=m.coloryuv(autogain=true).vdmc()

### Temporal NR
sm=m.SmDegrain(prefilter=p,tr=tr,thsad=thsad,blksize=blk).tweak(sat=1.06)

sh=sm.awarpsharp2(depth=warp)
sh = sh.sharpen(sharp)

### Debanding
sh.neo_f3kdb(grainY=40,grainC=3,mt=true)

return last
}
I also tried this code but I get a strange error that fft3dgpu.hlsl is missing a ')':
function AutoNR3(clip c, string "Preset", int "TR", int "BLK", int "THSAD", float "SHARP",
\ int "WARP")
{

# Select presets:
Preset = default( Preset, "Medium" )
pNum = (Preset == "Low" ) ? 0 : \
(Preset == "Medium" ) ? 1 : \
(Preset == "High" ) ? 2 : \
Assert( FALSE , "'Preset' choice is invalid" )


# Preset defaults: Low Medium High
TR = default( TR, Select( pNum, 1 , 3 , 4 ) )
BLK = default( BLK, Select( pNum, 16, 16, 16 ) )
THSAD = default( THSAD, Select( pNum, 220, 340, 470 ) )
SHARP = default( SHARP, Select( pNum, 0.16, 0.20, 0.24 ) )
WARP = default( WARP, Select( pNum, 4 , 6 , 7 ) )

ScriptClip(c,function[tr,blk,thsad,sharp,warp] () {
luma = AverageLuma()
orig = last


### Temporal color NR
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)

### Spatial NR
s=fft3dgpu(sigma=0.3,sigma2=0.4,sigma3=1.4,sigma4=1,plane=3,bt=3).
\ fft3dgpu(sigma=0.3,sigma2=0.4,sigma3=1.6,sigma4=2.7,plane=0,bt=3).ex_vibrance(1.2)

f = last

### Dynamic NR mask
emask=ex_levels((luma/340),(luma/6100),237,0,170)
mt_merge(f,s,emask.mt_invert().mt_inpand(),Y=3,U=3,V=3, luma=true)

### Dynamic prefilter
p=coloryuv(autogain=true).vdmc()

### Temporal NR
SmDegrain(prefilter=p,tr=tr,thsad=thsad,blksize=blk).tweak(sat=1.06)

### Sharpen
awarpsharp2(depth=warp)
sharpen(sharp)

### Debanding
neo_f3kdb(grainY=40,grainC=3,mt=true)

#return last
luma < last
} ) }
Im sure this is totally wrong what I just tried though. Yes I skipped the "thr" part since I didn't get the levels right with it included.
This line looks good:ex_levels((luma/340),(luma/6100),237,0,170)
But this line doesn't get it quite right: ex_levels((luma/340),1.0+0.5*(thr-luma)/thr,237,0,170)

kedautinh12
10th February 2022, 10:49
Just copy fft3dgpu.hlsl next to fft3dgpu.dll

anton_foy
10th February 2022, 13:07
Just copy fft3dgpu.hlsl next to fft3dgpu.dll

Thanks but it already is. FFT3DGpu worked without any problems before I made that script I just posted.

anton_foy
11th February 2022, 22:23
You can use Eval() or use a pointer, I prefer the second.

function AutoL(clip c, int "thr") {
thr = Default(thr, 55)
ScriptClip(c,function[thr] () {
luma = AverageLuma()
orig = last
ex_levels((luma/340),1.0+0.5*(thr-luma)/thr,237,0,170)
blabla()
luma < thr : last : orig
} ) }

Maybe by March I have SceneStats, first I'm making SceneChange() for robust SC detection with lookahead.

I had to remove "current_frame" because it screws up the resulting numbers completely so I must go with the ScriptClip.
As I read about ScriptClip and how it works I find:
Calling a lot of filters / functions inside the runtime script will slow down your encoding speed. Those filters will be created and destroyed on every frame; thus you pay initialisation/cleanup costs at every frame.
If you can, put outside the runtime environment those filter calls not essential for the runtime processing; break the runtime script into more scripts if you have to. For example, instead of doing this: http://avisynth.nl/index.php/The_script_execution_model/Performance_considerations

I tested out my new function and found that I need to use "RDifferenceFromPrevious()" instead of AverageLuma. Still need to
get scriptclip to work inside my function and for more than one line.

Like this:

function AutoNR(clip c, int "TR", int "BLK", float "SHARP", int "WARP")
{
tr = Default(tr, 4)
blk = Default(blk, 16)
sharp = Default(sharp, 0.24)
warp = Default(warp, 7)

###ScriptClip lines in BOLD
rex = ex_levels(0,0.48,48).converttorgb24().ExtractR()
red = RDifferenceFromPrevious(rex)
low = red/4.6
mid = low/1.7
ths = int(red)*36

c.fft3dgpu(sigma=0.3,sigma2=0.4,sigma3=(MID),sigma4=(LOW),plane=4,bt=3)
FluxSmoothT(temporal_threshold=10, luma=false, chroma=true)
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
p=coloryuv(autogain=true).vdmc()
SmDegrain(prefilter=p,tr=tr,thsad=ths,blksize=blk).tweak(sat=1.06)
awarpsharp2(depth=warp)
sharpen(sharp)
neo_f3kdb(grainY=40,grainC=3,mt=true)

return last
}


"Simply" what I want is to feed the resulting number from RDifferenceFromPrevious to "MID", "LOW" and "THS" so I guess these two lines fft3dgpu(sigma=0.3,sigma2=0.4,sigma3=(MID),sigma4=(LOW),plane=4,bt=3)
SmDegrain(prefilter=p,tr=tr,thsad=ths,blksize=blk)
have to be separated with a Scriptclip call? I have a hard time to wrap my head around this.

anton_foy
18th February 2022, 00:21
This test is working how I want it resulting in a number:

ScriptClip(last, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR().invert()
redavg = RDifferenceFromPrevious(red)
Subtitle("luma=" + String(redavg), align=2)
""")

But not if I want to make a function like this to feed the number into fft3dgpu:

function ANR(clip c)
s=ScriptClip(last, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR().invert()
redavg = RDifferenceFromPrevious(red)
#return last
""")

sig = s/4.6
sig2 = s/1.6
c.fft3dgpu(sigma=sig,sigma2=sig2)
return last

Not getting this to work. Is my way of thinking totally off? To feed the 'RDifferenceFromPrevious' resulting number to sigma (for example) and divide it (or do some other math).

Dogway
18th February 2022, 00:53
You have to put everything that's dynamic inside ScriptClip, that's the basis.
Sometimes you can do some tricks/cheats like writing to frameprops and then retrieving them but it's not standard practice.

anton_foy
18th February 2022, 01:33
You have to put everything that's dynamic inside ScriptClip, that's the basis.
Sometimes you can do some tricks/cheats like writing to frameprops and then retrieving them but it's not standard practice.

Thanks! Then I have to cheat I guess using frameprops to retrieve them. What you say makes more sense now but I still am not sure how it is suppose to be written. More testing ahead.

Dogway
18th February 2022, 10:49
This? also I really don't like fft3dgpu, unless you are doing some dirty job (very damaged clips) and it gets the job done I would rather use the CPU version which is totally different (more correct?)
ScriptClip(last, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR().invert()
redavg = RDifferenceFromPrevious(red)
sig = redavg/4.6
sig2 = redavg/1.6
fft3dgpu(sigma=sig,sigma2=sig2)
""")

anton_foy
18th February 2022, 15:08
This? also I really don't like fft3dgpu, unless you are doing some dirty job (very damaged clips) and it gets the job done I would rather use the CPU version which is totally different (more correct?)
ScriptClip(last, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR().invert()
redavg = RDifferenceFromPrevious(red)
sig = redavg/4.6
sig2 = redavg/1.6
fft3dgpu(sigma=sig,sigma2=sig2)
""")
Dogway!!! Thanks man!!! I lost hair over this. Yes I agree I noticed this too with fft3dgpu but for now to speed things up a bit. Probably will use neo_fft3d in the end. Checked your grainfactory3mod.avsi which use scriptclip in the end so I was in the area of correct usage but this was a bomb what you just put. I will have to use the 'redavg' results later in the script with your version of smdegrain aswell. Would you suggest I do another scriptclip line again replacing fft3dgpu with smdegrain or is there a more effective way? I hope I dont push it, I learn so much from you.

Btw. your new smdegrain version is so fast and pleasant looking at default. The reason I dumped fastdegrain.

anton_foy
18th February 2022, 22:16
This? also I really don't like fft3dgpu, unless you are doing some dirty job (very damaged clips) and it gets the job done I would rather use the CPU version which is totally different (more correct?)
ScriptClip(last, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR().invert()
redavg = RDifferenceFromPrevious(red)
sig = redavg/4.6
sig2 = redavg/1.6
fft3dgpu(sigma=sig,sigma2=sig2)
""")

Tried it but it gives me error "invalid arguments to function ScriptClip":

function anr(clip c){
ScriptClip(last, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR().invert()
redavg = RDifferenceFromPrevious(red)
sig = redavg/4.6
sig2 = redavg/1.6
fft3dgpu(sigma=sig,sigma2=sig2)
""") #<--- error on this line
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
return last
}

Dogway
18th February 2022, 23:14
Maybe this:
Tried it but it gives me error "invalid arguments to function ScriptClip":

function anr(clip c){
ScriptClip(c, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR().invert()
redavg = RDifferenceFromPrevious(red)
sig = redavg/4.6
sig2 = redavg/1.6
fft3dgpu(sigma=sig,sigma2=sig2)
""")
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
return last
}

anton_foy
19th February 2022, 03:35
Maybe this:

Thanks it works now but the number from RDifferenceFromPrevious
seems to get wrong when fed into the sigma's. For example on frame 1 on my test clip I got 12.524107 according to Subtitle("redavg=" + String(redavg), align=2)
So I would think that csig4 = redavg/6 would result in: 2.087351166666667 (although I would like it to be rounded to just 2.0 or 2.1)
When I try the script below sigma's seem to be super high like 40 or something, totally smeared out the chroma.
Do I need to convert into string(redavg, "%0.1f") and then to float or something to get correct values?

function anr(clip c){
ScriptClip(c, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR()
redavg = RDifferenceFromPrevious(red)
csig3 = redavg/30
csig4 = redavg/6
mergechroma(temporalsoften(4,0,255,0,2).
\ neo_fft3d(sigma=0,sigma2=0,sigma3=csig3,sigma4=csig4,bt=1,y=1,u=3,v=3))""")
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
return last
}

EDIT: Update, tried the whole script as intended (think I got the numbers correct at last) but it is unusable, too slow to even start and my cpu goes up to 100% for 10 minutes without anything happening. Because I put almost everything into ScriptClip? Feels like such a hassle with ScripClip only to get one number to recalculate and feed the different parameters in the script. But I guess the whole filter (fft3dgpu for example) must be in runtime mode for it to work and not just the parameters in it.


function anr(clip c){
ScriptClip(c, """
red = ex_levels(0,0.48,48).converttorgb().ExtractR()
redavg = RDifferenceFromPrevious(red)
csig3 = redavg/8400
csig4 = redavg/1700
sig3 = redavg/1700
sig4 = redavg/1260
ths_ = redavg*0.138
ths = int(ths_)
shr = redavg*0.00006
mergechroma(temporalsoften(4,0,255,0,2).
\ neo_fft3d(sigma=0,sigma2=0,sigma3=csig3,sigma4=csig4,bt=1,y=1,u=3,v=3))
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
neo_fft3d(sigma=0.4,sigma2=0.6,sigma3=sig3,sigma4=sig4,y=3,u=2,v=2,bt=3)
p=convertbits(8).coloryuv(autogain=true).TemporalSoften(3,4,8,scenechange=0,mode=2)
SmDegrain(prefilter=p,tr=4,thsad=ths)
sharpen(shr)""")
awarpsharp2(depth=7)
neo_f3kdb(grainY=40,grainC=3,mt=true)
return last
}


Edit2:
Look here at "mdiff2" by raffriff42: https://forum.doom9.org/showthread.php?p=1756852#post1756852
This shows difference from the previous frame without the use of scriptclip. Is there no way of getting resulting numbers instead of visual difference by using this technique?

anton_foy
5th March 2022, 14:12
At it again...this code below gives me error "MAnalyse: Clip must be YUV or YUY2 ...SmDegrain.avsi, line 294, line 345, line 634"

Code:
function anv(clip c){
converttoPlanarRGB(c)
fft3dfilter(sigma=0.3,sigma2=0.4,sigma3=1.7,sigma4=2.1,plane=4,bt=4)
S=ScriptClip("""
lum = converttorgb().invert().averageG
rgb = converttorgb().RGBDifferenceFromPrevious
luma = int(lum + rgb)
ltr = int(luma*0.00009)
ths = int(luma*0.01)

p = convertbits(8).TemporalSoften(3,4,6,0,2).ex_levels(10,0.95,126)
SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=1)
#Subtitle("luma=" + String(ths) +","+ String(ltr), align=2)
""")
n = s.converttoyuv444()
n = n.vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
n = n.neo_f3kdb(grainY=40,grainC=3,mt=true).tweak(sat=1.16)
return n
}

Although SmDegrain works in Planar RGB outside scriptclip...why not here?

EDIT: Aaah I missed the "c,"
Now it is working but damn it is slow (I feared it would be) and only because of scriptclip since without it is pretty fast :(

New code:

function anv(clip c){
converttoPlanarRGB(c) #
S=ScriptClip(c,"""
lum = converttorgb().invert().averageG
rgb = converttorgb().RGBDifferenceFromPrevious
luma = int(lum + rgb)
ltr = int(luma*0.00009)
ths = int(luma*0.01)

p = convertbits(8).TemporalSoften(3,4,6,0,2).ex_levels(10,0.95,126)
SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=1)
#Subtitle("luma=" + String(ths) +","+ String(ltr), align=2)
""")
n = s.fft3dfilter(sigma=0.3,sigma2=0.4,sigma3=1.7,sigma4=2.1,plane=4,bt=1)
n = n.converttoyuv444()
n = n.vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
n = n.neo_f3kdb(grainY=40,grainC=3,mt=true).tweak(sat=1.16)
return n
}

kedautinh12
5th March 2022, 15:04
You can try neo_fft3d, i think it's faster

StainlessS
5th March 2022, 15:41
Totally untested. [No idea what its supposed to be doing - my best guess at intended use]
[EDIT: Ignore this, methinks the later EDIT is as intended.]

Function anv(clip c){
converttoPlanarRGB(c) # Last is planar RGB, input bitdepth : ## c clip NOT used after here.
rgbInvertC = invert() # Inverted rgb, input depth
Rgb8 = convertbits(8) # planar RGB, 8 bit
p = Rgb8.TemporalSoften(3,4,6,0,2).ex_levels(10,0.95,126) # SmDegrain Prefilter clip
SSS = """
lum = rgbInvertC.averageG
rgb = RGBDifferenceFromPrevious # on last, ie planar RGB, input bitdepth
luma = int(lum + rgb)
ltr = int(luma*0.00009)
ths = int(luma*0.01)
SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=1) # Horrible, real slow call to SmDegrain at every frame.
#Subtitle("luma=" + String(ths) +","+ String(ltr), align=2)
return last
"""
# ScriptClip: Input Last, ie PlanarRgb at input depth
ScriptClip(Last,SSS,args="rgbInvertC,p",local=true) # NEEDS Grunt Plugin for Args.
fft3dfilter(sigma=0.3,sigma2=0.4,sigma3=1.7,sigma4=2.1,plane=4,bt=1)
converttoyuv444()
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
neo_f3kdb(grainY=40,grainC=3,mt=true).tweak(sat=1.16)
return Last
}


__END__

# HERE old script. After above __END__ is not executed.


Function anv(clip c){
converttoPlanarRGB(c) #
# *** NOTE, NOT calling below scriptclip with planarRGB, is input clip c ***
S=ScriptClip(c,"""
lum = converttorgb().invert().averageG
rgb = converttorgb().RGBDifferenceFromPrevious
luma = int(lum + rgb)
ltr = int(luma*0.00009)
ths = int(luma*0.01)

p = convertbits(8).TemporalSoften(3,4,6,0,2).ex_levels(10,0.95,126)
SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=1)
#Subtitle("luma=" + String(ths) +","+ String(ltr), align=2)
""")
n = s.fft3dfilter(sigma=0.3,sigma2=0.4,sigma3=1.7,sigma4=2.1,plane=4,bt=1)
n = n.converttoyuv444()
n = n.vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
n = n.neo_f3kdb(grainY=40,grainC=3,mt=true).tweak(sat=1.16)
return n
}


EDIT: SmDegrain called on input bitdepth planar RGB [ie Last], but with 8bit prefilter,
dont know if intended nor if works properley, I dont use SmDegrain.

EDIT:
On 2nd thoughts, maybe this as intended [again untested at all]
But p clip is 8 bits and function input clip c may not be, dont know if smdegrain will handle correctly. [maybe below in RED needs removal]

Function anv(clip c){
InputPlanarRGB = converttoPlanarRGB(c)
rgbInvertC = InputPlanarRGB.invert() # Inverted rgb, input depth
p = c.convertbits(8).TemporalSoften(3,4,6,0,2).ex_levels(10,0.95,126) # SmDegrain Prefilter clip
SSS = """
lum = rgbInvertC.averageG
rgb = InputPlanarRGB.RGBDifferenceFromPrevious # on planar RGB, input bitdepth
luma = int(lum + rgb)
ltr = int(luma*0.00009)
ths = int(luma*0.01)
SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=1) # Horrible, real slow call to SmDegrain at every frame.
#Subtitle("luma=" + String(ths) +","+ String(ltr), align=2)
return last
"""
# ScriptClip: Input c, ie Input clip
ScriptClip(c,SSS,args="rgbInvertC,p,InputPlanarRGB",local=true) # NEEDS Grunt Plugin for Args.
fft3dfilter(sigma=0.3,sigma2=0.4,sigma3=1.7,sigma4=2.1,plane=4,bt=1)
converttoyuv444()
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
neo_f3kdb(grainY=40,grainC=3,mt=true).tweak(sat=1.16)
return Last
}

SmDegrain() in scriptclip will execute the smdegrain script code eg process default args and preparation code for every frame.

anton_foy
5th March 2022, 16:16
@StailessS
Thank you! I have to change to rgb = converttorgb().RGBDifferenceFromPrevious Since RGBDifferencefromPrevious needs packed RGB but then
SmDegrain get this again: "MAnalyse: Clip must be YUV or YUY2 ...SmDegrain.avsi, line 294, line 345, line 634"
No idea what its supposed to be doing
I found that a combo of averageG and RGBDifference gives me a pretty good estimation for how much denoising is needed (at least for my footage) so I feed those values (ltr, ths) to the parameters of SmDegrain to make it dynamic/automatic. In short auto denoise attempt.

@kedautinh12
Thanks but for me neo_fft3d is a bit slower than fft3dfilter at the same ncpu setting.

StainlessS
5th March 2022, 16:20
A.F.,
What version AVS+ are you using, I thought Pinterf implemented RGBDifferenceFromPrevious [and similar] for
all RGB colorspace [maybe I is wrong].

EDIT: Forget that, you are correct, it dont work in planar RGB.

StainlessS
5th March 2022, 16:28
Hows bouts dis den

Function anv(clip c){
InputPlanarRGB = converttoPlanarRGB(c)
rgbInvertC = InputPlanarRGB.invert() # Inverted rgb, input depth
p = c.convertbits(8).TemporalSoften(3,4,6,0,2).ex_levels(10,0.95,126) # SmDegrain Prefilter clip
InputRGB24 = InputPlanarRGB.converttorgb24() # 8 bit Interleaved, RGB24
SSS = """
lum = rgbInvertC.averageG
rgb = InputRGB24.RGBDifferenceFromPrevious # on planar RGB, input bitdepth
luma = int(lum + rgb)
ltr = int(luma*0.00009)
ths = int(luma*0.01)
SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=1) # Horrible, real slow call to SmDegrain at every frame.
#Subtitle("luma=" + String(ths) +","+ String(ltr), align=2)
return last
"""
# ScriptClip: Input c, ie Input clip
ScriptClip(c,SSS,args="rgbInvertC,p,InputRGB24",local=true) # NEEDS Grunt Plugin for Args.
fft3dfilter(sigma=0.3,sigma2=0.4,sigma3=1.7,sigma4=2.1,plane=4,bt=1)
converttoyuv444()
vsCnr2(mode="ooo",ln=5,un=40,vn=40,sceneChroma=false)
neo_f3kdb(grainY=40,grainC=3,mt=true).tweak(sat=1.16)
return Last
}


There is still potential mismatch in p (8 bit) and input clip depth in SmDegrain and also rgb and lum.

EDIT:
OK, seems RGBDifferenceFromPrevious returns 0->255.0 [could not remember range]

This group of functions return a float value between 0 and 255 of the absolute difference between two planes from two different clips

EDIT: Actually AverageLuma does NOT return 255.0 on white frame at eg 16 bit. [nearer 64K]
EDIT: And AvergeG and RGBDifferenceFromPrevious produce about 64K for 16 bit, so this RED line above not really true,
and potential mismatch in 8 bit to other bit depth is true.

anton_foy
5th March 2022, 16:28
A.F.,
What version AVS+ are you using, I thought Pinterf implemented RGBDifferenceFromPrevious [and similar] for
all RGB colorspace [maybe I is wrong].

EDIT: Forget that, you are correct, it dont work in planar RGB.

AVS+ ver 3593 x64
Ahh I see, tried to convert the RGB line to packed and then converttoplanarRGB() again before SmDegrain but error still remains.

kedautinh12
5th March 2022, 16:49
I think avs+ now is 3.7.2 test 12, i think it's ver r36xx

StainlessS
5th March 2022, 16:53
Latest v3.7.2 r3642.

Dogway
6th March 2022, 16:15
@anton_foy: Try with this. You need to take out from ScriptClip anything that is not utmost required. DCT was also very low, typically you want between 200 and 800.
function anv(clip c){

pk = converttoRGB(c)
pl = pk.converttoPlanarRGB()
in = pl.ex_invert()
p = c.convertbits(8,dither=-1).TemporalSoften(3,4,6,0,2).ex_levels(10,0.95,126)

S=ScriptClip(c,function[in,p,pl,pk] () {

lum = pl.averageG()
rgb = pk.RGBDifferenceFromPrevious()
luma = int(lum + rgb)
ltr = int(luma*0.00009)
ths = int(luma*0.01)

SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=300)
#Subtitle("luma=" + String(ths) +","+ String(ltr), align=2)
} )

n = s.fft3dfilter(sigma=0.3,sigma2=0.4,sigma3=1.7,sigma4=2.1,plane=4,bt=1)
n = n.converttoyuv444()
n = n.neo_f3kdb(grainY=40,grainC=3,mt=true).tweak(sat=1.16)
return n
}

anton_foy
7th March 2022, 21:39
@anton_foy: Try with this. You need to take out from ScriptClip anything that is not utmost required. DCT was also very low, typically you want between 200 and 800.
function anv(clip c){

pk = converttoRGB(c)
pl = pk.converttoPlanarRGB()
in = pl.ex_invert()
p = c.convertbits(8,dither=-1).TemporalSoften(3,4,6,0,2).ex_levels(10,0.95,126)

S=ScriptClip(c,function[in,p,pl,pk] () {

lum = pl.averageG()
rgb = pk.RGBDifferenceFromPrevious()
luma = int(lum + rgb)
ltr = int(luma*0.00009)
ths = int(luma*0.01)

SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=300)
#Subtitle("luma=" + String(ths) +","+ String(ltr), align=2)
} )

n = s.fft3dfilter(sigma=0.3,sigma2=0.4,sigma3=1.7,sigma4=2.1,plane=4,bt=1)
n = n.converttoyuv444()
n = n.neo_f3kdb(grainY=40,grainC=3,mt=true).tweak(sat=1.16)
return n
}

@Dogway
My god now its really fast and working almost perfectly, many thanks man!
Just one question, one clip I test has small waves in the water and they get all smeared out almost disappearing with SmDegrain. Is there any parameter to avoid this or compensate?

@StainlessS and kedautinh12
Thanks I will get the latest version!

StainlessS
7th March 2022, 23:49
A.F.,
Its faster mainly because the clip conversions are done outside of scriptclip, and so done only once, not at every frame.

anton_foy
8th March 2022, 07:17
A.F.,
Its faster mainly because the clip conversions are done outside of scriptclip, and so done only once, not at every frame.

But SmDegrain is inside of ScriptClip where the parameters are suppose to be changed at every frame, how come they are not in this one?

EDIT: oh you mean that the conversions are only done once (although weren't they also called outside ScriptClip in your script)? Early in the morning here ;) Thanks for the explanation, huge difference now.

Ceppo
8th March 2022, 10:18
Is there any parameter to avoid this or compensate?
Lower the thSAD parameter or change the prefilter clip.

Dogway
8th March 2022, 11:03
Faint shading is a known issue with degraining, try truemotion=true, and the DCT options. Also try to lower thSAD or tr.

StainlessS
8th March 2022, 11:35
A.F.,
(although weren't they also called outside ScriptClip in your script)?
I dont know, I dont have SmDegrain set up and so was totally untested.
I presume that SmDegrain still has a pretty 'heavy' startup at each frame.

anton_foy
8th March 2022, 12:23
A.F.,

I dont know, I dont have SmDegrain set up and so was totally untested.
I presume that SmDegrain still has a pretty 'heavy' startup at each frame.

Actually I get almost no speed down compared to the same script without scriptclip. SMDegrain set with approximately the same settings.

@Ceppo
Thanks which prefilter technique would you suggest?

@Dogway
Thanks but truemotion always blurs the crap out of my clips for some reason. But I will try it.

kedautinh12
8th March 2022, 12:36
I like prefilter with BM3DGPU:D

Ceppo
8th March 2022, 13:45
Thanks which prefilter technique would you suggest?
In my opinion, temporal filters shouldn't be used as pre-filters, I prefer spatial ones. With my own degrain filter I use FFT3DFilter(sigma=0,sigma2=1,sigma3=2,sigma4=4,bt=1,plane=4) since grain and noise are low frequency, you want to use higher values for them and lower values for high ones. Also, TemporalSoften will give good results only on static pixels, and, unless your source is an anime, there is little gain from using it, it might get even worse.

anton_foy
8th March 2022, 14:14
In my opinion, temporal filters shouldn't be used as pre-filters, I prefer spatial ones. With my own degrain filter I use FFT3DFilter(sigma=0,sigma2=1,sigma3=2,sigma4=4,bt=1,plane=4) since grain and noise are low frequency, you want to use higher values for them and lower values for high ones. Also, TemporalSoften will give good results only on static pixels, and, unless your source is an anime, there is little gain from using it, it might get even worse.

Wow thanks I was under the impression that temporal filtering was more suitable for real life footage rather than anime. I remember Dogway and others discussed this in his thread a while back when DGdenoise came up as an alternative prefilter to SMdegrain to be used mostly for anime:
https://forum.doom9.org/showthread.php?p=1963573#post1963573

EDIT: Also remember Dideé's first choice of prefilter for overall denoising was fft3dfilter.

Ceppo
8th March 2022, 14:40
My argument is that in real footage there is not much static stuff as the camera is rarely static. In anime you might have a static scene where only a character is doing something and everything else is static, so temporalsoften might work, but in reality, pre temporal filters lead always to ghosting, at least in my experience.

anton_foy
8th March 2022, 14:53
My argument is that in real footage there is not much static stuff as the camera is rarely static. In anime you might have a static scene where only a character is doing something and everything else is static, so temporalsoften might work, but in reality, pre temporal filters lead always to ghosting, at least in my experience.

Your fft3d suggestion seems logical to me to use a low sigma value in high frequencies and a higher value for lower frequencies to prefilter. I have used fft3dfilter(sigma=4) as a prefilter to SMDegrain but it blurred the image alot so I will try your suggestion later today. Thanks!

@kedautinh12
Thanks I will try that too. Although isnt it a bit on the heavy side for a prefilter? Guess I have to down block_step to 2?

BTW. Adding colorYUV(autogain=true)."some denoiser"() as prefilter removes the extra motionblur SMDegrain usually adds to my clips. Otherwise to keep original motionblur I had to lower blocksize to 8 but thats slow. Adding colorYUV is fast.

Dogway
8th March 2022, 21:45
Motion estimation is very sensitive to temporal fluctuations so it is safe to add constrained safe temporal filters like FluxSmooth which Didée also tended to use, or STPresso.

Using autogain is not advised, I tested once and it can create nasty DCT artifacts due to temporal autogain instabilities, thSAD would also need to be dynamic for it to work fine, or use a static contrast.

One of my solution was LFR and DCT. LFR recovers low frequencies from output but also applies a low frequency local contrast to prefilter to counteract the loss of shading. Maybe also use refinemotion instead of blocksize=8.

SMDegrain should have a rather fast startup since all logic is mostly nested so only the required is parsed and by default it practically does nothing at all.

kedautinh12
9th March 2022, 00:11
Don't need change to 2. If you use radius = 1, just change block_step=[8,7,8,7]
https://github.com/Dogway/Avisynth-Scripts/blob/f38f458f1c9a0da1c2bd3cc1606485ef6cba297b/SMDegrain%20v3.4.7d/SMDegrain%20v3.4.7d.avsi#L997

anton_foy
9th March 2022, 01:36
Using autogain is not advised, I tested once and it can create nasty DCT artifacts due to temporal autogain instabilities, thSAD would also need to be dynamic for it to work fine, or use a static contrast.


But I am making thSAD (and "tr") dynamic with this script :D
Regarding static contrast did you mean like using ex_levels as I did in my test script in this thread? I tried to mimic the same levels as ColorYUV(autogain=true) gave me for the particular test clip I used but ex_levels did not give me at all the same result and motion blur was introduced. Did a few hours this evening of testing different prefilter settings.
For me the winner was: (kept detail well and sharp, barely any extra motion blur)
p = c.convertbits(8,dither=-1).ColorYUV(autogain=true).fft3dfilter(sigma=0.7,sigma2=1,sigma3=1.7,sigma4=1.7,plane=0,bt=1,ncpu=4)
2nd place: (introduced some wavy motionblur in finer detailed areas but not larger ones, soft on some details)
p = c.convertbits(8,dither=-1).ColorYUV(autogain=true).ex_minblur()

3rd place: (introduced more wavy motionblur in finer detailed areas but not larger ones, soft on some details)
p = c.convertbits(8,dither=-1).ColorYUV(autogain=true).ex_minblur().fluxsmoothT(4)

4th place: (slow and lost some finer details and got blotchyness in lower frequencies, must compare motion blur though)
p=c.ColorYUV(autogain=true).ConvertBits(bits=32).BM3D_CUDA(sigma=9,radius=1,block_step=4).BM3D_VAggregate(radius=1).convertbits(8,dither=-1)

For SMDegrain I used:
SmDegrain(prefilter=p,tr=ltr,thsad=ths,DCT=300,mode="temporalsoften")

anton_foy
9th March 2022, 01:40
Don't need change to 2. If you use radius = 1, just change block_step=[8,7,8,7]
https://github.com/Dogway/Avisynth-Scripts/blob/f38f458f1c9a0da1c2bd3cc1606485ef6cba297b/SMDegrain%20v3.4.7d/SMDegrain%20v3.4.7d.avsi#L997

Thanks okay. Last time I tried ex_bm3d my computer couldn't run it.
Memory error or something but I will try it tomorrow.

kedautinh12
9th March 2022, 02:03
Thanks okay. Last time I tried ex_bm3d my computer couldn't run it.
Memory error or something but I will try it tomorrow.

Maybe your GPU don't support CUDA or NVidia card very old. Can you try ex_bm3d(CUDA=false)?

anton_foy
9th March 2022, 02:05
Maybe your GPU don't support CUDA or NVidia card very old. Can you try ex_bm3d(CUDA=false)?

BM3D Cuda works but not CPU.

kedautinh12
9th March 2022, 02:22
If you want ex_bm3d work, you need extools, transformspack, ResizerPack from Dogway