Simple MDegrain Mod — SMDegrain()
Abstract
Author: Dogway
Version: v4.6.0d
Download: https://github.com/Dogway/Avisynth-Scripts/SMDegrain
Discussion: https://forum.doom9.org/showthread.php?t=182881
Category: Temporal Denoiser
Date: 30-March-2024
Table of contents
Dependencies ▲
Required
Optional
- LSFplus
| (v6.1 or higher) | (for Contrasharp>0) |
- SharpenersPack
| (v5.2 or higher) | (for Contrasharp or LFR) |
- GradePack
| (v9.0 or higher) | (for Str=0.1 to 1.0 ~ex_retinex()~ or show) |
- ScenesPack
| (v4.5 or higher) | (for Str=0.1 to 1.0 ~ex_retinex()~ if '_SceneRange' frameprops exist) |
- MasksPack
| (v6.7 or higher) | (for show) |
- RgTools
| (v1.2 or higher) | (for Contrasharp or prefilter=0~3) |
- DFTTest
| (v1.9.7 or higher) | (for prefilter=5) |
- KNLMeansCL
| (v1.1.1e or higher) | (for prefilter=6) |
- DGDecNV
| (v254 or higher) | (for prefilter=7) |
- BM3D
| (test10 or higher) | (for prefilter=8) |
- TransformsPack
| (v2.2.1 or higher) | (for prefilter=7 or prefilter=8) |
- neo_tmedian
| (r2 or higher) | (for mode="medianT") (broken for interlaced inputs) |
- vsTTempSmooth
| (v1.2.6 or higher) | (for mode="TemporalSmooth") |
- NNEDI3CL
| (v1.0.7 or higher) | (for subpixel=4) |
- Average
| (v0.95 or higher) | (for LFR or mfilter + (Contrasharp or mode!=MDegrain) ) |
Aknowledgements ▲
Original SMDegrain() by Caroliano
This function uses code from Didée, and cretindesalpes' creations,
and has parts inspired by LaTo's functions (Show panel, etc)
and Jawed's Killer() function, as well as relying on third-party tools for certain features.
Special thanks go to: cretindesalpes, Didée, Gavino, Sagekilla, and MVtools developers.
Introduction ▲
SMDegrain is a simple wrapper for MVTools and client functions for general purpose temporal denoising.
Unlike other MVTools based denoising filters, here and specially at default values the output will be source agnostic and similar to a plain MVTools code block.
The changes are mainly for useability and convenience, so you can think of it like an interface for MVTools or an extension of it so to speak. For example it will work out of the box with YUY2, interlaced inputs, HBD clips or a combination of them.
Internally default values have been optimized with pareto statistics via Zopti, so except for tr (radius) and thSAD there isn't a need to tweak much further.
What SMDegrain brings though is an interface to apply prefilters, either via the internal presets or external custom ones, motion filters, different degrain modes, lowpassing to recover smearing, etc. Following a list of the main features:
Frame properties support: Reads frame properties for details on luma/chroma range, bitdepth, source matrix or interlacing.
High bitdepth denoising: Supports AviSynth+ native HBD formats, from 8-bit up to 16-bit.
Contrasharpening: The pretty much standarized sharpening method created by Didée is blended into the function, so you can easily use it in HBD pipelines. An strength biased method is also possible via an internal LSFplus call. A CClip parameter is also supplied so you can choose another source to sharpen from, other than the default SMDegrain() input.
Interlaced support: It supports interlaced sources, for YUY2 color spaces and most parameters as well.
UHD optimized: UHD denoising can be optimized via motion vector scaling providing much higher performance. Enabled by default with UHDhalf argument.
Extended Subpixel Accuracy: nnedi3 is added as the 4th option for subpixel. Not strictly necessary in most cases.
Better Motion Vectors: An internal conversion from TV levels (16-235) to PC levels (0-255) and a dark zone luma expansion is done to the clip where the motion analysis will be performed on, so you can get much better motion vectors
Prefilters: An easy parameter to load predefined prefilters that perform well in most situations. It also accepts loading your personal prefiltered clips.
Degrain modes: As a bonus you can try other temporal denoisers (mainly from the ex_median() function) with mode so you can test temporal medians from a simple medianT to a ML3Dex algorithm in a motion compensated fashion.
Smear protection: Smearing of low contrast shading is a known side-effect of MDegrain, as a solution the LFR argument was added to recover low frequency details along DCTFlicker to temporally calm down the recovered frequencies.
Motion Filters: It will allow you to filter those parts where SMDegrain() couldn't find a matching block, or in other words motion areas where SMDegrain() couldn't denoise. One use for it would be spatial denoisers or deblockers since motion areas are prone to heavy blocking and artifacts.
Motion Vectors Globals Input/Output: Reuse motion vectors globals for faster processing, or just use SMDegrain() as a shortcut for creating nice quality motion vectors.
RefineMotion Option (MRecalculate): Performs finer block matching refinement, unless you are very performance deprived you should use this as default for a quality boost.
Show Panel: Everything is off by default, but a few settings change in context (i.e. when in HD). Check what is happening behind the scenes and have a fast look at all your settings.
Robust: Everything listed above works together with each other indistinctly with interoperability, reliability and optimization in mind. The general idea is to serve as an user friendly front end for vanilla mvtools2+mdegrain or as the original script creator entitled "To make your scripts shorter and less geeky". Most parameters are turned off or defaulted to MVTools2 defaults or close. Features are based on popular general conceived good practices and time tried-and-tested procedures.
Parameters are arranged in 2 blocks.
Basic: For people who just need the most basic parameters because either they don't have the time, knowledge or interest into looking for complex settings. Or they are content with defaults (pretty much mvtools defaults)
Advanced: If you run into some problems, are nitpicking or just want to fine tune your settings according to the source, have a look at this block, it contains the rest and bulk of the function parameters.
To picture what the function does, a simple SMDegrain() call matches the next code (for SD resolutions):
super_search = ex_Luma_Rebuild(S0=5.0,c=0.0312, bits=8).MSuper(rfilter=3,sharp=2)
bv2 = super_search.MAnalyse(isb = true, delta = 2, overlap = 4, search = 2)
bv1 = super_search.MAnalyse(isb = true, delta = 1, overlap = 4, search = 2)
fv1 = super_search.MAnalyse(isb = false, delta = 1, overlap = 4, search = 2)
fv2 = super_search.MAnalyse(isb = false, delta = 2, overlap = 4, search = 2)
MDegrain2(MSuper(levels=1), bv1, fv1, bv2, fv2, thSAD=300, thSADC=57, thSCD1=365, thSCD2=130)
As you see nothing drastic. The only changes made are the TV->PC luma expansion (ex_Luma_Rebuild() call) so you have more range to detect motion vectors, and some Zopti optimized values; rfilter to 3 for a bit more quality super search, the changed default of overlap from 0 to 4, search from 0 to 2 which has a higher performance/quality ratio, and thSAD and thSADC from 400 to 300 and 57 respectively for safer results.
This setup optimized internally along with RefineMotion might be all you need for most sources, but eventually you might encounter very grainy clips or simply noise and/or blocking. For these cases you can make use of the internal prefilter presets, but if those don't help even more creative approaches are required (see prefilter notes). The basis for good temporal denoising with SMDegrain is a good, source centric prefiltering, which in itself is a form of art.
Parameters ▲
SMDegrain (clip input, int "tr", int "thSAD", int "thSADC", bool "RefineMotion", val "contrasharp", clip "CClip", string "mode", bool "interlaced", int "plane", int "Globals", bool "tv_range", \
int "pel", int "subpixel", val "prefilter", clip "mfilter", int "blksize", int "overlap", int "limit", float "limitC", bool "limitS", val "LFR", bool "DCTFlicker", int "thSCD1", int "thSCD2", \
bool "luma", bool "chroma", int "hpad", int "vpad", val "Show", float "Str", float "Amp", int "DCT", int "searchparam", int "pelsearch", int "search", bool "truemotion", int "gpuid", int "rfilter", bool "UHDhalf")
Basic ▲
tr
[int: 1, "2", 3, 4, 5, 6, ...]
Temporal radius. Select between MDegrain 1, 2, 3, 4, 5, 6 or higher. The higher generally the better, but also much slower and improvements get less drastic (diminished returns) to circumvent smearing or ghosting.
Also with larger 'tr' all the truemotion and vector penalty settings lose their meaning and turn basically to no-op.
This can be considered the strength of the denoising. Supports up to tr=128, 64 for interlaced.
thSAD, thSADC
[int:"300"], [int:"226"] (for HD)
"Sum of Absolute Differences" threshold. This is the spatial difference threshold where the motion search will consider whether to denoise given the next formula: Denoise_Weight = max( 0, 1 - 2*blockSAD² / (thSAD² + blockSAD²) )
This spatial difference will be compared in blocks (blksize). If your noise is not getting into consideration for the denoising try raising this value, or reduce its SAD with previous prefiltering.
You can alternatively raise the block size (blksize), which will likely even blocks SAD. Low values can result in staggered/blotchy denoising, large values can result in ghosting and artifacts. Values in the range 200~600 are usual.
thSADC is the same logic applied to chroma planes, since there are less differences on the chroma planes it uses by default ~thSAD/5 for safer chroma results (internally uses a function fit).
Contrasharp
[bool: true, "false"] or [int: 0 ~ 100 ]
Contrasharpening is a technique that compares the differences between the clip before blurring (original) and after blurring (filtered), and compensates (sharpens) locally with consequent strength.
By default the before "sharp" clip is the one used as input for SMDegrain(), the "after" clip is the denoised clip. Independently a "before" clip can be specified with the CClip parameter (See below)
Contrasharp when set to "true", will use ex_ContraSharpening() (an ExTools mod to Didée's Contrasharpening()) which:
"Sharpens the denoised clip, but doesn't add more to any pixel than what was removed previously"
In the practice you will get a slightly sharper result than the source, which is welcome.
In the other hand if your parameter input is an integer, LSFplus() (an optimized LSFmod mod) will be used instead. It will be slower, but maybe better for certain sources.
Its value will serve as a contrasharpening multiplier, use one around 50 for similar strength as ex_ContraSharpening().
RefineMotion
[bool: true, "false"]
Refines and recalculates motion data of previously estimated (by MAnalyse) motion vectors.
Turn it on for better motion vectors, specially when dealing with ghosting issues, small details or lineart fading and whatnot.
*Beware: It won't enhance much if you use a prefilter (in case you use it) so strong that blurs too much or kills all the details you are aiming to "refine" in first place.
Interlaced
[bool: true, "false"]
By default not needed since it will be read from frame properties, but if you are getting issues or just want to play it safe set this parameter to true. Output will also be interlaced.
Note that must feed directly interlaced clips into CClip, prefilter, or mfilter, without the need to separate fields. Check examples on the bottom section.
Given the packing sub-format for interlaced clips, the minimum 'tr' allowed is of 2 even if tr=1 is set, and jumps in 2 so for tr=3 -> 4, tr=4 -> 4, and so on.
plane
[int: 0, 1, 2, 3, "4"]
Select the planes you wish to process:
- 0 - luma only
- 1 - chroma U
- 2 - chroma V
- 3 - both chromas
- 4 - all (Default)
*Keep in mind that plane=4 (2 and 3 as well) can sometimes create chroma smearing. In such case I recommend denoising chroma planes separately in the spatial domain.
prefilter
[int: "-1", 0, 1, 2, 3, 4, 5, 6, 7, 8] or [clip: - ] or [string: "", "SBR", "MinBlur", "MinBlur2", "MinBlur3", "IQMST", "DFTTest", "KNLMeans", "DGDenoise", "BM3D"]
See below for a review of prefilter presets.
Advanced ▲
mode
[string: "MDegrain", MedianT, MedianST, MedianSTS, TemporalSoften, TemporalSmooth, TemporalGauss, FluxSmoothT, DFTTest, ML3DEx, Hybrid, TL3D, STWM, IQMT, GaussST5]
Defines the filter for the temporal degrain. Normally should be left at default MDegrain which works best, but using other modes can provide Motion Compensation filtering
to filters that aren't motion protected like ML3DEx, IQMT, etc. probably for prefiltering or other uses. Most of these modes are explained in ExTools ex_median() entry (link).
If you append 'r' to the mode string (ie. rMedianT) it tells the filter to run twice for recursion, as a cheap way of Degrain Refinement.
TemporalSoften and TemporalSmooth are not supported in recursion mode to prevent ghosting, caution with TemporalGauss as well.
pel
[int: "1", 2, 4]
Accuracy of the motion estimation.
- 1: means a precision to the pixel. (Default for HD material)
- 2: means a precision to half a pixel. (Default for SD material)
- 4: means a precision to quarter a pixel, produced by spatial interpolation (more accurate but slower and not always better due to big level scale step).
subpixel
[int: 0, 1, 2, "3", 4]
Subpixel accuracy. It chooses an interpolation method for pel=2 or 4. This is the 'sharp' parameter in msuper() extended with modes 3 and 4.
Unrelated to output sharpness but accuracy for the motion estimation.
- subpixel = 0 for soft interpolation (bilinear)
- subpixel = 1 for bicubic interpolation (4 tap Catmull-Rom)
- subpixel = 2 for sharper Wiener interpolation (6 tap, similar to Lanczos)
- subpixel = 3 for blackman taps=6 high quality subpixel interpolation (Default)
- subpixel = 4 for nnedi3 high quality subpixel interpolation
For subpixel=4 you will need nnedi3 (gpuid=-1) or NNEDI3CL (gpuid=0) plugin. Very useful when used along pel=4 on very small sources, although overkill and unnecesary in most cases.
rfilter
[int: 0, 1, 2, "3"]
- 0 : simple 4 pixels averaging like unfiltered SimpleResize (old method)
- 1 : triangle (shifted) filter like ReduceBy2 for more smoothing (decreased aliasing)
- 2 : triangle filter like BilinearResize for even more smoothing
- 3 : quadratic filter for even more smoothing (Default)
- 4 : cubic filter like BicubicResize(b=1,c=0) for even more smoothing
Hierarchical levels smoothing and reducing (halving) filter.
Set and forget setting. Mode 3 gives the most accuracy for downscaling.
prefilter
[int: "-1", 0, 1, 2, 3, 4, 5, 6, 7, 8] or [clip: - ] or [string: "", "SBR", "MinBlur", "MinBlur2", "MinBlur3", "IQMST", "DFTTest", "KNLMeans", "DGDenoise", "BM3D"]
- -1 = off (Default)
- 0 = light controlled gauss blur
- 1 = mild median/gauss blur
- 2 = strong median/gauss blur
- 3 = very strong median/gauss blur (IQMV -Variable Inter Quartile Median- filter)
- 4 = spatio-temporal median/gauss filter (IQMST)
- 5 = DFTTest (spatial)
- 6 = KNLmeansCL (spatio-temporal non-local means OpenCL GPU filter)*
- 7 = DGDenoise (spatial non-local means Cuda GPU filter)*
- 8 = BM3D (temporal BM3D Cuda GPU filter)*
- - = prefiltered clip input variable
*Watch out for OpenCL or CUDA version compatibilities with your GPU vendor
Despite being one of the most advanced filters for AviSynth, MVTools is lacking important motion predictors like rotate/scale-zoom/skew...
Currently only translation transforms are being predicted and therefore we need to help MAnalyse client function as much as possible to create accurate motion vectors.
For this reason precisely one of the most important aspects for a satisfactory denoising in SMDegrain is to provide clean reference frames for MAnalyse,
specially when the source is grainy, technically speaking by lowering the SAD (Sum of Absolute Differences) where it matters most.
If you didn't realize already, most of the settings in MVTools and SMDegrain revolve around conditioning this prefiltered clip.
From pel, going through subpixel, to luma expansion (Str and Amp) and obviously prefilters.
In general terms spatial prefiltering is enough (presets from 0 to 3 and 5 and 7) while very grainy sources might require spatio-temporal filters (presets 4, 6 and 8).
The goal here is not to provide a fully perfectly denoised clip but a slightly soft or out-of-focus version of an ideal clean clip, that is, soft edges (but not blurry) and clean flat areas.
For example cartoons may display many flat areas that work great with median filters (1 to 3) or even non-local means (6 and 7). While live action, depending on
the nature of the grain, can use the spatial prefilters which are faster or BM3D (preset 8). Custom external prefilters will also be explained below.
To put denoising filters in comparison back to back, we can broadly order them in the following sequence of quality:
BM3D (Block Matching 3D) > NLMeans > SAD Block Matching (MVTools) > Frequency Filters (FFT/DFT..) > Bilateral > Median > simple linear filters (Gaussian Filter, Wiener Filter...)
Another useful way to think about prefilters for example when building custom prefiltered clips is to treat the clip as if you were filtering as usual without SMDegrain, that is,
using Deblockers if blocking is present, Decrawlers, cleaning Gibbs noise, some spatial denoiser, etc. Then this clip is only fed to prefilter while the original is used as input for SMDegrain.
By doing this all those issues will be cleaned temporally more effectively while retaining more details. Now, yes, areas where block matching failed (motion areas) will passthrough
the original clip with all its artifacts, so the trick is to feed the same clip to mfilter, so motion areas will apply the prefilter clip spatially while stable areas will only treat them temporally.
pre=my_custom_prefiltering().ex_sbr() # sbr to soften edges
SMDegrain(last,prefilter=pre,mfilter=pre)
Now you might think, if SMDegrain is so good, why not use it also for prefiltering?
Good question, and yes, that's actually one of the recommendations for fizz grain or simply very grainy sources (films like "300", "21 grams", etc).
Just keep in mind that running MVTools2 twice in the same script may lower performance greatly, but using a low radius (tr) can help towards that.
For example, we have a very grainy 1080p source so we are going to apply quite extreme settings.
pre=SMDegrain(tr=1,mode="TemporalSoften",blksize=32,prefilter=8 ,thSAD=700,LFR=400,DCTFlicker=false,contrasharp=false,refinemotion=true)
SMDegrain(tr=2,mode="MDegrain" ,blksize=32,prefilter=pre,thSAD=400,LFR=200,DCTFlicker=true ,contrasharp=true ,refinemotion=true)
TemporalSoften and TemporalGauss are two degraining modes that switch a few internal settings to make it more temporally stable. It's quite an extreme approach
also with blksize=32 and thSAD=700, therefore we should recover some low frequency smearing with LFR=400 and LFR=200, DCTFlicker=true in the second call.
Following we feed this prefilter clip to the next SMDegrain call with saner settings of 'MDegrain' and thSAD=400.
*For these two degraining modes you might want to manually tweak the thSCD1 value, specially in the thSAD 400 to 800 range.
Higher than that it's automatically parametrized to give the lowest thSCD1 value (prevents filtering across scene changes) with reasonable filtering.
The above is for mild to strong sources, for very strong ones like "21 grams" I found myself using a double call:
SMDegrain(tr=3,mode="TemporalSoften",blksize=32,thSAD=1200,LFR=300,DCTFlicker=true,contrasharp=false,refinemotion=true)
SMDegrain(tr=1,mode="MDegrain" ,blksize=32,thSAD=300 ,LFR=false ,contrasharp=true ,refinemotion=true)
Another option:
SMDegrain(tr=3,mode="TemporalGauss" ,blksize=32,thSAD=1300,LFR=300 ,contrasharp=false,refinemotion=true)
SMDegrain(tr=2,mode="TemporalSoften",blksize=32,thSAD= 600,LFR=false,contrasharp=true ,refinemotion=true)
Another one this time with prefilter:
pre=ex_bm3d(60,3,preset="noisy")
SMDegrain(tr=2,mode="TemporalSoften",blksize=32,thSAD=600,prefilter=pre,refinemotion=true)
ex_unsharp(0.2,Fc=width()/2) # Remove the dreamy/softness look
And another one with prefilter (the possibilities are endless so choose your poison):
SMDegrain(tr=3,mode="TemporalSoften",thSAD=600,LFR=300,DCTFlicker=true,prefilter="IQMST",refinemotion=true)
The double call method is called Degrain refinement, while the ones using prefilter are called Motion Vector refinement, and both are considered
pyramidal refinements as you lower the strength of the prefilter/denoising the lower the stack. You can also mix both methods and experiment.
Double calls are effective in the sense that it naturally applies a binomial weighting to the pixels, the furthest frames having less weight,
just like two stacked mean/box blurs approximate a binomial blur in the spatial domain.
Needless to say you can get prefiltering as complex as you wish, by using masking and other filters like ex_retinex(), ex_autolevels(), etc.
Creating these discerning masks and prefiltering chains is a research task on the end user side.
Might sound obvious but note that when feeding a clip to prefilter the clip format (dimensions, pixel type, etc) should match SMDegrain() input format.
Some (very) old examples of custom prefiltering, for history:
This last example is a function called Calm(), wrapped by Terka but it's basically QTGMC's default prefiltering from line 467 to 499 using TR0=2 and SrchClipPP=3.
It's basically a TemporalGauss, with some limiting and a gaussian blur. What he missed was adding KeepOnlyBobShimmerFixes() which removes "most" TemporalSoften frame blending artifacts.
My improved alternative was already given above, but adding ex_sbr() instead of a gaussian blur:
pre=SMDegrain(2,thSAD=1600,mode="TemporalGauss",pel=1,rfilter=0,str=0,tv_range=false,plane=0,truemotion=true) # Tuned for speed or "dumb" MV
pre=pre.ex_sbr(3,UV=3)
*You can read more about this and a stronger alternative more similar to Calm() for (film) de-wobble purposes on this post and following pages.
Notes:
To sum it up; generally in denoising, temporal filters are always preferred due to its natural look (versus spatial filters).
But more often than not for good results prefiltering plays a key role on the output quality, and setting it up nicely can be looked as an art by itself.
mfilter
[clip: - ]
As with prefilter, in mfilter (Motion Filter) you can add a clip variable. This clip will be passed through those areas where SMDegrain() couldn't find a matching block, normally high motion areas.
One use for it would be to use spatial filters, like deblockers or blurring filters that mimic motion blur.
Clip should match input format.
Str
[float: 0.0 ~ 8.0] Default: 5.0
Based on the original function by cretindesalpes', with this parameter you control the strength of the brightening of the prefilter clip.
Unless you are filtering sports or TV shows aimed at daytime you most likely want this turned on at default value.
MVTools2 has issues on low frequency areas like shadows and shade details where the human eye excels at, so enhancing
the dynamic range of this area makes it easier for MAnalyse to create better motion vectors and avoid smearing.
This luma expansion is performed in the same stage as the TV->PC range conversion thus more memory friendly and less quantization artifacts.
From 0.0 to 1.0 (1.0 being no-op) uses ex_retinex(), the value will serve as the normalization factor (ie. 0.40 to normalize black to pixel value of 40 -in 8-bit scale-).
Use show to review the brightening curve for >1.0 values.
Amp
[float: 0.0 ~ 1.0] Default: 0.0312
Use this together with Str. This defines the amplitude of the brightening in the luma range, for example by using 1.0 all the
luma range will be used and the brightening will find its peak at luma value 128 in the original. Default is 0.0625 (1.0/16) which just sits over luma value 16 (256/16)
LFR
[bool: true, "false"] or [int: 50 ~ Resolution]
Cutoff frequency for Low Frequency Restore -LFR-. 'true' enables a lowpass equal to 300 for a 1080p clip.
Useful in the presence of smearing when using too extreme settings (high tr, thSAD, prefiltering, etc).
The value represents a cutoff in resolution units of the maximum dimension, so for example 300 would lowpass all details above 1920/300 = 6.4 pixels wide.
DCTFlicker
[bool: true, "false"]
Only works when LFR is activated. It tries to stabilize low frequency flicker produced by grain propagated to low frequencies by the DCT compression algorithm.
When enabled it will only pass low frequencies to motion areas and filtered through a custom temporal denoiser to calm the flicker. Only enable this when your source is very grainy.
blksize
[int: 4, 8, "16", 32, 48, 64]
Size of a block (horizontal). (Default 16 for HD material)
Larger blocks are less sensitive to noise, are faster, but also less accurate.
overlap
[int: "blksize/2"]
Must be *even* and *less* than block size. Common overlap values: blksize/4 or blksize/2.
The greater overlap, the more block count, and the lesser more processing speed.
Search
[int: 0, 1, "2", 3, 4, 5, 6, 7]
- 0 = 'OneTimeSearch'
- 1 = 'NStepSearch'
- 2 = Logarithmic (Default)
- 3 = Exhaustive
- 4 = Hexagon
- 5 = Uneven Multi Hexagon (UMH)
- 6 = pure Horizontal exhaustive search
- 7 = pure Vertical exhaustive search
By default 2, but switched to 4 when RefineMotion is enabled.
See details at MVTools2 documentation.
DCT, searchparam, pelsearch
[-]
See details at MVTools2 documentation.
Truemotion
[bool: true, "false"] * "true" for SD
Truemotion is a preset of some parameters values. It allows easy to switch default values of all "true motion" parameters at once.
Set it 'true' for true motion search (high vector coherence), set it 'false' to search motion vectors with best SAD.
Default is 'true' (as in MVtools2 default, and contrary to MCTemporalDenoise()).
By turning it off it could protect better low frequency
details (shading) when in motion (i.e. walls, grounds, clouds texture, motion blur, etc), and also protect from tiny details loss but it could leave more noise unfiltered.
Default is 'true' for SD for smoother/cleaner (more temporal coherence) high frequency details or lineart. For HD sources where the main problems are just excessive grain,
I have defaulted it to false, this is not only faster but honors detail accuracy (the main existing point for HD sources) and overall object shading.
Chroma
[bool: "true", false]
Takes chroma planes into consideration for calculating the motion vectors.
Turn it off for more speed with little cost in quality, or when your chroma is not reliable enough for motion estimation.
*Whatch out if you turn this off when processing chroma planes (aka luma vectors when chroma denoising), it has shown problems in previous tests.
Luma
[bool: "true", false]
Takes luma plane into consideration for calculating the motion vectors.
For example if you were to denoise only Chroma planes (plane=1, 2 or 3), you might or might not want to use vectors from the Luma plane.
Actually MVTools2 doesn't have an option for this, so what this does is concerned to prefilters and finally a luma weighting that is half of the chroma on the MVTools2 side.
Hpad, Vpad
[int: "blksize"]
It is horizontal/vertical padding added internally to source frame (both left and right, and top and bottom).
Small padding is added for more correct motion estimation near frame borders.
Try to have clean borders in your source (no NAB*/black borders) to start with before tweaking this setting.
If necessary, crop beforehand ideally in multiples of 16. Turn it to 0 if you are running out of resources in your system.
*Nominal Analog Blanking
thSCD1
[int: "365"]
Threshold which decides whether a block has changed between the previous frame and the current one. So it is one of the thresholds used to tweak the scene changes detection engine.
Raising it will lower the number of blocks detected as changed. It may be useful for noisy or flickered video. To fix blending on scene changes on dark scenes, try first the Str and Amp parameters.
thSCD2
[int: 0~"130"~255]
Threshold which sets how many blocks have to change for the frame to be considered as a scene change.
limit,limitC
[int: 1 ~ "255"]
Maximal change of pixel luma/chroma (post-process like DeGrainMedian plugin
and LimitChange function of SSETools plugin, to prevent some artifacts)
limitS
[bool: "true", false]
Limit type for the contrasharpening: True: Spatial, False: Temporal (ignores CClip).
False (temporal) might give a more natural look albeit softer, so you might want to raise the contrasharpening a bit.
CClip
[clip: - ]
Define here a variable name referencing an earlier stage of your processing chain as the sharp version for the contrasharpening to compare against.
If contrasharp is not declared, by default it will use the ex_ContraSharpening() function, add contrasharp='an integer' to force LSFplus() instead.
Clip should match input format.
gpuid
[int: -1, "0", 1... ]
Enables GPU processing for the filters that support them. -1 is CPU mode, 0 is default GPU and >0 is device ID if you have more than one GPU.
-1 (CPU mode) is only for NNEDI3 (for subpixel=4) and BM3D (prefilter=8) as prefilter with KNLMeansCL is currently GPU only.
UHDhalf
[bool: "true", false]
For performance reasons computes motion vectors from a halved version of an UHD clip. Then the motion vectors are upscaled back to UHD resolution for denoising.
Keep aware that quality while good won't be on par with plain UHD denoising (UHDHalf=false), specially on low SAD areas where some slight blurring
or detail warping can happen. For this reason you might want to limit denoising to a value of 2 or 1 to minimize the effect (test with limit=2).
Globals
[int: "0", 1, 2, 3 ]
With this parameter you can, among other things, load pre-processed motion vectors (Globals=1), so you save doing this step again.
The integers define what to do with the global variables. Default is 0.
- 0: Don't read nor output globals (Just process) (Default)
- 1: Read globals --> Process
- 2: Process --> Output globals
- 3: Output globals only (Don't process clip)
Some parameters MUST MATCH those from the processed vectors stage (e.g. Globals=2 or 3) and the read vectors stage (e.g. Globals=1).
pel=, subpixel=, chroma= and vpad/hpad.
Other than that the only settings that work when reading (Globals=1) are: tr=, thSAD=, plane, limit, limitc, contrasharp, CClip and the interlaced parameters. Others are ignored.
Global names that can be reused are: srchSuper, bVec1, fVec1, bVec2, fVec2, bVec3, fVec3, bVec4, fVec4, bVec5, fVec5, bVec6, fVec6, vmulti.
e.g.:
SMDegrain(tr=3,thSAD=400,globals=3) # Outputs vectors
SMDegrain(tr=2,thSAD=200,globals=1) # You can use a same or lower "tr" or "thSAD" if you want
or
SMDegrain(tr=3,thSAD=400,globals=3) # Outputs vectors
Super = MSuper(levels=1) # Add this line just before if you have some processing between Globals Output and Input.
MDegrain3(Super, bVec1, fVec1, bVec2, fVec2, bVec3, fVec3, thSAD=400)
Show
[bool: true, "false" ] or [string: "Speed", "Memory", "Quality" ]
This will show the brightening curve graph over the prefiltered clip to be used for the motion search to the left(<--), and the used parameters list to the right (-->)
If you set Show to a string as indicated above, related parameters will be highlighted to guide you on correctly tweaking the function.
This is loosely based, so it doesn't exclude you from reading carefully every parameter explanation.
Even when you are not using any prefiltering, the clip to be used for the motion search where you obtain the motion vectors,
will be converted from TV levels to PC levels, the only exception being when using Globals=1 (Read) in which case the "prefiltered" clip
will be exactly the same as input clip (that is no luma conversion, although constrained to 8 bit). Additionally you can tweak the dark expansion with
Str and Amp parameters and check the effects in the left panel, but be aware to change your viewing conditions as it is in PC levels.
If you are not processing chroma for motion analysis (chroma=false) the prefiltered clip will be green, don't panic, this is correct, this happens when the
U and V planes are set to a value of 0 which is a dummy value meaning nothing or "discard". In this regard for previewing tasks simply set chroma to true temporarily.
Example Scripts ▲
A basic yet very functional call for light grain.
SMDegrain(tr=1,thSAD=300,contrasharp=true)
A personal preference. Turned all chroma off for safeness (on SD, chroma is rarely temporal-reliable enough) and speed.
SMDegrain(tr=2,thSAD=300,contrasharp=true,refinemotion=true,chroma=false,plane=0)
This is a good example to show that interlaced YUY2 sources can be processed seamlessly.
# Interlaced YUY2 source
SMDegrain(tr=1,thSAD=250,interlaced=true,contrasharp=true)
Denoising interlaced with a custom prefilter.
pre=SMD_UnfoldFieldsVertical().STTWM().SMD_FoldFieldsVertical() # Tailored SeparateFields then Interleaving back
SMDegrain(tr=1,thSAD=250,interlaced=true,prefilter=pre,contrasharp=true)
HD sources are detected automatically, and as so settings are optimized for speed; pel=1, blksize=16, overlap=8, truemotion=false
# HD source (from 1100px wide or 600px high up)
SMDegrain(tr=2,thSAD=180,prefilter=2,contrasharp=30,refinemotion=true,chroma=false,plane=0)
Tackling a grainy source pragmatically.
SMDegrain(tr=3,thSAD=500,contrasharp=40,prefilter=8,refinemotion=true)
How to reference a prior state of the script for the contrasharpening process.
sharp_ref=last
Deblock_QED(quant1=30, quant2=40)
SMDegrain(tr=3,thSAD=300,CClip=sharp_ref)
Leverage prefilter and mfilter for a spatio-temporal deblock on an mpeg file.
Also set contrasharpening to temporal limited (limitS)
pre=Deblock_QED(quant1=30, quant2=40)
SMDegrain(2, 200, prefilter=pre, mfilter=pre, refinemotion=true, contrasharp=60, limitS=false, chroma=false)
How to degrain an PQ encoded HDR clip. Note that prefilter clips also pass through ex_Luma_Rebuild() internally.
pre=DGHDRtoSDR(YUV420P16_Lim, mode="pq", gamma=1/2.4, tm=1.0, white=1500) # Check different white levels (60, 100, 203 or default 400) depending on source metadata
SMDegrain(tr=3,thSAD=300,prefilter=pre,UHDHalf=true) # 'UHDHalf' enabled (Default) for a performance boost
(Re)using motion vectors globals.
SMDegrain(tr=1,thSAD=400,prefilter=3,str=1.4,globals=3) # Output vectors only
MFlowFps(Super, bVec1, fVec1, num=60,den=1)
Final Notes ▲
If there is an important parameter not implemented,
you have any issue or found a bug, please don't hesitate
and ask in the main Doom9 thread:
(https://forum.doom9.org/showthread.php?t=182881)
What to expect for the future?
As DLSS3 enabled RTX GPUs lower the prices and AMD plays the catch up game
we might see more GPU based motion estimation APIs that open up advanced options
for very high quality motion vectors at reasonable or even good speeds.
Machine learning is also getting its way into AviSynth+ thanks
to the work of Asd-g and other active members, so the future is bright.
Changelog ▲
v4.6.0d (30-03-2024)
- ex_DGDenoise(), updated to new v254 DGDenoise() arguments.
- ex_BM3D(), 'preset' is now case insensitive.
- ex_Luma_Rebuild(), fix logic for 'lo' and 'hi'. Still need to fix when HBD.
- Changed the parser for Globals Out in multi mode.
- Removed an unneded check for Globals Out in non-multi mode.
v4.5.0d (12-07-2023)
- Match global variable names to those of QTGMC
- Fix check of vector vars when doing vector output
v4.4.0d (16-05-2023)
- Change back default for 'limit'
- Add better example for DGHDRtoSDR() prefiltering.
- Documentation updates.
v4.3.0d (01-04-2023)
- Construct vector variables in a for loop
- Fix 'mode', 'mfilter' and 'LFR' when isMult (tr > 6)
- Swizzle in unprocessed planes to MFilter clip when the option is used
v4.2.0d (27-03-2023)
- Fix ex_DGDenoise() when processing chroma
- Limit prefilter=6 (KNLMeansCL) gpuid to 0 minimum
- Optimization. Reuse Mavg var conversion to YUV
- Optimization. Engulf CClip code block into !GlobalO logic
- Optimization. Add 'luma' arg, for chroma only MV, or luma denoise with chroma only MVs
- Logic cleanup for isInter in show code block
v4.1.0d (09-03-2023)
- Remove all references to RGB since it isn't supported by MVTools2
- Pass LFR through the motion mask to further mask out DCT flicker (even when DCTFlicker=false, when true mask is stronger)
- Replace prefilter=4 (FluxSmoothST) with "IQMST", suited for very grainy live action HD sources
- Update documentation
v4.0.0d (02-03-2023)
- YUY2 support for all clip type arguments via internal planar conversion (CClip, mfilter, prefilter and input)
- Direct interlaced support for all 'mode' filters and clip type arguments (CClip, mfilter, prefilter and input)
- Update handling of interlaced content. Bugfix + Performance + Code optimization
- Update chroma shift for UHDHalf to use Catmull-Rom instead of slower spline16
- Allow string types for 'prefilter' argument to define the preset
- Replace GaussT5 with TemporalGauss 'mode' and add TemporalSmooth mode (IDW weightings)
- Reparametrize thSCD1, DCTR and scaleCSAD for TS (Temporal___) modes (regression fix)
- Add 'mode' to show panel
- Allow recursion for all 'mode's except TemporalSoften
- Optimizations for chroma only denoising
- Add 'threads' arg for when CPU nnedi3 (pel>1, subpixel=4 and gpuid=-1)
- ex_retinex() - Fixed highlights=false for lvl=1 and lvl=2
- ex_retinex() - Fixed range conversion for all 'lvl' modes
- ex_BM3D() - Fix range string format when converting to other formats
- ex_DGDenoise() - Update chroma subsampling kernel to 'Didee' instead of slower spline36
- Finished Documentation
v3.6.0d (06-02-2023)
- ex_Luma_Rebuild - Add 'lo' and 'hi' args for optional normalization
- Some typos and cosmetics
v3.5.9d (18-01-2023)
- Better field parity detection for interlaced clips
- Frame property assignments for interlaced clips
v3.5.8d (16-01-2023)
- Support back YUY2 via internal YV16 conversion
- Add IQMV as prefilter=3 and tune ex_FluxSmoothST() (prefilter=4)
- Optimize ex_BM3D() and ex_DGDenoise() format revert, and support Y clips
- Support Y clips when show=true
v3.5.7d (02-12-2022)
- Fix logic for nnedi3 pixel center shift (subpixel=4)
- Fix Globals output (Globals=3)
- Fix super_render pelclip being set to nop() when reading Globals
v3.5.6d (30-11-2022)
- Fix pixel center shift deviation in nnedi3 (subpixel=4) for high pel
- Swap prefilter 6 and 7 order for more coherence
- Tweak mode="dfttest" internal 'tmode' arg to work with odd 'tr'
v3.5.5d (20-09-2022)
- Add 'DFTTest' as mode
- Update Documentation (WIP)
- Cosmetics
v3.5.4d (02-08-2022)
- Replaced NNEDI3CL() with nnedi3wrap() so you can switch to CPU or GPU nnedi3 via 'gpuid' arg
- Since ResizersPack is now mandatory, nmod() was used where appropiate
- Fixed dimension references when UHDHalf is used
- Changed Str=1 to go directly to ConvertBits()
- Fixed 'show' panel for UHD and increased curve precision in 'show'
- ex_retinex() - Fixed normalization in HBD for lvl=3
- ex_retinex() - Expanded mask terminator
v3.5.3d (08-07-2022)
- Replace nnedi3 calls (CPU based) with NNEDI3CL (GPU) when subpixel=4
v3.5.2d (28-06-2022)
- ex_luma_rebuild() - Add RGB support
- ex_retinex() - Support for single channel clips
- ex_retinex() - Argument to disable highlight compression
v3.5.1d (01-06-2022)
- Update function definitions
- Rename 'device_id' arg to 'gpuid'
- Allow CPU processing for prefilters via gpuid=-1
- Update UHD downscale coefficients
- 'Str=1.0' is inclusive for ex_luma_rebuild() (only does a range conversion)
- ex_retinex() - Default UV to 3, for when used as stand-alone
- ex_retinex() - Add proper greyscale conversion
- ex_BM3D() - Add 'gpuid' argument
- ex_KNLMeansCL() - Change 'device_id' to 'gpuid'
v3.5.0d (17-04-2022)
- Change 'search' and 'thSCD1' Defaults
- ex_Luma_Rebuild() - Add 'tv_out' and 'bits' args
- ex_retinex() - Change pmax to not thresholded max for lvl=3
v3.4.9d (01-04-2022)
- Tweak some defaults; searchr, DCTR, pelsearch, plevel, pglobal, searchparam and searchparamr
- Force input to frame based also for pel > 2
- Fix pelclip height for interlaced sources
- Retrieve prefilter '_ColorRange' instead of using input's
- Use lvl=3 for ex_retinex() prefiltering if '_SceneRange' is present
- ex_retinex() - Add 'tv_out' arg when output is not for prefiltering use cases
- ex_retinex() - Add 'lvl=3' mode, will use scene based accumulated min and max stats
v3.4.8d (09-03-2022)
- Rebase to latest ExTools
- Rebase to latest LSFPlus
- Fine tune function definitions
- ex_luma_rebuild() - Add selective propCopy and update 'Str' and 'c' defaults
- ex_KNLMeansCL - Add 'DCT' arg and add propCopy
- ex_KNLMeansCL/ex_DGDenoise - Default 'DCT' to true
v3.4.7d (15-02-2022)
- Adjust defaults for internal ex_luma_rebuild()
- Subpixel=3 (now Default) is blackmanresize(taps=8), nnedi3 is now subpixel=4
- Fine tuned prefiltering settings and ex_BM3D() uses CUDA back again
- ex_BM3D() - Add 'preset' arg and add additional arguments to BM3D_CUDA and BM3D_CPU calls
- ex_DGDenoise() - Add LFR and DCT args
- ex_KNLMeansCL() - Turn 'LFR' to float and rebase with ex_LFR()
v3.4.6d (08-02-2022)
- Fix typo in ex_KNLMeansCL()
- Reimplement back ex_KNLMeansCL() as prefilter=5
- Shift ex_DGDenoise() to prefilter=7
- Add post-blur to prefilter=5 and prefilter=7
- Default prefilter=6 (ex_BM3D) to CPU mode (CUDA is bugged)
v3.4.5d (08-02-2022)
- ex_DGDEnoise() - New GPU based denoiser wrapper
- ex_KNLMeansCL() - Add 'wref' arg and limit 's' to 8
- Replace ex_KNLMeansCL() with ex_DGDenoise() as prefilter=5
- Optimize 'thSADR' and 'thSADC' Defaults
- LSFmod() - Change 'smode' to 4 for HD
- ex_Luma_Rebuild() - Fix 'show' setting
- ex_retinex() - frameprops passthrough
- ex_BM3D() - Add better matrix detection for the format conversions
- ex_BM3D() - Default chroma sigma to 1 when not used otherwise garbage output
v3.4.4d (28-01-2022)
- Add 'IQMT' as degrain mode
- Add range arg to nnedi3
- Rebase LSFmod to latest version
v3.4.3d (23-01-2022)
- Removed 'trymany' and 'divide' arguments
- Changed a few defaults; revert 'overlap', tune 'sharp', 'rfilter' and scaleCSAD
- Add a low frequency sharpened prefilter when LFR is enabled
- Optimize/simplify ex_KNLMeansCL() 'LFR' algorithm
- Add a stronger LFR for ex_KNLMeansCL prefilter
- Fix issue when subpixel=3 was used (limit 'sharp' to 2 in MSuper)
- ex_minblur()/ex_sbr() - Fixed last call clip order to properly inherit frameprops
v3.4.2d (10-01-2022)
- Add function definitions
- Fix for ex_luma_rebuild() plot
v3.4.1d (08-01-2022)
- Default overlap to blksize/4 when refinemotion is used. (Slight +detail retention when motion and +performance)
- Rebase to latest ExTools. Affected 'fulls' args in prefilter=0 and prefilter=4
- ex_luma_rebuild() - Add 'show' argument to show curve plot
v3.4.0d (14-12-2021)
- Rebase to latest ExTools
- Fix for default LFR value on UHD clips
- Optimized tv to pc luma range for HBD inputs and Str=0
v3.3.9d (03-12-2021)
- Recursion for MDegrain
- Defaults when input is single plane or plane=0
- Clean Asserts and allow blksize of 24
- Prefilter UHD clips in its halved version (if UHDHalf=true, default)
- New prefilter=3 for ex_FluxSmoothST(), following modes are shifted up in number
- Fix super_render when reading Globals
- ex_Luma_Rebuild() use internal scale_inputs when tv_range=false (faster) + ditch 'fulls'
- ex_retinex() use internal scale_inputs when tv_range=false (faster) + ditch 'fulls'
- ex_retinex() replace old YPlaneMin/Max with PlaneMinMaxStats
- ex_BM3D() switch 'fulls' arg with 'tv_range'
- ex_BM3D() new arg 'OPP' to filter in OPP space as originally intended
v3.3.8d (14-11-2021)
- Optimize nnedi3 for subpixel=3
- Rename srfilter to rfilter
- Final tweaks to DCTFlicker
v3.3.7d (13-11-2021)
- ex_MinBlur() 'th' arg.
- Add 'smart2' and 'smart3' modes
- Use 8-bit for subpixel=3.
v3.3.6d (12-11-2021)
- Remove 'fulls' arg, now it's derived from frameprops or overriden by tv_range arg
- Fill in appropiate values for 'fulld'
- Increase blksize limit to 64
- Improve DCTFlicker filtering
- Default DCTFlicker to false
v3.3.5d (05-11-2021)
- Small optimization to ex_sbr() and ex_MinBlur()
- Add "FluxSmoothT" degrain mode
- Repurpose 'LFR' argument to frequency values (100 ~ 500)
- Rework nnedi3 multithreading arguments (requires SysInfo)
- Fix 'mfilter' for tr > 6
- Replace non-MDegrain LFR process code with that of MDegrain (faster)
- Add 'DCTFlicker' argument, to 'calm' restored low frequency detail
- Fix show panel when input is 32-bit float
- Helper functions - 32-bit support. Preparing for SMDegrain 32-bit support
v3.3.4d (10-10-2021)
- Implement back recursion for "medianT" mode
- 'LFR' setting, to restore lost low-frequency details
- Fix UHDhalf chroma placement (assumes 'top_left')
- ex_KNLMeansCL() - Update passing more arguments including 'lores' to restore low-frequency details
- Tune prefilter=4 (ex_KNLMeansCL()) for a bit more sharpness
- Implement mfilter contrasharpening fix to defined CClip as well
- ex_retinex() - use clip instead of scale for NaN blocks bug
v3.3.3d (08-10-2021)
- More denoising modes
- Fix mfilter for Contrasharpening and non MDegrain modes
- ex_retinex() - convert to function objects
- ex_retinex() - aminorate black clipping issue
- Add dependency list
v3.3.2d (23-09-2021)
- Add recursion mode when using alternative denoisers
- Export in above cases the MC clip directly instead of vectors for temporal limiting contrasharpening
- Let more room (overshoot) for not heavy grain contrasharpening when using TemporalSoften and ex_contrasharpening
v3.3.1d (22-09-2021)
- Updated ex_gaussianblur() call in ex_retinex()
- Updated LSFmod call to accept temporal limiting if limitS=true and LRad if isHD
- New 'mode' arg to select MC denoiser of choice from TemporalSoften (for very grainy sources) and ex_median() modes. Might be faster than MDegrain for comparable results
v3.3.0d (15-09-2021)
- Reordered Defaults
- limitS, new setting for spatial/temporal contrasharpening limiting
- Relaxed supersampling in LSFmod for more performance
- ex_MinBlur() and ex_sbr() Expr optimizations
- ex_retinex(), 'lo' and 'hi' arguments for post normalization in fixed mode (lvl=1)
v3.2.9d (09-09-2021)
- Optimize + improve ex_retinex() with 'level' modes
v3.2.8d (07-09-2021)
- Fine tune ex_retinex()
- ex_retinex() add missing "fulls"
- Bugfix for fulls in ex_BM3D()
v3.2.7d (01-09-2021)
- ex_retinex(). Reworked luma rebuild logic with FrameProps
- Make ex_retinex() more temporal stable
- Optimize ex_retinex()
- Optimize ex_MinBlur()
v3.2.6d (27-08-2021)
- 'UHDhalf' and 'Interlaced' logic fixed
v3.2.5d (25-08-2021)
- Add UHDhalf argument
- ex_MinBlur() optimizations
- Moved ex_ContraSharpening() to SharpenersPack
- ex_MinBlur() corner case bugfixes
v3.2.4d (12-08-2021)
- ex_ContraSharpening() - Revert to removegrain(20)
- Rebase to latest ExTools
- Fix ex_BM3D() issue when 32-bit
- Fix 'threads' issue
- Remove masktools2 dependency
v3.2.3d (04-08-2021)
- Add BM3D as prefilter
- Fix contrasharpening for HD
- Fix Thread var when argument is empty
- Use BilinearResize for UHD (vector scaling)
v3.2.2d (22-06-2021)
- Rebase to latest ExTools
- Add 'fulls' arg
v3.2.1d (18-06-2021)
- Rebase to latest ExTools
- Add 'tv_range' arg
- Enable 'Str' as default (str=2)
v3.2.0d (11-06-2021)
- Resume from v3.1.2.111s (continuation mod from real.finder)
- Code sanitation (remove old avisynth support -pre AVS+-, DitherTools support and YUY2 support)
- Ported masktools2 to ExTools
- Merged back prefilters from function based to SMDegrain¡s in-code
- Change DCT and subpixel defaults
- Add internal scaleCSAD defaults
- Add UHD optimization via MScaleVect
- Remove 'bits' arg from MScaleVect
- ex_sbr()/ex_MinBlur() optimizations
- ex_Luma_Rebuild() optimizations and cleanup
v3.1.2d (21-07-2015)
- Fixed regression where external prefilters wouldn't be parsed for luma expansion
v3.1.1d (16-07-2015)
- Workaround to force KNLMeansCL use discrete video card (now required)
v3.1d (14-07-2015)
- New prefilter mode 4 for grainy sources. GPU based spatio-temporal KNLmeans
- Added dither output mode "Random Dither".
- Added "slices" option from Dither
- Added soft=-2 (automatic) to internal lsfmod
- Added assert for chroma denoise when luma only motion vectors (mvtools bug)
- Improved lsb_in code (now using sub/add method)
- Removed vpad/hpad=0 optimization preset for HD
- Fixed prefilter=3 code for lsb_in YUY2
- More fixes to Show Panel...
- Updated and fixed documentation (notes on YUY2 support)
v3.0d (27-03-2015)
- Adjusted SD<>HD discretion
- Added mfilter (Motion Filter) new feature
- subpixel=3 (nnedi3); removed qual=2 due to possible blending bug (quote by cretindesalpes), this also boosts speed
- Lowered the defaults for less aggressive denoise (still somewhat high)
- Fixed chroma not showing in debug (show) mode when lsb=true and prefilter=3 were paired
- Fixed long lasting issues in Show Panel for certain not mod height resolutions
- Now prefilter=0 is minblur(0), lighter denoising than prefilter=1, default is now -1 (off)
- Documentation update (plugin updates, notes, links, examples, etc)
v2.2d (05-03-2013)
- Removed one residual variable in Contrasharpening function
- Fixed a regression at v2.0 for Interlaced YUY2 sources by changing wrong variable ifC to if0, and...
- ...adding a missing weave() to the last MergeChroma() call
- Dropped Dither support. (Will still work/not work as before, but lack of official support renders it to a YMMV condition)
v2.1d (09-09-2012)
- Fixed Refinemotion Globals Input labels
- Fixed ContrasharpeningHD Vectors for Interlaced HD sources
- Added ability to import Global Vectors even when "tr" is lower than parent instance "tr" (credit to cretindesalpes)
- Expanded support for Interlaced Denoising "tr" up to 64 (credit to cretindesalpes)
- Cosmetics
v2.0d (07-06-2012)
- Fixed and optimized chroma handling for lsb_in, contrasharpening and YUY2 content v.1.95
- Enhanced Chroma bypass on the sharpening stage
- Merged ContraHD() internally for Contrasharpening in HD sources
- Dropped QTGMC support on import/export motion vectors (small value for increased confusion)
- Fixed Median code for planar inputs in MinBlur() (needs RemoveGrainHD, dropped medianblur requirement)
- Defaulted truemotion to false for HD inputs
- Code Optimization and Clean up
- Others
v1.9d (23-03-2012)
- Added truemotion parameter (default=true), change it to false (as in MCTemporalDenoise()), so low frequency detail won't be lost (walls...), although it could leave more noise on high frequency details
- Added thSADC, and thSCD1/thSCD2 parameters for finer control
- Tweaked prefilter=3 dfttest sigmas for better low frequency detail protection
- Detached explanation and converted to html. Updated and extended the contents as well
- Fine tuned and robustized the Show Panel
- Optimized and organized code, more precisely the contrasharpening part
- Fixed a few ternary checks for when Globals=3
- Others
v1.8d (18-01-2012)
- Added automatic dark protection for prefilter=3 (dfttest performs badly in darks) v1.71d and extended its dark protection v1.8
- Fixed chroma variable when chroma=false, from 2 (copy chroma) to 1 (discard chroma) v1.71d
- Explanation and cosmetics v1.71d
- Added acknowledgments and updated explanation
- Added brackets to all functions (it has been reported to cause threading problems under certain circumstances) (https://forum.doom9.org/showthread.php?p=1515886)
- Reworked and fixed the parameters panel. Now you have a color guide to have an idea on what to tweak depending on selected mode in Show. For strings: "Speed", "Memory" and "Quality"
- Optimized lsb_in for HD resolutions which was causing memory hogs
- Fixed contrasharpening for YUY2 sources when lsb=true
- Fixed some inconsistencies for YUY2 sources when prefilter=3
v1.7d (11-01-2012)
- Fixed and extended introduction explanation v.1.61d
- Fixed some issues for Globals=1 (Read) in relation to lsb_in and luma expansion auto-prefilter v.1.61d
- Added mild gauss blur prefilter option as prefilter=1. Consequent modes are displaced v.1.61d
- Changed prefilter 1 and 2 to Minblur (Gauss/Median combination) v.1.63d
- Updated MinBlur function v.1.62d and v.1.66
- Code tidied up v.1.62d
- Updated luma expansion, now you can enhance darks (with 'Str' and 'Amp') in the same step as the TV->PC conversion stage, thus +optimized, +quality. v.1.63d by cretindesalpes (https://forum.doom9.org/showthread.php?p=1548318)
- Removed pre_custom. Now use prefilter to load a prefiltered clip, as well as modes 0~3
- Added Show parameter. Now you can see the used and default parameters along the prefilter clip as well
- Fixed one note related to prefilter clip input for interlaced content
v1.6d (24-12-2011) (first open release)
- Fixed and extended introduction explanation
- Fixed Ditherpost for interlaced sources
- Fixed a broken reference for reading MRecalculate globals when tr>3
- Fixed a Globals=1 MSuper automatization
- Fixed a plane processing bypass when chroma=false
- Added LSFmod as optional contrasharpening (slower, but biased contrasharpening and probably better depending on source)
- Added default luma expansion auto-prefilter for motion search (16% more values)
- Added YUY2 support
- Added the 'mode' parameter of Ditherpost()
- Added support for interlaced temporal radius up to 6
v1.5d (14-10-2011)
- Changed "srchSuper" Global variable to "QTGMC_srchSuper", compatible with QTGMC. Anyhow you may probably want to create a new super clip. Test it out! v.1.41d
- Introduction spelling and presentation v.1.42d
- Added lsb and lsb_in for prefilter=2 (dfttest) v.1.43d & v.1.44d
- Some better definitions for the settings help v.1.45d
- pelclip is now subpixel = 3 ('sharp' parameter before) v.1.45d
- Other minor tweaks v.1.45d
- Fixed an important issue when using prefilter with subpixel=3 ('pelclip' parameter before)
- Optimizations in Ditherpost for chroma
- Changed rfilter (hierarchical levels smoothing/scaling) from default 2 to 4. Better results in my judge
- Some more little tweaks in code and introduction
v1.4d (16-09-2011)
- Added pelclip option for top quality subpixel interpolation when pel > 1
- Changed QTGMCV parameter to Globals, and added a bunch of new features like vectors output from SMDegrain()
- Big introduction and code optimization tweaks
v1.3d (14-09-2011)
- Fixed an important issue on the Interlaced parameter and improved overall handling (v.1.21d & v.1.3d)
v1.2d (13-09-2011)
- Added Interlaced parameter, for processing interlaced sources
- Some introduction and code optimization tweaks (v.1.12d & v.1.2d)
v1.1d (12-09-2011)
- Implemented MDegrainN for tr > 3, from the MVTools2 mod of Dither
- Minor introduction and code optimization tweaks
v1.0d (09-09-2011)
- Added CClip parameter. Reference an earlier stage of your processing chain as your sharp version for the contrasharpening
v0.9d (09-09-2011)
- Added QTGMCV parameter, for reusing vectors from QTGMC bob deinterlacer
v0.8d (05-09-2011)
- Fixed a few things related to the lsb_in option
- Minor introduction and code optimization tweaks
v0.7d (05-09-2011)
- Implemented "fake" lsb_in option. Output will have slightly more quality (if any), and will compress better. (Experimental)
- Fixed a not passed argument in the hpad, vpad parameters
v0.6d (04-09-2011)
- Minor introduction and code optimization tweaks
v0.5d (19-07-2011)
- Added dfttest option for preblur (now prefilter) option. Slower but better due to its internal deblock+denoise operation, plus sharper results
- Added pre_custom option for the prefilter process, define here a denoised clip as your prefiltered version
- Updated the introduction help
v0.4d (03-06-2011)
v0.3d (04-03-2011)
- First Mod version
- Fixed plane (for MDegrain) and added chroma (for MAnalyse) parameters
v0.2 (24-01-2010)
- Added introductory section
- Added more parameters
v0.1
- Basic working version
- Not released