Advertisement
Guest User

Untitled

a guest
Feb 1st, 2011
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 83.14 KB | None | 0 0
  1. #-------------------------------------------------------------------#
  2. # #
  3. # QTGMC 3.0, by Vit, 2011 #
  4. # #
  5. # Deinterlacer using motion-compensated temporal binomial smoothing #
  6. # Originally based on TempGaussMC_beta2 by Did馥 #
  7. # #
  8. #-------------------------------------------------------------------#
  9.  
  10. # See below for "Getting Started" instructions
  11.  
  12. # --- VERSION HISTORY ---
  13. #
  14. # v3.0: Introduced source-match modes and settings for higher fidelity output - supported for interlaced and progressive input
  15. # Most lossless settings removed - superseded by source-match, only Lossless integer remains
  16. # Added ProgSADMask setting for progressive repair modes (InputType=2,3) to help recover stable detail
  17. # Added RepChroma setting to allow disabling of chroma processing in repair stages (rep0,1,2)
  18. # Added DetailRestore setting for NoiseBypass - allowing denoising with some fine detail retention
  19. # Noise bypass with NoiseDeint="Generate" is now motion-compensated for better grain/detail restoral, NoiseDeint="Copy" removed
  20. # Corrected minor luma shift when using NoiseBypass (FFT3DFilter noise center is 128.5 not 128)
  21. # Added ShowNoise setting to display extracted noise, helps in determining Sigma
  22. # TDeint added as interpolator (suitable for source-match)
  23. # YadifPath no longer global
  24. # EdiMode for "Ultra Fast" changed from "TDIYadif" to "Yadif" (otherwise slower than "Super Fast" for non-threaded)
  25. # Bug fixes in Sbb and InputType=3
  26. # Complete rewrite of documentation and some script tidying
  27. # v2.51: Changed default interpolator to "NNEDI3" for presets up to "Super Fast" and (new) lossless presets up to "Faster"
  28. # Range of preset tweaks including higher quality output from "Super Fast" & "Ultra Fast" but with a little speed loss
  29. # Support for EdiMode="EEDI3+NNEDI3": EEDI3 with sclip taken from NNEDI3
  30. # Added LosslessPreset and EdiThreads parameters
  31. # Tidied up output from ShowSettings and small bug fix
  32. # Fixed serious bug when using lossless modes on the higher speed presets
  33. # v2.47: Fixed bug with default overlap when an explicit blocksize was given
  34. # v2.46: Replaced mt_average with merge - was causing exceptions in certain MT situations
  35. # v2.45: Tweaked use of Yadif: explicit loading is now optional, see YadifPath variable
  36. # v2.41: Removed explicit Yadif plugin load
  37. # v2.40: Support for lossless output with added parameters: Lossless, LosslessTR, LosslessEdi
  38. # Support for EdiMode("NNEDI3", "EEDI3")
  39. # Paramters NNeurons added & NNSize reworked for new -EDI3 versions
  40. # Minor preset tweaks for better quality/speed spread
  41. # v2.30: Added EdiExt (edeint in original TGMC)
  42. # Improved progressive input modes
  43. # v2.20: All rep values, SVThin and motion search settings supported
  44. # Better matching of Sbb
  45. # "Draft" preset. Default preset changed from "Slow" to "Slower"
  46. # Support for progressive input (InputType)
  47. # Sharpness values/defaults normalized
  48. # v2.10: Supported most of the remaining core TGMC features:
  49. # EdiMode("NNEDI", "Yadif"), TR2(3), SLmode(3,4), SLRad, Sbb(2,3)
  50. # Added noise bypass (removal / restoration)
  51. # Added ShowSettings
  52. # v2.00: First fully featured version
  53. # Supported majority of core TGMC features
  54. # Additional speed tweaks:
  55. # NNSize, SrchClipPP, SubPel, Precise
  56. # Added Presets system and beginnings of Tunings
  57. # v1.00: First draft - high speed basic TGMC algorithm only
  58.  
  59.  
  60. # --- REQUIREMENTS ---
  61. #
  62. # Download these plugins and put them in your plugin autoload folder (or load them in your calling script):
  63. # MVTools2 (2.58 or above)
  64. # MaskTools V2 (recommend 2.0a45 or above)
  65. # RemoveGrain + Repair
  66. # VerticalCleaner
  67. # Choice of: NNEDI3 (recommend 0.9.2 or above), NNEDI2, NNEDI, EEDI3, EEDI2, Yadif & TDeint
  68. # [Presets require NNEDI3 except "Ultra Fast", which requires Yadif]
  69. # FFT3DFilter (+FFTW3) (if using noise bypass)
  70. # AddGrainC (if using "Generate" mode for noise bypass)
  71. # [NNEDI3, EEDI3, TDeInt, FFT3DFilter and AddGrainC beyond standard TGMCb2 requirements]
  72.  
  73.  
  74. #---------------------------------------
  75.  
  76. # --- GETTING STARTED ---
  77. #
  78. # Install AviSynth and ensure you have the plugins listed in the requirements section above. Then to use QTGMC, write a script like this:
  79. # YourSource("yourfile") # DGDecode_mpeg2source, FFVideoSource, AviSource, whatever your source requires
  80. # QTGMC( Preset="Slow" )
  81. # SelectEven() # Add this line to keep original frame rate, leave it out for smoother doubled frame rate
  82. #
  83. # Save this script with an ".avs" extension. You can now use it as an AVI source for encoding.
  84. #
  85. # The "Preset" used selects sensible settings for a given encoding speed. Choose a preset from:
  86. # "Placebo", "Very Slow", "Slower", "Slow", "Medium", "Fast", "Faster", "Very Fast", "Super Fast", "Ultra Fast" & "Draft"
  87. # The default preset is "Slower". If you get crashes with the fastest presets ("Super Fast" and above) then use the SafeMode setting (described below)
  88. #
  89. # There are many settings for tweaking this script, full details are provided below. The settings have been divided into categories, which each having key
  90. # points, a detailed description, settings specifications/defaults, and several examples. The key points and examples should get you going.
  91. #
  92. # You can display the exact settings being used by a preset by using "ShowSettings":
  93. # QTGMC( Preset="Slow", ShowSettings=true )
  94.  
  95.  
  96. #--- CORE SETTINGS ---
  97. #
  98. # Key Points: For basic usage, select a preset and leave the core settings alone. Most useful setting is TR2, which controls smoothness and denoising of output.
  99. #
  100. # The core algorithm is this:
  101. # 0. Bob the source clip. Temporally smooth the bob to remove shimmer then analyse its motion
  102. # 1. More accurately interpolate the source clip (e.g. NNEDI3). Use the motion analysis from previous step to temporally smooth this interpolate with motion
  103. # compensation. This removes shimmer whilst retaining detail. Resharpen the result to counteract any blurring
  104. # 2. A final light temporal smooth to clean the result
  105. #
  106. # Stages 0 & 1 use a binomial smooth (similar to a Gaussian) to remove deinterlacing shimmer. Stage 2 uses a simple linear smoothing. So each stage involves a
  107. # temporal smooth with the radius (number of frames involved) given in the settings "TR0", "TR1" and "TR2". The binomial smooths are critical for the algorithm
  108. # so TR0 and TR1 should be at least 1. TR0 only affects the motion analysis and is only indirectly visible, increasing it to 2 will generally give a better
  109. # motion match. Increasing TR1 and TR2 will create a smoother and more stable output and more strongly denoise. The downside is that you will get more blurring
  110. # and may lose detail. The blur is counteracted by the sharpening settings described below. Also note that increased TR1 & TR2 can cause/strengthen halos where
  111. # the motion analysis is inaccurate
  112. #
  113. # The deinterlacer primarily tries to reduce "bob shimmer": horizontal lines of shimmer created when interpolating an interlaced stream. Consequently any
  114. # changes made to the initial interpolation (e.g. NNEDI3) are expected to be horizontal lines of change only. The repair stages "Rep0", "Rep1" & "Rep2"
  115. # occur after each temporal smooth. They only allow such horizontal lines of change - shimmer fixes, discarding other changes. This prevents the motion blur
  116. # that temporal smoothing could generate. The repX settings control the size of areas to allow through. See the RemoveNonBobDiff function comments for details.
  117. #
  118. # Settings:
  119. # TR0 (0,1,2) : Temporal binomial smoothing radius used to create motion search clip. In general 2=quality, 1=speed, 0=don't use
  120. # TR1 (0,1,2) : Temporal binomial smoothing radius used on interpolated clip for inital output. --------------"----------------
  121. # TR2 (0,1,2,3) : Temporal linear smoothing radius used for final stablization / denoising. Adjust for your denoising/smoothing requirements
  122. # Rep0 (>= 0) : Repair motion search clip (0 = off): only keep thin areas of difference from bob (see RemoveNonBobDiff function for details)
  123. # Rep1 (>= 0) : Repair initial output clip (0 = off): only keep thin areas of difference from edi
  124. # Rep2 (>= 0) : Repair final output clip (0 = off): --"--
  125. # RepChroma (bool) : Whether the repair modes affect chroma
  126. #
  127. # The presets determine the defaults for all these settings (see table in script or use "ShowSettings"), except RepChroma which defaults to true
  128. #
  129. # Examples:
  130. # QTGMC( Preset="Slow", TR2=3 ) # Strong final smooth (e.g. noisy / shimmery source)
  131. # QTGMC( 2,1,3, 4,0,4 ) # TempGaussMC style
  132.  
  133.  
  134. #--- INTERPOLATION ---
  135. #
  136. # Key Points: Interpolation affects quality and speed. The presets can be relied on to provide sensible defaults mostly using NNEDI3.
  137. #
  138. # The first step to create the deinterlaced output is to spatially interpolate a single half-height field into a full-height frame. A variety of interpolators
  139. # are supported, with various settings to control the quality/speed of the output.
  140. #
  141. # Settings:
  142. # EdiMode (string) : Interpolation method, from "NNEDI3", "NNEDI2", "NNEDI", "EEDI3+NNEDI3" (EEDI3 with sclip from NNEDI3), "EEDI3", "EEDI2",
  143. # "Yadif", "TDeint" or "TDIYadif" (combined TDeInt+Yadif), anything else uses "Bob"
  144. # NNSize (0-6) : Area around each pixel used as predictor for NNEDI3. A larger area is slower with better quality, read the NNEDI3 docs to see
  145. # : the area choices. Note: area sizes are not in increasing order (i.e. increased value doesn't always mean increased quality)
  146. # NNeurons (0-4) : Controls number of neurons in NNEDI2 (0-2) & NNEDI3 (0-4), larger = slower and better quality but improvements are small
  147. # EdiQual (1,2,3) : Quality setting for NNEDI2 (1,2,3) & NNEDI3 (1,2 only). Higher values for better quality - but improvements are marginal
  148. # EdiMaxD (>= 1) : Spatial search distance for finding connecting edges in EEDI2 and EEDI3
  149. # EdiThreads (>= 0) : Number of threads to use in EEDI3 & NNEDI2/3, 0 = default = number of logical processors on system. Also affects source-match
  150. # : interpolations. Source-match can add 2 further interpolations per frame, adjusting this setting can help balance system load
  151. # EdiExt (clip) : Provide externally created interpolated clip rather than use one of the above modes
  152. #
  153. # The presets determine defaults for NNEDIx and EEDIx (see table in script or use "ShowSettings"). Other defaults are EdiThreads=0, EdiExt=undefined
  154. #
  155. # Examples:
  156. # QTGMC( Preset="Slow", EdiMode="EEDI3", EdiMaxD=16 ) # Use EEDI3 with an explicit search radius
  157. # QTGMC( Preset="Very Slow", EdiThreads=2 ) # Specify number of threads (with default NNEDI3) useful to tweak if using SetMTMode or source-match
  158.  
  159.  
  160. #--- SHARPNESS ---
  161. #
  162. # Key Points: Always consider adjusting Sharpness setting to taste. The default 1.0 is fairly sharp. If using source-match default is 0.2 (see comments below)
  163. #
  164. # The core of the algorithm involves a binomial smooth to remove shimmer. So the result needs to be resharpened to counteract this blur. The main setting
  165. # "sharpness" defaults to 1.0 and is designed to retain the sharpness of stable areas. However, at this level the algorithm can cause moving areas to be
  166. # oversharpened so you may wish to reduce the level depending on source. Sharpness when using source-match behaves differently - see the section below
  167. #
  168. # The sharpness processing for a given setting is tweaked to remain roughly similar regardless of other settings. However, there will be minor differences, so
  169. # always consider adjusting sharpness if you tweak other major settings.
  170. #
  171. # Oversharpening is limited either spatially (SLMode = 1,3) or temporally (SLMode = 2,4). Temporal limiting is more "correct" but also more aggressive in
  172. # preventing sharpening. It's also slower. You can set a small value in the overshoot setting (SOvs) to give the temporal limiting a bit of "headroom". You can
  173. # also perform sharpness limiting later in the algorithm (SLMode = 3,4) for more sharpness, but with the potential for minor artefacts.
  174. #
  175. # Settings:
  176. # Sharpness (float) : How much to resharpen the temporally blurred clip ( >= 0.0, default is always 1.0 unlike original TGMC)
  177. # SMode (0,1,2) : Resharpening mode: 0 = none, 1 = difference from 3x3 blur kernel, 2 = vertical max/min average + 3x3 kernel
  178. # SLMode (0,1,2,3,4) : Sharpness limiting: 0 = off, [1 = by spatial comparison, 2 = by temporal comparison] : done before final temporal smooth
  179. # : [3 = by spatial comparison, 4 = by temporal comparison] : done after final temporal smooth
  180. # SLRad (>= 0) : Temporal or spatial radius used with sharpness limiting (depends on SLMode). Temporal radius can only be 0,1 or 3
  181. # SOvs (0..255) : Amount of overshoot allowed with temporal sharpness limiting (SLMode == 2,4), i.e. allow some oversharpening
  182. # SVThin (0.0...) : How much to thin down 1-pixel wide lines that have been widened due to interpolation into neighboring field lines
  183. # Sbb (0,1,2,3) : Back blend (blurred) difference between pre & post sharpened clip (minor fidelity improvement) :
  184. # : 0 = Off, 1 = before (1st) sharpness limiting, 2 = after (1st) sharpness limiting, 3 = both
  185. #
  186. # The presets determine defaults for SMode, SLMode, SLRad and Sbb (see table in script or use "ShowSettings"). Other defaults are: SOvs=0, SVThin=0.0, Sbb=0
  187. #
  188. # Examples:
  189. # QTGMC( Preset="Slow", Sharpness=0.4 ) # Reduce oversharpening
  190. # QTGMC( Preset="Slow", Sharpness=1.2, SLMode=1 ) # Increase sharpness, use spatial sharpness limiting (which typically allows more sharpening)
  191.  
  192.  
  193. #--- SOURCE-MATCH / LOSSLESS ---
  194. # Very detailed section for new feature [documentation likely to be thinned as feature matures]
  195. #
  196. # Key Points: Source-match creates higher fidelity output with extra processing. Enable with SourceMatch = 1,2 & 3. Higher values are slower and more accurate.
  197. # Can combine with Lossless setting (especially Lossless=2) for more detail again. Tweak speed with MatchPreset (like Preset). Will honor artefacts
  198. # in source, so best used with quality sources. By default sharpness becomes 0.2 & sharpness limiting switched off, so adjust sharpness carefully.
  199. # NOTE: THE EFFECTS OF THIS FEATURE ARE BOTH SUBTLE & PRECISE, INTENDED ONLY FOR EXACTING DETAIL. MAKE SURE YOU CAN SEE EXACTING DETAIL FIRST.
  200. #
  201. # Quickstart: The templates below increase in both quality and slowness. Choose preset as required (very fastest presets are not suitable though). Start with
  202. # Sharpness=0.2 and increase slightly if necessary. Set TR2=1 for clean source, set TR2=2 or TR2=3 (slower) if more denoising required or use Noise Bypass
  203. # QTGMC( Preset=XXXX, SourceMatch=1, Sharpness=XXX, TR2=X ) # Basic mode, fastest
  204. # QTGMC( Preset=XXXX, SourceMatch=1, Lossless=2, Sharpness=XXX, TR2=X ) # Good quality, efficient, minor residual combing
  205. # QTGMC( Preset=XXXX, SourceMatch=3, Sharpness=XXX, TR2=X ) # Good quality, slower, no combing
  206. # QTGMC( Preset=XXXX, SourceMatch=3, Lossless=2, Sharpness=XXX, TR2=X ) # Best quality, slowest, very minor residual combing
  207. #
  208. # Intuitively, a deinterlacer should just inject new fields into the source, leaving the original pixels untouched. The temporal blur/resharpen in this script
  209. # means that doesn't happen - the source pixels are changed in the output. The (optional) source-match steps attempt to fix this and make the result closer to
  210. # the source. They work by looking at the difference between output and source at different points in the algorithm and correcting for that difference.
  211. #
  212. # Matching to the source will capture more source detail and reduce oversharpening / haloing. Caveat: the default algorithm strongly temporally smooths but with
  213. # source-matching much less so (by necessity / design). Source-matching may faithfully recreate artefacts in the source (e.g blocking, banding & some noise) so
  214. # it's better for quality sources. The SourceMatch setting sets the mode: 0=off (standard [Q]TGMC algorithm), 1,2,3 for progressively more accurate but slower
  215. # processing. Modes 2 & 3 restore almost exact source detail but are sensitive to noise & introduce occasional aliasing (mode 3 is less affected). Mode 1 is a
  216. # more conservative halfway stage that rarely introduces artefacts.
  217. #
  218. # Since source-matching recovers sharpness, the Sharpness default is reduced to 0.2. Source-matching may initially appear less sharp than standard processing
  219. # because it will not oversharpen. However, be careful if raising the sharpness, because ***sharpness limiting is switched off by default***. This is because
  220. # sharpness limiting reduces the the accuracy of these modes. Use the MatchEnhance setting to exaggerate additional detail found by modes 2 & 3. This gives a
  221. # sharpening / detail enhancing effect and works well at sensible levels - but it's a slight cheat that should be used with care as it can easily enhance noise.
  222. # Since source-match is sensitive to source noise you may want to set TR2 to 2 or 3 and/or use noise bypass (see below) for extra denoising.
  223. #
  224. # The additional Lossless modes are designed to take SourceMatch to its logical conclusion: Lossless mode 1 restores the *exact* pixels of the source into the
  225. # output (provided NoiseRestore=0). This recovers a liitle more source detail but can introduce shimmering, minor combing, noise etc. Note the Sharpness and
  226. # MatchEnhance settings have little effect in lossless mode 1. Lossless mode 2 makes the clip lossless before the sharpening & final temporal smooth. Removes
  227. # most of the lossless artefacts and also allows sharpness control. This mode will not give an exactly lossless output, but it will gain a little more detail.
  228. #
  229. # The source-match settings introduce further processing. SourceMatch mode 1 requires a second interpolation (e.g. NNEDI3), but it can use a lower quality
  230. # settings than the main stage. SourceMatch mode 2 requires yet another interpolation, but works effectively with just a bob (but using a better interpolator
  231. # can reduce occasional aliasing). Mode 3 adds just a little more processing and is usually worth it as it reduces artefacts. There is no exact control over
  232. # the interpolations used (too many settings required), instead there is are MatchPresets that work in a similar way to the main Preset. The extra processing
  233. # suggests much slower speeds, but actually using higher speed presets (both MatchPreset and Preset) with source-matching can give results comparable to slower
  234. # presets without it. Having said that, the extra detail from source-matching is too subtle to significantly affect very high speed main presets.
  235. #
  236. # Settings:
  237. # SourceMatch (0,1,2,3) : 0 = Source-matching off (standard algorithm), 1 = basic source-match, 2 = refined match, 3 = twice refined match
  238. #
  239. #---SourceMatch=1,2,3---
  240. # MatchPreset (string) : Speed/quality for basic source-match processing, select from "Placebo", "Very Slow", "Slower", "Slow", "Medium", "Fast",
  241. # : "Faster", "Very Fast", "Super Fast", "Ultra Fast" ("Draft" not supported). Ideal choice is the same as main preset, but
  242. # : can choose a faster setting (but not a slower setting). Default is 3 steps faster than main preset.
  243. # MatchEdi (string) : Override default interpolation method for basic source-match. Default method is same as main EdiMode setting (usually NNEDI3)
  244. # : Only need to override if using slow method for main interpolation (e.g. EEDI3) and want a faster method for source-match
  245. #
  246. #---SourceMatch=2,3---
  247. # MatchPreset2 (string) : Speed/quality for refined source-match processing, select from "Placebo", "Very Slow", "Slower", "Slow", "Medium", "Fast",
  248. # : "Faster", "Very Fast", "Super Fast", "Ultra Fast" ("Draft" not supported). Default is 2 steps slower than MatchPreset.
  249. # : Use slower settings to help reduce aliasing that doesn't occur without source-match.
  250. # MatchEdi2 (string) : Override interpolation method for refined source-match. Rarely needed, maybe to explicitly pick bob for speed (MatchEdi2="")
  251. # MatchTR2 (0,1,2) : Temporal radius for refined source-matching. 2=quality, 1=speed/sharper, 0=not recommended. Difference very marginal
  252. # : Basic source-match doesn't need this setting as its temporal radius must match TR1 core setting (i.e. there is no MatchTR1)
  253. # MatchEnhance (0.0...) : Enhance the detail found by source-match modes 2 & 3. A slight cheat - will enhance noise if set too strong. Best at <= 1.0
  254. #
  255. #---Optional Extras---
  256. # Lossless (0,1,2) : Puts exact source fields into result & cleans any artefacts. 0=off, 1=after final temporal smooth, 2=before resharpening.
  257. # : Get a little extra detail but: mode 1 gets shimmer / minor combing, mode 2 is more stable/tweakable but not exactly lossless
  258. #
  259. # The defaults are: SourceMatch=0, MatchPreset=[3 settings quicker than main Preset], MatchPreset2=[2 settings quicker than MatchPreset]
  260. # MatchEdi = same as EdiMode, except if MatchPreset="Ultra Fast" when it is "Yadif"
  261. # MatchEdi2 = "NNEDI3", except if MatchPreset="Super Fast" when it is "TDeint", or if MatchPreset="Ultra Fast" when it is "" (bob)
  262. # MatchTR2=1, MatchEnhance=0.5, Lossless=0
  263. #
  264. # Examples:
  265. # QTGMC( Preset="Slow", SourceMatch=1 ) # Enable basic source-match. Result somewhat closer to source.
  266. # QTGMC( Preset="Slow", SourceMatch=1, Sharpness=0.4 ) # Basic source-match but sharper (up from 0.2). Be careful as sharpness limiting defaults to off
  267. # QTGMC( Preset="Slow", SourceMatch=1, Lossless=2 ) # Basic source-match with "fake" lossless. Efficient setting for quality, may bring minor combing
  268. #
  269. # QTGMC( Preset="Medium", SourceMatch=2, TR2=2 ) # Refined source-match, closer to source with no combing, slower. Increased TR2 reduces noise
  270. #
  271. # QTGMC( Preset="Slower", SourceMatch=3 ) # Twice refined source-match, higher quality than mode 2, but a little bit slower again
  272. # QTGMC( Preset="Slower", SourceMatch=3, Lossless=2 ) # Twice refined source-match with fake lossless. Almost perfect fidelity mode with few artefacts
  273. # QTGMC( Preset="Slower", SourceMatch=3, Lossless=1 ) # Twice refined source-match with true lossless. Exact detail, but likely combing and shimmer
  274. #
  275. # QTGMC( Preset="Slow", SourceMatch=3, Lossless=2, MatchEnhance=0.75 ) # Further enhance detail found by refined match, a little sharper, may be noisier
  276. # QTGMC( Preset="Slow", SourceMatch=3, Lossless=2, MatchEnhance=0.75, NoiseBypass=1, NoiseRestore=0.7, Sigma=1.5 ) # As above, denoise a little to help
  277. #
  278. # QTGMC( Preset="Slower", MatchPreset="Very Fast", SourceMatch=1 ) # Faster basic source-match preset (defaults to 3 steps faster than main Preset)
  279. # QTGMC( Preset="Slower", MatchPreset="Faster", MatchPreset2="Ultra Fast", SourceMatch=3 ) # Faster refined source-match preset as well
  280. # # (defaults to 2 steps faster than basic match Preset)
  281. # QTGMC( Preset="Slower", MatchPreset="Slow", MatchPreset2="Slow", SourceMatch=3 ) # Or use slower source-match presets (usually unnecessary)
  282. #
  283. # Very high quality tweaked example: use slow main preset but faster basic source-match preset. Adjust sharpness. Use detail-retaining noise bypass (see below)
  284. # QTGMC( Preset="Very Slow", MatchPreset="Medium", SourceMatch=3, Lossless=2, MatchEnhance=0.6, Sharpness=0.25, \
  285. # NoiseBypass=2, NoiseRemove=1.0, DetailRestore=0.5, NoiseRestore=0.1, Sigma=3, NoiseDeint="Generate" )
  286.  
  287.  
  288. #--- NOISE BYPASS ---
  289. #
  290. # Key Points: The Noise Bypass feature is used to retain, remove or strengthen noise & very fine detail. Refer to examples below for the different methods
  291. #
  292. # The use of multiple temporal smooths means that this script strongly denoises by default. When noise bypass is used, noise/grain is extracted from the source
  293. # at the start, then added back in again at the end. This allows the grain from the source to be kept and also helps retain fine detail/sharpness. There are
  294. # two modes, NoiseBypass=1 actually denoises at the start, whereas NoiseBypass=2 just identifies the noise in the source without removing it. So NoiseBypass=1
  295. # will denoise when the restore level is moved below 1.0, and NoiseBypass=2 will tend to strengthen/sharpen as the restore level exceeds about 0.3 or so
  296. #
  297. # First set a Sigma value to estimate the level of source noise. Then select how much noise to remove, NoiseRemove=1.0 is appropriate for most cases. Then
  298. # decide how much of that noise to restore. There are two restore points called DetailRestore/NoiseRestore (see below), the amount of noise restored depends on
  299. # their sum. A good starting point is 0.7/0.3 for NoiseBypass=1 and 0.3/0.1 for NoiseBypass=2. Note, only luma noise is considered in this script.
  300. #
  301. # Very fine detail can be detected as noise, but fine detail is often lost in the same way as noise. The setting DetailRestore helps restore such detail without
  302. # restoring too much noise, it controls how much of the extracted "noise" is restored before the final temporal smooth. This smooth will remove any actual noise
  303. # but keep fine detail that went through the bypass. By balancing the DetailRestore and NoiseRestore settings you can denoise whilst limiting the removal of
  304. # real detail. Usually best if DetailRestore is greater than NoiseRestore unless seeking to restore actual grain/noise. Start with the values given above, then
  305. # adjust up or down to get the grain/sharpness/detail you want. Too high restoral values will give detail/grain exaggeration and even luma changes.
  306. #
  307. # Settings:
  308. # NoiseBypass (0,1,2) : Noise bypass mode: 0 = disable, 1 = denoise source, storing the removed noise - add some of this noise back at end of script,
  309. # : 2 = store noise found in source but don't remove it (let QTGMC denoise) - add some back at end of script
  310. # NoiseRemove (0.0...1.0) : How much noise/grain to extract from the source clip (before the main processing)
  311. # DetailRestore(0.0...1.0...) : How much removed noise/grain to restore before final temporal smooth. Helps retain detail.
  312. # NoiseRestore (0.0...1.0...) : How much removed noise/grain to restore after final temporal smooth. Helps retain detail and noise.
  313. # NoiseDeint (string) : When noise is taken from interlaced source, how to 'deinterlace' it before restoring: "Bob", "DoubleWeave", or "Generate"
  314. # : "Bob" & "DoubleWeave" are fast but with minor issues: bob may shimmer and doubleweave lags by one frame. "Generate" is a
  315. # : high quality mode that motion-compensates the noise, but it is slower. Any unknown value selects "DoubleWeave"
  316. # Sigma (>= 0.0) : Amount of noise known to be in the source - typical values are 1.0 - 2.5 for DV. Must be high enough to find noticable noise
  317. # BT (0...5) : Temporal window for noise removal (see FFT3DFilter docs)
  318. # ShowNoise (0.0...) : Display extracted and "deinterlaced" noise rather than normal output. 0.0=off, otherwise multiplier for strength, set to
  319. # : around 4.0-8.0 to ensure noise is visible. Visualising noise helps to determine suitable value for Sigma.
  320. #
  321. # For most presets the defaults are: NoiseBypass=0, NoiseRemove=1.0, Noise/DetailRestore=0.0, NoiseDeint="DoubleWeave", Sigma=2.0 and BT varies by preset
  322. # In "Placebo", "Very Slow" the defaults are: NoiseBypass=2, NoiseRemove=1.0, DetailRestore=0.3, NoiseRestore=0.1, Sigma=2.0 & NoiseDeint/BT varies by preset
  323. # Be sure to override all the values you are interested in
  324. #
  325. # Examples:
  326. # QTGMC( Preset="Slower", NoiseBypass=1, NoiseRemove=1.0, NoiseRestore=1.0, Sigma=2.0 ) # Pass through all the noise of a somewhat noisy source
  327. # QTGMC( Preset="Slower", NoiseBypass=1, NoiseRemove=1.0, NoiseRestore=0.2, Sigma=2.5 ) # Pass through a little of the noise of a noisy source
  328. # QTGMC( Preset="Slower", NoiseBypass=2, NoiseRemove=1.0, NoiseRestore=0.4, Sigma=2.5 ) # Using stronger mode 2, retains noise and sharpens slightly
  329. # QTGMC( Preset="Slower", NoiseBypass=1, NoiseRemove=1.0, NoiseRestore=0.0, Sigma=1.5 ) # Denoise the source (sigma controls amount of denoising)
  330. # QTGMC( Preset="Slower", NoiseBypass=2, NoiseRemove=1.0, NoiseRestore=0.6, Sigma=1.8, NoiseDeint="Generate" ) # Strengthen with good quality grain
  331. # QTGMC( Preset="Slower", NoiseBypass=1, NoiseRemove=1.0, DetailRestore=0.8, NoiseRestore=0.3, Sigma=2.0 ) # Denoise, but retain some fine detail
  332. # QTGMC( Preset="Slower", NoiseBypass=2, NoiseRemove=1.0, DetailRestore=0.4, NoiseRestore=0.2, Sigma=1.8, NoiseDeint="Generate" ) # As above with stronger
  333. # # precise detail & grain
  334.  
  335. #--- MOTION ANALYSIS ---
  336. #
  337. # Key Points: The presets make sensible choices for motion analysis. Some sources or requirements may require tweaks, but read these and MVTools2 docs first.
  338. #
  339. # The bobbed source clip is sent to the MVTools2 plugin to perform motion analysis. Almost all these settings are used directly in MVTools2 functions.
  340. # Read the MVTools2 documentation for more details on their purpose. Some settings can be altered for a speed / accuracy tradeoff. Less accurate motion search
  341. # can result in blurring and/or oversharpening (in different circumstances) as well as slight distortions of visual elements. The faster presets gain speed by
  342. # simplifying the motion search parameters, use the "ShowSettings" parameter or look at the table a short way into the script to see how.
  343. #
  344. # Settings:
  345. # SrchClipPP (0,1,2) : Pre-processing for motion search clip, 0 = none, 1 = Gauss blur (spatial), 2 = Gauss blur + edge soften
  346. # SubPel (1,2,4) : Sub-pixel accuracy for motion analysis (1 = 1 pixel, 2 = 1/2 pixel, 4 = 1/4 pixel)
  347. # SubPelInterp (0,1,2) : Interpolation used for sub-pixel motion analysis: 0 = bilinear (soft), 1 = bicubic (sharper), 2 = Weiner (sharpest)
  348. # Blocksize (4,8,16,32) : Size of blocks that are matched during motion analysis
  349. # Overlap (< Blocksize/2) : How much to overlap motion analysis blocks (requires more blocks, but essential to smooth block edges in motion compenstion)
  350. # Search (0...5) : Search method used for matching motion blocks - see MVTools2 documentation for available algorithms
  351. # SearchParam (0...) : Parameter for search method chosen. For default search method (hexagon search) it is the search range
  352. # PelSearch (0...) : Search parameter (as above) for the finest sub-pixel level (see SubPel)
  353. # TrueMotion (bool) : Whether to use the 'truemotion' defaults from MAnalyse (see MVTools2 documentation)
  354. # Lambda (0...) : Motion vector field coherence - how much the motion analysis favors similar motion vectors for neighboring blocks
  355. # : Should be scaled by BlockSize*BlockSize/64
  356. # LSAD (0...) : How much to reduce need for vector coherence (i.e. Lambda above) if prediction of motion vector from neighbors is poor,
  357. # : typically in areas of complex motion. This value is scaled in MVTools (unlike Lambda)
  358. # PNew (0...) : Penalty for choosing a new motion vector for a block over an existing one - avoids chosing new vectors for minor gain
  359. # PLevel (0,1,2) : Mode for scaling lambda across different sub-pixel levels (??) - see MVTools2 documentation for choices
  360. # GlobalMotion (bool) : Whether to estimate camera motion to assist in selecting block motion vectors
  361. # DCT (0...10) : Modes to use DCT (frequency analysis) or SATD as part of the block matching process - see MVTools2 documentation for choices
  362.  
  363.  
  364. #--- PROGRESSIVE INPUT ---
  365. #
  366. # Key Points: Can remove horizontal shimmering effects from progressive sources. Experiment with InputType=1, 2 or 3 for best results. FPS will not be doubled
  367. #
  368. # This script is designed for deinterlacing and so by default expects an interlaced clip. However, much of its operation concerns the reduction of horizontal
  369. # shimmering. It is possible to use the script to remove similar shimmer from a progressive clip by using the InputType setting. InputType=1 is used for
  370. # general progressive material that contains less severe problems. InputType=2,3 are designed for badly deinterlaced material with considerable horizontal
  371. # artefacts. These modes drop half the fields and recreate an interlaced stream from the others, which is then treated in the normal way. Mode 3 differs from
  372. # mode 2 only in that it complements field parity of the input. Generally mode 1 will retain more detail, but repair less artefacts than modes 2,3. You may
  373. # consider setting TR2 to a higher value (e.g. 2 or 3) when repairing progressive material.
  374. #
  375. # Source-match is supported for progressive material. It works well for InputType=2,3, where the input is converted to an interlaced stream, and helps in detail
  376. # retention. Source-match is much less useful for InputType=1
  377. #
  378. # Settings:
  379. # InputType (0,1,2,3) : Default = 0 for interlaced input. Values > 0 to accept progressive input - for deshimmer and denoising (fps not changed)
  380. # : Mode 1 is for general progressive material. Modes 2 & 3 are designed for badly deinterlaced material
  381. # ProgSADMask (0.0...) : Only applies to InputType=2,3. If ProgSADMask > 0.0 then blend InputType modes 1 and 2/3 based on block motion SAD. Higher
  382. # : values will recover more detail, but repair less artefacts. Reasonable range about 2.0 to 20.0, or 0.0 for no blending
  383. #
  384. # The defaults are InputType=0, ProgSADMask = 10.0 (slower presets) or 0.0 (faster presets)
  385. #
  386. # Examples:
  387. # QTGMC( Preset="Slower", InputType=1 ) # Process progressive source, it will be temporally smoothed / deshimmered
  388. # QTGMC( Preset="Slower", InputType=2, ProgSADMask=12.0 ) # Process progressive source with major artefacts, slightly favoring detail over repairs
  389.  
  390.  
  391. #--- MISCELLANEOUS ---
  392. #
  393. # Settings not covered above. Note that Border is false by default, which differs from TempGaussMC
  394. #
  395. # Settings:
  396. # Border (bool) : Pad a little vertically while processing (doesn't affect output size) - set true you see flickering at top or bottom edges
  397. # Precise (bool) : Set to false to use faster algorithms with *very* slight imprecision in places
  398. # Preset (string) : Sets a range of defaults for different encoding speeds. Select from "Placebo", "Very Slow", "Slower", "Slow", "Medium",
  399. # : "Fast", "Faster", "Very Fast", "Super Fast", "Ultra Fast" & "Draft"
  400. # Tuning (string) : Tweaks the defaults for different source types. Choose from "None", "DV-SD", "DV-HD". Default is "None".
  401. # : An idea for development based on the x264 approach, but as I don't work with many source types it has seen little development
  402. # SafeMode (bool) : Avoid settings that potentially cause errors with other plugins. Use if "Ultra Fast" preset causes crashes.
  403. # ShowSettings (bool) : Display all the current parameter values - useful to find preset defaults
  404.  
  405.  
  406. # --- TempGaussMC NOTES ---
  407. #
  408. # In its default setup this script is very similar in operation to TempGaussMC_beta2. The call QTGMC() is almost exactly the same as:
  409. # TempGaussMC_beta2( 2,2,1, EdiMode="nnedi3", Border=false, SVthin=0.0 )
  410. # There are a few key differences:
  411. # Sharpness default is always 1.0 (or 0.2 if using source-match) - adjusted internally to give very roughly the same sharpness across settings / presets
  412. # SVThin defaults to 0, Border defaults to false
  413. # Lossless and Draft modes are supported but in a different way
  414. # The parameter order is the same up to "EdiMode", a couple of 'lesser' parameters have had name changes for consistency
  415.  
  416.  
  417. function QTGMC( clip Input, int "TR0", int "TR1", int "TR2", int "Rep0", int "Rep1", int "Rep2", bool "RepChroma", string "EdiMode", int "NNSize", \
  418. int "NNeurons", int "EdiQual", int "EdiMaxD", int "EdiThreads", clip "EdiExt", float "Sharpness", int "SMode", int "SLMode", int "SLRad", \
  419. int "SOvs", float "SVThin", int "Sbb", int "SrchClipPP", int "SubPel", int "SubPelInterp", int "BlockSize", int "Overlap", int "Search", \
  420. int "SearchParam", int "PelSearch", bool "TrueMotion", int "Lambda", int "LSAD", int "PNew", int "PLevel", bool "GlobalMotion", int "DCT", \
  421. int "SourceMatch", string "MatchPreset", string "MatchEdi", string "MatchPreset2", string "MatchEdi2", int "MatchTR2", \
  422. float "MatchEnhance", int "Lossless", int "NoiseBypass", float "NoiseRemove", float "DetailRestore", float "NoiseRestore", \
  423. string "NoiseDeint", float "Sigma", int "BT", int "InputType", float "ProgSADMask", bool "Border", bool "Precise", \
  424. string "Preset", string "Tuning", bool "SafeMode", float "ShowNoise", bool "ShowSettings" )
  425. {
  426. # The preset "Ultra Fast" & EdiMode="TDIYadif"/"Yadif" require the Yadif plugin, which doesn't autoload. Typically the calling script would load it.
  427. # To have this script load Yadif put it's full path in string below (e.g. "C:\Plugins\Yadif.dll"). Use empty string ("") if calling script will load Yadif
  428. YadifPath = "" # Or just enter "yadif.dll" if Yadif is placed in the system path (e.g. windows\system32)
  429.  
  430.  
  431. #---------------------------------------
  432. # Presets
  433.  
  434. SafeMode = default( SafeMode, false )
  435.  
  436. # Select presets / tuning
  437. Preset = default( Preset, "Slower" )
  438. pNum = (Preset == "Placebo" ) ? 0 : \
  439. (Preset == "Very Slow" ) ? 1 : \
  440. (Preset == "Slower" ) ? 2 : \
  441. (Preset == "Slow" ) ? 3 : \
  442. (Preset == "Medium" ) ? 4 : \
  443. (Preset == "Fast" ) ? 5 : \
  444. (Preset == "Faster" ) ? 6 : \
  445. (Preset == "Very Fast" ) ? 7 : \
  446. (Preset == "Super Fast") ? 8 : \
  447. (Preset == "Ultra Fast") ? 9 : \
  448. (Preset == "Draft" ) ? 10 : 11
  449. Assert( pNum < 11, "'Preset' is invalid" )
  450. mpNum1 = (!defined(MatchPreset)) ? ((pNum + 3 <= 9) ? (pNum + 3) : 9) : \
  451. (MatchPreset == "Placebo" ) ? 0 : \
  452. (MatchPreset == "Very Slow" ) ? 1 : \
  453. (MatchPreset == "Slower" ) ? 2 : \
  454. (MatchPreset == "Slow" ) ? 3 : \
  455. (MatchPreset == "Medium" ) ? 4 : \
  456. (MatchPreset == "Fast" ) ? 5 : \
  457. (MatchPreset == "Faster" ) ? 6 : \
  458. (MatchPreset == "Very Fast" ) ? 7 : \
  459. (MatchPreset == "Super Fast") ? 8 : \
  460. (MatchPreset == "Ultra Fast") ? 9 : \
  461. (MatchPreset == "Draft" ) ? 10 : 11
  462. Assert( mpNum1 < 11, "'MatchPreset' is invalid/unsupported" )
  463. MatchPreset = Select( mpNum1, "Placebo", "Very Slow", "Slower", "Slow", "Medium", "Fast", "Faster", "Very Fast", "Super Fast", "Ultra Fast", "Draft" )
  464. mpNum2 = (!defined(MatchPreset2)) ? ((mpNum1 + 2 <= 9) ? (mpNum1 + 2) : 9) : \
  465. (MatchPreset2 == "Placebo" ) ? 0 : \
  466. (MatchPreset2 == "Very Slow" ) ? 1 : \
  467. (MatchPreset2 == "Slower" ) ? 2 : \
  468. (MatchPreset2 == "Slow" ) ? 3 : \
  469. (MatchPreset2 == "Medium" ) ? 4 : \
  470. (MatchPreset2 == "Fast" ) ? 5 : \
  471. (MatchPreset2 == "Faster" ) ? 6 : \
  472. (MatchPreset2 == "Very Fast" ) ? 7 : \
  473. (MatchPreset2 == "Super Fast") ? 8 : \
  474. (MatchPreset2 == "Ultra Fast") ? 9 : \
  475. (MatchPreset2 == "Draft" ) ? 10 : 11
  476. Assert( mpNum2 < 11, "'MatchPreset2' is invalid/unsupported" )
  477. MatchPreset2 = Select( mpNum2, "Placebo", "Very Slow", "Slower", "Slow", "Medium", "Fast", "Faster", "Very Fast", "Super Fast", "Ultra Fast", "Draft" )
  478. Tuning = default( Tuning, "None" )
  479. tNum = (Tuning == "None" ) ? 0 : \
  480. (Tuning == "DV-SD" ) ? 1 : \
  481. (Tuning == "DV-HD" ) ? 2 : 3
  482. Assert( tNum < 3, "'Tuning' is invalid" )
  483.  
  484. # Tunings only affect blocksize in this version
  485. bs = Select( tNum, 16, 16, 32 )
  486. bs2 = (bs >= 16) ? 32 : bs * 2
  487. ovf = (SafeMode) ? 2 : 4 # Overlap other than 1/2 blocksize sometimes causes crashes in MVTools (??)
  488.  
  489. # Very Very Super Ultra
  490. # Preset groups: Placebo Slow Slower Slow Medium Fast Faster Fast Fast Fast Draft
  491. TR0 = default( TR0, Select( pNum, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1 ))
  492. TR1 = default( TR1, Select( pNum, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 ))
  493. TR2 = default( TR2, Select( pNum, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0 ))
  494. Rep0 = default( Rep0, Select( pNum, 4, 4, 4, 4, 3, 3, 0, 0, 0, 0, 0 ))
  495. Rep1 = default( Rep1, Select( pNum, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ))
  496. Rep2 = default( Rep2, Select( pNum, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 0 ))
  497. EdiMode = default( EdiMode, Select( pNum, "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "Yadif", "" ))
  498. NNSize = default( NNSize, Select( pNum, 1, 1, 1, 1, 5, 5, 4, 4, 4, 4, 4 ))
  499. NNeurons = default( NNeurons, Select( pNum, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0 ))
  500. EdiMaxD = default( EdiMaxD, Select( pNum, 12, 10, 8, 7, 7, 6, 6, 5, 4, 4, 4 ))
  501. EdiQual = default( EdiQual, Select( pNum, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ))
  502. SMode = default( SMode, Select( pNum, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 ))
  503. SLMode = default( SLMode, Select( pNum, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0 ))
  504. SLRad = default( SLRad, Select( pNum, 3, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ))
  505. Sbb = default( Sbb, Select( pNum, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ))
  506. NoiseBypass = default( NoiseBypass, Select( pNum, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 ))
  507. NoiseDeint = default( NoiseDeint, Select( pNum, "Generate","Bob", "", "", "", "", "", "", "", "", "" ))
  508. BT = default( BT, Select( pNum, 5, 3, 3, 3, 3, 2, 1, 1, 1, 1, 1 ))
  509. SrchClipPP = default( SrchClipPP, Select( pNum, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0 ))
  510. SubPel = default( SubPel, Select( pNum, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 ))
  511. Blocksize = default( Blocksize, Select( pNum, bs, bs, bs, bs, bs, bs, bs2, bs2, bs2, bs2, bs2 ))
  512. bs = Blocksize
  513. Overlap = default( Overlap, Select( pNum, bs/2, bs/2, bs/2, bs/2, bs/2, bs/2, bs/2, bs/2, bs/ovf, bs/ovf, bs/ovf ))
  514. Search = default( Search, Select( pNum, 5, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0 ))
  515. SearchParam = default( SearchParam, Select( pNum, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1 ))
  516. PelSearch = default( PelSearch, Select( pNum, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 ))
  517. Precise = default( Precise, Select( pNum, true, true, false, false, false, false, false, false, false, false, false ))
  518. ProgSADMask = default( ProgSADMask, Select( pNum, 10.0, 10.0, 10.0, 10.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ))
  519.  
  520. # The basic source-match step corrects and re-runs the interpolation of the input clip. So it initialy uses same interpolation settings as the main preset
  521. SourceMatch = default( SourceMatch, 0 )
  522. MatchEdi = EdiMode
  523. MatchNNSize = NNSize
  524. MatchNNeurons = NNeurons
  525. MatchEdiMaxD = EdiMaxD
  526. MatchEdiQual = EdiQual
  527.  
  528. # However, can use a faster initial interpolation when using source-match allowing the basic source-match step to "correct" it with higher quality settings
  529. Assert( mpNum1 >= pNum, "'MatchPreset' cannot use a slower setting than 'Preset'" )
  530. # Very Very Super Ultra
  531. # Basic source-match presets Placebo Slow Slower Slow Medium Fast Faster Fast Fast Fast
  532. NNSize = (SourceMatch == 0) ? NNSize : Select( mpNum1, 1, 1, 1, 1, 5, 5, 4, 4, 4, 4 )
  533. NNeurons = (SourceMatch == 0) ? NNeurons : Select( mpNum1, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0 )
  534. EdiMaxD = (SourceMatch == 0) ? EdiMaxD : Select( mpNum1, 12, 10, 8, 7, 7, 6, 6, 5, 4, 4 )
  535. EdiQual = (SourceMatch == 0) ? EdiQual : Select( mpNum1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 )
  536. EdiMode = (SourceMatch == 0) ? EdiMode : default( MatchEdi, ((mpNum1 < 9) ? EdiMode : "Yadif") ) # Default: use main preset EdiMode, except "Ultra Fast"
  537.  
  538. # Very Very Super Ultra
  539. # Refined source-match presets Placebo Slow Slower Slow Medium Fast Faster Fast Fast Fast
  540. MatchEdi2 = default( MatchEdi2, Select( mpNum2, "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "NNEDI3", "TDeint", "" ) )
  541. MatchNNSize2 = Select( mpNum2, 1, 1, 1, 1, 5, 5, 4, 4, 4, 4 )
  542. MatchNNeurons2 = Select( mpNum2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0 )
  543. MatchEdiMaxD2 = Select( mpNum2, 12, 10, 8, 7, 7, 6, 6, 5, 4, 4 )
  544. MatchEdiQual2 = Select( mpNum2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 )
  545.  
  546.  
  547. #---------------------------------------
  548. # Settings
  549.  
  550. # Core and Interpolation defaults
  551. RepChroma = default( RepChroma, true )
  552. EdiThreads = default( EdiThreads, 0 )
  553. NNeurons = (EdiMode == "NNEDI2" && NNeurons > 2) ? 2 : NNeurons # Smaller range for NNeurons in NNEDI2 (which calls it nsize)
  554. EdiQual = (EdiMode == "NNEDI3" && EdiQual > 2 ) ? 2 : EdiQual # Smaller range for EdiQual in NNEDI3
  555. ((FindStr( EdiMode, "Yadif" ) != 0 || FindStr( MatchEdi, "Yadif" ) != 0 || FindStr( MatchEdi2, "Yadif" ) != 0 ) && YadifPath != "") ? \
  556. Load_Stdcall_Plugin( YadifPath ) : NOP() # Load Yadif as required
  557.  
  558. # Source-match / lossless defaults
  559. MatchTR1 = TR1
  560. MatchTR2 = default( MatchTR2, 1 )
  561. MatchEnhance = default( MatchEnhance, ((SourceMatch > 1) ? 0.5 : 0.0) ) # Shouldn't need to force to 0 if SourceMatch <= 1, but goes slightly slower if
  562. # this isn't done. Bug in AviSynth graph-building?
  563. Lossless = default( Lossless, 0 )
  564.  
  565. # Sharpness defaults. Sharpness default is always 1.0 (0.4 with source-match), but adjusted to give roughly same sharpness for all settings
  566. SMode = (defined(Sharpness) && Sharpness == 0.0) ? 0 : SMode
  567. SLMode = (SourceMatch > 0 || SLRad <= 0) ? 0 : SLMode # ***Sharpness limiting disabled for source-match***
  568. Sharpness = default( Sharpness, (SMode == 0) ? 0.0 : ((SourceMatch > 0) ? 0.2 : 1.0) ) # Default sharpness is 1.0, or 0.2 if using source-match
  569. sharpMul = (SLMode == 2 || SLMode == 4) ? 2 : (SLMode == 1 || SLMode == 3) ? 1.5 : 1 # Adjust sharpness based on other settings
  570. sharpAdj = Sharpness * (sharpMul * (0.2 + TR1*0.15 + TR2*0.25) + ((SMode == 1) ? 0.1 : 0)) # [This needs a bit more refinement]
  571. Sbb = (SMode == 0) ? 0 : Sbb
  572. SOvs = default( SOvs, 0 )
  573. SVThin = default( SVThin, 0.0 )
  574.  
  575. # Noise bypass settings
  576. NoiseRemove = default( NoiseRemove, Select( NoiseBypass, 1.0, 1.0, 1.0 ))
  577. DetailRestore = default( DetailRestore, Select( NoiseBypass, 0.0, 0.7, 0.3 ))
  578. NoiseRestore = default( NoiseRestore, Select( NoiseBypass, 0.0, 0.3, 0.1 ))
  579. Sigma = default( Sigma, 2.0 )
  580. NoiseBypass = (NoiseRemove <= 0.0) ? 0 : NoiseBypass
  581. NoiseRemove = (NoiseBypass == 0) ? 0.0 : NoiseRemove
  582. DetailRestore = (NoiseBypass == 0) ? 0.0 : DetailRestore
  583. NoiseRestore = (NoiseBypass == 0) ? 0.0 : NoiseRestore
  584.  
  585. # MVTools settings
  586. SubPelInterp = default( SubPelInterp, 2 )
  587. TrueMotion = default( TrueMotion, false )
  588. Lambda = default( Lambda, ((TrueMotion) ? 1000 : 100 ) * (BlockSize*BlockSize)/(8*8) )
  589. LSAD = default( LSAD, (TrueMotion) ? 1200 : 400 )
  590. PNew = default( PNew, (TrueMotion) ? 50 : 25 )
  591. PLevel = default( PLevel, (TrueMotion) ? 1 : 0 )
  592. GlobalMotion = default( GlobalMotion, true )
  593. DCT = default( DCT, 0 )
  594.  
  595. # Some sensitive MVTools settings are no longer parameters
  596. _thSAD1 = 10 * 8*8 # SAD threshold for motion block matching: for intial temporal smooth (over 8x8 block as required by MVTools)
  597. _thSAD2 = 4 * 8*8 # SAD threshold for motion block matching: stabilising temporal smooth (--"--)
  598. _thSCD1 = 180 # Scene change detection parameter
  599. _thSCD2 = 98 # --"--
  600.  
  601. # Miscellaneous
  602. InputType = default( InputType, 0 )
  603. Border = default( Border, false )
  604. ShowNoise = default( ShowNoise, 0.0 )
  605. ShowSettings = default( ShowSettings, false )
  606. rgBlur = (Precise) ? 11 : 12 # Version of RemoveGrain blur to use
  607.  
  608.  
  609. #---------------------------------------
  610. # Pre-Processing
  611.  
  612. w = Input.Width()
  613. h = Input.Height()
  614. epsilon = 0.0001 # Error margin to avoid rounding problems
  615.  
  616. # Reverse "field" dominance for progressive repair mode 3 (only difference from mode 2)
  617. compl = (InputType == 3) ? Input.ComplementParity() : Input
  618.  
  619. # Pad vertically during processing (to prevent artefacts at top & bottom edges)
  620. bordered = (Border) ? compl.PointResize( w,h+8, 0,-4,0,h+8+epsilon ) : compl
  621. h = (Border) ? h+8 : h
  622.  
  623. # Extract noise/grain from source, keep removed noise for restoring later. If NoiseBypass == 2, the noise is extracted and stored but not removed from
  624. # the source - allowing the QTGMC process to do the denoising (avoids effectively denoising twice)
  625. denoised = (NoiseRemove > 0.0) ? bordered.FFT3DFilter( sigma=Sigma, beta=1.0 / NoiseRemove, bt=BT, interlaced=true, plane=0 ) : bordered
  626. noise = mt_makediff( bordered, denoised, U=1,V=1 )
  627. clip = (NoiseBypass == 1) ? denoised : bordered
  628.  
  629. # 'Deinterlace' the extracted noise. Noise is extracted from interlaced source but will be added back to progressive, so create the missing lines of noise.
  630. deintNoise = (InputType > 0) ? noise : \
  631. (NoiseDeint == "Bob") ? noise.Bob( 0,0.5 ) : \
  632. (NoiseDeint == "Generate") ? noise.Generate2ndFieldNoise() : \
  633. noise.DoubleWeave()
  634.  
  635. #---------------------------------------
  636. # Motion Analysis
  637.  
  638. # Bob the input as a starting point for motion search clip
  639. bobbed = (InputType == 0) ? clip.Bob( 0,0.5 ) : \
  640. (InputType == 1) ? clip : \
  641. clip.Blur( 0,1 )
  642.  
  643. # Support badly deinterlaced progressive content - drop half the fields and reweave to get 1/2fps interlaced stream appropriate for QTGMC processing
  644. ediInput = (InputType < 2) ? clip : clip.SeparateFields().SelectEvery(4,0,3).Weave()
  645.  
  646. # Create interpolated image as starting point for output
  647. edi = defined(EdiExt) ? EdiExt.PointResize( w,h, 0,(EdiExt.Height()-h)/2, -0,h+epsilon ) : \
  648. Interpolate( ediInput, InputType, EdiMode, NNSize, NNeurons, EdiQual, EdiMaxD, EdiThreads, bobbed )
  649.  
  650. # WARNING: Excessively long comment to precisely capture the algorithm
  651. # The bobbed clip will shimmer due to being derived from alternating fields, which makes motion analysis erratic. Blurring the image over a few frames will
  652. # remove the shimmer if done precisely. The shimmer will be an alternating effect between even and odd fields. We can guarantee to remove a shimmer of this
  653. # frequency by giving equal overall weight to the even and odd fields in the temporal average. For example, give the three frames centered on the current
  654. # frame the weights: 1, 2, 1 - this gives 50% weight to the central frame, and *a total* of 50% weight for the previous/next (opposite parity) frames. The
  655. # alternating shimmer is averaged away by such a kernel and for a temporal radius of 1 it's actually the only choice. For a wider temporal radius of 2, we
  656. # have a few choices of kernel, e.g. 1,3,4,3,1 or 1,4,6,4,1 or 2,3,2,3,2 etc. Any kernel where the odd values total to the same as the even values.
  657. # Now, a gaussian temporal blur is a decent pre-filter before a motion search - keeping the central frame prominent, but also removing high frequency noise
  658. # that would disturb the search. The kernel 1,4,6,4,1 above is a close approximation to a Gaussian kernel, so is chosen for the default temporal radius of 2
  659. # Actually the kernels 1,2,1 and 1,4,6,4,1 are *not* Gaussian kernels, but *Binomial* kernels. The kernel weights are taken from the coefficients of the
  660. # polynomial (x+1)^n, where n = (temporal radius * 2). Or more simply rows taken from "Pascal's Triangle". All Binomial kernels satisfy the "sum of odd
  661. # weights = sum of even weights" concept and they are all good approximations to Gaussian kernels. But it does imply that this script (and the original)
  662. # should properly be called (Q)TBMC: Temporal Binomial smooth with Motion-Compensation
  663.  
  664. # Create linear weightings of neighbors first -2 -1 0 1 2
  665. ts1 = bobbed.TemporalSoften( 1, 255,255, 28, 2 ) # 0.00 0.33 0.33 0.33 0.00
  666. ts2 = bobbed.TemporalSoften( 2, 255,255, 28, 2 ) # 0.20 0.20 0.20 0.20 0.20
  667.  
  668. # Combine linear weightings to give binomial weightings - TR0=0: (1), TR0=1: (1:2:1), TR0=2: (1:4:6:4:1)
  669. binomial0 = (TR0 == 0) ? bobbed : \
  670. (TR0 == 1) ? ts1.Merge( bobbed, 0.25 ) : \
  671. ts1.Merge( ts2, 0.357 ).Merge( bobbed, 0.125 )
  672.  
  673. # Remove areas of difference between temporal blurred motion search clip and bob that are not due to bob-shimmer - removes general motion blur
  674. repair0 = (Rep0 == 0) ? binomial0 : binomial0.RemoveNonBobDiff( bobbed, Rep0, RepChroma )
  675.  
  676. # Soften edges to assist in motion matching of edge blocks. Blocks are matched by SAD (sum of absolute differences between blocks), but even a slight
  677. # difference around an edge from frame to frame will give a high SAD due to the higher contrast of edges
  678. spatialBlur = repair0.RemoveGrain(rgBlur).GaussResize( w,h, 0,0, w+epsilon,h+epsilon, p=2 ).Merge( repair0, 0.1 )
  679. tweaked = mt_lutxy( repair0, bobbed, "x 3 + y < x 3 + x 3 - y > x 3 - y ? ?", U=3,V=3 )
  680. srchclip = (SrchClipPP == 0) ? repair0 : \
  681. (SrchClipPP == 1) ? spatialBlur : \
  682. spatialBlur.mt_lutxy( tweaked, "x 7 + y < x 2 + x 7 - y > x 2 - x 51 * y 49 * + 100 / ? ?", U=3,V=3 )
  683.  
  684. # Calculate forward and backward motion vectors from motion search clip
  685. srchSuper = srchClip.MSuper( pel=SubPel, sharp=SubPelInterp )
  686. bVec3 = srchSuper.MAnalyse( isb=true, delta=3, blksize=BlockSize, overlap=Overlap, search=Search, searchparam=SearchParam, pelsearch=PelSearch, \
  687. truemotion=TrueMotion, lambda=Lambda, lsad=LSAD, pnew=PNew, plevel=PLevel, global=GlobalMotion, DCT=DCT )
  688. bVec2 = srchSuper.MAnalyse( isb=true, delta=2, blksize=BlockSize, overlap=Overlap, search=Search, searchparam=SearchParam, pelsearch=PelSearch, \
  689. truemotion=TrueMotion, lambda=Lambda, lsad=LSAD, pnew=PNew, plevel=PLevel, global=GlobalMotion, DCT=DCT )
  690. bVec1 = srchSuper.MAnalyse( isb=true, delta=1, blksize=BlockSize, overlap=Overlap, search=Search, searchparam=SearchParam, pelsearch=PelSearch, \
  691. truemotion=TrueMotion, lambda=Lambda, lsad=LSAD, pnew=PNew, plevel=PLevel, global=GlobalMotion, DCT=DCT )
  692. fVec1 = srchSuper.MAnalyse( isb=false, delta=1, blksize=BlockSize, overlap=Overlap, search=Search, searchparam=SearchParam, pelsearch=PelSearch, \
  693. truemotion=TrueMotion, lambda=Lambda, lsad=LSAD, pnew=PNew, plevel=PLevel, global=GlobalMotion, DCT=DCT )
  694. fVec2 = srchSuper.MAnalyse( isb=false, delta=2, blksize=BlockSize, overlap=Overlap, search=Search, searchparam=SearchParam, pelsearch=PelSearch, \
  695. truemotion=TrueMotion, lambda=Lambda, lsad=LSAD, pnew=PNew, plevel=PLevel, global=GlobalMotion, DCT=DCT )
  696. fVec3 = srchSuper.MAnalyse( isb=false, delta=3, blksize=BlockSize, overlap=Overlap, search=Search, searchparam=SearchParam, pelsearch=PelSearch, \
  697. truemotion=TrueMotion, lambda=Lambda, lsad=LSAD, pnew=PNew, plevel=PLevel, global=GlobalMotion, DCT=DCT )
  698.  
  699. # InputType=2,3: use motion mask to blend luma between original clip & reweaved clip based on ProgSADMask setting. Use chroma from original clip in any case
  700. inputTypeBlend = (ProgSADMask > 0.0) ? MMask( srchClip, bVec1, kind=1, ml=ProgSADMask ) : NOP()
  701. edi = (InputType < 2) ? edi : \
  702. (ProgSADMask <= 0.0) ? edi.MergeChroma( clip ) : \
  703. mt_merge( clip, edi, inputTypeBlend, U=2,V=2 )
  704.  
  705. # Get the max/min value for each pixel over neighboring motion-compensated frames - used for temporal sharpness limiting
  706. ediSuper = edi.MSuper( pel=SubPel, sharp=SubPelInterp, levels=1 )
  707. bComp1 = edi.MCompensate( ediSuper, bVec1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  708. fComp1 = edi.MCompensate( ediSuper, fVec1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  709. tMax = edi.mt_logic( fComp1, "max", U=3,V=3 ).mt_logic( bComp1, "max", U=3,V=3 )
  710. tMin = edi.mt_logic( fComp1, "min", U=3,V=3 ).mt_logic( bComp1, "min", U=3,V=3 )
  711. bComp3 = edi.MCompensate( ediSuper, bVec3, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  712. fComp3 = edi.MCompensate( ediSuper, fVec3, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  713. tMax = (SLRad > 1) ? tMax.mt_logic( fComp3, "max", U=3,V=3 ).mt_logic( bComp3, "max", U=3,V=3 ) : tMax
  714. tMin = (SLRad > 1) ? tMin.mt_logic( fComp3, "min", U=3,V=3 ).mt_logic( bComp3, "min", U=3,V=3 ) : tMin
  715.  
  716. # Motion-compensate generated noise
  717. noiseSuper = deintNoise.MSuper( pel=SubPel, sharp=SubPelInterp, levels=1, chroma=false )
  718. mcNoise = deintNoise.MCompensate( noiseSuper, bVec1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  719. deintNoise = (InputType > 0 || NoiseDeint != "Generate") ? deintNoise : \
  720. mt_lutxy( deintNoise, mcNoise, "x 128 - abs y 128 - abs > x y ? 0.6 * x y + 0.2 * +", U=1,V=1 )
  721.  
  722.  
  723. #---------------------------------------
  724. # Create Output
  725.  
  726. # Create basic ouput: use motion vectors to blur interpolated image (edi) with motion-compensated previous and next frames. As above, this is done to
  727. # remove shimmer from alternate frames so the same binomial kernels are used. However, by using motion-compensated smoothing this time we avoid motion blur.
  728. # The use of MDegrain1 (motion compensated) rather than TemporalSmooth makes the weightings *look* different, but they evaluate to the same values
  729. # Create linear weightings of neighbors first -2 -1 0 1 2
  730. degrain1 = edi.MDegrain1( ediSuper, bVec1,fVec1, thSAD=_thSAD1, thSCD1=_thSCD1,thSCD2=_thSCD2 ) # 0.00 0.33 0.33 0.33 0.00
  731. degrain2 = edi.MDegrain1( ediSuper, bVec2,fVec2, thSAD=_thSAD1, thSCD1=_thSCD1,thSCD2=_thSCD2 ) # 0.33 0.00 0.33 0.00 0.33
  732.  
  733. # Combine linear weightings to give binomial weightings - TR1=0: (1), TR1=1: (1:2:1), TR1=2: (1:4:6:4:1)
  734. binomial1 = (TR1 == 0) ? edi : \
  735. (TR1 == 1) ? degrain1.Merge( edi, 0.25 ) : \
  736. degrain1.Merge( degrain2, 0.2 ).Merge( edi, 0.0625 )
  737.  
  738. # Remove areas of difference between smoothed image and interpolated image that are not bob-shimmer fixes: repairs residual motion blur from temporal smooth
  739. repair1 = (Rep1 == 0) ? binomial1 : binomial1.RemoveNonBobDiff( edi, Rep1, RepChroma )
  740.  
  741. # Basic source-match. Find difference between source clip & equivalent fields in interpolated/smoothed clip (called the "error" in formula below). Ideally
  742. # there should be no difference, we want the fields in the output to be as close as possible to the source whilst remaining shimmer-free. So adjust the
  743. # *source* in such a way that smoothing it will give a result closer to the unadjusted source. Then rerun the interpolation (edi) and binomial smooth with
  744. # this new source. Result will still be shimmer-free and closer to the original source.
  745. # Formula used for correction is P0' = P0 + (P0-P1)/(k+S(1-k)), where P0 is original image, P1 is the 1st attempt at interpolation/smoothing , P0' is the
  746. # revised image to use as new source for interpolation/smoothing, k is the weighting given to the current frame in the smooth, and S is a factor indicating
  747. # "temporal similarity" of the error from frame to frame, i.e. S = average over all pixels of [neighbor frame error = S * current frame error] . Decreasing
  748. # S will make the result sharper, sensible range is about -0.25 to 1.0. Empirically, S=0.5 is effective [will do deeper analysis later]
  749. errorTemporalSimilarity = 0.5 # S in formula described above
  750. errorAdjust1 = Select( MatchTR1, 1.0, 2.0 / (1.0 + errorTemporalSimilarity), 8.0 / (3.0 + 5.0 * errorTemporalSimilarity) )
  751. match1Clip = (InputType == 1) ? repair1 : repair1.SeparateFields().SelectEvery( 4, 0,3 ).Weave()
  752. match1Update = (MatchTR1 == 0) ? ediInput : \
  753. mt_lutxy( ediInput, match1Clip, "x " + string(errorAdjust1 + 1) + " * y " + string(errorAdjust1) + " * -", U=3,V=3 )
  754. match1Edi = Interpolate( match1Update, InputType, MatchEdi, MatchNNSize, MatchNNeurons, MatchEdiQual, MatchEdiMaxD, EdiThreads )
  755. match1Super = match1Edi.MSuper( pel=SubPel, sharp=SubPelInterp, levels=1 )
  756. match1Degrain1 = match1Edi.MDegrain1( match1Super, bVec1,fVec1, thSAD=_thSAD1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  757. match1Degrain2 = match1Edi.MDegrain1( match1Super, bVec2,fVec2, thSAD=_thSAD1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  758. match1 = (SourceMatch == 0) ? repair1 : \
  759. (MatchTR1 == 0) ? match1Edi : \
  760. (MatchTR1 == 1) ? match1Degrain1.Merge( match1Edi, 0.25 ) : \
  761. match1Degrain1.Merge( match1Degrain2, 0.2 ).Merge( match1Edi, 0.0625 )
  762.  
  763. # Enhance effect of source-match stages 2 & 3 by sharpening clip prior to refinement (source-match tends to underestimate so this will leave result sharper)
  764. enhance = (MatchEnhance > 0.0) ? match1.mt_lutxy( match1.RemoveGrain(rgBlur), "x x y - "+ string(MatchEnhance) + " * +", U=3,V=3 ) : match1
  765.  
  766. # Source-match refinement. Find difference between source clip & equivalent fields in (updated) interpolated/smoothed clip. Interpolate & binomially smooth
  767. # this difference then add it back to output. Helps restore differences that the basic match missed. However, as this pass works on a difference rather than
  768. # the source image it can be prone to occasional artefacts (difference images are not ideal for interpolation). In fact a lower quality interpolation such
  769. # as a simple bob often performs nearly as well as advanced, slower methods (e.g. NNEDI3)
  770. match2Clip = (InputType == 1) ? enhance : enhance.SeparateFields().SelectEvery( 4, 0,3 ).Weave()
  771. match2Diff = mt_makediff( ediInput, match2Clip, U=3,V=3 )
  772. match2Edi = Interpolate( match2Diff, InputType, MatchEdi2, MatchNNSize2, MatchNNeurons2, MatchEdiQual2, MatchEdiMaxD2, EdiThreads )
  773. match2Super = match2Edi.MSuper( pel=SubPel, sharp=SubPelInterp, levels=1 )
  774. match2Degrain1 = match2Edi.MDegrain1( match2Super, bVec1,fVec1, thSAD=_thSAD1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  775. match2Degrain2 = match2Edi.MDegrain1( match2Super, bVec2,fVec2, thSAD=_thSAD1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  776. match2Degrain = (MatchTR2 == 0) ? match2Edi : \
  777. (MatchTR2 == 1) ? match2Degrain1.Merge( match2Edi, 0.25 ) : \
  778. match2Degrain1.Merge( match2Degrain2, 0.2 ).Merge( match2Edi, 0.0625 )
  779.  
  780. # Source-match second refinement - correct error introduced in the refined difference by temporal smoothing. Similar to error correction from basic step
  781. errorAdjust2 = Select( MatchTR2, 1.0, 2.0 / (1.0 + errorTemporalSimilarity), 8.0 / (3.0 + 5.0 * errorTemporalSimilarity) )
  782. match3Update = (MatchTR2 == 0) ? match2Edi : \
  783. mt_lutxy( match2Edi, match2Degrain, "x " + string(errorAdjust2 + 1) + " * y " + string(errorAdjust2) + " * -", U=3,V=3 )
  784. match3Super = match3Update.MSuper( pel=SubPel, sharp=SubPelInterp, levels=1 )
  785. match3Degrain1 = match3Update.MDegrain1( match3Super, bVec1,fVec1, thSAD=_thSAD1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  786. match3Degrain2 = match3Update.MDegrain1( match3Super, bVec2,fVec2, thSAD=_thSAD1, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  787. match3Degrain = (SourceMatch < 3) ? match2Degrain : \
  788. (MatchTR2 == 0) ? match3Update : \
  789. (MatchTR2 == 1) ? match3Degrain1.Merge( match3Update, 0.25 ) : \
  790. match3Degrain1.Merge( match3Degrain2, 0.2 ).Merge( match3Update, 0.0625 )
  791.  
  792. # Apply difference calculated in source-match refinement
  793. match2 = (SourceMatch < 2) ? match1 : enhance.mt_adddiff( match3Degrain, U=3,V=3 )
  794.  
  795. # Lossless=2 - after preparing an interpolated, de-shimmered clip, restore the original source fields into it and clean up any artefacts.
  796. # This mode will not give a true lossless result because the resharpening and final temporal smooth are still to come, but it will add further detail.
  797. # However, it can introduce minor combing. This setting is best used together with source-match (it's effectively the final source-match stage).
  798. lossed1 = (Lossless == 2) ? MakeLossless( match2, clip ) : match2
  799.  
  800. # Resharpen to counteract temporal blurs. Little sharpening needed for source-match mode since already as sharp as source
  801. vresharp = Merge( lossed1.mt_expand( mode="vertical", U=3,V=3 ), lossed1.mt_inpand( mode="vertical", U=3,V=3 ) )
  802. vresharp = (Precise) ? vresharp.mt_lutxy( lossed1, "x y < x 1 + x y > x 1 - x ? ?", U=3,V=3 ) : vresharp # Precise mode: reduce tiny overshoot
  803. resharp = (SMode == 0) ? lossed1 : \
  804. (SMode == 1) ? lossed1.mt_lutxy( lossed1.RemoveGrain(rgBlur), "x x y - "+ string(sharpAdj) + " * +", U=3,V=3 ) : \
  805. lossed1.mt_lutxy( vresharp.RemoveGrain(rgBlur), "x x y - "+ string(sharpAdj) + " * +", U=3,V=3 )
  806.  
  807. # Slightly thin down 1-pixel high horizontal edges that have been widened into neigboring field lines by the interpolator
  808. SVThinSc = SVThin * 6.0
  809. vertMedD = mt_lutxy( lossed1, lossed1.VerticalCleaner(mode=1), "y x - " + string(SVThinSc) + " * 128 +", U=1,V=1 ).Blur( 1,0 )
  810. neighborD = mt_lutxy( vertMedD, vertMedD.RemoveGrain( rgBlur,-1 ), "y 128 - abs x 128 - abs > y 128 ?" )
  811. thin = (SVthin == 0.0) ? resharp : resharp.mt_adddiff( neighborD, U=2,V=2 )
  812.  
  813. # Back blend the blurred difference between sharpened & unsharpened clip, before (1st) sharpness limiting (Sbb == 1,3). A small fidelity improvement
  814. backBlend1 = (Sbb != 1 && Sbb != 3) ? thin : \
  815. thin.mt_makediff( mt_makediff( thin, lossed1, U=1,V=1 ).RemoveGrain( rgBlur, -1 ).GaussResize( w,h, 0,0, w+epsilon,h+epsilon, p=5 ), U=2,V=2 )
  816.  
  817. # Limit over-sharpening by clamping to neighboring (spatial or temporal) min/max values in original
  818. # Occurs here (before final temporal smooth) if SLMode == 1,2. This location will restrict sharpness more, but any artefacts introduced will be smoothed
  819. sharpLimit1 = (SLMode == 1) ? backBlend1.Repair( ((SLrad < 2) ? edi : backBlend1.Repair( edi, 12 )), 1 ) : \
  820. (SLMode == 2) ? backBlend1.mt_clamp( tMax,tMin, Sovs,Sovs, U=3,V=3 ) : \
  821. backBlend1
  822.  
  823. # Back blend the blurred difference between sharpened & unsharpened clip, after (1st) sharpness limiting (Sbb == 2,3). A small fidelity improvement
  824. backBlend2 = (Sbb < 2) ? sharpLimit1 : \
  825. sharpLimit1.mt_makediff( mt_makediff( sharpLimit1, repair1, U=1,V=1 ).GaussResize( w,h, 0,0, w+epsilon,h+epsilon, p=5 ), U=2,V=2 )
  826.  
  827. # Add back any extracted noise, prior to final temporal smooth - this will restore detail that was removed as "noise" without restoring the noise itself
  828. # Average luma of FFT3DFilter extracted noise is 128.5, so deal with that too
  829. addNoise1 = (DetailRestore > 0.0) ? backBlend2.mt_adddiff( deintNoise.mt_lut( "x 128.5 - " + string(DetailRestore) + " * 128 +", U=1,V=1 ), U=2,V=2 ) : backBlend2
  830.  
  831. # Final light linear temporal smooth for denoising
  832. stableSuper = addNoise1.MSuper( pel=SubPel, sharp=SubPelInterp, levels=1 )
  833. stable = (TR2 == 0) ? addNoise1 : \
  834. (TR2 == 1) ? addNoise1.MDegrain1( stableSuper, bVec1,fVec1, thSAD=_thSAD2, thSCD1=_thSCD1,thSCD2=_thSCD2 ) : \
  835. (TR2 == 2) ? addNoise1.MDegrain2( stableSuper, bVec1,fVec1, bVec2,fVec2, thSAD=_thSAD2, thSCD1=_thSCD1,thSCD2=_thSCD2 ) : \
  836. addNoise1.MDegrain3( stableSuper, bVec1,fVec1, bVec2,fVec2, bVec3,fVec3, thSAD=_thSAD2, thSCD1=_thSCD1,thSCD2=_thSCD2 )
  837.  
  838. # Remove areas of difference between final output & basic interpolated image that are not bob-shimmer fixes: repairs motion blur caused by temporal smooth
  839. repair2 = (Rep2 == 0) ? stable : stable.RemoveNonBobDiff( edi, Rep2, RepChroma )
  840.  
  841. # Limit over-sharpening by clamping to neighboring (spatial or temporal) min/max values in original
  842. # Occurs here (after final temporal smooth) if SLMode == 3,4. Allows more sharpening here, but more prone to introducing minor artefacts
  843. processed = (SLMode == 3) ? repair2.Repair( ((SLrad < 2) ? edi : repair2.Repair( edi, 12 )), 1 ) : \
  844. (SLMode == 4) ? repair2.mt_clamp( tMax,tMin, Sovs,Sovs, U=3,V=3 ) : \
  845. repair2
  846.  
  847.  
  848. #---------------------------------------
  849. # Post-Processing
  850.  
  851. # Lossless=1 - inject source fields into result and clean up inevitable artefacts. Provided NoiseRestore=0, this mode will make the script result properly
  852. # lossless, but it will strongly retain source artefacts
  853. lossed2 = (Lossless == 1) ? MakeLossless( processed, clip ) : processed
  854.  
  855. # Add back any extracted noise, after final temporal smooth. This will appear as noise/grain in the output
  856. # Average luma of FFT3DFilter extracted noise is 128.5, so deal with that too
  857. addNoise2 = (NoiseRestore > 0.0) ? lossed2.mt_adddiff( deintNoise.mt_lut( "x 128.5 - " + string(NoiseRestore) + " * 128 +", U=1,V=1 ), U=2,V=2 ) : lossed2
  858.  
  859. # Crop off temporary vertical padding
  860. cropped = Border ? addNoise2.Crop( 0, 4, -0, -4 ) : addNoise2
  861. h = Border ? h-8 : h
  862.  
  863. # Show output of choice + settings
  864. output = (ShowNoise == 0.0) ? cropped : deintNoise.mt_lut( "x 128 - " + string(ShowNoise) + " * 128 +", U=-128,V=-128 )
  865. return (ShowSettings == false) ? output : \
  866. output.Subtitle( "TR0=" + string(TR0) + " | TR1=" + string(TR1) + " | TR2=" + string(TR2) + " | Rep0=" + string(Rep0) + " | Rep1=" + string(Rep1) + \
  867. " | Rep2=" + string(Rep2) + " | RepChroma=" + string(RepChroma) + "\nEdiMode='" + EdiMode + "' | NNSize=" + string(NNSize) + " | NNeurons=" + \
  868. string(NNeurons) + " | EdiQual=" + string(EdiQual) + " | EdiMaxD=" + string(EdiMaxD) + " | EdiThreads=" + string(EdiThreads) + "\nSharpness=" + \
  869. string(Sharpness, "%.2f") + " | SMode=" + string(SMode) + " | SLMode=" + string(SLMode) + " | SLRad=" + string(SLRad) + " | SOvs=" + string(SOvs) + \
  870. " | SVThin=" + string(SVThin, "%.2f") + " | Sbb=" + string(Sbb) + "\nSrchClipPP=" + string(SrchClipPP) + " | SubPel=" + string(SubPel) + \
  871. " | SubPelInterp=" + string(SubPelInterp) + " | BlockSize=" + string(BlockSize) + " | Overlap=" + string(Overlap) + "\nSearch=" + string(Search) + \
  872. " | SearchParam=" + string(SearchParam) + " | PelSearch=" + string(PelSearch) + " | TrueMotion=" + string(TrueMotion) + "\nLambda=" + string(Lambda) + \
  873. " | LSAD=" + string(LSAD) + " | PNew=" + string(PNew) + " | PLevel=" + string(PLevel) + " | GlobalMotion=" + string(GlobalMotion) + " | DCT=" + \
  874. string(DCT) + "\nSourceMatch=" + string(SourceMatch) + " | MatchPreset='" + MatchPreset + "' | MatchEdi='" + MatchEdi + "'\nMatchPreset2='" + \
  875. MatchPreset2 + "' | MatchEdi2='" + MatchEdi2 + "' | MatchTR2=" + string(MatchTR2) + " | MatchEnhance=" + string(MatchEnhance, "%.2f") + \
  876. " | Lossless=" + string(Lossless) + "\nNoiseBypass=" + string(NoiseBypass) + " | NoiseRemove=" + string(NoiseRemove, "%.2f") + " | DetailRestore=" + \
  877. string(DetailRestore, "%.2f") + " | NoiseRestore=" + string(NoiseRestore, "%.2f") + "\nNoiseDeint='" + NoiseDeint + "' | Sigma=" + \
  878. string(Sigma, "%.2f") + " | BT=" + string(BT) + " | ShowNoise=" + string(ShowNoise, "%.2f") + " | InputType=" + string(InputType) + \
  879. " | ProgSADMask=" + string(ProgSADMask, "%.2f") + "\nBorder=" + string(Border) + " | Precise=" + string(Precise) + " | SafeMode=" + string(SafeMode) + \
  880. "\nPreset='" + Preset + "' | Tuning='" + Tuning + "'", font="Lucida Console", size=11, lsp=12 )
  881. }
  882.  
  883.  
  884. #---------------------------------------
  885. # Helpers
  886.  
  887. # Interpolate input clip using method given in EdiMode. Use Fallback clip as result if mode is not in list. Used by main interpolation and source-match
  888. function Interpolate( clip Input, int InputType, string EdiMode, int NNSize, int NNeurons, int EdiQual, int EdiMaxD, int EdiThreads, clip "Fallback" )
  889. {
  890. Fallback = default( Fallback, Input.Bob( 0,0.5 ) )
  891. return (InputType == 1) ? Input : \
  892. (EdiMode == "NNEDI3") ? Input.NNEDI3( field=-2, nsize=NNSize, nns=NNeurons, qual=EdiQual, threads=EdiThreads ) : \
  893. (EdiMode == "NNEDI2") ? Input.NNEDI2( field=-2, nsize=NNeurons, qual=EdiQual, threads=EdiThreads ) : \
  894. (EdiMode == "NNEDI") ? Input.NNEDI( field=-2 ) : \
  895. (EdiMode == "EEDI3+NNEDI3") ? Input.EEDI3( field=-2, mdis=EdiMaxD, threads=EdiThreads, \
  896. sclip=Input.NNEDI3( field=-2, nsize=NNSize, nns=NNeurons, qual=EdiQual, threads=EdiThreads ) ) : \
  897. (EdiMode == "EEDI3") ? Input.EEDI3( field=-2, mdis=EdiMaxD, threads=EdiThreads ) : \
  898. (EdiMode == "EEDI2") ? Input.SeparateFields().EEDI2( field=-2, maxd=EdiMaxD ) : \
  899. (EdiMode == "Yadif") ? Input.Yadif( mode=1 ) : \
  900. (EdiMode == "TDeint") ? Input.TDeInt( mode=1 ) : \
  901. (EdiMode == "TDIYadif") ? Merge( Input.Yadif( mode=1 ), Input.TDeInt( mode=1 ) ) : \
  902. Fallback
  903. }
  904.  
  905.  
  906. # Functions (from original TGMC) used instead of mt_xxflate with similar operation but a somewhat stronger result. Originally added for speed, they are
  907. # no longer faster due to improvements in masktools. Difference (visual and speed) is small so may be reverted in a later version.
  908. function TGMC_inflate( clip c, int "Y", int "U", int "V" )
  909. {
  910. mtY =default( Y, 3 )
  911. mtU =default( U, 1 )
  912. mtV =default( V, 1 )
  913. rgY = (mtY == 3) ? 20 : -1
  914. rgU = (mtU == 3) ? 20 : -1
  915. rgV = (mtV == 3) ? 20 : -1
  916. mt_logic( c, c.RemoveGrain( rgY, rgU, rgV ), "max", Y=mtY,U=mtU,V=mtV )
  917. }
  918.  
  919. function TGMC_deflate( clip c, int "Y", int "U", int "V" )
  920. {
  921. mtY =default( Y, 3 )
  922. mtU =default( U, 1 )
  923. mtV =default( V, 1 )
  924. rgY = (mtY == 3) ? 20 : -1
  925. rgU = (mtU == 3) ? 20 : -1
  926. rgV = (mtV == 3) ? 20 : -1
  927. mt_logic( c, c.RemoveGrain( rgY, rgU, rgV ), "min", Y=mtY,U=mtU,V=mtV )
  928. }
  929.  
  930. # Helper function: Compare processed clip with reference clip: only allow thin, horizontal areas of difference, i.e. bob shimmer
  931. # Rough algorithm: Get difference, deflate vertically by a couple of pixels or so, then inflate again. Thin regions will be removed
  932. # by this process. Restore remaining areas of difference back to as they were in reference clip.
  933. function RemoveNonBobDiff( clip Input, clip Ref, int Rep, bool Chroma )
  934. {
  935. # ed is the erosion distance - how much to deflate then reflate to remove thin areas of interest: 0 = minimum to 5 = maximum
  936. # od is over-dilation level - extra inflation to ensure areas to restore back are fully caught: 0 = none to 3 = one full pixel
  937. # If Rep < 10, then ed = Rep and od = 0, otherwise ed = 10s digit and od = 1s digit (nasty method, but kept for compatibility with original TGMC)
  938. Rep = default( Rep, 1 )
  939. Chroma = default( Chroma, true )
  940. ed = (Rep < 10) ? Rep : Rep / 10
  941. od = (Rep < 10) ? 0 : Rep % 10
  942. uvT = Chroma ? 3 : 1
  943. uvO = Chroma ? 3 : 2
  944.  
  945. diff = mt_makediff( Ref, Input, U=3,V=3 )
  946.  
  947. # Areas of positive difference # ed = 0 1 2 3 4 5
  948. choke1 = diff. mt_inpand( mode="vertical", U=uvT,V=uvT ) # x x x x x x 1 pixel \
  949. choke1 = (ed > 2) ? choke1.mt_inpand( mode="vertical", U=uvT,V=uvT ) : choke1 # . . . x x x 1 pixel | Deflate to remove thin areas
  950. choke1 = (ed != 0 && ed != 3) ? choke1.TGMC_deflate( U=uvT,V=uvT ) : choke1 # . x x . x x a bit more |
  951. choke1 = (ed == 2 || ed == 5) ? choke1.RemoveGrain(4) : choke1 # . . x . . x & more(?) / [median - may actually inflate??]
  952.  
  953. choke1 = choke1.mt_expand( mode="vertical", U=uvT,V=uvT ) # x x x x x x 1 pixel \
  954. choke1 = (ed > 1) ? choke1.mt_expand( mode="vertical", U=uvT,V=uvT ) : choke1 # . . x x x x 1 pixel | Reflate again
  955. choke1 = (ed > 4) ? choke1.mt_expand( mode="vertical", U=uvT,V=uvT ) : choke1 # . . . . . x 1 pixel /
  956.  
  957. # Over-dilation - extra reflation up to 1 pixel
  958. choke1 = (od == 0) ? choke1 : \
  959. (od == 1) ? choke1.TGMC_inflate( U=uvT,V=uvT ) : \
  960. (od == 2) ? choke1.TGMC_inflate( U=uvT,V=uvT ).TGMC_inflate( U=uvT,V=uvT ) : \
  961. choke1.mt_expand( U=uvT,V=uvT )
  962.  
  963. # Areas of negative difference (similar to above)
  964. choke2 = diff. mt_expand( mode="vertical", U=uvT,V=uvT )
  965. choke2 = (ed > 2) ? choke2.mt_expand( mode="vertical", U=uvT,V=uvT ) : choke2
  966. choke2 = (ed != 0 && ed != 3) ? choke2.TGMC_inflate( U=uvT,V=uvT ) : choke2
  967. choke2 = (ed == 2 || ed == 5) ? choke2.RemoveGrain(4) : choke2
  968. choke2 = choke2.mt_inpand( mode="vertical", U=uvT,V=uvT )
  969. choke2 = (ed > 1) ? choke2.mt_inpand( mode="vertical", U=uvT,V=uvT ) : choke2
  970. choke2 = (ed > 4) ? choke2.mt_inpand( mode="vertical", U=uvT,V=uvT ) : choke2
  971. choke2 = (od == 0) ? choke2 : \
  972. (od == 1) ? choke2.TGMC_deflate( U=uvT,V=uvT ) : \
  973. (od == 2) ? choke2.TGMC_deflate( U=uvT,V=uvT ).TGMC_deflate( U=uvT,V=uvT ) : \
  974. choke2.mt_inpand( U=uvT,V=uvT )
  975.  
  976. # Combine above areas to find those areas of difference to restore
  977. restore = diff.mt_lutxy( choke1, "x 129 < x y 128 < 128 y ? ?", U=uvT,V=uvT ).mt_lutxy( choke2, "x 127 > x y 128 > 128 y ? ?", U=uvT,V=uvT )
  978.  
  979. return Input.mt_adddiff( restore, U=uvO,V=uvO )
  980. }
  981.  
  982.  
  983. # Given noise extracted from an interlaced source (i.e. the noise is interlaced), generate "progressive" noise with a new "field" of noise injected. The new
  984. # noise is centered on a weighted local average and uses the difference between local min & max as an estimate of local variance
  985. function Generate2ndFieldNoise( clip Input )
  986. {
  987. origNoise = Input.SeparateFields()
  988. noiseMax = origNoise.mt_expand( mode="square", U=3,V=3 ).mt_expand( mode="horizontal", U=1,V=1 )
  989. noiseMin = origNoise.mt_inpand( mode="square", U=3,V=3 ).mt_inpand( mode="horizontal", U=1,V=1 )
  990. random = BlankClip( origNoise, color_yuv=$808080 ).AddGrain( var=256 )
  991. varRandom = mt_makediff( noiseMax, noiseMin, U=3,V=3 ).mt_lutxy( random, "x 128 - y 128 - * 128 / 128 +", U=1,V=1 )
  992. newNoise = origNoise.RemoveGrain(12).mt_adddiff( varRandom, U=1,V=1 )
  993. return Interleave( origNoise, newNoise ).Weave()
  994. }
  995.  
  996.  
  997. # Insert the source lines into the result to create a true lossless output. However, the other lines in the result have had considerable processing and won't
  998. # exactly match source lines. There will be some slight residual combing. Use vertical medians to clean a little of this away
  999. function MakeLossless( clip Input, clip Source )
  1000. {
  1001. # Weave the source fields and the "new" fields that have generated in the input
  1002. srcFields = Source.SeparateFields()
  1003. newFields = Input.SeparateFields().SelectEvery( 4, 1,2 )
  1004. processed = Interleave( srcFields, newFields ).SelectEvery(4, 0,1,3,2 ).Weave()
  1005.  
  1006. # Clean some of the artefacts caused by the above - creating a second version of the "new" fields
  1007. vertMedian = processed.VerticalCleaner( mode=1 )
  1008. vertMedDiff = mt_makediff( processed, vertMedian, U=3,V=3 )
  1009. vmNewDiff1 = vertMedDiff.SeparateFields().SelectEvery( 4, 1,2 )
  1010. vmNewDiff2 = vmNewDiff1.VerticalCleaner( mode=1 ).mt_lutxy( vmNewDiff1, "x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?", U=3,V=3 )
  1011. vmNewDiff3 = vmNewDiff2.Repair( vmNewDiff2.removegrain(2), 1 )
  1012.  
  1013. # Reweave final result
  1014. return Interleave( SrcFields, newFields.mt_makediff( vmNewDiff3, U=3,V=3 )).SelectEvery( 4, 0,1,3,2 ).Weave()
  1015. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement