Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
22nd September 2016, 21:42 | #1 | Link |
Beyond Kawaii
Join Date: Feb 2008
Location: Russia
Posts: 724
|
Smart deinterlace script
I wanted a way to detect combing in frames and only deinterlace frames that contain it. As result, this script was born. It applies local contrast enhancement to clip before combing detection - works great even on those dark crossfades or where combing is barely seen. You can also use the local contrast enhancement function for your needs.
Requires TDeintMod and Retinex plugins. Code:
import vapoursynth as vs def retinex_y(clip, out_format = None): #------------------------------------------------------------------------------------------------------------------------------------- core = vs.get_core() if out_format is None: out_format = clip.format #------------------------------------------------------------------------------------------------------------------------------------- intformat = core.register_format(clip.format.color_family, vs.INTEGER, 16, 0, 0) clip_in = core.resize.Spline36(clip, format=intformat.id) retinex = core.retinex.MSRCP(clip_in) retinex_out = core.resize.Spline36(retinex, format=out_format.id) clip_out = core.resize.Spline36(clip, format=out_format.id) shuffled = core.std.ShufflePlanes([retinex_out, clip_out, clip_out], [0,1,2], colorfamily=out_format.color_family) return shuffled # END OF retinex_y(clip, out_format = None) #========================================================================================================================================= def cond_deint(clip, deinterlaced, cthresh = None, blockx = None, blocky = None, chroma = None, mi = None, metric = None): core = vs.get_core() if not isinstance(clip, vs.VideoNode): raise TypeError('''cond_deint: 'clip' argument is not a clip''') if not isinstance(deinterlaced, vs.VideoNode): raise TypeError('''cond_deint: 'deinterlaced' argument is not a clip''') is_combed_arguments = { 'cthresh': cthresh, 'blockx': blockx, 'blocky': blocky, 'chroma': chroma, 'mi': mi, 'metric': metric, } old_format = clip.format new_format = core.register_format(old_format.color_family, vs.INTEGER, 16, old_format.subsampling_w, old_format.subsampling_h) refOriginal = core.resize.Point(clip, format=new_format.id) refOriginal = core.tdm.IsCombed(refOriginal, **is_combed_arguments) refEnhanced = retinex_y(clip, new_format) refEnhanced = core.tdm.IsCombed(refEnhanced, **is_combed_arguments) def cond_deint_transfer_property(n, f): fout = f[1].copy() if f[0].props._Combed: fout.props._Combed = True return fout combProps = core.std.ModifyFrame(refEnhanced, [refOriginal, refEnhanced], cond_deint_transfer_property) final = core.std.FrameEval(clip, lambda n, f: deinterlaced if f.props._Combed else clip, combProps) return final # END OF cond_deint(clip, deinterlaced, cthresh = None, blockx = None, blocky = None, chroma = None, mi = None, metric = None) #=========================================================================================================================================
__________________
...desu! Last edited by Mystery Keeper; 12th December 2016 at 17:51. |
22nd September 2016, 22:55 | #2 | Link |
Registered User
Join Date: Sep 2016
Posts: 67
|
Sweet! I've been banging my head against the wall trying to tune VFM's combing detection, this looks like what I need.
EDIT: What are some good default values? Last edited by brucethemoose; 22nd September 2016 at 23:02. |
23rd September 2016, 01:01 | #4 | Link |
Registered User
Join Date: Sep 2016
Posts: 67
|
I get the error "Python exception: 'NoneType' object has no attribute 'set_output'" on my "clip.set_output()" line.
Which means it's not outputting a clip, I think. This is using the new code, I haven't tried the old code. |
23rd September 2016, 02:57 | #6 | Link | |
Registered User
Join Date: Sep 2016
Posts: 67
|
It's basically this:
Quote:
EDIT2: Thought I fixed it, was wrong. Last edited by brucethemoose; 23rd September 2016 at 03:07. |
|
23rd September 2016, 03:05 | #7 | Link |
Beyond Kawaii
Join Date: Feb 2008
Location: Russia
Posts: 724
|
Ugh. I do it like this. No errors.
Code:
from __future__ import print_function import vapoursynth as vs core = vs.get_core(threads=8) core.set_max_cache_size(12000) import sys sys.path.append('D:\\vapoursynth-plugins\\py\\') import platform architecture = platform.architecture() if architecture[0] == '64bit': vapoursynth_plugins_path = 'D:\\vapoursynth-plugins\\64bit\\' else: vapoursynth_plugins_path = 'D:\\vapoursynth-plugins\\32bit\\' print('Plugins folder: ', vapoursynth_plugins_path, end='\n', file=sys.stderr) import os for filename in os.listdir(vapoursynth_plugins_path): if filename[-4:] != '.dll': continue try: core.std.LoadPlugin(vapoursynth_plugins_path + filename) except Exception as e: print('Error: ', e, end='\n', file=sys.stderr) #=========================================================================================================== d2vfile = r'D:\Video to Process\KOTOKO - Tsukiyo no Butoukai\VTS_01_1.d2v' src = core.d2v.Source(input=d2vfile, rff=False) src = core.std.CropRel(src, left=0, top=66, right=0, bottom=62) src = core.vivtc.VFM(src, order=1, mode=5) src = core.vivtc.VDecimate(src) src.set_output() #======================================================================== # Denoising import MCDenoise as mcd tlamcArguments = { 'radius': 5, 'search': 5, 'pelsearch': 2, 'subpelinterp': 2, 'searchparam': 5, 'truemotion': True, 'chromamotion': False, 'thsad': 200, 'thscd1': 150, 'thscd2': 150, 'dct': 5, 'refine': True, } separated = core.std.SeparateFields(src, True) even = core.std.SelectEvery(separated, 2, 0) even_denoised = mcd.TempLinearApproximateMC(even, **tlamcArguments) #even_denoised = mcd.TempLinearApproximateMC(even_denoised, **tlamcArguments) odd = core.std.SelectEvery(separated, 2, 1) odd_denoised = mcd.TempLinearApproximateMC(odd, **tlamcArguments) #odd_denoised = mcd.TempLinearApproximateMC(odd_denoised, **tlamcArguments) interleaved = core.std.Interleave([even_denoised, odd_denoised]) double_weaved = core.std.DoubleWeave(interleaved, True) src = core.std.SelectEvery(double_weaved, 2, 0) #======================================================================== import helpers as h deint = core.nnedi3.nnedi3(src, field=0, nsize=3, nns=4, qual=2) deint = core.sub.Subtitle(deint, 'X') cdeint = h.cond_deint(src, deint, mi=8) cdeint.set_output() retinex_src = h.retinex_y(src) retinex_deint = h.retinex_y(cdeint) top_row = core.std.StackHorizontal([src, cdeint]) bottom_row = core.std.StackHorizontal([retinex_src, retinex_deint]) cmp = core.std.StackVertical([top_row, bottom_row]) #cmp.set_output()
__________________
...desu! |
23rd September 2016, 03:09 | #8 | Link |
Registered User
Join Date: Sep 2016
Posts: 67
|
Might have something to do with my source, let me try another file.
I'll also try importing it like you did. Sorry for the ninja edit. Thought I fixed it, but 1 line I forgot to comment out meant it was outputting another clip. |
23rd September 2016, 03:56 | #9 | Link |
Registered User
Join Date: Sep 2016
Posts: 67
|
Works great, thanks! Maybe I was tuning IsCombed() and VFM wrong, but this seems to be better at detecting combing:
EDIT: This is mi=64, btw. EDIT2: Another note, I get alot of false positives without a really high CThresh. Last edited by brucethemoose; 23rd September 2016 at 04:48. |
23rd September 2016, 05:39 | #10 | Link | |
Beyond Kawaii
Join Date: Feb 2008
Location: Russia
Posts: 724
|
Quote:
Play with parameters and pray. Sacrifice few uncombed frames and deinterlace them anyway.
__________________
...desu! |
|
23rd September 2016, 06:23 | #11 | Link | |
Registered User
Join Date: Sep 2016
Posts: 67
|
Quote:
Proper decimation is another story. AFAIK VS has no equivalent to "TDecimate(mode = 1, hybrid = 1)", so motion is not as smooth as it should be. |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|