Log in

View Full Version : adaptive temporal degrain using MVTools (or similar)?


bennynihon
8th August 2014, 02:34
I'm trying to archive my Blu-ray collection and am struggling to find a nice "one script fits all" approach to degraining some of my movies. Right now I use MDegrain2 like below

bs = 16
super = MSuper(pel=2, sharp=1)
bvec2 = MAnalyse(super, isb = true, delta = 2, blksize=bs, overlap=bs/2)
bvec1 = MAnalyse(super, isb = true, delta = 1, blksize=bs, overlap=bs/2)
fvec1 = MAnalyse(super, isb = false, delta = 1, blksize=bs, overlap=bs/2)
fvec2 = MAnalyse(super, isb = false, delta = 2, blksize=bs, overlap=bs/2)
MDegrain2(super,bvec1,fvec1,bvec2,fvec2,thSAD=400)

the problem with the above, is that the default value of 400 for thSAD is far too strong for many clips leading to too much blocking/banding when encoding with x264. I've tried lowering it to 100 which helps, but then this value is not strong enough for movies like Black Swan which have tons of grain. Is there no way to have the strength of the degraining applied adaptively depending on how much grain is present? For movies with a ton of grain in the source, strong degraining will be applied. For movies with a small amount of grain, weak or no degraining will be applied. Thanks for any suggestions

colours
8th August 2014, 09:23
First off, "grain" is not a very precisely defined term. It would, however, not be difficult to make a script to very roughly approximate how much noise there is in a source. After which you'd still have to figure out how to adjust thsad based on the amount of noise, but that's the easy part.

But! Given that your main complaint is regarding the banding and blocking…

There are specifically modified denoising plug-ins allowing 16-bit output (I called them “mod16”), currently dfttest, MDegrain1, MDegrain2 and MDegrain3. They are included in the Dither package and can safely replace the regular versions, when up-to-date. Use the named parameter lsb=true to enable 16 bit output. Then, MSB is stacked on top of the LSB.

feisty2
8th August 2014, 10:42
you can increase aqstrength in x264 to give more bitrates to flat areas

bennynihon
8th August 2014, 16:39
actually I don't have any problem with banding as I already apply 16-bit grain and dither down to 8-bit prior to encoding, using the dither plugin (and encode with aq-mode=3 which is a huge help). My problem now is with sources which already contain a great deal of grain, such as Black Swan or 300. The encoded files are too large to my liking due to all that grain in the source. So for those movies I'd like to degrain prior to encoding, which I do with MDegrain2 from mvtools. The problem is that I have to manually decide before hand whether a movie has too much grain or not, and if it does how strongly should I degrain it? For movies with too little grain that make themselves susceptible to banding, I need to add some grain as I mention above but then again just how much is enough? And all of these things may vary scene to scene within a movie.

Point is, there's an ideal amount of grain that has just enough to avoid banding when encoding and not enough to blow up the encoded file size. And an Avisynth script is going to have a much easier time identifying that on a frame by frame basis, then I ever could manually determining just how much grain to add or remove. I may have to crack open the mvtools and dither source to hack something together to add the option of a target amount of grain.

DeathAngelBR
8th August 2014, 23:12
You could try fft3dfilter or fft3dgpu AFTER mdegrain, like this:

fft3dfilter(sigma=2.0,sigma2=1.0,sigma3=0.1,sigma4=0.1,bw=16,bh=16,ow=8,oh=8,bt=3,wintype=1)
or
fft3dgpu(precision=2,sigma=2.0,sigma2=1.0,sigma3=0.1,sigma4=0.1,bw=16,bh=16,ow=8,oh=8,bt=3,wintype=1)

This supposedly removes some of the annoying grain (sigma and sigma2) without killing details (sigma3 and sigma4).

Then use gradfun3 from dither package to recude banding.

foxyshadis
9th August 2014, 01:49
Any decide-for-you script is going to be inherently difficult. You might be interested in a lightweight script from Didée (https://forum.doom9.org/showthread.php?p=1503898#post1503898), which will be much faster for both cleaner and grainier sources, and you can more easily add in slower degraining if too much is left. There's also the GrainOptimizer plugin that's supposed to make grain more amenable to compression.

As for how, well, you can chop a video up into small pieces and compare how large it is with and without, and adjust the value based on that, or someone might be able to make some script wizardry that analyzes the output of some fast denoiser and applies the slow denoiser based on that. I don't know of anyone who's successfully automated the process yet, though.

bennynihon
10th August 2014, 01:40
I've come up with something that seems to do a pretty good job, all things considered.

# Source
FFVideoSource("video.mkv")

# Crop
Crop(0,140,0,-140) # 1920x800

# Masks
vLumaMask=mt_binarize(threshold=64, upper=true).grayscale().BilinearResize((width/16)*2, (height/16)*2).BilinearResize(width,height).mt_binarize(threshold=254)
vEdgeMask=mt_edge(mode="prewitt",thy1=0,thy2=16).grayscale().mt_binarize(threshold=16, upper=true).BilinearResize((width/16)*2, (height/16)*2).BilinearResize(width,height).mt_binarize(threshold=254)
vGrainMask=mt_logic(vLumaMask,vEdgeMask,mode="and")
vDegrainMask=vGrainMask.mt_invert()

# Degrain
bs = 16
super = MSuper(pel=2, sharp=1)
bvec2 = MAnalyse(super, isb = true, delta = 2, blksize=bs, overlap=bs/2)
bvec1 = MAnalyse(super, isb = true, delta = 1, blksize=bs, overlap=bs/2)
fvec1 = MAnalyse(super, isb = false, delta = 1, blksize=bs, overlap=bs/2)
fvec2 = MAnalyse(super, isb = false, delta = 2, blksize=bs, overlap=bs/2)
vClean=MDegrain2(super,bvec1,fvec1,bvec2,fvec2,thSAD=400)
mt_merge(vClean,vDegrainMask, u=2, v=2)

# Dither
Dither_convert_8_to_16()
vGrain=Dither_add_grain16(var=0.6,uvar=0,lsb_in=true)
Dither_merge16_8(vGrain, vGrainMask, u=2, v=2)

# Output
DitherPost(mode=3)

Basically I create two masks, one that I use for Degraining, and another to add 16-bit grain+dither. For the grain mask, it essentially allows grain to be added to portions of each frame that are both dark AND flat (doesn't have complexity). Portions which can be degrained are the inverse of that, those that are light OR not flat (already have complexity).