Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import vapoursynth as vs
- import G41Fun
- import havsfunc as haf
- import mvsfunc as mvf
- import muvsfunc as muf
- from vsutil import *
- from math import ceil
- from functools import partial
- core = vs.core
- w, h, b, c = 1280, 720, 0.2, 0.4
- def dogahomo(clip):
- clamp = clip.rgvs.RemoveGrain(1)
- des_a = descale(clip)
- des_b = descale(clamp)
- dif_a = absdiff(clip, des_a)
- dif_b = absdiff(clamp, des_b)
- return core.std.Expr([dif_a, dif_b, clamp, clip], 'x y - 1000 > x 2500 > and z a ?')
- def weakaa(clip, mask):
- aa = clip.std.Transpose()
- eaa = aa
- eaa = eaa.eedi3m.EEDI3(0,1,0, 0.2, 0.6, mclip=mask.std.Transpose()).resize.Spline36(height=eaa.height, src_top=.5)
- eaa = eaa.std.Transpose()
- eaa = eaa.eedi3m.EEDI3(0,1,0, 0.2, 0.6, mclip=mask ).resize.Spline36(height=eaa.height, src_top=.5)
- naa = aa
- naa = naa.znedi3.nnedi3(0,1,0,0,3,2).resize.Spline36(height=naa.height, src_top=.5)
- naa = naa.std.Transpose()
- naa = naa.znedi3.nnedi3(0,1,0,0,3,2).resize.Spline36(height=naa.height, src_top=.5)
- return median(eaa, naa, clip)
- def eedi3aa(clip, mask, ssw=3520, ssh=1980, nsize=0, nns=4, qual=2, alpha=0.2, beta=0.5, gamma=None, nrad=2, mdis=20, sclip=True):
- gamma = fallback(gamma, 20 if sclip is None else 69)
- base = clip.resize.Spline36(1080, 1920).std.Transpose()
- mclip = mask.fmtc.resample(ssw, ssh, kernel='box', fulls=1, fulld=1)
- aa = clip.resize.Spline36(ssh, ssw)
- aa = aa.eedi3m.EEDI3(0,0,0, alpha, beta, gamma, nrad, mdis, sclip=None if sclip is None else aa.znedi3.nnedi3(0,0,0, nsize, nns, qual), mclip=mclip.std.Transpose())
- aa = aa.std.Transpose()
- aa = aa.eedi3m.EEDI3(0,0,0, alpha, beta, gamma, nrad, mdis, sclip=None if sclip is None else aa.znedi3.nnedi3(0,0,0, nsize, nns, qual), mclip=mclip)
- aa = aa.resize.Spline36(1920, 1080)
- return base.std.MaskedMerge(aa, mask)
- def median(*clips): return core.std.Expr(clips, 'x y z min max y z max min')
- def contrast_adaptive_diff(clip, desc, rad=2, thr=0.125, lopass=1000):
- error = absdiff(clip, desc)
- contrast = range_mask(clip, rad)
- return core.std.Expr([error, contrast], f'x y {thr} * {lopass} max > 65535 0 ?')
- def absdiff(clip, desc):
- error = desc.resize.Bicubic(1920, 1080, filter_param_a=b, filter_param_b=c)
- return core.std.Expr([clip, error], 'x y - abs')
- def descale(clip): return depth(depth(clip, 32, dither_type='none').descale.Debicubic(w, h, b=b, c=c), 16, dither_type='none')
- def error_mask(clip, desc, thr1=2500, thr2=None, expand1=2, expand2=3, blur=3):
- start = 0
- error = absdiff(clip, desc)
- for x in range(expand1):
- error = error.std.Maximum(coordinates=[[1]*8, [0,1,0,1,1,0,1,0]][min(start%3,1)])
- start += 1
- if thr2 is not None:
- error = error.std.Binarize(thr2).misc.Hysteresis(error.std.Binarize(thr1))
- else:
- error = error.std.Binarize(thr1)
- for x in range(expand2):
- error = error.std.Maximum(coordinates=[[1]*8, [0,1,0,1,1,0,1,0]][min(start%3,1)])
- start += 1
- if blur:
- return error.std.BoxBlur(hradius=blur, vradius=blur)
- return error
- def ringing_mask(clip, rad=4, ethr1=30<<8, ethr2=50<<8, minthr=0.5):
- prew = clip.std.Prewitt()
- mask_lo = prew.std.Binarize(ethr1)
- mask_hi = prew.std.Binarize(ethr2)
- main = core.std.Expr([mask_lo, mask_hi.std.Maximum().std.Maximum(), mask_hi], 'x y - z max')
- main = main.std.Maximum().std.Maximum().std.Minimum().std.Minimum()
- shrink = main.std.Minimum()
- mask = core.std.Expr([main, shrink.std.Maximum(), main.std.Merge(shrink, minthr)], f'x y 0 = and x z ?')
- imask = iterate(mask, core.std.Maximum, rad).std.Invert()
- return core.std.Expr([mask, imask], 'x y +')
- def straight_line_mask(mask, thr=0.95, rad=69, expand=0):
- mask = core.std.Expr(mask, 'x 255 0 ?', vs.GRAY8)
- shift = ceil(rad / 2)
- grow = shift // 2
- v_avg = mask.std.BoxBlur(hradius=0, vradius=rad)
- v_avg = [v_avg.resize.Point(src_top=-shift), v_avg, v_avg.resize.Point(src_top=shift)]
- v_avg = core.std.Expr(v_avg, f'x y z max max {255 * thr} > 255 0 ?')
- v_avg = iterate(v_avg, partial(core.std.Maximum, coordinates=[0,1,0,1,1,0,1,0]), expand)
- v_avg = iterate(v_avg, partial(core.std.Maximum, coordinates=[0,1,0,0,0,0,1,0]), grow - expand)
- h_avg = mask.std.BoxBlur(hradius=rad, vradius=0)
- h_avg = [h_avg.resize.Point(src_left=-shift), h_avg, h_avg.resize.Point(src_left=shift)]
- h_avg = core.std.Expr(h_avg, f'x y z max max {255 * thr} > 255 0 ?')
- h_avg = iterate(h_avg, partial(core.std.Maximum, coordinates=[0,1,0,1,1,0,1,0]), expand)
- h_avg = iterate(h_avg, partial(core.std.Maximum, coordinates=[0,0,0,1,1,0,0,0]), grow - expand)
- return [h_avg, v_avg]
- def morpho_mask(clip, radius=3, **mode):
- refa = haf.mt_inpand_multi(haf.mt_expand_multi(clip, sw=radius, sh=radius, **mode), sw=radius, sh=radius, **mode)
- refb = haf.mt_expand_multi(haf.mt_inpand_multi(clip, sw=radius, sh=radius, **mode), sw=radius, sh=radius, **mode)
- return core.std.Expr([clip, refa, refb], 'x y - abs x z - abs max')
- def repair1(clip, repairclip, rad=1):
- if rad == 1:
- return clip.rgvs.Repair(repairclip, 1)
- rmax = haf.mt_expand_multi(repairclip, sw=rad, sh=rad, mode='ellipse')
- rmin = haf.mt_inpand_multi(repairclip, sw=rad, sh=rad, mode='ellipse')
- return core.std.Expr([clip, rmax, rmin], 'x y min z max')
- def repairmod(clip, rad=1):
- rmax = muf.Sort(clip, 2)
- rmin = muf.Sort(clip, 8)
- rmax = haf.mt_expand_multi(rmax, sw=rad, sh=rad, mode='ellipse')
- rmin = haf.mt_inpand_multi(rmin, sw=rad, sh=rad, mode='ellipse')
- return core.std.Expr([clip, rmax, rmin], 'x y min z max')
- def resize_mclip(mclip, w=None, h=None):
- iw = mclip.width
- ih = mclip.height
- ow = fallback(w, iw)
- oh = fallback(h, ih)
- if (ow > iw and ow/iw != ow//iw) or (oh > ih and oh/ih != oh//ih):
- mclip = mclip.resize.Point(iw * ceil(ow / iw), ih * ceil(oh / ih))
- return mclip.fmtc.resample(ow, oh, kernel='box', fulls=1, fulld=1)
- clip = core.ffms2.Source()
- clip = depth(clip, 16)
- # prep stuff
- clipy = get_y(clip)
- pre_descale = dogahomo(clipy)
- descaled = descale(pre_descale)
- error = error_mask(pre_descale, descaled, thr1=2500, thr2=3500, expand1=2, expand2=2, blur=3)
- FDOG = G41Fun.EdgeDetect(clipy, 'FDOG').std.Maximum().std.Minimum()
- sharp_edges = FDOG.std.Binarize(60<<9)
- # reupscale w/ protection from nnedi3 line/halo weirdness on straight lines
- slm = sharp_edges.std.Maximum()
- slm = straight_line_mask(slm)
- slm = core.std.Expr(slm, 'x y or 65535 0 ?', vs.GRAY16)
- slmt = slm.std.Transpose()
- mclip1 = resize_mclip(slm, w, h)
- mclip2 = resize_mclip(slmt, h * 2, w)
- slm_final = resize_mclip(slmt, h * 2, w * 2)
- nedi = descaled.znedi3.nnedi3(0,1,0,0,4,2).std.Transpose().znedi3.nnedi3(0,1,0,0,4,2).resize.Spline36(src_left=0.5, src_top=0.5)
- fsr = get_y(join([descaled.std.Transpose()]*3).placebo.Shader(shader=r'C:\Users\Zastin\AppData\Roaming\mpv\shaders\FSRCNNX_x2_16-0-4-1.glsl', filter='box', width=h * 2, height=w * 2))
- doubled = nedi.std.Merge(fsr, 0.5)
- eedi = descaled.eedi3m.EEDI3(0,1,0,mclip=mclip1).resize.Spline36(src_top=0.5).std.Transpose().eedi3m.EEDI3(0,1,0,mclip=mclip2).resize.Spline36(src_top=0.5)
- spline = descaled.std.Transpose().resize.Spline16(h * 2, w * 2)
- merged = median(doubled, eedi, spline)
- upscaled = core.std.Expr([doubled, merged, slm_final], 'z y x ?')
- # anti-aliasing
- aamask = sharp_edges.rgvs.RemoveGrain(11)
- upscaled = eedi3aa(upscaled, aamask, alpha=0.25, beta=0.6, gamma=0.15, sclip=False)
- #upscaled = upscaled.resize.Spline36(1080, 1920).std.Transpose()
- clipy = clipy.std.MaskedMerge(weakaa(clipy, core.std.Expr([aamask, error], 'y x 0 ?')), aamask)
- # reduce descale artifacts - "ref" varys based on source (upscale sharpness, post-processing, compression artifacts)
- safemask = ringing_mask(clipy)
- #ref = upscaled.bilateral.Bilateral(sigmaS=2, sigmaR=6 / 255, algorithm=0)
- #ref = mvf.LimitFilter(ref, upscaled, thr=5, elast=2, brighten_thr=3)
- #ref = median(clipy, upscaled, ref)
- ref = clipy
- noring = ref.std.MaskedMerge(upscaled, safemask)
- upscaled = repair1(upscaled, noring, rad=1)
- # build final detail mask
- morpho = morpho_mask(upscaled, 3).std.Binarize(1111)
- #morpho = morpho.rgvs.RemoveGrain(1)
- morpho = morpho.std.Maximum()
- lo, hi, start = [5000, 12000, 65536//16]
- edges = FDOG.std.Expr(f'x {lo} <= 0 x {hi} >= 65535 x {lo} - {(65535 - start)/(hi-lo)} * {start} + ? ?')
- edges_shrink = edges.std.Minimum().std.Maximum()
- detail = core.std.Expr([morpho, edges], 'x y and y 2 * y ?').std.Convolution([1]*9)
- detail = core.std.Expr([detail, edges, edges_shrink], 'y z > x y max x ?')
- descale_mask = core.std.Expr([detail, error], 'x y -')
- # merge descaled clip with original luma
- masked = clipy.std.MaskedMerge(upscaled, descale_mask)
- final = muf.MergeChroma(masked, clip)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement