View Full Version : Attempt at motion compensating dfttest


thewebchat
11th June 2009, 01:56
I was lazy and decided to write a script that motion compensates dfttest and came up with the following hackjob made from bits and pieces of other hacks:


# Motion-compensated dfttest by twc
# Aka: Really Really Really Slow
#
# Requirements:
# dfttest
# MVTools2
#
# Suggested:
# Dither (for stack16 processing)
#
# Description of function parameters:
#
# pp = Clip to calculate vectors from (default input)
# mc = Number of frames in each direction to compensate (default 2, max 5)
# mdg = Run MDeGrain before dfttest (default false)
# mdgSAD = thSAD for MDeGrain (default undefined)
# lsb = stack16 output and processing (default false)
#
# dfttest Y, U, V, sigma, sbsize, sosize, tbsize, and dither are supported.
# Extra dfttest parameters may be passed via dfttest_params.
# MVTools2 pel, thSCD, thSAD, blksize, overlap, dct, search, and
# searchparam are also supported.
#
# sigma is the main control of dfttest strength.
# tbsize should not be set higher than mc * 2 + 1.

function dfttestMC(clip input, clip "pp", int "mc", bool "mdg", bool "Y", bool "U", bool "V", float "sigma", int "sbsize", int "sosize", int "tbsize", int "dither", bool "lsb",
\ string "dfttest_params", int "mdgSAD", int "thSAD", int "thSCD1", int "thSCD2", int "pel", int "blksize", int "search", int "searchparam", int "overlap", int "dct")
{
# Set default options. Most external parameters are passed valueless.
mc = default(mc, 2).min(5)
mdg = default(mdg, false)
lsb = default(lsb, false)
Y = default(Y, true)
U = default(U, true)
V = default(V, true)
tbsize = default(tbsize, mc * 2 + 1)
dfttest_params = default(dfttest_params, "")
overlap = default(overlap, 2)

# Set chroma parameters.
chroma = U || V
plane = U && !Y && !V ? 1 : V && !Y && !U ? 2 : chroma && !Y ? 3 : Y && chroma ? 4 : 0

# Prepare supersampled clips.
pp_enabled = defined(pp)
pp_super = pp_enabled ? MSuper(pp, pel=pel, chroma=chroma) : MSuper(input, pel=pel, chroma=chroma)
super = pp_enabled ? input.MSuper(pel=pel, levels=1, chroma=chroma) : pp_super

# Motion vector search.
b5vec = MAnalyse(pp_super, delta=5, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, dct=dct)
b4vec = MAnalyse(pp_super, delta=4, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
b3vec = MAnalyse(pp_super, delta=3, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
b2vec = MAnalyse(pp_super, delta=2, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
b1vec = MAnalyse(pp_super, delta=1, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f1vec = MAnalyse(pp_super, delta=1, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f2vec = MAnalyse(pp_super, delta=2, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f3vec = MAnalyse(pp_super, delta=3, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f4vec = MAnalyse(pp_super, delta=4, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f5vec = MAnalyse(pp_super, delta=5, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)

# Optional MDegrain.
try {
degrained = mc >= 3 && mdg ? MDeGrain3(input, super, b1vec, f1vec, b2vec, f2vec, b3vec, f3vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb=true).DitherPost(mode=6) :
\ mc == 2 && mdg ? MDeGrain2(input, super, b1vec, f1vec, b2vec, f2vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb=true).DitherPost(mode=6) :
\ mdg ? MDeGrain1(input, super, b1vec, f1vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb=true).DitherPost(mode=6) : input
}
catch(err_msg) {
degrained = mc >= 3 && mdg ? MDeGrain3(input, super, b1vec, f1vec, b2vec, f2vec, b3vec, f3vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2) :
\ mc == 2 && mdg ? MDeGrain2(input, super, b1vec, f1vec, b2vec, f2vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2) :
\ mdg ? MDeGrain1(input, super, b1vec, f1vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2) : input
}

# Motion Compensation.
degrained_super = mdg ? MSuper(degrained, pel=pel, levels=1, chroma=chroma) : super
b5clip = MCompensate(degrained, degrained_super, b5vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
b4clip = MCompensate(degrained, degrained_super, b4vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
b3clip = MCompensate(degrained, degrained_super, b3vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
b2clip = MCompensate(degrained, degrained_super, b2vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
b1clip = MCompensate(degrained, degrained_super, b1vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f1clip = MCompensate(degrained, degrained_super, f1vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f2clip = MCompensate(degrained, degrained_super, f2vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f3clip = MCompensate(degrained, degrained_super, f3vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f4clip = MCompensate(degrained, degrained_super, f4vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f5clip = MCompensate(degrained, degrained_super, f5vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)

# Create compensated clip.
interleaved = mc >= 5 ? Interleave(f5clip, f4clip, f3clip, f2clip, f1clip, degrained, b1clip, b2clip, b3clip, b4clip, b5clip) :
\ mc == 4 ? Interleave(f4clip, f3clip, f2clip, f1clip, degrained, b1clip, b2clip, b3clip, b4clip) :
\ mc == 3 ? Interleave(f3clip, f2clip, f1clip, degrained, b1clip, b2clip, b3clip) :
\ mc == 2 ? Interleave(f2clip, f1clip, degrained, b1clip, b2clip) :
\ Interleave(f1clip, degrained, b1clip)

# Perform dfttest. Exception handling required for official dfttest.
try {
filtered = Eval("dfttest(interleaved, Y=Y, U=U, V=V, sigma=sigma, sbsize=sbsize, sosize=sosize, tbsize=tbsize, dither=dither, lsb=lsb" + dfttest_params + ")")
}
catch(err_msg)
{
filtered = Eval("dfttest(interleaved, Y=Y, U=U, V=V, sigma=sigma, sbsize=sbsize, sosize=sosize, tbsize=tbsize, dither=dither" + dfttest_params + ")")
}

return SelectEvery(filtered, mc * 2 + 1, mc)
}



Brief history of versions:

1) Original version. Had a bug regarding the usage of MSuper.
2) Second version. Added support for arbitrary prefilter clips.
3) Third version. Added support for n/s/xyz-file parameters.
4) Current version. Minor optimization in the use of MSuper without prefilters. Minor optimization in the use of motion-estimation and chroma parameters. Cleaned up handling of dfttest parameters.

Limitations:

1) Temporal radius can be no higher than 5 (tbsize=11). This is due to a lack of arrays in Avisynth.
2) Internal MDegrain does not support filtering only U or V planes. If U=true and V=false, the internal MDegrain will be bypassed.
3) Not all MVTools parameters are supported, esp. the MAnalyse truemotion parameters.
4) Depending on the strength and nature of noise, simple MVTools may be more effective.

Usage hints:

1) Prefilter clips are only useful with very heavy grain. Unlike MVTools, sigma must be set according to noise level. Powers of 2 are a good way to start.
2) If structural information is removed from the prefilter clip, it is likely to disappear from the final result.
3) Internal MDegrain is only there in case you want to use both (it is slightly faster due to caching of vector clips). Generally, it should not be used, as it is redundant.
4) Lowering sbsize should reduce the strength of the spatial filter, which is not motion-compensated. sbsize=1/sosize=0 results in a pure temporal denoiser.

Possible improvements:

1) Use GScript to clean up code.
2) Use MRecalculate somewhere.
3) Figure out how to remove dotcrawl with this.

Razorholt
11th June 2009, 06:15
I haven't tested your script (yet) but I know that overlap < 4 introduces blocks - from my own experience anyway.

- Dan

Didée
11th June 2009, 14:27
The usage of MVTools' "super" clip is wrong. You are using the "super" clip from the initial pre-denoising for all instances of MDegrain and MCompensate. Thus the final output contains very much of the pre-denoising. The idea is that the pre-filtering should be fully independent from the main filterchain, and only be used for the motion vector search.
What you need to do is to create new super-clips each time that the base clip in the processing chain has changed.

Like so:


#############################################
# Motion Compensated dfttest #
# Really Really Really Slow #
# #
# For best results, use a mcradius equal to #
# (tbsize-1)/2 #
# #
# MDegrain will also be run if mdg == true #
# #
# mcradius is hardlimited at 5 #
# #
#############################################

function dfttestMC (clip input, bool "Y", bool "U", bool "V", int "ftype", float "sigma", float "sigma2", float "pmin", float "pmax",
\ int "sbsize", int "smode", int "sosize", int "tbsize", int "tmode", int "tosize", int "swin", int "twin", float "sbeta",
\ float "tbeta", bool "zmean", float "f0beta", int "mcradius", bool "mdg", int "pp", int "ppstr", int "thSAD", int "mdgthSAD",
\ int "thSCD1", int "thSCD2", int "blksize", int "pel", int "overlap", int "dct", int "search")
{
o = input

# dfttest-related options
Y = default(Y, true)
U = default(U, true)
V = default(V, true)
ftype = default(ftype, 0)
sigma = default(sigma, 16.0)
sigma2 = default(sigma2, 16.0)
pmin = default(pmin, 0.0)
pmax = default(pmax, 500.0)
sbsize = default(sbsize, 12)
smode = default(smode, 1)
sosize = default(sosize, 9)
tbsize = default(tbsize, 5)
tmode = default(tmode, 0)
tosize = default(tosize, 0)
swin = default(swin, 0)
twin = default(twin, 7)
sbeta = default(sbeta, 2.5)
tbeta = default(tbeta, 2.5)
zmean = default(zmean, true)
f0beta = default(f0beta, 1.0)

# mvtools-related options
mcradius = default(mcradius, 2)
mcradius = (mcradius>5) ? 5 : (mcradius<1) ? 1 : mcradius
mdg = default(mdg, false)
pp = default(pp, 1)
ppstr = default(ppstr, (pp>=2) ? 16 : (pp==1) ? 1 : 9001)
mdgthSAD = default(thSAD, 400)
thSAD = default(thSAD, 10000)
thSCD1 = default(thSCD1, 400)
thSCD2 = default(thSCD2, 130)
blksize = default(blksize, 8)
pel = default(pel, 2)
overlap = default(overlap, 2)
dct = default(dct, 0)
search = default(search, 5)

# Pre-ME denoising
pp = (pp >= 2) ? o.dfttest(sigma=ppstr) : (pp == 1) ? o.DeGrainMedian(mode=ppstr) : o

# MSuper
pp_super = pp.MSuper(pel=pel)

# Motion vector search
b5vec = (mcradius>=5) ?
\ MAnalyse(pp_super,isb=true,search=search,delta=5,overlap=overlap,blksize=blksize,dct=dct) : NOP
b4vec = (mcradius>=4) ?
\ MAnalyse(pp_super,isb=true,search=search,delta=4,overlap=overlap,blksize=blksize,dct=dct) : NOP
b3vec = (mcradius>=3) ?
\ MAnalyse(pp_super,isb=true,search=search,delta=3,overlap=overlap,blksize=blksize,dct=dct) : NOP
b2vec = (mcradius>=2) ?
\ MAnalyse(pp_super,isb=true,search=search,delta=2,overlap=overlap,blksize=blksize,dct=dct) : NOP
b1vec = MAnalyse(super,isb=true,search=search,delta=1,overlap=overlap,blksize=blksize,dct=dct)
f1vec = MAnalyse(super,isb=false,search=search,delta=1,overlap=overlap,blksize=blksize,dct=dct)
f2vec = (mcradius>=2) ?
\ MAnalyse(pp_super,isb=false,search=search,delta=2,overlap=overlap,blksize=blksize,dct=dct) : NOP
f3vec = (mcradius>=3) ?
\ MAnalyse(pp_super,isb=false,search=search,delta=3,overlap=overlap,blksize=blksize,dct=dct) : NOP
f4vec = (mcradius>=4) ?
\ MAnalyse(pp_super,isb=false,search=search,delta=2,overlap=overlap,blksize=blksize,dct=dct) : NOP
f5vec = (mcradius>=5) ?
\ MAnalyse(pp_super,isb=false,search=search,delta=3,overlap=overlap,blksize=blksize,dct=dct) : NOP

# Optional MDegrain
o_super = mdg ? o.MSuper(pel=pel,levels=1) : o
mdegrained = (mcradius>=3 && mdg) ? o.MDegrain3(o_super,b1vec,f1vec,b2vec,f2vec,b3vec,f3vec,thSAD=mdgthSAD,thSCD1=thSCD1,thSCD2=thSCD2) :
\ (mcradius==2 && mdg) ? o.MDegrain2(o_super,b1vec,f1vec,b2vec,f2vec,thSAD=mdgthSAD,thSCD1=thSCD1,thSCD2=thSCD2) :
\ (mdg) ? o.MDegrain1(o_super,b1vec,f1vec,thSAD=mdgthSAD,thSCD1=thSCD1,thSCD2=thSCD2) : o

degrained = (mdg) ? mdegrained : o

# Motion Compensation
degrained_super = degrained.MSuper(pel=pel,levels=1)
b5clip = (mcradius>=5) ?
\ degrained.MCompensate(degrained_super,b5vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2) : NOP
b4clip = (mcradius>=4) ?
\ degrained.MCompensate(degrained_super,b4vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2) : NOP
b3clip = (mcradius>=3) ?
\ degrained.MCompensate(degrained_super,b3vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2) : NOP
b2clip = (mcradius>=2) ?
\ degrained.MCompensate(degrained_super,b2vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2) : NOP
b1clip = degrained.MCompensate(degrained_super,b1vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2)
f1clip = degrained.MCompensate(degrained_super,f1vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2)
f2clip = (mcradius>=2) ?
\ degrained.MCompensate(degrained_super,f2vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2) : NOP
f3clip = (mcradius>=3) ?
\ degrained.MCompensate(degrained_super,f3vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2) : NOP
f4clip = (mcradius>=4) ?
\ degrained.MCompensate(degrained_super,f4vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2) : NOP
f5clip = (mcradius>=5) ?
\ degrained.MCompensate(degrained_super,f5vec,thSAD=thSAD,thSCD1=thSCD1,thSCD2=thSCD2) : NOP

# Create compensated clip
interleaved = (mcradius>=5) ? Interleave(f5clip,f4clip,f3clip,f2clip,f1clip,degrained,b1clip,b2clip,b3clip,b4clip,b5clip) :
\ (mcradius==4) ? Interleave(f4clip,f3clip,f2clip,f1clip,degrained,b1clip,b2clip,b3clip,b4clip) :
\ (mcradius==3) ? Interleave(f3clip,f2clip,f1clip,degrained,b1clip,b2clip,b3clip) :
\ (mcradius==2) ? Interleave(f2clip,f1clip,degrained,b1clip,b2clip) :
\ Interleave(f1clip,degrained,b1clip)

# Perform dfttest
filtered = interleaved.dfttest(Y=Y,U=U,V=V,ftype=ftype,sigma=sigma,sigma2=sigma2,pmin=pmin,pmax=pmax,sbsize=sbsize,smode=smode,sosize=sosize,
\ tbsize=tbsize,tmode=tmode,tosize=tosize,swin=swin,twin=twin,sbeta=sbeta,tbeta=tbeta,zmean=zmean,f0beta=f0beta)

output = filtered.SelectEvery(mcradius*2+1,mcradius)

return(output)
}


You'll (probably) note that the function now gets slower and uses more memory, because the additional super-clips need additional ressources. That's how it is, sorry.

thewebchat
11th June 2009, 15:48
Thank you, Didee. I was wondering why the denoising got stronger every time I increased the sigma for the prepass dfttest. Now that I have fixed the function, I see no difference betwen prepassing with dfttest and degrainmedian and no difference between using mdegrain before dfttest and just using a stronger dfttest, so I have actually saved time thanks to your input. \o/

Edit: Not only have the blocks been fixed, I also noticed that prepassing with Blur().Blur().Blur().Blur() ad nauseam works just as well as dfttest/degrainmedian, saving even more time.

Didée
17th June 2009, 12:12
Think of (football/soccer/basketball/whatever) ... just because you buy the most-expensive players, there's no guarantee that it'll result in a superior team.

The usual stress test (http://www.mediafire.com/download.php?yzy53dbki4o) ...


Edit: Oh, I just got aware that your revised function doesn't use any internal default-pp any more, hence the comparison above isn't fair.

New testfile (http://www.mediafire.com/download.php?fymnq5tmlui), now with three different variants of dfttestMC: a) no pp, b) pp=blur(1.53).blur(1.53), c) pp=fft3dfilter(sigma=5/7/7/4,bt=3).
Note that all 4 filters use the same temporal radius of '2'. Also note that c) uses exactly-the-same prefilter as the simple MDegrain2 that's shown for comparison.

No change in regards to teamplay, though.

thewebchat
17th June 2009, 18:05
I do not know how your fft3d with mdegrain works, but I wrote this as an exercise in pointlessness. The only clip I tested it on was a brief animated clip with no detail + AddGrainC(100,100). It seemed to me that MDegrain hit an upper limit in terms of effectiveness and I could not get it to remove more noise no matter how high I raised thSAD. Of course, I don't actually use this function (would be a waste of time as you demonstrated).

Edit: I took a look at it again. And I suppose if you do mdegrain + deen, you get identical results to dfttest with mc.

tritical
17th June 2009, 20:48
Not saying it is as good as mdegrain, but I just want to show that dfttest isn't quite as crappy as Didée's example shows :)... here (http://bengal.missouri.edu/~kes25c/mcdfttest.avi) is my mc'd dfttest attempt on that clip (uses only dfttest and manalyze/mcompensate from mvtools).

EDIT: Also, if you don't want/like the spatial blurring, use smaller block sizes when applying dfttest to the mc'd clip. See this clip (http://bengal.missouri.edu/~kes25c/mcdfttest2.avi). So in my previous example I did basic mc'd dfttest with these steps:

Use manalyse on dfttest filtered clip to get motion vectors, use those vectors with mcompensate on original noisy clip, then apply dfttest/selectevery on the mc'd clip.

In mcdfttest.avi (the first example) the final dfttest call used smode=1/sbsize=8/sosize=7/tmode=0/tbsize=7. In mcdfttest2.avi I made 4 versions with smode/sosize/sbsize indicated in a subtitle in the upper left. I also trimmed/cropped to match Didée's example. The upper left clip corresponds to using dfttest as a pure temporal denoiser (smode=0/sbsize=1), the lower right clip uses the same settings as my first example (smode=1/sosize=7/sbsize=8). The other two clips use sosize/sbsize settings inbetween those two. All other settings were the same for all 4 clips. Notice how the amount of spatial blurring changes.

Didée
18th June 2009, 12:17
That looks more reasonable! And I'm the one to blame. At first, I didn't think about the result I got yesterday. Just on my way home I started wondering about the result ... since in that^ scene, dfttest should be able to remove the noise even without any motion compensation.

The explanation is: just yesterday I switched from dfttest v1.1 to v1.6, but didn't do any cross-check between them. Big mistake!;) - Having done that, it reveals there's a major difference in behaviour! While v1.1 acted very strong with rather small sigma's, v1.6 behaves more reasonably (and, to me, visually much better than v1.1).

So it seems the main culprit was "sigma" ... I wondered a bit about the default of '16'. While sigma=16 would've been an extremely strong value for dfttest v1.1 (in the default "spatio-temporal" mode it would more or less "destroy" the input...), it is a rather small value for v1.6 (definetly too low for this source).

rkalwaitis
24th July 2009, 23:07
Can the nfile process of dfttest be used somehow in the above script to determine by itself which sigma value to apply for denoising?

Gavino
25th July 2009, 09:42
I originally didn't add them because I was unsure how they worked when unset, but it seems they default to empty strings.
sfile = default(sfile, "")
... etc ...
Actually, there is no need to set any default values inside your function if all you are doing is passing them on to another function (in this case dfttest). That way you don't need to know the internal details of the other function.
User defined script functions (http://avisynth.org/mediawiki/User_defined_script_functions)

A void ('undefined') value can be passed on to another function as one of its optional arguments. This is useful when you want to write a wrapper function that calls another function, preserving the same defaults.

thewebchat
25th July 2009, 19:00
Ah, I did not know that Gavino. That is very helpful.

rkalwaitis
26th July 2009, 06:56
How would I change dfttest so that the nfile function works on everyframe and not on a select few. Am interested to see if it would work well at self determining how much to denoise a frame.

thewebchat
26th July 2009, 14:42
Huh? Isn't the whole point of nfile for *you* to specify where the noise is? Therefore, the only way to make "the nfile function work on every frame" is to write an override for each frame into your nfile.

moviefan
26th July 2009, 17:57
I have just tried out your function encoding the filtered clip with VirtualDub to Lagarith lossless avi, but VD crashes after a couple of frames. Can anyone help me to find out why this happens?

Edit: An approach would be to get up to date with my dfttest version. Tritical's website is down though. Can anyone please upload the v1.6 dll-file?

rkalwaitis
26th July 2009, 20:35
If I overroad each frame, then how would dfttest know via the nfile how much denoising to apply to it? Maybe I stated it incorrectly before. Is there a way to use nfile on each frame instead of a sample from somewhere in the clip. In other words not a sample for the whole movie but the nfile applied frame by frame, which would hopefully ensure the proper amount of denoising throughout the clip and not to much here or not enough there.

thewebchat
26th July 2009, 22:36
moviefan: tritical's site works just fine for me: http://web.missouri.edu/~kes25c/
Old versions of dfttest would indeed cause problems as the parameters have changed.

rkalwaitis: Sorry, but I'm not sure I can answer that. That sounds like a question to ask in the main dfttest thread.

rkalwaitis
27th July 2009, 06:42
thanks thewebchat, I like your script. Im trying it out now and so far seems to be doing a fine job.

moviefan
27th July 2009, 12:27
@thewebchat: You're right. It's up again and now working for me too. Thanks!

thewebchat
25th June 2010, 05:48
It has come to my attention that tritical has updated dfttest, so the previous script is no longer all-encompassing. Since tritical keeps adding new parameters every release, I have decided to limit support in the script to the most important (sigma, sbsize, sosize, tbsize, dither), with additional features addable with the "dfttest_opts" parameter. This sets the required version of dfttest at v1.8+ and should suffice for the foreseeable future.

elguaxo
9th July 2010, 01:43
I'm trying this filter for the first time. The source is a Bluray and I have problems when using pp. It crashes after aprox. 65 consecutive frames. I get the crash when doing an actual encode (x264) or just previewing with VirtualDub. I tried increasing SetMemoryMax, but it still crashes after the same amount of frames.

This is the script:

denoised=MinBlur(2).FluxSmoothT() #MinBlur from MCBob
dfttestMC(mc=1,sigma=8,pp=denoised)

It works fine if I don't use pp. Any hints?


BTW, I'm still using AviSynth 2.5.7, so I had to change mc = default(mc, 2).min(5) to mc = default(mc, 2)

thewebchat
9th July 2010, 02:00
This sounds like a bug in FluxSmoothT (ancient filter), perhaps a memory leak or cache error.

I notice that you are using sigma=8, which is not a very strong setting. In this case, you could opt for leaving out the prefilter clip altogether. If you should insist on using one, I would recommend trying another filter. I have had good results from the internal Blur filter for speed-oriented scenarios. The most popular choice appears to be FFT3DFilter.

elguaxo
9th July 2010, 02:37
This sounds like a bug in FluxSmoothT (ancient filter), perhaps a memory leak or cache error.


That seems to be the problem. pp works fine with other filters! :thanks:

thewebchat
9th July 2010, 02:45
That seems to be the problem. pp works fine with other filters! :thanks:

Good to hear. Let me know what you think of the results -- in my own testing, it has always come up as a tie or loss against plain MVTools.

Bi11
10th July 2010, 03:10
You should use more accurate MAnaylse settings for delta>2 to reduce ghosting artifacts in compensated frames. Something like:
MAnalyse(delta=3, blksize=4, overlap=2, truemotion=false, search=5, searchparam=8))
delta=2 could use accurate settings as well, like:
MAnalyse(delta=2, blksize=8, overlap=4, truemotion=false, searchparam=4))
More details could be retained at delta=1 with blksize=16, overlap=8, truemotion=false

thewebchat
10th July 2010, 16:30
You should use more accurate MAnaylse settings for delta>2 to reduce ghosting artifacts in compensated frames. Something like:
MAnalyse(delta=3, blksize=4, overlap=2, truemotion=false, search=5, searchparam=8))
delta=2 could use accurate settings as well, like:
MAnalyse(delta=2, blksize=8, overlap=4, truemotion=false, searchparam=4))
More details could be retained at delta=1 with blksize=16, overlap=8, truemotion=false

You should really justify why different settings are needed for each frame, particularly those specific settings. dfttest does not perform a blind average of blocks like MDeGrain does, so increasing compensation accuracy has limited overall effect. In fact, compensation beyond 1 frame may be unnecessary.

Mr.Sandman
29th November 2011, 17:47
hello. :) new(bie) in the forum.
I woul like to know if its possible to add custom dfttest parameters into your script? i would like to change swin twin to 7, and to change smode and tmode = 0... is it possible???

thanks :P

thewebchat
24th May 2012, 07:05
Script now works with both FSLG's 16-bit dfttest and original.

Mystery Keeper
17th January 2013, 18:20
#================================================
c=separatefields()
a=c.selecteven()
b=c.selectodd()

prea=dfttest(a, sigma=0.5, sbsize=11, smode=0, dither=1)
preb=dfttest(b, sigma=0.5, sbsize=11, smode=0, dither=1)

string ssxstring = """ "0.0:1.0 1.0:1.0" """
string ssystring = """ "0.0:1.0 1.0:1.0" """
string sststring = """ "0.0:1.0 0.01:0.0 1.0:0.0" """

a=a.dfttestMC(pp=prea, mc=3, sbsize=1, sosize=0, pel=4, blksize=4, search=5, searchparam=64, dfttest_params=", smode=0, ftype=2, ssx=" + ssxstring + ", ssy=" + ssystring + ", sst=" + sststring)
b=b.dfttestMC(pp=preb, mc=3, sbsize=1, sosize=0, pel=4, blksize=4, search=5, searchparam=64, dfttest_params=", smode=0, ftype=2, ssx=" + ssxstring + ", ssy=" + ssystring + ", sst=" + sststring)

interleave(a,b)
weave()
#================================================

QTGMC(Preset="Placebo", EdiMode="NNEDI3", ChromaEdi="", EdiQual=2, NNeurons=4, NNSize=3, NoiseProcess=0, SubPel=4, SubPelInterp=2, TrueMotion=true, Precise=true, ChromaMotion=true, GlobalMotion=true, search=5, searchparam=64).SelectEven()

Awesome result, but causes ghosting artifacts on some scenes.

upd: Mentioned artifacts are not ghosting. I think they are glitches in MVTools. I've read MVTools documentation, and there's function MFlow, which is said to be more suitable for denoising than MCompensate and doesn't produce blocking artifacts. Also, how should I tune dfttestMC and what preprocess clip should I use to get more accurate compensation without these artifacts?

upd2: Tried with MFlow. Result was horrible. Since I'm playing with "searchparam", my next attempt is adding "badrange".

Mystery Keeper
20th January 2013, 01:39
Guys, please help me with this one. I really really want to use this script safely. On most frames it produces the closest to perfection result I can get. But on some it spawns block artifacts and rarely destroys the frame completely. I'm pretty sure artifacts come from MVTools errors.

Is there a way to eliminate these errors and make the script safe? Is there a way to detect spawn artifacts and apply a fallback solution? Fine tuning for each source is a bad option. The script is slow. Encodes take days. I can not encode, check each frame for artifacts and try again and again every time.

StainlessS
26th January 2013, 22:23
You could try ClipClop().
http://forum.doom9.org/showthread.php?t=162266&highlight=clipclop

Use your default settings and save to eg UT_Video lossless, and then for bad frames replace with either the original frame, or an alternatively
processed frame. ClipClop can be used with 1 source clip and up to 255 replacement clips, where you can replace individual frames or ranges
of frames. Audio always comes from source clip.
It will be tedious, but not as tedious as trying to find a single setting that works all of the time. Good luck.

Overdrive80
2nd October 2014, 20:27
Sorry for rebirth, I had modified script for inserting lsb_in parameter...

# Motion-compensated dfttest by twc
# Aka: Really Really Really Slow
#
# Requirements:
# dfttest
# MVTools2
#
# Suggested:
# Dither (for stack16 processing)
#
# Description of function parameters:
#
# pp = Clip to calculate vectors from (default input)
# mc = Number of frames in each direction to compensate (default 2, max 5)
# mdg = Run MDeGrain before dfttest (default false)
# mdgSAD = thSAD for MDeGrain (default undefined)
# lsb = stack16 output and processing (default false)
#
# dfttest Y, U, V, sigma, sbsize, sosize, tbsize, and dither are supported.
# Extra dfttest parameters may be passed via dfttest_params.
# MVTools2 pel, thSCD, thSAD, blksize, overlap, dct, search, and
# searchparam are also supported.
#
# sigma is the main control of dfttest strength.
# tbsize should not be set higher than mc * 2 + 1.

function dfttestMC(clip input, clip "pp", int "mc", bool "mdg", bool "Y", bool "U", bool "V", float "sigma", int "sbsize", int "sosize", int "tbsize", int "dither", bool "lsb_in", bool "lsb",
\ string "dfttest_params", int "mdgSAD", int "thSAD", int "thSCD1", int "thSCD2", int "pel", int "blksize", int "search", int "searchparam", int "overlap", int "dct")
{
# Set default options. Most external parameters are passed valueless.
mc = default(mc, 2).min(5)
mdg = default(mdg, false)
lsb_in = default (lsb_in, false)
lsb = default(lsb, false)
Y = default(Y, true)
U = default(U, true)
V = default(V, true)
tbsize = default(tbsize, mc * 2 + 1)
dfttest_params = default(dfttest_params, "")
overlap = default(overlap, 2)

# Set chroma parameters.
chroma = U || V
plane = U && !Y && !V ? 1 : V && !Y && !U ? 2 : chroma && !Y ? 3 : Y && chroma ? 4 : 0

# Prepare supersampled clips.
pp_enabled = defined(pp)
pp_super = pp_enabled ? MSuper(pp, pel=pel, chroma=chroma) : MSuper(input, pel=pel, chroma=chroma)
super = pp_enabled ? input.MSuper(pel=pel, levels=1, chroma=chroma) : pp_super

# Motion vector search.
b5vec = MAnalyse(pp_super, delta=5, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, dct=dct)
b4vec = MAnalyse(pp_super, delta=4, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
b3vec = MAnalyse(pp_super, delta=3, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
b2vec = MAnalyse(pp_super, delta=2, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
b1vec = MAnalyse(pp_super, delta=1, isb=true, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f1vec = MAnalyse(pp_super, delta=1, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f2vec = MAnalyse(pp_super, delta=2, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f3vec = MAnalyse(pp_super, delta=3, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f4vec = MAnalyse(pp_super, delta=4, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)
f5vec = MAnalyse(pp_super, delta=5, chroma=chroma, search=search, searchparam=searchparam, overlap=overlap, blksize=blksize, dct=dct)

# Optional MDegrain.
try {
degrained = mc >= 3 && mdg ? MDeGrain3(input, super, b1vec, f1vec, b2vec, f2vec, b3vec, f3vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb=true).DitherPost(mode=6) :
\ mc >= 3 && mdg && lsb_in == true ? MDeGrain3(input, super, b1vec, f1vec, b2vec, f2vec, b3vec, f3vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb_in=true).DitherPost(mode=6) :
\ mc == 2 && mdg ? MDeGrain2(input, super, b1vec, f1vec, b2vec, f2vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb=true).DitherPost(mode=6) :
\ mc == 2 && mdg && lsb_in == true ? MDeGrain2(input, super, b1vec, f1vec, b2vec, f2vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb_in=true).DitherPost(mode=6) :
\ mdg ? MDeGrain1(input, super, b1vec, f1vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb=true).DitherPost(mode=6) :
\ mdg && lsb_in == true ? MDeGrain1(input, super, b1vec, f1vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb_in=true).DitherPost(mode=6) : input

}
catch(err_msg) {
degrained = mc >= 3 && mdg ? MDeGrain3(input, super, b1vec, f1vec, b2vec, f2vec, b3vec, f3vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2) :
\ mc >= 3 && mdg && lsb_in == true ? MDeGrain3(input, super, b1vec, f1vec, b2vec, f2vec, b3vec, f3vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb_in= true) :
\ mc == 2 && mdg ? MDeGrain2(input, super, b1vec, f1vec, b2vec, f2vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2) :
\ mc == 2 && mdg && lsb_in == true ? MDeGrain2(input, super, b1vec, f1vec, b2vec, f2vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb_in= true) :
\ mdg ? MDeGrain1(input, super, b1vec, f1vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2) :
\ mdg && lsb_in == true ? MDeGrain1(input, super, b1vec, f1vec, thSAD=mdgSAD, plane=plane, thSCD1=thSCD1, thSCD2=thSCD2, lsb_in = true) : input
}

# Motion Compensation.
degrained_super = mdg ? MSuper(degrained, pel=pel, levels=1, chroma=chroma) : super
b5clip = MCompensate(degrained, degrained_super, b5vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
b4clip = MCompensate(degrained, degrained_super, b4vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
b3clip = MCompensate(degrained, degrained_super, b3vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
b2clip = MCompensate(degrained, degrained_super, b2vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
b1clip = MCompensate(degrained, degrained_super, b1vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f1clip = MCompensate(degrained, degrained_super, f1vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f2clip = MCompensate(degrained, degrained_super, f2vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f3clip = MCompensate(degrained, degrained_super, f3vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f4clip = MCompensate(degrained, degrained_super, f4vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)
f5clip = MCompensate(degrained, degrained_super, f5vec, thSAD=thSAD, thSCD1=thSCD1, thSCD2=thSCD2)

# Create compensated clip.
interleaved = mc >= 5 ? Interleave(f5clip, f4clip, f3clip, f2clip, f1clip, degrained, b1clip, b2clip, b3clip, b4clip, b5clip) :
\ mc == 4 ? Interleave(f4clip, f3clip, f2clip, f1clip, degrained, b1clip, b2clip, b3clip, b4clip) :
\ mc == 3 ? Interleave(f3clip, f2clip, f1clip, degrained, b1clip, b2clip, b3clip) :
\ mc == 2 ? Interleave(f2clip, f1clip, degrained, b1clip, b2clip) :
\ Interleave(f1clip, degrained, b1clip)

# Perform dfttest. Exception handling required for official dfttest.
try {
filtered = Eval("dfttest(interleaved, Y=Y, U=U, V=V, sigma=sigma, sbsize=sbsize, sosize=sosize, tbsize=tbsize, dither=dither, lsb_in=lsb_in, lsb=lsb" + dfttest_params + ")")
}
catch(err_msg)
{
filtered = Eval("dfttest(interleaved, Y=Y, U=U, V=V, sigma=sigma, sbsize=sbsize, sosize=sosize, tbsize=tbsize, dither=dither" + dfttest_params + ")")
}

return SelectEvery(filtered, mc * 2 + 1, mc)
}

BakaProxy
24th February 2015, 20:28
Made an update for dfttestmc https://github.com/BakaProxy/Avisynth-shenanigans/blob/master/dfttestMC.avsi .

Added:

-Recalculate
-(proper) 16 bit input handling
-dither_luma_rebuild
-some masking to prevent 16 bit data loss from 8 bit Mdegrain and Mcompensate

AzraelNewtype
26th February 2015, 11:54
Made an update for dfttestmc https://github.com/BakaProxy/Avisynth-shenanigans/blob/master/dfttestMC.avsi .

Added:

-Recalculate
-(proper) 16 bit input handling
-dither_luma_rebuild
-some masking to prevent 16 bit data loss from 8 bit Mdegrain and Mcompensate

So, uh... how do you load it? It's absolutely not a regular avisynth function with that if and try/catch block in there, but GImport is throwing me a different error about trying to divide a variable by an integer not being allowed since they aren't both integers.

StainlessS
26th February 2015, 15:59
At a guess I'de say that it might be intended to be run under avs+ (which implements GScript functionality I believe).

BakaProxy
27th February 2015, 10:19
Yes this was made under avs+, but I'll make a version that doesn't require it.

real.finder
4th June 2015, 19:19
update to make BakaProxy edition work with avs again

https://pastebin.com/j4LhHq46