Mystery Keeper
22nd September 2016, 21:42
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 (https://github.com/HomeOfVapourSynthEvolution/VapourSynth-TDeintMod/releases) and Retinex (https://github.com/HomeOfVapourSynthEvolution/VapourSynth-Retinex/releases) plugins.
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)
#=========================================================================================================================================
Requires TDeintMod (https://github.com/HomeOfVapourSynthEvolution/VapourSynth-TDeintMod/releases) and Retinex (https://github.com/HomeOfVapourSynthEvolution/VapourSynth-Retinex/releases) plugins.
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)
#=========================================================================================================================================