View Full Version : Clay - Denoising script
anton_foy
19th June 2023, 19:30
Back again with yet another denoising function.
Clay tries to remove all noise while keeping the details intact. Simple, fast and temporally stable.
(loads of thanks to DTL, Dogway and StainlessS for the ideas and development etc.)
How it works:
Clay denoises bright areas in one mdegrain call and the dark areas in another then merging them together with a mask.
Dogway's brilliant ccd + iqmv + sbr combo for prefiltering.
To regain sharpness and detail it uses ex_unsharp before MSuper.
To smooth out bad blocks it uses vsdegrainmedian before mdegrain.
Neo VagueDenoiser in the dark areas for spatial smoothness.
(The same settings were used for all three images, see usage settings on the bottom of the page)
Before-After (https://imgsli.com/MTg3MDY1) (ImgSli is compressing the images so banding occurs here)
House (Requested by Coolgit) (https://imgsli.com/MTg4Mzg0)
Test Clips (https://we.tl/t-NlrDfSGxDs) (93mb)
#vsdegrainmedian = FAST!
#iqmv + ex_sbr = FAST!
#neo_vd = FAST!
#ex_unsharp = FAST!
#Clay - mdegrain = medium-fast.
#Results in combination = fine quality and fast!
requirements:
mvtools2, masktools2, neo vaguedenoiser
Additional(with my settings):
Vsdegrainmedian, deblock, neo_F3KDB, (Dogway's): extools, sharpeners pack, deblock pack
Function:
function clay(clip Input, clip "preclip", clip "superclip", clip "darkclip", clip "brightclip", int "DthSAD", int "DthSADC",
\ int "BthSAD", int "BthSADC", int "TR", int "BLKSize", int "Rb", int "Overlap", int "Pel", bool "Chroma",
\ float "VDTh", bool "tm", float "Falloff", int "UV", int "lo", int "hi", float "mid", int "mix", bool "fast")
{
DthSAD = default(DthSAD, 150)
DthSADC= default(DthSADC, 150)
BthSAD = default(BthSAD, 70)
BthSADC= default(BthSADC, 70)
TR = default(TR, 6)
BLKSize = default(BLKSize, 32)
Overlap = default(Overlap, 16)
Rb = default(Rb, 8)
Pel = default(Pel, 1)
Chroma = default(Chroma, true)
Tm = default(Tm, false)
Falloff = default(Falloff, 0.9)
VDth = default(VDth, 1.5)
lo = default(lo, 60)
mid = default(mid, 0.57)
hi = default(hi, 127)
mix = default(mix, 230)
UV = default(UV, 3)
Fast = default(Fast, false)
Bt= BitLShift(1,input.BitsPerComponent - 8)
preclip = Default(preclip,input)
superclip = Default(superclip,input)
darkclip = Default(darkclip,input)
brightclip = Default(brightclip,input)
super = MSuper(superclip, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superB = MSuper(superclip.merge(input), pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superfilt = MSuper(preclip, pel=pel, hpad = 0, vpad = 0, mt=false,sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm ,global=true)
vmulti2 = Mrecalculate(superfilt,multi_vector,thsad=Dthsad,truemotion=tm,tr=tr,blksize=rb,overlap=rb/2,mt=false,chroma=true)
mv_bw1=SelectEvery(multi_vector, tr*2, 0)
mv_fw1=SelectEvery(multi_vector, tr*2, 1)
mv_bw2=SelectEvery(multi_vector, tr*2, 2)
mv_fw2=SelectEvery(multi_vector, tr*2, 3)
dark=darkclip.MDegrainN(Super, vmulti2, TR, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).neo_vd(VDth,1,6,90)
bright = Fast ? input : brightclip.MDegrain2(SuperB, mv_bw1, mv_fw1, mv_bw2, mv_fw2, thSAD=BthSAD, thSADC=BthSADC)
mask=dark.extractY().levels(lo*bt, mid, hi*bt, 0, mix*bt)
mt_merge(dark, bright, mask, luma=true, u=uv, v=uv)
return last
}
Usage (my own settings):
convertbits(16)
converttoYUV444()
# My prefiltering (or use your own desired prefilter):
cd=convertbits(8,dither=-1).convertToYv12()
pre=cd.CCD(13).ex_median("IQMV",Y=3,UV=3).ex_sbr(2)
# Clay with preclip, superclip, darkclip and brightclip:
Clay(tr=7,dthsad=170,dthsadc=170,bthsad=100,preclip=pre,superclip=ex_unsharp(1.77,th=1.1,fc=width(),safe=true,UV=1),darkclip=vsdegrainmedian(),brightclip=last,chroma=true)
# Deblocking chroma and debanding luma:
deblock(planes="UV")
neo_F3KDB(grainY=0,grainC=0,Y=46,mt=true,output_depth=16,range=22,sample_mode=3).mergechroma(last)
Convertbits(10,dither=1)
prefetch(4)
Please give input :)
Enjoy!
Edit: changed "input" to "bright" in mt_merge call and inputD instead of darkclip, inputB instead of brightclip.
Edit2: updated function and usage with DTL's, StainlessS's and Gavino's input. Thanks guys!
Edit3: StainlessS cleanup for preclip, superclip, darkclip and brightclip, thanks!
Edit4: New "settings", changed params for neo_f3kdb for less smearing of details in dark areas.
For better MVs search in MAnalyse it may be recommended for 'slow/slowest/placebo' mode search=3, searchparam>2 and pelsearch>2, trymany=true. And may be some manual play with all penalties (non-zero values).
Also after yet another time reading the docs:
multi
When set to true, MAnalyse generates the motion vectors for all the reference frames −delta…−1 and +1…+delta. The resulting clip is made of single MAnalyse results interleaved in the delta order −1, +1, −2, +2, …, −delta, +delta, where negative values indicate backward searchs. This order is similar to the motion vector parameters in MDegrain3. The output clip is intended to be used directly in MDegrainN. Single motion vector clips can be extracted with a SelectEvery(delta*2, n).
So may be if it is required to use different MDegrainN with different tr-settings (for lower denoise and better details saving for example at one of the processing stream) - may be it is possible to extract required 'mv-frames' from single MAnalyse and reuse at different MDegrainN with different tr-settings ? With old stable 2.7.45 version from pinterf. It will make better performance of script because of AVS caching required mv-frames from single MAnalyse output to different MDegrainN.
At least before tr>6 the MDegrainX may be used as 'low-tr' degrain with extracted bv/fv mv-frames using SelectEvery ?
anton_foy
20th June 2023, 00:21
For better MVs search in MAnalyse it may be recommended for 'slow/slowest/placebo' mode search=3, searchparam>2 and pelsearch>2, trymany=true. And may be some manual play with all penalties (non-zero values).
Thank you I will experiment with these params.
It will make better performance of script because of AVS caching required mv-frames from single MAnalyse output to different MDegrainN.
At least before tr>6 the MDegrainX may be used as 'low-tr' degrain with extracted bv/fv mv-frames using SelectEvery ?
Sounds great but I do not know how to script that to my function correctly, could you show me an example maybe? I am tired now and maybe I can understand better tomorrow.
coolgit
20th June 2023, 01:15
Nice one. The photo was a good example, the face doesn't look plasticity and the winkle lines are still there. How about a photo example of a building?
anton_foy
20th June 2023, 08:38
Nice one. The photo was a good example, the face doesn't look plasticity and the winkle lines are still there. How about a photo example of a building?
Thanks! Yes I actually have one old building with an uneven facade thats a bit noisy. Will do.
This idea:
tr = 6 # Temporal radius
super = MSuper ()
multi_vec = MAnalyse (super, multi=true, delta=tr)
big_tr=MDegrainN(super, multi_vec, tr, thSAD=400, thSAD2=150)
mv_bw1=SelectEvery(tr*2, 1) // or may be correct start from 0 ?
mv_fw1=SelectEvery(tr*2, 2)
mv_bw2=SelectEvery(tr*2, 3)
mv_fw2=SelectEvery(tr*2, 4)
mv_bw3=SelectEvery(tr*2, 5)
mv_fw4=SelectEvery(tr*2, 6)
mdgn3=MDegrain3(super, mvbw=mv_bw1, mvfw=mv_fw1, mvbw2=mv_bw2, mvfw2=mv_fw2, mvbw3=mv_bw3, mvfw3=mv_fw3, ...)
Also may be mv_bw1...mv_fwN may be interleaved to feed other MDegrainN with different tr so only MDegrainN may be used with any tr up to max supported. The tr-converting of multi-MAnalyse output may be assembled into some function to use.
anton_foy
20th June 2023, 11:31
This idea:
tr = 6 # Temporal radius
super = MSuper ()
multi_vec = MAnalyse (super, multi=true, delta=tr)
big_tr=MDegrainN(super, multi_vec, tr, thSAD=400, thSAD2=150)
mv_bw1=SelectEvery(tr*2, 1) // or may be correct start from 0 ?
mv_fw1=SelectEvery(tr*2, 2)
mv_bw2=SelectEvery(tr*2, 3)
mv_fw2=SelectEvery(tr*2, 4)
mv_bw3=SelectEvery(tr*2, 5)
mv_fw4=SelectEvery(tr*2, 6)
mdgn3=MDegrain3(super, mvbw=mv_bw1, mvfw=mv_fw1, mvbw2=mv_bw2, mvfw2=mv_fw2, mvbw3=mv_bw3, mvfw3=mv_fw3, ...)
Also may be mv_bw1...mv_fwN may be interleaved to feed other MDegrainN with different tr so only MDegrainN may be used with any tr up to max supported. The tr-converting of multi-MAnalyse output may be assembled into some function to use.
You mean like this if using mdegrain2?
function clay(clip Input, clip "preclip", clip "superclip", clip "darkclip", clip "brightclip", int "DthSAD", int "DthSADC", int "BthSAD", int "BthSADC", int "TR", int "BLKSize", int "Rb", int "Overlap", int "Pel", bool "Chroma",
\ float "VDTh", int "Shrp", int "Rad", float "thr", bool "tm", float "Falloff", int "UV", int "lo", int "hi", float "mid", int "mix", bool "fast")
{
DthSAD = default(DthSAD, 150)
DthSADC= default(DthSADC, 150)
BthSAD = default(BthSAD, 70)
BthSADC= default(BthSADC, 70)
TR = default(TR1, 6)
#TR2 = default(TR2, 2) #not needed for mdg2
BLKSize = default(BLKSize, 32)
Overlap = default(Overlap, 16)
Rb = default(Rb, 8)
Pel = default(Pel, 1)
Chroma = default(Chroma, true)
Tm = default(Tm, false)
Falloff = default(Falloff, 0.9)
VDth = default(VDth, 1.5)
lo = default(lo, 60)
mid = default(mid, 0.57)
hi = default(hi, 127)
mix = default(mix, 230)
UV = default(UV, 3)
Fast = default(Fast, false)
Bt= BitLShift(1,input.BitsPerComponent - 8)
pre = defined(preclip)
inputP = pre ? preclip : input
sup = defined(superclip)
inputS = sup ? superclip : input
drk = defined(darkclip)
inputD = drk ? darkclip : input
brt = defined(brightclip)
inputB = brt ? brightclip : input
super = MSuper(inputS, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superB = MSuper(inputS.merge(input), pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superfilt = MSuper(inputP, pel=pel, hpad = 0, vpad = 0, mt=false,sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm ,global=true)
vmulti2 = Mrecalculate(superfilt,multi_vector,thsad=Dthsad,truemotion=false,tr=tr,blksize=rb,overlap=rb/2,mt=false,chroma=true)
dark=darkclip.MDegrainN(Super, vmulti2, tr, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).neo_vd(VDth,1,6,90)
mv_bw1=Multi_Vector.SelectEvery(tr*2, 1) // or 0?
mv_fw1=Multi_Vector.SelectEvery(tr*2, 2)
mv_bw2=Multi_Vector.SelectEvery(tr*2, 3)
mv_fw2=Multi_Vector.SelectEvery(tr*2, 4)
bright = Fast ? dark.merge(input, 0.7) : brightclip.MDegrain2(SuperB, mvbw=mv_bw1, mvfw=mv_fw1, mvbw2=mv_bw2, mvfw2=mv_fw2, mvbw3=mv_bw3, mvfw3=mv_fw3, thSAD=BthSAD, thSAD2=Int(BthSAD*Falloff), thSADC=BthSADC, thSADC2=Int(BthSADC*Falloff))
mask=dark.extractY().levels(lo*bt, mid, hi*bt, 0, mix*bt)
mt_merge(dark, bright, mask, luma=true, u=uv, v=uv)
return last
}
And also would it maybe be better to use something like:
bright=mdegrain2(...)
dark=bright.deblock(planes="yuv", quant=50).mdegrain5(...)
mask=...
mt_merge(dark,bright,mask...)
Thinking mdg2+mdg5 would equal mdegrain with strength of tr=7? EDIT: No I did not think clearly, tr is still max 5 then.
StainlessS
20th June 2023, 12:08
I have not tried your script, but this stuck out a bit for me.
dark=darkclip.MDegrainN(Super, vmulti2, tr, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).neo_vd(VDth,1,6,90)
darkclip is an optional arg, and is not defaulted anywhere, so could be "UnDefined".
Suggest maybe try see if all works OK with ALL defaulted optional args.
I have not looked for additional problems.
anton_foy
20th June 2023, 12:16
I have not tried your script, but this stuck out a bit for me.
dark=darkclip.MDegrainN(Super, vmulti2, tr, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).neo_vd(VDth,1,6,90)
darkclip is an optional arg, and is not defaulted anywhere, so could be "UnDefined".
Suggest maybe try see if all works OK with ALL defaulted optional args.
I have not looked for additional problems.
Here it is defined:
function clay(clip Input, clip "preclip", clip "superclip", clip "darkclip", clip "brightclip", int "DthSAD", int "DthSADC", int "BthSAD", int "BthSADC", int "TR1", int "TR2", int "BLKSize", int "Rb", int "Overlap", int "Pel", bool "Chroma",
\ float "VDTh", int "Shrp", int "Rad", float "thr", bool "tm", float "Falloff", int "UV", int "lo", int "hi", float "mid", int "mix", bool "fast")
{
DthSAD = default(DthSAD, 150)
DthSADC= default(DthSADC, 150)
BthSAD = default(BthSAD, 70)
BthSADC= default(BthSADC, 70)
TR1 = default(TR1, 6)
TR2 = default(TR2, 2)
BLKSize = default(BLKSize, 32)
Overlap = default(Overlap, 16)
Rb = default(Rb, 8)
Pel = default(Pel, 1)
Chroma = default(Chroma, true)
Tm = default(Tm, false)
Falloff = default(Falloff, 0.9)
VDth = default(VDth, 1.5)
lo = default(lo, 60)
mid = default(mid, 0.57)
hi = default(hi, 127)
mix = default(mix, 230)
UV = default(UV, 3)
Fast = default(Fast, false)
Bt= BitLShift(1,input.BitsPerComponent - 8)
pre = defined(preclip)
inputP = pre ? preclip : input
sup = defined(superclip)
inputS = sup ? superclip : input
drk = defined(darkclip)
inputD = drk ? darkclip : input
brt = defined(brightclip)
inputB = brt ? brightclip : input
super = MSuper(inputS, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superB = MSuper(inputS.merge(input), pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superfilt = MSuper(inputP, pel=pel, hpad = 0, vpad = 0, mt=false,sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=max(tr1, tr2), BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm ,global=true)
vmulti2 = Mrecalculate(superfilt,multi_vector,thsad=Dthsad,truemotion=false,tr=max(tr1, tr2),blksize=rb,overlap=rb/2,mt=false,chroma=true)
dark=darkclip.MDegrainN(Super, vmulti2, TR1, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).neo_vd(VDth,1,6,90)
bright = Fast ? dark.merge(input, 0.7) : brightclip.MDegrainN(SuperB, vmulti2, TR1, thSAD=BthSAD, thSAD2=Int(BthSAD*Falloff), thSADC=BthSADC, thSADC2=Int(BthSADC*Falloff))
mask=dark.extractY().levels(lo*bt, mid, hi*bt, 0, mix*bt)
mt_merge(dark, bright, mask, luma=true, u=uv, v=uv)
return last
}
Not correct?
StainlessS
20th June 2023, 12:22
Nope, drk and inputD are defined [EDIT: assigned to] there, darkclip is unchanged, ie potentially Undefined.
Suggest maybe try see if all works OK with ALL defaulted optional args.
Give it a try. [I expect Error Abort]
EDIT: Like (untested)
Colorbars(Pixel_type="YV12").KillAudio
clay() # expect "BANG !!!"
anton_foy
20th June 2023, 12:28
Nope, drk and inputD are defined [EDIT: assigned to] there, darkclip is unchanged, ie potentially Undefined.
Give it a try. [I expect Error Abort]
EDIT: Like (untested)
Colorbars(Pixel_type="YV12").KillAudio
clay()
Oh I see but read my usage example in the first post.
Usage (my own settings):
Code:
convertbits(16)
converttoYUV444()
cd=convertbits(8,dither=-1).convertToYv12()
pre=cd.CCD(13).ex_median("IQMV",Y=3,UV=3).ex_sbr(2)
sup=ex_unsharp(1.77,th=1.1,fc=width(),safe=true,UV=1)
drk=deblock(planes="yuv",quant=50)
Clay(tr1=7,tr2=2,dthsad=160,dthsadc=160,bthsad=70,preclip=pre,superclip=sup,darkclip=drk,brightclip=last,chroma=true)
deblock(planes="UV")
neo_F3KDB(grainY=0,grainC=0,mt=false,output_depth=16,range=30).mergechroma(last)
Convertbits(10,dither=1)
prefetch(4)
StainlessS
20th June 2023, 12:33
Your usage examples are a bit irrelevant, you should never, ever, ever, have function with optional args which do not default to something, when not supplied. [ie, are NOT actually optional at all]
EDIT: The error is HERE (darkclip may still be undefined, you try call MDegrainN() on undefined clip arg. [there will be tears before bedtime]
dark=darkclip.MDegrainN(Super, vmulti2, tr, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).neo_vd(VDth,1,6,90)
EDIT: Try the ALL optionals defaulted test, and keep fixing the function until it does not produce error abort. [I dont know if there are problems additional to the darkclip one]
Gavino
20th June 2023, 12:42
You should be using inputD instead of darkclip in the latter part of the script.
The same goes for inputB instead of brightclip.
StainlessS
20th June 2023, 12:50
Thanx Gavin, looks like that was the intention, but I did not want to make any assumptions. [All defaulted optionals test still a good idea, perhaps Gavin already tried that].
anton_foy
20th June 2023, 13:00
You should be using inputD instead of darkclip in the latter part of the script.
The same goes for inputB instead of brightclip.
Yes of course sorry both of you I was confused and interrupted. Just cannot figure out how my script is working since I copied it straight from my avsi-file into here. Will look and fix. Thanks!
you should never, ever, ever, have function with optional args which do not default to something, when not supplied. [ie, are NOT actually optional at all]
Sure, my intention was to use inputD if defined otherwise Input. Just copied the same lines I always use for prefilter in my other scripts.
Gavino
20th June 2023, 13:05
[All defaulted optionals test still a good idea, perhaps Gavin already tried that].
Your advice is 100% sound, but I hadn't tried the script myself.
It simply seemed the obvious intention, as otherwise inputD and inputB were not used for anything.
"mv_bw1=Multi_Vector.SelectEvery(tr*2, 1)"
Yes - in the first example I forgot to set initial MAnalyse mv_multi clip as source for SelectEvery().
This is working example (and I still not sure about numbering from 0 or 1 for SelectEvery)
tr = 6 # Temporal radius
super = MSuper ()
multi_vec = MAnalyse (super, multi=true, delta=tr)
big_tr=MDegrainN(super, multi_vec, tr, thSAD=400, thSAD2=350)
mv_bw1=SelectEvery(multi_vec, tr*2, 0)
mv_fw1=SelectEvery(multi_vec, tr*2, 1)
mv_bw2=SelectEvery(multi_vec, tr*2, 2)
mv_fw2=SelectEvery(multi_vec, tr*2, 3)
mv_bw3=SelectEvery(multi_vec, tr*2, 4)
mv_fw3=SelectEvery(multi_vec, tr*2, 5)
MDegrain3(super, mv_bw1, mv_fw1, mv_bw2, mv_fw2, mv_bw3, mv_fw3, thSAD=300)
Also it looks MDegrain3 not accept mvclips as named arguments.
takla
20th June 2023, 16:41
https://imgsli.com/MTg3MjMz/0/1
Spline64ResizeMT(1920, 1080)
EZdenoise(Chroma=true, out16=true).ConvertBits(10, dither=1)
Downscaled, because 4k with such low quality is extremely pointless.
And personally, I wouldn't denoise the castle clip at all (very little noise).
On the moving water near the castle you can see EZdenoise preserves slightly more detail then Clay.
I used frame 20 for all 3 clips.
anton_foy
20th June 2023, 17:17
https://imgsli.com/MTg3MjMz/0/1
Spline64ResizeMT(1920, 1080)
EZdenoise(Chroma=true, out16=true).ConvertBits(10, dither=1)
Downscaled, because 4k with such low quality is extremely pointless.
And personally, I wouldn't denoise the castle clip at all (very little noise).
On the moving water near the castle you can see EZdenoise preserves slightly more detail then Clay.
I used frame 20 for all 3 clips.
Sorry but how can you compare this downscaled (please compare in full screen, before/after and with your downscaled images) it is extremely low in detail and the denoising on your part is showing alot of noise even still. How can you not see this? Yes the castle clip was denoised a tad too hard just to make the point that with the same settings for all the clips it still works pretty well.
Comparison (https://www.imagebam.com/view/MEM6ZR5)
takla
20th June 2023, 19:52
Sorry but how can you compare this downscaled (please compare in full screen, before/after and with your downscaled images) it is extremely low in detail and the denoising on your part is showing alot of noise even still. How can you not see this? Yes the castle clip was denoised a tad too hard just to make the point that with the same settings for all the clips it still works pretty well.
Comparison (https://www.imagebam.com/view/MEM6ZR5)
I'm using a 55" native 4k display, calibrated to 203nits, 100% srgb (with an average deviation of 0.8 on 50 color test patterns) with 2.2 gamma.
I really don't want to know what kind of miscalibrated garbage display you use that overexposes everything.
How can you not see that your footage is bottom of the barrel, bitrate starved garbage? The chromatic aberration on that cameras footage is so bad, I'd straight up throw it into the trash.
Also, if the denoiser is set too high you'll lose too much detail in lossy encodes.
anton_foy
20th June 2023, 19:58
I'm using a 55" native 4k display, calibrated to 203nits, 100% srgb (with an average deviation of 0.8 on 50 color test patterns) with 2.2 gamma.
I really don't want to know what kind of miscalibrated garbage display you use that overexposes everything.
How can you not see that your footage is bottom of the barrel, bitrate starved garbage? The chromatic aberration on that cameras footage is so bad, I'd straight up throw it into the trash.
Also, if the denoiser is set too high you'll lose too much detail in lossy encodes.
Ok boy be happy. But you see black on white your details lost then and everyone can see for themselves But do your thing :)
Edit: of course I use crappy footage to denoise just for demonstration. Would you denoise perfectly clean clips?
takla
20th June 2023, 20:03
Ok boy be happy. But you see black on white your details lost then and everyone can see for themselves But do your thing :)
Looks perfectly fine on a display which follows industry standards, kiddo :)
There is no reason to re-invent the wheel.
I think what you mistake for noise on the guys face, is skin detail. But I can see how working with garbage footage can warp ones perception.
anton_foy
20th June 2023, 20:08
Looks perfectly fine on a display which follows industry standards, kiddo :)
There is no reason to re-invent the wheel.
;) I am a colorist so I have access to calibrated top gear. Dont worry. But if you have any constructive input please share.
takla
20th June 2023, 20:10
;) I am a colorist so I have access to calibrated top gear. Dont worry. But if you have any constructive input please share.
The best equipment is wasted if you're half blind. Maybe get glasses?
Sure I have constructive input.
How about not providing pseudo 4k footage that is outclassed by 5 year old phone cameras?
How about taking lossy encoding into consideration? All relevant encoders expect noise.
With not very last MPEG encoders (with internal temporal noise reduction like AV1) feeding completely temporal noiseless image (also from static camera so static background) make significant increasing of 'skip' blocks and visibly lower output bitrate - https://forum.doom9.org/showthread.php?p=1984512#post1984512 . So in the 202x season we have some work in progress with internal noise reduction tools in modern MPEG encoders and can help old MPEG encoders with external noise reduction.
anton_foy
20th June 2023, 23:35
With not very last MPEG encoders (with internal temporal noise reduction like AV1) feeding completely temporal noiseless image (also from static camera so static background) make significant increasing of 'skip' blocks and visibly lower output bitrate - https://forum.doom9.org/showthread.php?p=1984512#post1984512 . So in the 202x season we have some work in progress with internal noise reduction tools in modern MPEG encoders and can help old MPEG encoders with external noise reduction.
Yes I agree. This is why I started this experiment to externally with avisynth clean up unusable footage to get usable results. Really it is quite baffling how great mdegrain (and avisynth) is. This is why I use heavily compressed and noisy footage in UHD to see how much can be improved. Your prior post on using selectevery and mdegrain3/2 made alot of speed improvement btw.!
anton_foy
20th June 2023, 23:48
Sure I have constructive input.
How about not providing pseudo 4k footage that is outclassed by 5 year old phone cameras?
How about taking lossy encoding into consideration? All relevant encoders expect noise.
How do you mean dear sir? If I try to make a script to improve badly compressed and noisy footage then why should I use already clean footage? And why the personal attacks? The best equipment is wasted if you're half blind. Maybe get glasses?
:D
Looks perfectly fine on a display which follows industry standards, kiddo
StainlessS
21st June 2023, 00:16
Your usage examples are a bit irrelevant, you should never, ever, ever, have function with optional args which do not default to something, when not supplied. [ie, are NOT actually optional at all]
I'm gonna backtrack/clarify a little bit on above,
you can leave an undefined argument to be defaulted in some other function, eg
Function Kung(clip c, Int "OptArg") {
return Fu(c, OptArg) # Here, we just pass OptArg on, and leave it to Fu() to handle default when not supplied to us here.
}
Function Fu(clip c Int "OptArg") {
OptArg = Default(OptArg, 42) # Optionals MUST default (Somewhere) when not supplied.
... # some other stuff
return last
}
Colorbars()
Kung() # OptArg will default to 42 in Fu().
Although Kung() does indeed provide an optional arg to Fu(), that optional arg [EDIT: optional to Fu() arg] might actually be Undefined when not provided by the client/caller of Kung().
EDIT: BUT,
Function Kung(clip c, Int "OptArg") {
z = Fu(c, OptArg) # Here, we just pass OptArg on, and leave it to Fu() to handle default when not supplied to us here.
# some other stuff
MeaningOfLife = OptArg # FAIL [is Undefined], OptArg only defaults in Fu(), is still undefined here, if not supplied by our caller.
# some more other stuff
return last
}
Function Fu(clip c Int "OptArg") {
OptArg = Default(OptArg, 42) # Optionals MUST default when not supplied.
... # some other stuff
return last
}
Colorbars()
Kung() # OptArg will default to 42 in Fu(), but "MeaningOfLife = OptArg" in Kung() will fail [be Undefined].
anton_foy
21st June 2023, 00:51
@StainlessS
Got back and tested the script yet again but I did not get any errors even if darkclip.mdegrain...
But if I left out darkclip in the avs-script I got an error so thats why I didn't spot it.
Anyway thanks, I changed the function in many ways now.
StainlessS
21st June 2023, 11:38
This bit here,
pre = defined(preclip)
inputP = pre ? preclip : input
could use
preclip = Default(preclip,input)
and continue to use preclip where the un-necessary inputP is later used.
<unless you actually want to later remember if preclip was defined or defaulted, [where you might use your pre from pre = defined(preclip) stuff instead]>
Similar for the other places where you use the defined() keyword.
Using Default(), is just a bit less messy than using Defined(). Having to later test if an optional was defaulted or not, is rarely necessary.
Nothing wrong with what you do there, Default() just a little more succinct and less messy.
[EDIT: And creation of un-necessary vars pre and inputP just make understanding the script less easy.]
anton_foy
21st June 2023, 12:16
@StainlessS
Thanks yes much more clean.
Did it out of old habit. So then I can use:
dark = darkclip.mdegrain... and skip the InputD or did I misunderstand?
StainlessS
21st June 2023, 12:46
or did I misunderstand?
Sounds like you understood perfectly. :)
Gavino
21st June 2023, 18:04
...
Colorbars()
Kung() # OptArg will default to 42 in Fu(), but "MeaningOfLife = OptArg" in Kung() will fail [be Undefined].
It won't exactly 'fail', you won't get an error at this point.
Yes, "MeaningOfLife" will be Undefined, but that's a perfectly legal value.
Of course, you will get an error if you later use "MeaningOfLife" in a context that expects it not to be Undefined.
(Which is probably the point you were actually making, Mr S)
StainlessS
21st June 2023, 18:46
(Which is probably the point you were actually making, Mr S)
Exactly, thanx for pointing out my shortcomings :)
EDIT: Will the Meaning Of Life, always be undefined ???
[I'm of the "Yes" persuasion - We are microbes in the soup.]
anton_foy
21st June 2023, 23:27
The House image shows some smearing of the dark red boards on the wood house. Tried Local Contrast Enhancement in the prefilter stage but it did not do anything. Any suggestions? Minor detail but if possible it would improve the function alot. Dogway looking your way :)
Edit: seems it is not Clay but neo_f3kdb that is doing the smearing of details in shadow areas. Will either exclude it or fiddle with the knobs.
DTL
11th August 2023, 19:04
This is example of usage Auto-thSAD feature of the hopefully not (very) buggy release of https://github.com/DTL2020/mvtools/releases/tag/r.2.7.46-e.02 :
function clay(clip Input, clip "preclip", clip "superclip", clip "darkclip", clip "brightclip", int "DthSAD", int "DthSADC",
\ int "BthSAD", int "BthSADC", int "TR", int "BLKSize", int "Rb", int "Overlap", int "Pel", bool "Chroma",
\ float "VDTh", bool "tm", float "Falloff", int "UV", int "lo", int "hi", float "mid", int "mix", bool "fast",
\ float "thSADA_a", float "thSADA_b")
{
DthSAD = default(DthSAD, 150)
DthSADC= default(DthSADC, 150)
BthSAD = default(BthSAD, 70)
BthSADC= default(BthSADC, 70)
_thSADA_a = default(thSADA_a, 0) #disabled
_thSADA_b = default(thSADA_b, 0) #disabled
TR = default(TR, 6)
BLKSize = default(BLKSize, 32)
Overlap = default(Overlap, 16)
Rb = default(Rb, 8)
Pel = default(Pel, 1)
Chroma = default(Chroma, true)
Tm = default(Tm, false)
Falloff = default(Falloff, 0.9)
VDth = default(VDth, 1.5)
lo = default(lo, 60)
mid = default(mid, 0.57)
hi = default(hi, 127)
mix = default(mix, 230)
UV = default(UV, 3)
Fast = default(Fast, false)
Bt= BitLShift(1,input.BitsPerComponent - 8)
preclip = Default(preclip,input)
superclip = Default(superclip,input)
darkclip = Default(darkclip,input)
brightclip = Default(brightclip,input)
super = MSuper(superclip, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superB = MSuper(superclip.merge(input), pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superfilt = MSuper(preclip, pel=pel, hpad = 0, vpad = 0, mt=false,sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm ,global=true)
vmulti2 = Mrecalculate(superfilt,multi_vector,thsad=Dthsad,truemotion=tm,tr=tr,blksize=rb,overlap=rb/2,mt=false,chroma=true)
mv_bw1=SelectEvery(multi_vector, tr*2, 0)
mv_fw1=SelectEvery(multi_vector, tr*2, 1)
mv_bw2=SelectEvery(multi_vector, tr*2, 2)
mv_fw2=SelectEvery(multi_vector, tr*2, 3)
dark=darkclip.MDegrainN(Super, vmulti2, TR, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff))
multi_2fixed=Interleave(mv_bw1, mv_fw1, mv_bw2, mv_fw2)
bright = Fast ? input : brightclip.MDegrainN(SuperB, multi_2fixed, 2, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=BthSAD, thSADC=BthSADC)
mask=dark.extractY().levels(lo*bt, mid, hi*bt, 0, mix*bt)
mt_merge(dark, bright, mask, luma=true, u=uv, v=uv)
return last
}
Using only MDegrainN for dark and bright to use Auto-thSAD in both processing. Hope I combine forward and backward mv clips for tr=2 correctly ? Also I not found where to take ".neo_vd(VDth,1,6,90)" plugin/script so it deleted from this example.
Usage example:
Clay(tr=7,dthsad=100,dthsadc=100,bthsad=100,chroma=true, thSADA_a=1.3, thSADA_b=50)
It looks Auto-thSAD currently work not completely equally for 8 and 16 bit sources and result in residual noise levels a bit different. It is subject of more thinking about better normalizing maybe or other corrections.
To use second input of MAnalyse with external 'prefiltered' clip it maybe:
super = MSuper(superclip, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, sharp=1)
superfilt = MSuper(preclip, pel=pel, hpad = 0, vpad = 0, mt=false, sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm, global=true, SuperCurrent=super)
I think it maybe no difference to feed super_ref and super_current to (1 and 2) or (2 and 1) inputs of the ME algorithm in MAnalyse. But both ways may be tested if it cause any difference in quality.
Second way to test looks like
Multi_Vector = super.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm, global=true, SuperCurrent=superfilt)
anton_foy
12th August 2023, 10:34
This is example of usage Auto-thSAD feature of the hopefully not (very) buggy release of https://github.com/DTL2020/mvtools/releases/tag/r.2.7.46-e.02 :
function clay(clip Input, clip "preclip", clip "superclip", clip "darkclip", clip "brightclip", int "DthSAD", int "DthSADC",
\ int "BthSAD", int "BthSADC", int "TR", int "BLKSize", int "Rb", int "Overlap", int "Pel", bool "Chroma",
\ float "VDTh", bool "tm", float "Falloff", int "UV", int "lo", int "hi", float "mid", int "mix", bool "fast",
\ float "thSADA_a", float "thSADA_b")
{
DthSAD = default(DthSAD, 150)
DthSADC= default(DthSADC, 150)
BthSAD = default(BthSAD, 70)
BthSADC= default(BthSADC, 70)
_thSADA_a = default(thSADA_a, 0) #disabled
_thSADA_b = default(thSADA_b, 0) #disabled
TR = default(TR, 6)
BLKSize = default(BLKSize, 32)
Overlap = default(Overlap, 16)
Rb = default(Rb, 8)
Pel = default(Pel, 1)
Chroma = default(Chroma, true)
Tm = default(Tm, false)
Falloff = default(Falloff, 0.9)
VDth = default(VDth, 1.5)
lo = default(lo, 60)
mid = default(mid, 0.57)
hi = default(hi, 127)
mix = default(mix, 230)
UV = default(UV, 3)
Fast = default(Fast, false)
Bt= BitLShift(1,input.BitsPerComponent - 8)
preclip = Default(preclip,input)
superclip = Default(superclip,input)
darkclip = Default(darkclip,input)
brightclip = Default(brightclip,input)
super = MSuper(superclip, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superB = MSuper(superclip.merge(input), pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superfilt = MSuper(preclip, pel=pel, hpad = 0, vpad = 0, mt=false,sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm ,global=true)
vmulti2 = Mrecalculate(superfilt,multi_vector,thsad=Dthsad,truemotion=tm,tr=tr,blksize=rb,overlap=rb/2,mt=false,chroma=true)
mv_bw1=SelectEvery(multi_vector, tr*2, 0)
mv_fw1=SelectEvery(multi_vector, tr*2, 1)
mv_bw2=SelectEvery(multi_vector, tr*2, 2)
mv_fw2=SelectEvery(multi_vector, tr*2, 3)
dark=darkclip.MDegrainN(Super, vmulti2, TR, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff))
multi_2fixed=Interleave(mv_bw1, mv_fw1, mv_bw2, mv_fw2)
bright = Fast ? input : brightclip.MDegrainN(SuperB, multi_2fixed, 2, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=BthSAD, thSADC=BthSADC)
mask=dark.extractY().levels(lo*bt, mid, hi*bt, 0, mix*bt)
mt_merge(dark, bright, mask, luma=true, u=uv, v=uv)
return last
}
Using only MDegrainN for dark and bright to use Auto-thSAD in both processing. Hope I combine forward and backward mv clips for tr=2 correctly ? Also I not found where to take ".neo_vd(VDth,1,6,90)" plugin/script so it deleted from this example.
Usage example:
Clay(tr=7,dthsad=100,dthsadc=100,bthsad=100,chroma=true, thSADA_a=1.3, thSADA_b=50)
It looks Auto-thSAD currently work not completely equally for 8 and 16 bit sources and result in residual noise levels a bit different. It is subject of more thinking about better normalizing maybe or other corrections.
To use second input of MAnalyse with external 'prefiltered' clip it maybe:
super = MSuper(superclip, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, sharp=1)
superfilt = MSuper(preclip, pel=pel, hpad = 0, vpad = 0, mt=false, sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm, global=true, SuperCurrent=super)
I think it maybe no difference to feed super_ref and super_current to (1 and 2) or (2 and 1) inputs of the ME algorithm in MAnalyse. But both ways may be tested if it cause any difference in quality.
Second way to test looks like
Multi_Vector = super.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm, global=true, SuperCurrent=superfilt)
Thank you alot! Need to test it out after the weekend when Im back home. I cannot wait! The question is if the two instances of mdegrain is needed when using autoSAD.
Edit: hmm neo_vd is needed only as an extra smoothing of noise in the "dark" part so if only using one mdegrain instance I maybe can do it with masking.
DTL
12th August 2023, 12:22
"The question is if the two instances of mdegrain is needed when using autoSAD."
If you process differently pre-processed clips - it is needed. The Auto-thSAD makes thSAD computing based only on SAD data from mvclip (output of MAnalyse of MRecalculate) so it not depend on super and 'input' clip to MDegrain. But you can also provide a bit different thSAD_a and thSAD_b params to different MDegrain (for dark and light processing paths ?) so to additionally tweak resulted thSAD used internally.
thSAD_a is 'variability' of internal thSAD based on 'noise estimation' between current frame and +1 or -1 valid frame (at scenecut points +1 or -1 frames may be invalidated by scenechange detection, so Auto-thSAD tries to check if any of +1 or -1 frame is valid, if both not valid - it performs fallback to provided thSAD, thSAD2, thSADC, thSADC2).
thSAD_b is constant offset to calculated thSAD.
anton_foy
22nd August 2023, 13:03
I did tests with autoSAD and without but the results are totally different from pinterf's version of mdegrain, I get temporally unstable and much less denoising. What is it that makes this? I would think that the mdegrain itself is very different that is causing this low denoising and temporal instabilities compared to pinterf's version?
DTL
22nd August 2023, 22:37
You may share some small sample footage and scripts you use with static thSAD and auto-settings. I will try to compare what happens with internal th-values created by the 'auto' algorithm and how are they compared to static values internally. Maybe I miss some internal scaling of th-values depending on blocksize and bitdepth. I not test all possible blocksize and bitdepth combinations and real used th-values internally greatly depends on blocksize and bitdepth. Static thSADx provided as param to MDegrainX/N scaled internally depending on some algorithm from bitdepth/blocksize and maybe other params.
Though MAnalyse should work about equal to pinterf build of 2.7.45 so 'temporal instabilities' maybe some side effect of too low denoising with auto-settings enabled ? If you test -e.02 build with standard static thSAD values for Clay script - does it produce equal result to pinterf 2.7.45 build ?
" much less denoising. What is it that makes this? "
With thSADA_a=1.0 (and thSADA_b close to 0) the produced thSAD values are very close to 'noise levels' and may leave too much noise (or some blocks visibly low denoised). So to produce higher thSAD values higher settings like 1.3..1.5 for thSADA_a may be used. If with thSADA_a setting about 2.0 the denoising is still no good - it looks like some bug exists and needs debugging. Also about thSADA_b offset param - I am not sure if it correctly auto-scaled for different bitdepth/blocksize. The 'not scaled' th-values should pass over auto-scaling in the mode of 8bit and blocksize of 8x8. For 16bit it is about x256 and for blocksize > 8x8 it is about multiplication to sample count of bigger blocksize divided to 64 (samples count in 8x8 block).
For testing may be used combination of thSADA_a=0 and thSADA_b=typically used thSAD. The result should be equal to static thSAD mode with the same thSAD param setting. If denosing is different - so something is not correct with auto-scaling and need debugging.
I think this new 'auto' mode also greatly needs the 'debug print' additional mode of MDegrainX/N to display lots of internal debug statistics to help users understand what is happening internally and adjust params with more digital control. At least all internally generated th-values used for each frame (thSAD/thSAD2/thSADC/thSADC2).
I still do not add printing of statistics modes because if we collect stat data with standard processing of frames it will create more or less performance penalty for action of lots of 'performance counters' if they are also not displayed. To make more nice program text I think of 'templating' most of processing functions with bool param like 'bCollectStatsInfo' so compiler will auto-generate 2 versions of processing functions to keep performance of main production mode and to collect stat data in debug/tuning mode with printing statistics over frame. mvtools already has a working function for printing text over frame (it is used in MShow) so it is only required to gather data to display and call this function with x,y placement of text over frame.
anton_foy
22nd August 2023, 23:47
function clayDTL(clip Input, clip "Preclip", clip "Superclip", clip "Darkclip", clip "Brightclip", int "DthSAD", int "DthSADC",
\ int "BthSAD", int "BthSADC", int "TR", int "BLKSize", int "Rb", int "Overlap", int "Pel", bool "Chroma",
\ float "VDTh", bool "TM", float "Falloff", int "UV", int "LO", int "HI", float "MID", int "MIX", bool "Fast", bool "Spat",
\ float "thSADA_a", float "thSADA_b")
{
DthSAD = default(DthSAD, 150)
DthSADC= default(DthSADC, 150)
BthSAD = default(BthSAD, 70)
BthSADC= default(BthSADC, 70)
_thSADA_a = default(thSADA_a, 0) #disabled
_thSADA_b = default(thSADA_b, 0) #disabled
TR = default(TR, 6)
BLKSize = default(BLKSize, 32)
Overlap = default(Overlap, 16)
Rb = default(Rb, 8)
Pel = default(Pel, 1)
Chroma = default(Chroma, true)
Tm = default(Tm, false)
Falloff = default(Falloff, 0.9)
VDth = default(VDth, 1.5)
Spat = default(Spat, true)
LO = default(LO, 60)
MID = default(MID, 0.57)
HI = default(HI, 127)
MIX = default(MIX, 230)
UV = default(UV, 3)
Fast = default(Fast, false)
Bt= BitLShift(1,input.BitsPerComponent - 8)
preclip = Default(preclip,input)
superclip = Default(superclip,input)
darkclip = Default(darkclip,input)
brightclip = Default(brightclip,input)
super = MSuper(superclip, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superB = MSuper(superclip.merge(input), pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superfilt = MSuper(preclip, pel=pel, hpad = 0, vpad = 0, mt=false,sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm, global=true)
vmulti2 = Mrecalculate(superfilt,multi_vector,thsad=Dthsad,truemotion=tm,tr=tr,blksize=rb,overlap=rb/2,mt=false,chroma=true)
mv_bw1=SelectEvery(multi_vector, tr*2, 0)
mv_fw1=SelectEvery(multi_vector, tr*2, 1)
mv_bw2=SelectEvery(multi_vector, tr*2, 2)
mv_fw2=SelectEvery(multi_vector, tr*2, 3)
dark = spat ? darkclip.MDegrainN(Super, vmulti2, TR, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)) :
\ darkclip.MDegrainN(Super, vmulti2, TR, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).
\ neo_VD(VDTh, 1, 6, 90, UV=UV)
multi_2fixed=Interleave(mv_bw1, mv_fw1, mv_bw2, mv_fw2)
bright = Fast ? input : brightclip.MDegrainN(SuperB, multi_2fixed, 2, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=BthSAD, thSADC=BthSADC)
mask=dark.extractY().levels(lo*bt, mid, hi*bt, 0, mix*bt)
mt_merge(dark, bright, mask, luma=true, u=uv, v=uv)
return last
}
avs-usage:
LSMASHVideoSource("C:\Videos\C0135.mp4", decoder="h264_cuvid")
propclearall()
convertbits(16)
Levels(0, 1, 255*256, 0, 235*256, coring=false)
converttoYUV444()
cd=convertbits(8,dither=-1).convertToYv12()
pre=cd.CCD(13).ex_median("IQMV",Y=3,UV=3).ex_sbr(2)
ClayDTL(tr=7,dthsad=170,dthsadc=170,bthsad=100, thSADA_a=1.3, thSADA_b=50,preclip=pre,superclip=ex_unsharp(1.77,th=1.1,fc=width(),safe=true,UV=1),darkclip=vsdegrainmedian(),brightclip=last,chroma=true)
deblock(planes="UV")
neo_F3KDB(grainY=0,grainC=0,Y=46,mt=true,output_depth=16,range=22,sample_mode=3).mergechroma(last)
Convertbits(10,dither=1)
prefetch(4)
If you test -e.02 build with standard static thSAD values for Clay script - does it produce equal result to pinterf 2.7.45 build ?
Yes, if I just use ClayDTL (-e.02 build) without autoSAD the result is normal as with the 2.7.45 build.
Same ol' test clip (151mb) (https://we.tl/t-96kEtOjpNr)
neo_VD (https://github.com/HomeOfAviSynthPlusEvolution/neo_Vague_Denoiser/releases)
If the quality of denoising with autoSAD (and all the other great features of your version) can get the same or very similar to 2.7.45 build it will be a bomb.
DTL
23rd August 2023, 11:32
"thsad=170,dthsadc=170,bthsad=100,"
Is it also your target settings for static thSADs mode ? To compare auto mode result and attempt to make close to static thSADs mode.
anton_foy
23rd August 2023, 12:44
"thsad=170,dthsadc=170,bthsad=100,"
Is it also your target settings for static thSADs mode ? To compare auto mode result and attempt to make close to static thSADs mode.
Yes I used my original thSAD settings but I also tried with 70-600 thSAD together with autoSAD and I could not see much difference.
DTL
23rd August 2023, 16:10
Well - will try with that values.
"tried with 70-600 thSAD together with autoSAD "
If Auto-thSAD enabled - the old th-values only define the ratio from internally calculated 'main' thSAD and other thSAD2, thSADC, thSADC2 (and used as fail-safe fallback if no valid frames near current present). Main adjustments in auto mode are only thSADA_a (possible typical useful range 1.0f to 2.0f..3.0f) and thSADA_b (possible useful range - about 0.2..0.5 of typically used static thSAD (absolute) value).
So if you provide params like thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), and enable auto mode - the algorithm only calculate back 'Falloff' value from thSAD and thSAD2 and use it to calculate new thSAD2 from current auto-computed 'base' thSAD. So if you start to set thSAD to some very high values - it does not change internally calculated thSAD but only cause lower thSAD2 values computed and used internally (because thSAD/thSAD2 ratio become very large).
So in 'auto' mode setting only thSAD to some very high values will cause a great decrease of denoising because it will cause very small thSAD2 and usage only few near frames.
If you see not enough denoising in 'auto' mode - the first to try is to set thSADA_a to higher values.
anonymlol
2nd September 2023, 08:44
I have a similar script called GlutenFree (https://github.com/anonymlol/avs-scripts/blob/114d34a8b11e5d609424b319896ae01cdfb6c6b0/GlutenFree.avsi). (based on mandarinka's script (http://forum.doom9.org/showthread.php?p=1541058#post1541058))
Feel free to have a look.
anton_foy
3rd September 2023, 08:40
I have a similar script called GlutenFree (https://github.com/anonymlol/avs-scripts/blob/114d34a8b11e5d609424b319896ae01cdfb6c6b0/GlutenFree.avsi). (based on mandarinka's script (http://forum.doom9.org/showthread.php?p=1541058#post1541058))
Feel free to have a look.
Cool thanks! Seems that mandarinka's script touches more in bright areas than dark, Clay is opposite but must give them a try :)
anton_foy
18th September 2023, 22:34
@Anonymlol I tried it and it is good but even if I lowered lut to 2 it is stil not enough denoising. Perhaps mdegrain2 is not enough.
DTL
21st September 2023, 12:14
I am back from vacation to work and trying to test the script with auto-thSAD. I was able to run only the simplified version because it uses many external functions.
Current tested script:
LoadPlugin("mvtools2.dll")
LoadPlugin("masktools2.dll")
LoadPlugin("ffms2.dll")
LoadPlugin("LSMASHSource.dll")
LoadPlugin("vsdegrainmedian.dll")
#LoadVirtualDubPLugin("ccd_64bit.vdf", "CCD") - returns error 0x7e
function clayDTL(clip Input, clip "Preclip", clip "Superclip", clip "Darkclip", clip "Brightclip", int "DthSAD", int "DthSADC",
\ int "BthSAD", int "BthSADC", int "TR", int "BLKSize", int "Rb", int "Overlap", int "Pel", bool "Chroma",
\ float "VDTh", bool "TM", float "Falloff", int "UV", int "LO", int "HI", float "MID", int "MIX", bool "Fast", bool "Spat",
\ float "thSADA_a", float "thSADA_b")
{
DthSAD = default(DthSAD, 150)
DthSADC= default(DthSADC, 150)
BthSAD = default(BthSAD, 70)
BthSADC= default(BthSADC, 70)
_thSADA_a = default(thSADA_a, 0) #disabled
_thSADA_b = default(thSADA_b, 0) #disabled
TR = default(TR, 6)
BLKSize = default(BLKSize, 32)
Overlap = default(Overlap, 16)
Rb = default(Rb, 8)
Pel = default(Pel, 1)
Chroma = default(Chroma, true)
Tm = default(Tm, false)
Falloff = default(Falloff, 0.9)
VDth = default(VDth, 1.5)
Spat = default(Spat, true)
LO = default(LO, 60)
MID = default(MID, 0.57)
HI = default(HI, 127)
MIX = default(MIX, 230)
UV = default(UV, 3)
Fast = default(Fast, false)
Bt= BitLShift(1,input.BitsPerComponent - 8)
preclip = Default(preclip,input)
superclip = Default(superclip,input)
darkclip = Default(darkclip,input)
brightclip = Default(brightclip,input)
super = MSuper(superclip, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superB = MSuper(superclip.merge(input), pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superfilt = MSuper(preclip, pel=pel, hpad = 0, vpad = 0, mt=false,sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm, global=true)
vmulti2 = Mrecalculate(superfilt,multi_vector,thsad=Dthsad,truemotion=tm,tr=tr,blksize=rb,overlap=rb/2,mt=false,chroma=true)
mv_bw1=SelectEvery(multi_vector, tr*2, 0)
mv_fw1=SelectEvery(multi_vector, tr*2, 1)
mv_bw2=SelectEvery(multi_vector, tr*2, 2)
mv_fw2=SelectEvery(multi_vector, tr*2, 3)
dark = spat ? darkclip.MDegrainN(Super, vmulti2, TR, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)) :
\ darkclip.MDegrainN(Super, vmulti2, TR, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).
\ neo_VD(VDTh, 1, 6, 90, UV=UV)
multi_2fixed=Interleave(mv_bw1, mv_fw1, mv_bw2, mv_fw2)
bright = Fast ? input : brightclip.MDegrainN(SuperB, multi_2fixed, 2, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=BthSAD, thSADC=BthSADC)
mask=dark.extractY().levels(lo*bt, mid, hi*bt, 0, mix*bt)
mt_merge(dark, bright, mask, luma=true, u=uv, v=uv)
return last
}
LSMASHVideoSource("C0135.mp4")
#FFmpegSource2("C0135.mp4")
Crop(700, 540, 1000, 640)
propclearall()
convertbits(16)
Levels(0, 1, 255*256, 0, 235*256, coring=false)
converttoYUV444()
cd=convertbits(8,dither=-1).convertToYv12()
pre=cd #.CCD(13).ex_median("IQMV",Y=3,UV=3).ex_sbr(2)
sup01=last # ex_unsharp(1.77,th=1.1,fc=width(),safe=true,UV=1)
staticthsad=ClayDTL(tr=7,dthsad=170,dthsadc=170,bthsad=100, thSADA_a=0, thSADA_b=0,preclip=pre,superclip=sup01,darkclip=vsdegrainmedian(),brightclip=last,chroma=true)
autothsad=ClayDTL(tr=7,dthsad=17,dthsadc=17,bthsad=10, thSADA_a=1.3, thSADA_b=50,preclip=pre,superclip=sup01,darkclip=vsdegrainmedian(),brightclip=last,chroma=true)
Interleave(last.Subtitle("src"), staticthsad.Subtitle("static"), autothsad.Subtitle("auto"))
Convertbits(8,dither=1)
Prefetch(4)
It looks working close between static and auto modes. To show that auto working I cut 0 from dthsad,dthsadc,bthsad params in a call with auto enabled.
Function clayDTL() used unchanged as it uses only mvtools and masktools external plugins .dlls and neo_VD() plugin not called with the script calling params (spat=true as default).
The still not found functions:
CCD(13).
ex_median("IQMV",Y=3,UV=3).ex_sbr(2)
ex_unsharp(1.77,th=1.1,fc=width(),safe=true,UV=1)
CCD is a virtualdub plugin only ? Downloaded from http://acobw.narod.ru/ version x64 returns error at load 0x7e. Also ex_* are Dogway functions from some libraries scripts ? As I use only manual loading of plugins and not use external functions libraries I do not have all required functions libraries installed and do not have experience where and how to install (I assume it is installed in some auto-load folders for AVS+ ?). So to test script with auto-loading of plugins and script functions libraries can you provide some archived form of all required plugins and functions scripts libraries with paths to install (maybe archived from drive C:\ root with paths ?) ? Or a description how to install all required functions libraries to the clean AVS+ installation only.
Also my development system does not have NVIDIA hardware h.264 decoder so I can run LSMASHVideoSource in software decode mode only. I hope it does not make a difference and ffmpegsource also working good at my system.
kedautinh12
21st September 2023, 14:42
CCD
https://github.com/Dogway/Avisynth-Scripts/blob/9b0dcf5ba9e115cfc63e56f7b7dfc5b9d90bf15b/EX%20mods/DeblockPack.avsi#L198
ex_median
https://github.com/Dogway/Avisynth-Scripts/blob/9b0dcf5ba9e115cfc63e56f7b7dfc5b9d90bf15b/ExTools.avsi#L2452C1-L2452C1
ex_sbr
https://github.com/Dogway/Avisynth-Scripts/blob/9b0dcf5ba9e115cfc63e56f7b7dfc5b9d90bf15b/SMDegrain/SMDegrain.avsi#L796
ex_unsharp
https://github.com/Dogway/Avisynth-Scripts/blob/9b0dcf5ba9e115cfc63e56f7b7dfc5b9d90bf15b/MIX%20mods/SharpenersPack.avsi#L518C3-L518C3
DTL
21st September 2023, 15:20
Thank you - with importing that .avsi files and adding RgTools.dll it starts to work with all functions. Now with full 'pre' clip preparation I see it really not reach required denoise levels in 'auto' mode. Will look in debugger now.
After looking into debug:
After pre=cd.CCD(13).ex_median("IQMV",Y=3,UV=3).ex_sbr(2) the prefiltered clip gives very low average SAD - about 57 for 1 frame (after 0), without prefiltering it is about 180. So default static thSAD about 170 (for dark clip) is really very big for this prefiltered clip. Auto-thSAD simply selects lower thSAD for processing so create lower denoise effect. If you need equal to static 170 thSAD for provided test clip it is autp settings about
thSADA_a=3.5, thSADA_b=50
Though both static thSAD=170 and thSADA_a=3.5, thSADA_b=50 is too high th-settings and may cause more bad blocks blending and detail loss. Also too high thSADA_a param setting will close to disable th-variation proportional to nosie level and will be close to simply too high static thSAD setting.
So with such prefiltering settings you can start with auto settings of thSADA_a=3.5, thSADA_b=50 and tune thSADA_a slowly to lower values looking for still enough denoise with details saving balance. And try to check with another clip with different noise level if auto feature will track threshold better in compare with manual thSAD adjusting.
I start to see some difference in dark parts between static and auto-thSAD only with thSADA_a about 2.7 (with thSADA_b=50).
Test script with prefiltering:
LoadPlugin("mvtools2.dll")
LoadPlugin("masktools2.dll")
LoadPlugin("ffms2.dll")
LoadPlugin("LSMASHSource.dll")
LoadPlugin("vsdegrainmedian.dll")
LoadPlugin("RgTools.dll")
Import("DeblockPack.avsi")
Import("ExTools.avsi")
Import("SMDegrain.avsi")
Import("SharpenersPack.avsi")
function clayDTL(clip Input, clip "Preclip", clip "Superclip", clip "Darkclip", clip "Brightclip", int "DthSAD", int "DthSADC",
\ int "BthSAD", int "BthSADC", int "TR", int "BLKSize", int "Rb", int "Overlap", int "Pel", bool "Chroma",
\ float "VDTh", bool "TM", float "Falloff", int "UV", int "LO", int "HI", float "MID", int "MIX", bool "Fast", bool "Spat",
\ float "thSADA_a", float "thSADA_b")
{
DthSAD = default(DthSAD, 150)
DthSADC= default(DthSADC, 150)
BthSAD = default(BthSAD, 70)
BthSADC= default(BthSADC, 70)
_thSADA_a = default(thSADA_a, 0) #disabled
_thSADA_b = default(thSADA_b, 0) #disabled
TR = default(TR, 6)
BLKSize = default(BLKSize, 32)
Overlap = default(Overlap, 16)
Rb = default(Rb, 8)
Pel = default(Pel, 1)
Chroma = default(Chroma, true)
Tm = default(Tm, false)
Falloff = default(Falloff, 0.9)
VDth = default(VDth, 1.5)
Spat = default(Spat, true)
LO = default(LO, 60)
MID = default(MID, 0.57)
HI = default(HI, 127)
MIX = default(MIX, 230)
UV = default(UV, 3)
Fast = default(Fast, false)
Bt= BitLShift(1,input.BitsPerComponent - 8)
preclip = Default(preclip,input)
superclip = Default(superclip,input)
darkclip = Default(darkclip,input)
brightclip = Default(brightclip,input)
super = MSuper(superclip, pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superB = MSuper(superclip.merge(input), pel=pel, hpad = 0, vpad = 0, chroma=chroma, mt=false, levels=1, sharp=1)
superfilt = MSuper(preclip, pel=pel, hpad = 0, vpad = 0, mt=false,sharp=1)
Multi_Vector = Superfilt.MAnalyse(Multi=True, Delta=tr, BLKSize=BLKSize, Overlap=Overlap, Chroma=Chroma, truemotion=tm, global=true)
vmulti2 = Mrecalculate(superfilt,multi_vector,thsad=Dthsad,truemotion=tm,tr=tr,blksize=rb,overlap=rb/2,mt=false,chroma=true)
mv_bw1=SelectEvery(multi_vector, tr*2, 0)
mv_fw1=SelectEvery(multi_vector, tr*2, 1)
mv_bw2=SelectEvery(multi_vector, tr*2, 2)
mv_fw2=SelectEvery(multi_vector, tr*2, 3)
dark = spat ? darkclip.MDegrainN(Super, vmulti2, TR, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)) :
\ darkclip.MDegrainN(Super, vmulti2, TR, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=DthSAD, thSAD2=Int(DthSAD*Falloff), thSADC=DthSADC, thSADC2=Int(DthSADC*Falloff)).
\ neo_VD(VDTh, 1, 6, 90, UV=UV)
multi_2fixed=Interleave(mv_bw1, mv_fw1, mv_bw2, mv_fw2)
bright = Fast ? input : brightclip.MDegrainN(SuperB, multi_2fixed, 2, thSADA_a=_thSADA_a, thSADA_b=_thSADA_b, thSAD=BthSAD, thSADC=BthSADC)
mask=dark.extractY().levels(lo*bt, mid, hi*bt, 0, mix*bt)
mt_merge(dark, bright, mask, luma=true, u=uv, v=uv)
return last
}
LSMASHVideoSource("C0135.mp4")
#FFmpegSource2("C0135.mp4")
Crop(700, 540, 1000, 640)
propclearall()
convertbits(16)
Levels(0, 1, 255*256, 0, 235*256, coring=false)
converttoYUV444()
cd=convertbits(8,dither=-1).convertToYv12()
pre=cd.CCD(13).ex_median("IQMV",Y=3,UV=3).ex_sbr(2)
sup01=ex_unsharp(1.77,th=1.1,fc=width(),safe=true,UV=1)
staticthsad=ClayDTL(tr=7,dthsad=170,dthsadc=170,bthsad=100, thSADA_a=0, thSADA_b=0,preclip=pre,superclip=sup01,darkclip=vsdegrainmedian(),brightclip=last,chroma=true)
autothsad=ClayDTL(tr=7,dthsad=1700,dthsadc=1700,bthsad=1000, thSADA_a=2.7, thSADA_b=50,preclip=pre,superclip=sup01,darkclip=vsdegrainmedian(),brightclip=last,chroma=true)
Interleave(last.Subtitle("src"), staticthsad.Subtitle("static"), autothsad.Subtitle("auto"))
Convertbits(8,dither=1)
Prefetch(4)
Also I see with auto-thSAD enabled the thSADX values better to keep in range 100 or higher - setting to 17 looks like cause additional computing issues. So better to keep thSADX values as usual.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.