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. |
15th January 2023, 12:02 | #1 | Link |
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,277
|
Trying to port CQTGMC to Vapoursynth
I'm trying to port CQTGMC to Vapoursynth, but got a few issues:
here's what I got Code:
# Imports import vapoursynth as vs import os import sys from typing import Optional, Union, Sequence # getting Vapoursynth core core = vs.core def CQTGMC(clip: vs.VideoNode, Sharpness: float=0.25, thSAD1: int=192, thSAD2: int=320, thSAD3: int=128, thSAD4: int=320) -> vs.VideoNode: flip = core.std.FlipHorizontal(clip) flip = Padding(clip=clip,top=clip.width%64) flip = Padding(clip=clip,right=clip.height%64) padded = core.std.StackHorizontal([clip,flip]) # todo: optional use nnedi3CL bobbed = core.znedi3.nnedi3(clip=padded, field=2) denoised = core.rgvs.RemoveGrain(clip=bobbed,mode=12) denoised = core.fmtc.resample(clip=denoised, kernel="gauss", w=denoised.width, h=denoised.height, scaleh=denoised.width+0.0001, interlaced=False, interlacedd=False) denoised = core.resize.Bicubic(clip=denoised, format=bobbed.format, dither_type="error_diffusion") # adjust format after fmtc denoised = core.std.Merge(clipa=denoised, clipb=bobbed,weight=0.25) srchClip = denoised csuper = core.mv.Super(clip=denoised); bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Comp1 = core.mv.Compensate(denoised,csuper,bvec,thsad=thSAD2) Comp2 = core.mv.Compensate(denoised,csuper,fvec,thsad=thSAD2) denoised = core.std.Interleave([Comp1,denoised,Comp2]) csuper = core.mv.Super(clip=denoised) bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Inter = core.mv.FlowInter(denoised, csuper, bvec,fvec,blend=False) a = core.std.SelectEvery(clip=Inter, cycle=2, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=2, offsets=1) P = core.std.PlaneStats(srchClip, srchClip[0] + srchClip) N = core.std.Trim(srchClip,1) N = core.std.PlaneStats(N, N[0] + N) srchClip = a # N < P doesn't work #srchClip = (N < P) ? a : b csuper = core.mv.Super(srchClip) bVec1 = core.mv.Analyse(csuper,isb=True,overlap=4,delta=1) fVec1 = core.mv.Analyse(csuper,isb=False,overlap=4,delta=1) csuper = core.mv.Super(bobbed,levels=1) bComp1 = core.mv.Compensate(bobbed,csuper,bVec1,thsad=thSAD3) fComp1 = core.mv.Compensate(bobbed,csuper,fVec1,thsad=thSAD3) X=1 # no clue how to get field order Inter = core.std.Interleave([ bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,0), fComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,1), bComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,2), bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,3) ]) weaved = core.std.DoubleWeave(Inter)[::2] csuper = core.mv.Super(weaved,levels=1) bComp1 = core.mv.Compensate(weaved, csuper, bVec1,thsad=thSAD4) fComp1 = core.mv.Compensate(weaved, csuper, fVec1,thsad=thSAD4) tMax = mt_logic(fComp1,mode="max").mt_logic(bComp1,mode="max") # does not work, missing c1&c2 parameters tMin = mt_logic(fComp1,mode="min").mt_logic(bComp1,"min") # does not work, missing c1&c2 parameters degrained = core.std.Degrain1(csuper,bVec1,fVec1,thsad=thSAD1) sharpen = mt_adddiff(degrained, mt_makediff(degrained.rgvs.RemoveGrain(mode=20))) sharpen = mt_clamp(sharpen,tMax,tMin,Sharpness,Sharpness,3,3) csuper = core.mv.Super(sharpen, levels=1) degrained = core.std.Degrain1(csuper,bVec1,fVec1,thsad=thSAD1) degrained = core.std.Crop(0,0,-(clip.width%64),-(clip.width%64)) return degrained def mt_adddiff(self, c1, c2, planes=[0]): expr = ('x y + {mid} -').format(mid=self.mid) expr = [(i in planes) * expr for i in range(3)] return self.std.Expr([c1, c2], expr) #from dehalo_alpha.py https://github.com/darealshinji/vapoursynth-plugins/blob/master/scripts/dehalo_alpha.py def mt_logic(self, c1, c2, mode, th1=0, th2=0, planes=0): if mode == 'min': expr = lambda x, y: min(x + th1, y + th2) elif mode == 'max': expr = lambda x, y: max(x + th1, y + th2) else: raise InvalidArgument('%s is not a valid mode for mt_logic' % mode) return self.mt_lutxy(c1, c2, expr, planes) # from havsfunc def Padding(clip: vs.VideoNode, left: int = 0, right: int = 0, top: int = 0, bottom: int = 0) -> vs.VideoNode: if not isinstance(clip, vs.VideoNode): raise vs.Error('Padding: this is not a clip') if left < 0 or right < 0 or top < 0 or bottom < 0: raise vs.Error('Padding: border size to pad must not be negative') width = clip.width + left + right height = clip.height + top + bottom return clip.resize.Point(width, height, src_left=-left, src_top=-top, src_width=width, src_height=height) # from havsfunc def mt_clamp( clip: vs.VideoNode, bright_limit: vs.VideoNode, dark_limit: vs.VideoNode, overshoot: int = 0, undershoot: int = 0, planes: Optional[Union[int, Sequence[int]]] = None, ) -> vs.VideoNode: if not (isinstance(clip, vs.VideoNode) and isinstance(bright_limit, vs.VideoNode) and isinstance(dark_limit, vs.VideoNode)): raise vs.Error('mt_clamp: this is not a clip') if bright_limit.format.id != clip.format.id or dark_limit.format.id != clip.format.id: raise vs.Error('mt_clamp: clips must have the same format') plane_range = range(clip.format.num_planes) if planes is None: planes = list(plane_range) elif isinstance(planes, int): planes = [planes] return core.std.Expr([clip, bright_limit, dark_limit], expr=[f'x y {overshoot} + min z {undershoot} - max' if i in planes else '' for i in plane_range]) Code:
a = core.std.SelectEvery(clip=Inter, cycle=2, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=2, offsets=1) P = core.std.PlaneStats(srchClip, srchClip[0] + srchClip) N = core.std.Trim(srchClip,1) N = core.std.PlaneStats(N, N[0] + N) srchClip = (N < P) ? a : b Issue 2: Code:
Inter = core.std.Interleave([ bobbed.std.SeparateFields().std.SelectEvery(4,0), fComp1.std.SeparateFields().std.SelectEvery(4,1), bComp1.std.SeparateFields().std.SelectEvery(4,2), bobbed.std.SeparateFields().std.SelectEvery(4,3) ]) I could change it to: Code:
X = 1 Inter = core.std.Interleave([ bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,0), fComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,1), bComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,2), bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,3) ]) Issue 3: Code:
tMax = mt_logic(fComp1,mode="max").mt_logic(bComp1,mode="max") tMin = mt_logic(fComp1,mode="min").mt_logic(bComp1,"min") Would be nice if someone could help. ----- Thanks to all that helped think I got a working (but still buggy) version https://github.com/Selur/Vapoursynth...ster/cqtgmc.py now. Cu Selur Last edited by Selur; 8th March 2023 at 08:21. |
15th January 2023, 12:19 | #3 | Link |
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,277
|
Code:
a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) P = core.std.PlaneStats(srchClip, srchClip[0] + srchClip) N = core.std.Trim(srchClip,1) N = core.std.PlaneStats(N, N[0] + N) srchClip = (N < P) ? a : b Cu Selur |
16th January 2023, 09:01 | #4 | Link | |
Registered User
Join Date: Jan 2018
Posts: 2,156
|
Quote:
Code:
a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) diffclip = core.std.PlaneStats(srchClip, srchClip[0] + srchClip) P = f.props['PlaneStatsDiff'] N = P.core.std.Trim(srchClip,1) def selectQTGMC(n, f): if N < P: return a else: return b srchClip = core.std.FrameEval(srchClip, selectQTGMC, prop_src=diffclip) return srchClip |
|
16th January 2023, 16:50 | #6 | Link |
Registered User
Join Date: Jan 2018
Posts: 2,156
|
Oh, my mistake
Code:
a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) diffclip = core.std.PlaneStats(srchClip, srchClip[0] + srchClip) def selectQTGMC(n, f): P = f.props['PlaneStatsDiff'] N = P.core.std.Trim(srchClip,1) if N < P: return a else: return b srchClip = core.std.FrameEval(srchClip, selectQTGMC, prop_src=diffclip) return srchClip |
16th January 2023, 20:17 | #7 | Link |
Registered User
Join Date: May 2011
Posts: 321
|
Code:
''' srchClip ScriptClip(""" P = YDifferenceFromPrevious() N = Trim(1,0).YDifferenceFromPrevious() N < P ? CQTGMC_A : CQTGMC_B """) ''' Code:
a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0)#trusting your code b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) srchClip = srchClip.std.PlaneStats(plane=0, prop='Y') srchClip_next = srchClip[1:]+srchClip[-1:] #delete first frame and double last frame to have same frame count srchClip_next = srchClip_next.std.PlaneStats(plane=0, prop='Y') def Y_preference(n,f,a,b): if f[0].props['YAverage'] < f[0].props['YAverage']: return a else: return b result = a.std.FrameEval(functools.partial(Y_preference, a=a,b=b), prop_src=[srchClip,srchClip_next]) |
16th January 2023, 20:38 | #8 | Link |
Registered User
Join Date: May 2011
Posts: 321
|
actually, it is just based on luma difference per pixel, so using Expr and Overlay:
Code:
srchClip_next = srchClip[1:]+srchClip[-1:] #delete first frame and double last frame to have same frame count srchClip_Y = srchClip.std.ShufflePlanes(0, vs.GRAY) srchClip_Y_next = srchClip_Y_next.std.ShufflePlanes(0, vs.GRAY) mask = core.std.Expr([srchClipY, srchClip_Y_next], 'x y > 255 0 ?')#255 or max size value for bitdepth result = havsfunc.Overlay(a, b, mask) Last edited by _Al_; 16th January 2023 at 20:51. |
16th January 2023, 21:35 | #9 | Link |
Registered User
Join Date: May 2011
Posts: 321
|
well, isn't like this, there is two differences going and one trimming as well:
Code:
Y = srchClip.std.ShufflePlanes(0, vs.GRAY) diffclip = core.std.PlaneStats(Y, Y[0]+Y[0:-1]) Y_trimmed =Y[1:]+Y[-1:] diffclip_trimmed = core.std.PlaneStats(Y_trimmed,Y_trimmed[0]+Y_trimmed[0:-1]) def selectQTGMC(n, f, a, b): P = f[0].props['PlaneStatsDiff'] N = f[1].props['PlaneStatsDiff'] if N < P: return a else: return b result = core.std.FrameEval(srchClip, partial(selectQTGMC,a=a,b=b), prop_src=diffclip,diffclip_trimmed) Last edited by _Al_; 16th January 2023 at 21:42. |
17th January 2023, 05:00 | #10 | Link |
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,277
|
Thanks that works.
Code:
# Imports import vapoursynth as vs import os import sys from functools import partial from typing import Optional, Union, Sequence # getting Vapoursynth core core = vs.core def CQTGMC(clip: vs.VideoNode, Sharpness: float=0.25, thSAD1: int=192, thSAD2: int=320, thSAD3: int=128, thSAD4: int=320) -> vs.VideoNode: flip = core.std.FlipHorizontal(clip) flip = Padding(clip=clip,top=clip.width%64) flip = Padding(clip=clip,right=clip.height%64) padded = core.std.StackHorizontal([clip,flip]) # todo: optional use nnedi3CL bobbed = core.znedi3.nnedi3(clip=padded, field=2) denoised = core.rgvs.RemoveGrain(clip=bobbed,mode=12) denoised = core.fmtc.resample(clip=denoised, kernel="gauss", w=denoised.width, h=denoised.height, scaleh=denoised.width+0.0001, interlaced=False, interlacedd=False) denoised = core.resize.Bicubic(clip=denoised, format=bobbed.format, dither_type="error_diffusion") # adjust format after fmtc denoised = core.std.Merge(clipa=denoised, clipb=bobbed,weight=0.25) srchClip = denoised csuper = core.mv.Super(clip=denoised); bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Comp1 = core.mv.Compensate(denoised,csuper,bvec,thsad=thSAD2) Comp2 = core.mv.Compensate(denoised,csuper,fvec,thsad=thSAD2) denoised = core.std.Interleave([Comp1,denoised,Comp2]) csuper = core.mv.Super(clip=denoised) bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Inter = core.mv.FlowInter(denoised, csuper, bvec,fvec,blend=False) a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) Y = srchClip.std.ShufflePlanes(0, vs.GRAY) diffclip = core.std.PlaneStats(Y, Y[0]+Y[0:-1]) Y_trimmed =Y[1:]+Y[-1:] diffclip_trimmed = core.std.PlaneStats(Y_trimmed,Y_trimmed[0]+Y_trimmed[0:-1]) def selectQTGMC(n, f, a, b): P = f[0].props['PlaneStatsDiff'] N = f[1].props['PlaneStatsDiff'] if N < P: return a else: return b srchClip = core.std.FrameEval(clip=srchClip, eval=partial(selectQTGMC,a=a,b=b), prop_src=diffclip, clip_src=diffclip_trimmed) csuper = core.mv.Super(srchClip) bVec1 = core.mv.Analyse(csuper,isb=True,overlap=4,delta=1) fVec1 = core.mv.Analyse(csuper,isb=False,overlap=4,delta=1) csuper = core.mv.Super(bobbed,levels=1) bComp1 = core.mv.Compensate(bobbed,csuper,bVec1,thsad=thSAD3) fComp1 = core.mv.Compensate(bobbed,csuper,fVec1,thsad=thSAD3) X=1 # no clue how to get field order Inter = core.std.Interleave([ bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,0), fComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,1), bComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,2), bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,3) ]) weaved = core.std.DoubleWeave(Inter)[::2] csuper = core.mv.Super(weaved,levels=1) bComp1 = core.mv.Compensate(weaved, csuper, bVec1,thsad=thSAD4) fComp1 = core.mv.Compensate(weaved, csuper, fVec1,thsad=thSAD4) tMax = mt_logic(fComp1,mode="max").mt_logic(bComp1,mode="max") tMin = mt_logic(fComp1,mode="min").mt_logic(bComp1,"min") degrained = core.std.Degrain1(csuper,bVec1,fVec1,thsad=thSAD1) sharpen = mt_adddiff(degrained, mt_makediff(degrained.rgvs.RemoveGrain(mode=20))) sharpen = mt_clamp(sharpen,tMax,tMin,Sharpness,Sharpness,3,3) csuper = core.mv.Super(sharpen, levels=1) degrained = core.std.Degrain1(csuper,bVec1,fVec1,thsad=thSAD1) degrained = core.std.Crop(0,0,-(clip.width%64),-(clip.width%64)) return degrained def mt_adddiff(self, c1, c2, planes=[0]): expr = ('x y + {mid} -').format(mid=self.mid) expr = [(i in planes) * expr for i in range(3)] return self.std.Expr([c1, c2], expr) #from dehalo_alpha.py https://github.com/darealshinji/vapoursynth-plugins/blob/master/scripts/dehalo_alpha.py def mt_logic(self, c1, c2, mode, th1=0, th2=0, planes=0): if mode == 'min': expr = lambda x, y: min(x + th1, y + th2) elif mode == 'max': expr = lambda x, y: max(x + th1, y + th2) else: raise InvalidArgument('%s is not a valid mode for mt_logic' % mode) return self.mt_lutxy(c1, c2, expr, planes) # from havsfunc def Padding(clip: vs.VideoNode, left: int = 0, right: int = 0, top: int = 0, bottom: int = 0) -> vs.VideoNode: if not isinstance(clip, vs.VideoNode): raise vs.Error('Padding: this is not a clip') if left < 0 or right < 0 or top < 0 or bottom < 0: raise vs.Error('Padding: border size to pad must not be negative') width = clip.width + left + right height = clip.height + top + bottom return clip.resize.Point(width, height, src_left=-left, src_top=-top, src_width=width, src_height=height) # from havsfunc def mt_clamp( clip: vs.VideoNode, bright_limit: vs.VideoNode, dark_limit: vs.VideoNode, overshoot: int = 0, undershoot: int = 0, planes: Optional[Union[int, Sequence[int]]] = None, ) -> vs.VideoNode: if not (isinstance(clip, vs.VideoNode) and isinstance(bright_limit, vs.VideoNode) and isinstance(dark_limit, vs.VideoNode)): raise vs.Error('mt_clamp: this is not a clip') if bright_limit.format.id != clip.format.id or dark_limit.format.id != clip.format.id: raise vs.Error('mt_clamp: clips must have the same format') plane_range = range(clip.format.num_planes) if planes is None: planes = list(plane_range) elif isinstance(planes, int): planes = [planes] return core.std.Expr([clip, bright_limit, dark_limit], expr=[f'x y {overshoot} + min z {undershoot} - max' if i in planes else '' for i in plane_range]) Code:
bVec1 = core.mv.Analyse(csuper,isb=True,overlap=4,delta=1) File "src\cython\vapoursynth.pyx", line 2612, in vapoursynth.Function.__call__ vapoursynth.Error: Analyse: failed to retrieve first frame from super clip. Error message: 'memoryview' object has no attribute 'props' Cu Selur |
17th January 2023, 21:31 | #11 | Link |
Registered User
Join Date: May 2011
Posts: 321
|
I tested it and I could go thru that line but
I used: Code:
srchClip = core.std.FrameEval(clip=srchClip, eval=partial(selectQTGMC,a=a,b=b), prop_src=[diffclip,diffclip_trimmed]) my test on your last script ended up on this line: tMax = mt_logic(fComp1,mode="max").mt_logic(bComp1,mode="max"), but that needs some fixing, I'm sure you know ... Last edited by _Al_; 17th January 2023 at 21:34. |
18th January 2023, 19:24 | #12 | Link | |
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,277
|
Quote:
There's also the issue that I use: Code:
X=1 # no clue how to get field order Inter = core.std.Interleave([ bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,0), fComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,1), bComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,2), bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,3) ]) |
|
21st January 2023, 11:31 | #13 | Link |
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,277
|
Now the script:
Code:
# Imports import vapoursynth as vs import os import sys from functools import partial from typing import Optional, Union, Sequence # getting Vapoursynth core core = vs.core def CQTGMC(clip: vs.VideoNode, Sharpness: float=0.25, thSAD1: int=192, thSAD2: int=320, thSAD3: int=128, thSAD4: int=320, tff: bool=True) -> vs.VideoNode: padded = core.std.AddBorders(clip, left=0, top=clip.height%4, right=clip.width%64, bottom=0) # alternative: #padded = core.std.StackHorizontal([clip, clip.std.FlipHorizontal().std.Crop(0,0,clip.width+clip.width()%64,0)]) #padded = core.std.StackVertical([padded, padded.std.FlipVertical().std.Crop(0,0,0,clip.height+clip.height%64)]) bobbed = core.znedi3.nnedi3(clip=padded, field=2) denoised = core.rgvs.RemoveGrain(clip=bobbed,mode=12) denoised = core.fmtc.resample(clip=denoised, kernel="gauss", w=denoised.width, h=denoised.height+0.0001, scaleh=denoised.width+0.0001, interlaced=False, interlacedd=False) denoised = core.resize.Bicubic(clip=denoised, format=bobbed.format, dither_type="error_diffusion") # adjust format after fmtc denoised = core.std.Merge(clipa=denoised, clipb=bobbed,weight=0.25) srchClip = denoised csuper = core.mv.Super(clip=denoised); bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Comp1 = core.mv.Compensate(clip=denoised,super=csuper,vectors=bvec,thsad=thSAD2) Comp2 = core.mv.Compensate(clip=denoised,super=csuper,vectors=fvec,thsad=thSAD2) denoised = core.std.Interleave([Comp1,denoised,Comp2]) csuper = core.mv.Super(clip=denoised) bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Inter = core.mv.FlowInter(denoised, csuper, bvec,fvec,blend=False) a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) Y = core.std.ShufflePlanes([srchClip],[0], vs.GRAY) diffclip = core.std.PlaneStats(Y, Y[0]+Y[0:-1]) Y_trimmed =Y[1:]+Y[-1:] diffclip_trimmed = core.std.PlaneStats(Y_trimmed,Y_trimmed[0]+Y_trimmed[0:-1]) def selectQTGMC(n, f, a, b): P = f[0].props['PlaneStatsDiff'] N = f[1].props['PlaneStatsDiff'] if N < P: return a else: return b srchClip = core.std.FrameEval(clip=srchClip, eval=partial(selectQTGMC,a=a,b=b), prop_src=[diffclip,diffclip_trimmed]) csuper = core.mv.Super(clip=srchClip) bVec1 = core.mv.Analyse(super=csuper, isb=True, overlap=4, delta=1) fVec1 = core.mv.Analyse(super=csuper, isb=False, overlap=4, delta=1) csuper = core.mv.Super(clip=bobbed,levels=1) bComp1 = core.mv.Compensate(clip=bobbed, super=csuper, vectors=bVec1, thsad=thSAD3) fComp1 = core.mv.Compensate(clip=bobbed, super=csuper, vectors=fVec1, thsad=thSAD3) X = 2 if tff else 1 # no clue how to get field order Inter = core.std.Interleave([ bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,0), fComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,1), bComp1.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,2), bobbed.std.SetFrameProp(prop="_FieldBased", intval=X).std.SeparateFields().std.SelectEvery(4,3) ]) weaved = core.std.DoubleWeave(clip=Inter)[::2] csuper = core.mv.Super(clip=weaved, levels=1) bComp1 = core.mv.Compensate(clip=weaved, super=csuper, vectors=bVec1, thsad=thSAD4) fComp1 = core.mv.Compensate(clip=weaved, super=csuper, vectors=fVec1, thsad=thSAD4) tMax = core.std.Expr(clips=[weaved, bComp1], expr=['x y max']) tMax = core.std.Expr(clips=[tMax, fComp1], expr=['x y max']) tMin = core.std.Expr(clips=[weaved, bComp1], expr=['x y min']) tMin = core.std.Expr(clips=[tMin, fComp1], expr=['x y min']) degrained = core.mv.Degrain1(clip=weaved, super=csuper, mvbw=bVec1, mvfw=fVec1, thsad=thSAD1) sharpen = core.std.MergeDiff(degrained, core.std.MakeDiff(degrained,degrained.rgvs.RemoveGrain(mode=20))) sharpen = mt_clamp(sharpen,tMax,tMin,Sharpness,Sharpness,[0]) csuper = core.mv.Super(sharpen, levels=1) degrained = core.mv.Degrain1(degrained, csuper,bVec1,fVec1,thsad=thSAD1) degrained = core.std.Crop(degrained, left=0, top=clip.height%4, right=clip.width%64, bottom=0) return degrained # from havsfunc def mt_clamp( clip: vs.VideoNode, bright_limit: vs.VideoNode, dark_limit: vs.VideoNode, overshoot: int = 0, undershoot: int = 0, planes: Optional[Union[int, Sequence[int]]] = None, ) -> vs.VideoNode: if not (isinstance(clip, vs.VideoNode) and isinstance(bright_limit, vs.VideoNode) and isinstance(dark_limit, vs.VideoNode)): raise vs.Error('mt_clamp: this is not a clip') if bright_limit.format.id != clip.format.id or dark_limit.format.id != clip.format.id: raise vs.Error('mt_clamp: clips must have the same format') plane_range = range(clip.format.num_planes) if planes is None: planes = list(plane_range) elif isinstance(planes, int): planes = [planes] return core.std.Expr([clip, bright_limit, dark_limit], expr=[f'x y {overshoot} + min z {undershoot} - max' if i in planes else '' for i in plane_range]) Must have mixed up something somewhere. => does anyone see where I went wrong? Cu Selur Last edited by Selur; 22nd January 2023 at 14:32. |
23rd January 2023, 22:15 | #14 | Link | |
Registered User
Join Date: Feb 2016
Location: Nonsense land
Posts: 339
|
Just wondering? Does the avisynth version deinterlaces it correctly? You have to think like a much strong lossless of QTGMC, so combed pixels might show up.
I don't speak vapoursynth language but I can't catch something that looks like this code, but I might be wrong. Quote:
My bad I spot it :\ Last edited by Ceppo; 23rd January 2023 at 22:25. |
|
24th January 2023, 00:03 | #15 | Link | ||||
Registered User
Join Date: Feb 2016
Location: Nonsense land
Posts: 339
|
Quote:
Quote:
Quote:
Quote:
|
||||
24th January 2023, 03:46 | #16 | Link |
Registered User
Join Date: May 2011
Posts: 321
|
HolyWu is working with YDifferenceFromPrevious here:
https://github.com/HomeOfVapourSynth...sfunc.py#L3321 |
24th January 2023, 19:31 | #17 | Link | ||
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,277
|
Quote:
Quote:
Without the 'std.SetFrameProp(prop="_FieldBased", intval=X)' part I get Code:
bComp1 = core.mv.Compensate(clip=weaved, super=csuper, vectors=bVec1, thsad=thSAD4) File "src\cython\vapoursynth.pyx", line 2612, in vapoursynth.Function.__call__ vapoursynth.Error: Compensate: failed to retrieve first frame from super clip. Error message: SeparateFields: no field order provided the Code:
global CQTGMC_A = Inter.SelectEvery(3,0) global CQTGMC_B = Inter.SelectEvery(3,1) srchClip ScriptClip(""" P = YDifferenceFromPrevious() N = Trim(1,0).YDifferenceFromPrevious() N < P ? CQTGMC_A : CQTGMC_B """) Code:
a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) Y = core.std.ShufflePlanes([srchClip],[0], vs.GRAY) diffclip = core.std.PlaneStats(Y, Y[0]+Y[0:-1]) Y_trimmed =Y[1:]+Y[-1:] diffclip_trimmed = core.std.PlaneStats(Y_trimmed,Y_trimmed[0]+Y_trimmed[0:-1]) def selectQTGMC(n, f, a, b): P = f[0].props['PlaneStatsDiff'] N = f[1].props['PlaneStatsDiff'] if N < P: return a else: return b srchClip = core.std.FrameEval(clip=srchClip, eval=partial(selectQTGMC,a=a,b=b), prop_src=[diffclip,diffclip_trimmed]) -> if someone can translate this to Vapoursynth in a working way, please do. |
||
4th February 2023, 14:20 | #18 | Link |
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,277
|
Thanks to all that helped think I got a working version now:
Code:
# Imports import vapoursynth as vs import os import sys from functools import partial from typing import Optional, Union, Sequence # getting Vapoursynth core core = vs.core # Vapoursynth port of CQTMC from https://forum.doom9.org/showthread.php?p=1963693 # # dependencies: # # fmtc when boxed=False https://github.com/EleonoreMizo/fmtconv # mvtools https://github.com/dubhater/vapoursynth-mvtools # NNEDI3CL when openCL=True https://github.com/HomeOfVapourSynthEvolution/VapourSynth-NNEDI3CL # NNEDI3 when openCL=False https://github.com/sekrit-twc/znedi3 def CQTGMC(clip: vs.VideoNode, Sharpness: float=0.25, thSAD1: int=192, thSAD2: int=320, thSAD3: int=128, thSAD4: int=320, tff: bool=True, openCL: bool=False, boxed: bool=False) -> vs.VideoNode: # pad to mod64 padded = core.std.AddBorders(clip, left=0, top=clip.height%64, right=clip.width%64, bottom=0) # deinterlace X = 2 if tff else 1 if openCL: bobbed = core.znedi3.nnedi3(clip=padded, field=X) else: bobbed = core.nnedi3cl.NNEDI3CL(clip=padded, field=X) # denoise denoised = core.rgvs.RemoveGrain(clip=bobbed,mode=12) if boxed: denoised = core.std.BoxBlur(clip=denoised) else: denoised = core.fmtc.resample(clip=denoised, kernel="gauss", w=denoised.width, h=denoised.height+0.0001, scaleh=denoised.width+0.0001, interlaced=False, interlacedd=False) denoised = core.resize.Bicubic(clip=denoised, format=bobbed.format, dither_type="error_diffusion") # adjust format after fmtc denoised = core.std.Merge(clipa=denoised, clipb=bobbed,weight=0.25) srchClip = denoised csuper = core.mv.Super(clip=denoised); bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Comp1 = core.mv.Compensate(clip=denoised,super=csuper,vectors=bvec,thsad=thSAD2) Comp2 = core.mv.Compensate(clip=denoised,super=csuper,vectors=fvec,thsad=thSAD2) denoised = core.std.Interleave([Comp1,denoised,Comp2]) csuper = core.mv.Super(clip=denoised) bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Inter = core.mv.FlowInter(denoised, csuper, bvec,fvec,blend=False) a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) Y = core.std.ShufflePlanes([srchClip],[0], vs.GRAY) diffclip = core.std.PlaneStats(Y, Y[0]+Y[0:-1]) Y_trimmed =Y[1:]+Y[-1:] diffclip_trimmed = core.std.PlaneStats(Y_trimmed,Y_trimmed[0]+Y_trimmed[0:-1]) def selectQTGMC(n, f, a, b): P = f[0].props['PlaneStatsDiff'] N = f[1].props['PlaneStatsDiff'] if N < P: return a else: return b srchClip = core.std.FrameEval(clip=srchClip, eval=partial(selectQTGMC,a=a,b=b), prop_src=[diffclip,diffclip_trimmed]) csuper = core.mv.Super(clip=srchClip) bVec1 = core.mv.Analyse(super=csuper, isb=True, overlap=4, delta=1) fVec1 = core.mv.Analyse(super=csuper, isb=False, overlap=4, delta=1) csuper = core.mv.Super(clip=bobbed,levels=1) bComp1 = core.mv.Compensate(clip=bobbed, super=csuper, vectors=bVec1, thsad=thSAD3) fComp1 = core.mv.Compensate(clip=bobbed, super=csuper, vectors=fVec1, thsad=thSAD3) Inter = core.std.Interleave([ bobbed.std.SeparateFields(tff=X).std.SelectEvery(4,0), fComp1.std.SeparateFields(tff=X).std.SelectEvery(4,1), bComp1.std.SeparateFields(tff=X).std.SelectEvery(4,2), bobbed.std.SeparateFields(tff=X).std.SelectEvery(4,3) ]) weaved = core.std.DoubleWeave(clip=Inter)[::2] csuper = core.mv.Super(clip=weaved, levels=1) bComp1 = core.mv.Compensate(clip=weaved, super=csuper, vectors=bVec1, thsad=thSAD4) fComp1 = core.mv.Compensate(clip=weaved, super=csuper, vectors=fVec1, thsad=thSAD4) tMax = core.std.Expr(clips=[weaved, bComp1], expr=['x y max']) tMax = core.std.Expr(clips=[tMax, fComp1], expr=['x y max']) tMin = core.std.Expr(clips=[weaved, bComp1], expr=['x y min']) tMin = core.std.Expr(clips=[tMin, fComp1], expr=['x y min']) degrained = core.mv.Degrain1(clip=weaved, super=csuper, mvbw=bVec1, mvfw=fVec1, thsad=thSAD1) sharpen = core.std.MergeDiff(degrained, core.std.MakeDiff(degrained,degrained.rgvs.RemoveGrain(mode=20))) sharpen = mt_clamp(sharpen,tMax,tMin,Sharpness,Sharpness,[0]) csuper = core.mv.Super(sharpen, levels=1) degrained = core.mv.Degrain1(clip=degrained, super=csuper, mvbw=bVec1,mvfw=fVec1,thsad=thSAD1) degrained = core.std.Crop(degrained, left=0, top=clip.height%64, right=clip.width%64, bottom=0) return degrained # from havsfunc # https://github.com/HomeOfVapourSynthEvolution/havsfunc/blob/7f0a9a7a37b60a05b9f408024d203e511e544a61/havsfunc.py#L5911 def mt_clamp( clip: vs.VideoNode, bright_limit: vs.VideoNode, dark_limit: vs.VideoNode, overshoot: int = 0, undershoot: int = 0, planes: Optional[Union[int, Sequence[int]]] = None, ) -> vs.VideoNode: if not (isinstance(clip, vs.VideoNode) and isinstance(bright_limit, vs.VideoNode) and isinstance(dark_limit, vs.VideoNode)): raise vs.Error('mt_clamp: this is not a clip') if bright_limit.format.id != clip.format.id or dark_limit.format.id != clip.format.id: raise vs.Error('mt_clamp: clips must have the same format') plane_range = range(clip.format.num_planes) if planes is None: planes = list(plane_range) elif isinstance(planes, int): planes = [planes] return core.std.Expr([clip, bright_limit, dark_limit], expr=[f'x y {overshoot} + min z {undershoot} - max' if i in planes else '' for i in plane_range]) Cu Selur |
19th February 2023, 18:35 | #19 | Link |
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,277
|
Nope, the padding and cropping is wrong.
Using: Code:
# Imports import vapoursynth as vs import os import sys from functools import partial from typing import Optional, Union, Sequence # getting Vapoursynth core core = vs.core # Vapoursynth port of CQTMC from https://forum.doom9.org/showthread.php?p=1963693 # # dependencies: # # fmtc when boxed=False https://github.com/EleonoreMizo/fmtconv # mvtools https://github.com/dubhater/vapoursynth-mvtools # NNEDI3CL when openCL=True https://github.com/HomeOfVapourSynthEvolution/VapourSynth-NNEDI3CL # NNEDI3 when openCL=False https://github.com/sekrit-twc/znedi3 def CQTGMC(clip: vs.VideoNode, Sharpness: float=0.25, thSAD1: int=192, thSAD2: int=320, thSAD3: int=128, thSAD4: int=320, tff: bool=True, openCL: bool=False, boxed: bool=False) -> vs.VideoNode: # pad to mod64 padded = core.std.AddBorders(clip, left=0, top=clip.height%4, right=clip.width%64, bottom=0) # spatial deinterlace # field: 2: Double rate, start with bottom field, 3: Double rate, start with top field. X = 3 if tff else 2 if openCL: spatial = core.nnedi3cl.NNEDI3CL(clip=padded, field=X) else: spatial = core.znedi3.nnedi3(clip=padded, field=X) # temporal deint # order: 0 = bottom field first (bff), 1 = top field first (tff) X = 1 if tff else 0 bobbed = core.tdm.TDeintMod(clip=padded, order=X, mode=1, edeint=spatial) # denoise denoised = core.rgvs.RemoveGrain(clip=bobbed,mode=12) if boxed: denoised = core.std.BoxBlur(clip=denoised) else: denoised = core.fmtc.resample(clip=denoised, kernel="gauss", w=denoised.width, h=denoised.height+0.0001, scaleh=denoised.width+0.0001, interlaced=False, interlacedd=False) denoised = core.resize.Bicubic(clip=denoised, format=bobbed.format, dither_type="error_diffusion") # adjust format after fmtc denoised = core.std.Merge(clipa=denoised, clipb=bobbed,weight=0.25) srchClip = denoised csuper = core.mv.Super(clip=denoised); bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Comp1 = core.mv.Compensate(clip=denoised,super=csuper,vectors=bvec,thsad=thSAD2) Comp2 = core.mv.Compensate(clip=denoised,super=csuper,vectors=fvec,thsad=thSAD2) denoised = core.std.Interleave([Comp1,denoised,Comp2]) csuper = core.mv.Super(clip=denoised) bvec = core.mv.Analyse(csuper,isb=True,blksize=64,overlap=32) fvec = core.mv.Analyse(csuper,isb=False,blksize=64,overlap=32) Inter = core.mv.FlowInter(denoised, csuper, bvec,fvec,blend=False) a = core.std.SelectEvery(clip=Inter, cycle=3, offsets=0) b = core.std.SelectEvery(clip=Inter, cycle=3, offsets=1) Y = core.std.ShufflePlanes([srchClip],[0], vs.GRAY) diffclip = core.std.PlaneStats(Y, Y[0]+Y[0:-1]) Y_trimmed =Y[1:]+Y[-1:] diffclip_trimmed = core.std.PlaneStats(Y_trimmed,Y_trimmed[0]+Y_trimmed[0:-1]) def selectQTGMC(n, f, a, b): P = f[0].props['PlaneStatsDiff'] N = f[1].props['PlaneStatsDiff'] if N < P: return a else: return b srchClip = core.std.FrameEval(clip=srchClip, eval=partial(selectQTGMC,a=a,b=b), prop_src=[diffclip,diffclip_trimmed]) csuper = core.mv.Super(clip=srchClip) bVec1 = core.mv.Analyse(super=csuper, isb=True, overlap=4, delta=1) fVec1 = core.mv.Analyse(super=csuper, isb=False, overlap=4, delta=1) csuper = core.mv.Super(clip=bobbed,levels=1) bComp1 = core.mv.Compensate(clip=bobbed, super=csuper, vectors=bVec1, thsad=thSAD3) fComp1 = core.mv.Compensate(clip=bobbed, super=csuper, vectors=fVec1, thsad=thSAD3) Inter = core.std.Interleave([ bobbed.std.SeparateFields(tff=tff).std.SelectEvery(4,0), fComp1.std.SeparateFields(tff=tff).std.SelectEvery(4,1), bComp1.std.SeparateFields(tff=tff).std.SelectEvery(4,2), bobbed.std.SeparateFields(tff=tff).std.SelectEvery(4,3) ]) weaved = core.std.DoubleWeave(clip=Inter)[::2] csuper = core.mv.Super(clip=weaved, levels=1) bComp1 = core.mv.Compensate(clip=weaved, super=csuper, vectors=bVec1, thsad=thSAD4) fComp1 = core.mv.Compensate(clip=weaved, super=csuper, vectors=fVec1, thsad=thSAD4) tMax = core.std.Expr(clips=[weaved, bComp1], expr=['x y max']) tMax = core.std.Expr(clips=[tMax, fComp1], expr=['x y max']) tMin = core.std.Expr(clips=[weaved, bComp1], expr=['x y min']) tMin = core.std.Expr(clips=[tMin, fComp1], expr=['x y min']) degrained = core.mv.Degrain1(clip=weaved, super=csuper, mvbw=bVec1, mvfw=fVec1, thsad=thSAD1) sharpen = core.std.MergeDiff(degrained, core.std.MakeDiff(degrained,degrained.rgvs.RemoveGrain(mode=20))) sharpen = mt_clamp(sharpen,tMax,tMin,Sharpness,Sharpness,[0]) csuper = core.mv.Super(sharpen, levels=1) degrained = core.mv.Degrain1(clip=degrained, super=csuper, mvbw=bVec1,mvfw=fVec1,thsad=thSAD1) degrained = core.std.Crop(degrained, left=0, top=clip.core%64, right=clip.width%64, bottom=0) return degrained # from havsfunc # https://github.com/HomeOfVapourSynthEvolution/havsfunc/blob/7f0a9a7a37b60a05b9f408024d203e511e544a61/havsfunc.py#L5911 def mt_clamp( clip: vs.VideoNode, bright_limit: vs.VideoNode, dark_limit: vs.VideoNode, overshoot: int = 0, undershoot: int = 0, planes: Optional[Union[int, Sequence[int]]] = None, ) -> vs.VideoNode: if not (isinstance(clip, vs.VideoNode) and isinstance(bright_limit, vs.VideoNode) and isinstance(dark_limit, vs.VideoNode)): raise vs.Error('mt_clamp: this is not a clip') if bright_limit.format.id != clip.format.id or dark_limit.format.id != clip.format.id: raise vs.Error('mt_clamp: clips must have the same format') plane_range = range(clip.format.num_planes) if planes is None: planes = list(plane_range) elif isinstance(planes, int): planes = [planes] return core.std.Expr([clip, bright_limit, dark_limit], expr=[f'x y {overshoot} + min z {undershoot} - max' if i in planes else '' for i in plane_range]) |
|
|