View Single Post
Old 6th December 2017, 00:14   #9  |  Link
lansing
Registered User
 
Join Date: Sep 2006
Posts: 1,657
This is the whole script for building montage clip for the Dragon Ball Z color matching. I added a few switches on the top controller for more user friendly.

Also I updated the DBZColorMatch_func file so that it can now work without having a scene change file.

Code:
import vapoursynth as vs
from functools import reduce, partial
from itertools import zip_longest, starmap
import DBZColorMatch_func as dbzf

############################################################################################################################
## 			Montage building script for Dragon Ball Z Level/Season Blu-ray Color Matching
##
##  Build a montage clip for both color reference video (Level/Season) and target video (Kai), switch at the
##  is_clip_color_ref parameter
##  
##  The script will first take a list of clip(s), apply cropping, user defined denoise and curve adjustment to each, then 
##  append them together. Then the clip will be splice around according to all the splicing text files.
## 
##  The resulting clip will be pass to the montage builder function to build a montage clip.
##
##  Setting output_img to True will output the montage clip to image sequence.
##
##  Basic Setting:
##  clip_paths, profile_paths, preset_paths, curve_paths:
##				Takes list as input. Position of each list correspond to one another. Leave list blank to disable. Or you can do 
## 				curve_paths = [None, r"001.acv"] to only apply curve on the 2nd clip.
##
##	is_clip_color_ref:
##				If set to false, all the splicing process will be skipped. (for DBZ Kai)
##
##  do_denoise: True to turn on, False to turn off
##				The DBZ level/season clips need to denoise for better color accuracy. Denoisers used are NeatVideo and 
##				KNLMeansCL. Setup profile_paths to use NeatVideo, leave it empty to use KNLMeansCL. 
##  			NeatVideo is the only denoiser that can remove the grains in level set. Use KNLMeansCL for Season BD.
##
##	use_neatvideo:
##				Trim out the first extra frame created by the filter		
############################################################################################################################

### Controller ###
clip_paths = [r"001.ts", r"002.ts"]

# neatvideo config files
profile_paths = [r"dbz01.dnp", r"dbz02.dnp"]
preset_paths = [r"dbz01.nfp", r"dbz02.nfp"]

# curve files, acv extension
curve_paths = [None, r'curve_level2kai_002.acv']

# True for color reference clip (level/season), False for target clip (kai/dragon box). 
# Set to False will disable all cut/scenechange files
is_clip_color_ref = False 

# color reference clip splicing config
pad_op = 4563 # frames to pad op so the clips match
reorder_file = r'reorder_level2kai_001.txt'
cut_file = r'cut_level2kai_001.txt'
dupe_file = r'dupe_level2kai_001.txt'

# compose clip config
cropside = False # crop 240 from left and right of frame
do_denoise = False
use_neatvideo = False # trigger the preroll frame adjust

# For montage builder
scenechange_file = r"scenechange_kai_001.txt"
scenechange_skip_file = r'scenechange_kai_001_skip.txt'

# output image sequence
output_img = False
img_dir = r"F:\temp_img_w\test_%06d.png"

###################
core = vs.get_core(accept_lowercase=True)

# load avs plugin
core.avs.LoadPlugin(r"C:\Program Files (x86)\AviSynth+\plugins64+\VDubFilter.dll")
core.avs.LoadVirtualdubPlugin(r'NeatVideo.vdf', 'NeatVideo', 1)

# compose clip with filters
def compose_clip(clip_path, profile, preset, curve, cropside=False, denoise=False):

	if clip_path:
		clip = core.ffms2.Source(clip_path)
	
		if cropside == True:
			clip = core.std.Crop(clip, 240, 240, 0, 0)
		
		if denoise:
			if profile: 
				# if profile exist, use neatvideo
				clip = core.resize.Bicubic(clip, matrix_in_s="709", format=vs.COMPATBGR32)
				clip = core.avs.NeatVideo_2(clip, profile, preset, 1, 1, 0, 0)
			else:
				# use knlmeanscl
				clip = core.knlm.KNLMeansCL(clip, d=1, a=1, s=1, h=1)
		
		if curve:
			clip = core.resize.Bicubic(clip, matrix_in_s="709", format=vs.RGB24)		
			clip = core.grad.Curve(clip, curve, ftype=2, pmode=1)
			clip = core.resize.Bicubic(clip, matrix_s="709", format=vs.YUV420P8)
		return clip

def add_clip(a, b):
	return a + b if b else a # skip clip b is it doesn't exist

# partial function of "composer_clip" function that takes user input switch
compose_clip_ctrler = partial(compose_clip, cropside=cropside, denoise=do_denoise)

# load and append clips
clip = reduce(add_clip, starmap(compose_clip_ctrler, zip_longest(clip_paths, profile_paths, preset_paths, curve_paths)))

	
# apply padding for level/season
if is_clip_color_ref:
	padding_clip = core.std.BlankClip(clip, length=pad_op)
	clip =  padding_clip + clip

	# rearrange order, first episode only?
	if reorder_file:
		reorder_list = []
	
		with open(reorder_file) as f:
		    for line in f:
		        start, end = (int(x.strip()) for x in line.split())
		        reorder_list.append(clip[start:end])

		clip = core.std.Splice(reorder_list)

	clip = clip[1:-1] if use_neatvideo else clip # adjust frames for preroll

	# apply cut list
	clip = dbzf.apply_cut(clip, cut_file)

	# apply dupe list
	if dupe_file:
		dupe_list = dbzf.read_dupe_file(dupe_file)
		clip = core.std.DuplicateFrames(clip, list(dupe_list))


# build montage sequence from scene change list
final_clip = dbzf.BuildMontage(clip, scenechange_file, scenechange_skip_file, per_row=4, mode=2, per_scene=9)

### output montage clip as image sequence ###
if output_img == True:
	final_clip = core.resize.Bicubic(final_clip, matrix_in_s="709", format=vs.RGB24)	
	imw = core.imwrif.Write(final_clip, imgformat="PNG", filename=img_dir ,firstnum=1)

	imw.set_output()
else:
	final_clip.set_output()
The script works on my tests, the only issue is with the neatvideo function naming that I reported last week. I couldn't put it inside a loop (I disabled it for now) because that'll means calling the function more than once, which will crash the program.
lansing is offline   Reply With Quote