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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > VapourSynth

Reply
 
Thread Tools Search this Thread Display Modes
Old 22nd September 2016, 21:42   #1  |  Link
Mystery Keeper
Beyond Kawaii
 
Mystery Keeper's Avatar
 
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.
Mystery Keeper is offline   Reply With Quote
Old 22nd September 2016, 22:55   #2  |  Link
brucethemoose
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.
brucethemoose is offline   Reply With Quote
Old 22nd September 2016, 23:20   #3  |  Link
Mystery Keeper
Beyond Kawaii
 
Mystery Keeper's Avatar
 
Join Date: Feb 2008
Location: Russia
Posts: 724
I've found mi=8 working good for me.

Upd: Updated the script with more neat version. Thanks to TheFluff.
__________________
...desu!

Last edited by Mystery Keeper; 22nd September 2016 at 23:34.
Mystery Keeper is offline   Reply With Quote
Old 23rd September 2016, 01:01   #4  |  Link
brucethemoose
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.
brucethemoose is offline   Reply With Quote
Old 23rd September 2016, 02:02   #5  |  Link
Mystery Keeper
Beyond Kawaii
 
Mystery Keeper's Avatar
 
Join Date: Feb 2008
Location: Russia
Posts: 724
Quote:
Originally Posted by brucethemoose View Post
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.
Works alright for me. Paste your script?
__________________
...desu!
Mystery Keeper is offline   Reply With Quote
Old 23rd September 2016, 02:57   #6  |  Link
brucethemoose
Registered User
 
Join Date: Sep 2016
Posts: 67
It's basically this:

Quote:
clip = core.ffms2.Source(r"C:\ReMasteringATLA\Book3\AVATAR\title06.mkv")
clip = core.vivtc.VFM(clip, mode = 0, order = 1, micmatch = 1) #IVTC
deint = clip #for debugging
clip = cond_deint.cond_deint(clip = clip, deinterlaced = deint)
clip.set_output()
With a bunch of imports and commented out code.

EDIT2: Thought I fixed it, was wrong.

Last edited by brucethemoose; 23rd September 2016 at 03:07.
brucethemoose is offline   Reply With Quote
Old 23rd September 2016, 03:05   #7  |  Link
Mystery Keeper
Beyond Kawaii
 
Mystery Keeper's Avatar
 
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!
Mystery Keeper is offline   Reply With Quote
Old 23rd September 2016, 03:09   #8  |  Link
brucethemoose
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.
brucethemoose is offline   Reply With Quote
Old 23rd September 2016, 03:56   #9  |  Link
brucethemoose
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.
brucethemoose is offline   Reply With Quote
Old 23rd September 2016, 05:39   #10  |  Link
Mystery Keeper
Beyond Kawaii
 
Mystery Keeper's Avatar
 
Join Date: Feb 2008
Location: Russia
Posts: 724
Quote:
Originally Posted by brucethemoose View Post
EDIT2: Another note, I get alot of false positives without a really high CThresh.
Remember: miracles don't happen.
Play with parameters and pray. Sacrifice few uncombed frames and deinterlace them anyway.
__________________
...desu!
Mystery Keeper is offline   Reply With Quote
Old 23rd September 2016, 06:23   #11  |  Link
brucethemoose
Registered User
 
Join Date: Sep 2016
Posts: 67
Quote:
Originally Posted by Mystery Keeper View Post
Remember: miracles don't happen.
Play with parameters and pray. Sacrifice few uncombed frames and deinterlace them anyway.
Actually, cthresh=70 and mi=16 is working almost perfectly.

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.
brucethemoose is offline   Reply With Quote
Old 12th December 2016, 17:52   #12  |  Link
Mystery Keeper
Beyond Kawaii
 
Mystery Keeper's Avatar
 
Join Date: Feb 2008
Location: Russia
Posts: 724
Updated. Now checks both original clip and contrast enhanced clip and combines the results.
__________________
...desu!
Mystery Keeper is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 16:23.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.