View difference between Paste ID: 8SZ8WdWJ and 8KSTcJ0C
SHOW: | | - or go back to the newest paste.
1
################################
2
## FixBlendIVTC  by MOmonster ##
3
################################
4
5
6
## FixBlendIVTC is a blend replacing / frame restoring function for doubleblends, caused by blenddeinterlacing
7
## of telecined sources. It will only work for this special case and is not created for any other conversions.
8
##
9
## Use import("FixBlendIVTC.avs") in your script and load the necessary filters to be able using this function
10
##
11
## required filters:
12
##		- Average
13
##		- mt_masktools
14
##		- removegrain
15
##      - TIVTC	(for cache>-1, not default. or for decimating (external))
16
##		- Decomb (if you want to use the function decimate for decimating)
17
## version:
18-
##		- v0.91b  - 11.11.2017
18+
##		- v0.92b  - 19.02.2019
19
##
20
## Thanks to Manao, Clouded and Kassandro for the really useful plugins,
21
## and of course also to foxyshadis, who gives me the idea and many inspirations.
22
23
24
25
## sample1:	source				#progressive
26
##		FixBlendIVTC(sbd=true)
27
##		decimate(cycle=5,quality=0)	#recommed decimating
28
##
29
## sample2:	source
30
##		FixBlendIVTC(post="""pp2.deen("a2d")""")
31
##		tdecimate(rate=23.976,mode=7)
32
33
34
## parameter description:
35
##	post
36
##		It's the parameter for the postprocessing. These are the modes:
37
##			0 ->	the fastest mode, no postprocessing
38
##			1 ->	like post=0 but with chromablurring
39
##			2 ->	use difference masking, higher quality and still good speed			[0...6  ->2]
40
##			3 ->	like post=2 but with chromablurring
41
##			4 ->	use a special blurring mask on luma and chroma that reduces artefacts
42
##			5 ->	combines post 2 and 4 but without chromapostprocessing
43
##			6 ->	like post=5 but with extra chromaprocessing (slowest)
44
##		If these postprocessing modes aren't strong or individual enough for you you can also use your own
45
##		favourit filter on the restored frames. Therefore set a string with your setted filters.
46
##		Use pp0 till pp6 for the postprocessing mode and add your filter like this:
47
##			post="pp4.blur(1)"		#post=4 + blurring
48
##		If you want to use a filter with inputstrings use three quotation marks like in the second example.
49
##	bthresh
50
##		The blendthreshold can be used to make the blenddetection less aggressive if there are some wrong detections.
51
##														[0...2.0  ->0.1]
52
##	mthresh
53
##		It´s used for (m)otion (thresh)olding. It regulates the blenddetection of frames with small pixelvaluedifferences.
54
##		A better quality of the source allows lower values and a more accurate detection. Don´t change this parameter too
55
##		much. It has a high influence on the double and single blenddetection.				[0...1.0  ->0.1]
56
##	sbd
57
##		The (s)ingle(b)lend(d)etection value is a boolean, Set it true for 12fps animations.	[bool  ->false]
58
##  chroma
59
##      With chroma=true you enable the processing of the chroma. This cost some speed, but depending on the source it
60
##      can improve	the blend and motion detection.                                         [bool  ->false]
61
##  cache
62
##	    With cache>=0 FixBlendIVTC use the RequestLinear function to be more compatible with non-linear requesting (codec or other functions).
63
##	    You can set the number of frames you want to have cached. If cache is negative FixBlendIVTC doesn´t use RequestLinear
64
##      (can be useful if you have problems with the memory usage).                         [-1...50  ->5]
65
##	dclip
66
##		The (d)etection(clip) you can set to improve the blenddetection (cleaning the clip before).
67
##		This clip is only used for the blenddetection and not for output.
68
69
70
71
72
Function FixBlendIVTC(clip input, "post", float "bthresh", "mthresh", bool "sbd", clip "dclip", bool "chroma", int "cache") 
73
{
74
avs26 = !(VersionNumber() < 2.6)
75-
ssispmt = Findstr(VersionString(), "AviSynth+") != 0 && Findstr(VersionString(), "r1576") == 0
75+
sisphbd = AvsPlusVersionNumber > 2294
76
###### PREPARATION ######
77
global pp 	= default(post, 6)						#(p)ost(p)rocessing string
78
global mthresh 	= default(mthresh, 0.1)						#(m)otion(thresh)old
79
global thresh	= 1+default(bthresh, 0.01)
80
global sbd	= default(sbd,false)						#(s)ingle(b)lend(d)etection
81
82
       cache	= default(cache,-1)							#caching for non-linear request
83
84
rate	= framerate(input)
85
86
87
###### DETECTION CLIPS ######
88
dclip	= default(dclip,input)							#(d)etection clip
89-
sis420  = ssispmt ? dclip.is420() : dclip.isyv12()
89+
sis420  = sisphbd ? dclip.is420() : dclip.isyv12()
90-
sislumaonly = ssispmt ? dclip.isy() : !avs26 ? false : dclip.isy8()
90+
sislumaonly = sisphbd ? dclip.isy() : !avs26 ? false : dclip.isy8()
91
dclip	= default(chroma,false)==false || !sislumaonly ? dclip : \
92-
                                                                 sis420 ? stackvertical(stackhorizontal(ssispmt ? dclip.ExtractU() : avs26 ? dclip.utoy8() : dclip.UtoY(),ssispmt ? dclip.ExtractV() : avs26 ? dclip.vtoy8() : dclip.VtoY()), ssispmt ? dclip.converttoy() : avs26 ? dclip.converttoy8() : dclip) : \
92+
                                                                 sis420 ? stackvertical(stackhorizontal(sisphbd ? dclip.ExtractU() : avs26 ? dclip.utoy8() : dclip.UtoY(),sisphbd ? dclip.ExtractV() : avs26 ? dclip.vtoy8() : dclip.VtoY()), sisphbd ? dclip.converttoy() : avs26 ? dclip.converttoy8() : dclip) : \
93-
                                                                        stackhorizontal(stackhorizontal(ssispmt ? dclip.ExtractU() : avs26 ? dclip.utoy8() : dclip.UtoY(),ssispmt ? dclip.ExtractV() : avs26 ? dclip.vtoy8() : dclip.VtoY()), ssispmt ? dclip.converttoy() : avs26 ? dclip.converttoy8() : dclip)
93+
                                                                        stackhorizontal(stackhorizontal(sisphbd ? dclip.ExtractU() : avs26 ? dclip.utoy8() : dclip.UtoY(),sisphbd ? dclip.ExtractV() : avs26 ? dclip.vtoy8() : dclip.VtoY()), sisphbd ? dclip.converttoy() : avs26 ? dclip.converttoy8() : dclip)
94
95
o_diff	= mt_makediff(dclip.trim(1,0), dclip.trim(4,0))
96
c_diff	= mt_makediff(dclip.trim(2,0), dclip.trim(3,0))
97
global re_lut	= mt_lutxy(o_diff, c_diff, yexpr="x 128 - abs 126 > y 128 - abs 63 > & 0 x 128 + y 2 * - 2 ^ x 128 + y 2 * - abs 0.8 ^ - y 128 - abs 1 + 0.5 ^ / ?", uexpr="x", vexpr="x")
98
global sdiff	= mt_lut(c_diff, yexpr="x 128 - 2 ^ 12 -", uexpr="x", vexpr="x").mt_inpand()
99
100
101
###### POSTPROCESSING ######
102
unblend1 = Average(input, 2.0, input.duplicateframe(0), -1.0)
103
unblend2 = Average(input.trim(2,0), -1.0, input.trim(1,0), 2.0)
104
105
qmask1 	= mt_makediff(unblend1.RemoveGrain(mode=19, modeU=-1, modeV=-1), unblend1)
106
qmask2 	= mt_makediff(unblend2.RemoveGrain(mode=19, modeU=-1, modeV=-1), unblend2)
107
bmask	= mt_lutxy(qmask1, qmask2, yexpr="x 128 - abs y 128 - abs == 128 x 128 - abs 3 + y 128 - abs < 0 y 128 - abs 3 + x 128 - abs < 255 x 128 - abs y 128 - abs < 1 254 ? ? ? ?", uexpr="x", vexpr="x")
108
109
diff	= mt_lutxy(input.duplicateframe(0), input, yexpr="x y - abs", uexpr="x", vexpr="x").mt_expand()
110
dmask	= mt_lutxy(diff,diff.trim(2,0), yexpr="x 2 * y < x 4 < & 0 y 2 * x < y 4 < & 255 x x y + / 200 * 28 + ? ?", uexpr="x", vexpr="x")
111
pmask	= mt_lutxy(dmask, bmask, yexpr="y 0 > y 255 < & x 0 == x 255 == | & x y ?", uexpr="x", vexpr="x")
112
113
pp0 	= Average(input.trim(2,0), -0.5, input.trim(1,0), 1.0, input, 1.0, input.duplicateframe(0), -0.5)
114
pp1 	= pp0.RemoveGrain(mode=0, modeU=12, modeV=12)
115
pp2 	= mt_merge(unblend1, unblend2, dmask.RemoveGrain(mode=12, modeU=-1, modeV=-1).greyscale(), Y=3, U=3, V=3)
116
pp3 	= pp2.RemoveGrain(mode=0, modeU=12, modeV=12)
117
pp4 	= mt_merge(unblend1, unblend2, bmask.RemoveGrain(mode=12, modeU=-1, modeV=-1), luma=true)
118
pp5 	= mt_merge(unblend1, unblend2, pmask.RemoveGrain(mode=12, modeU=-1, modeV=-1).greyscale(), Y=3, U=3, V=3)
119
pp6	= mt_merge(pp5, unblend2, bmask.RemoveGrain(mode=12, modeU=-1, modeV=-1), Y=3, U=2, V=2).RemoveGrain(mode=0, modeU=12, modeV=12)
120
121
122
###### OUTPUT ######
123
global source	= input
124
global final	= IsString(pp) ? Eval(pp) : pp==1 ? pp1 : pp==2 ? pp2 : pp==3 ? pp3 : pp==4 ? pp4 : pp==5 ? pp5 : pp==6 ? pp6 : pp0
125
126
127
###### VAR.. ######
128
global fdc0	= 1.0								#(f)rame(d)ifference
129
global fdn1 	= 1.0
130
global fdn2 	= 1.0
131
132
global rvp1	= 1.0								#(r)estore(v)alue
133
global rvc0 	= 1.0
134
global rvn1 	= 1.0
135
global rvn2 	= 1.0
136
137
global counter	= 2								#pattern count variable
138
139
140
###### Conditional Function Chain, evaluated from bottom to top (!) ######
141
#ScriptClip(source, " source.subtitle(string(rvc0)) ")
142
ScriptClip(source, " counter==0 ? final : counter==1 ? source.trim(1,0) : source ")
143
144
FrameEvaluate(last, "
145
	global fdp1	= fdc0
146
	global fdc0	= fdn1
147
	global fdn1	= fdn2
148
	global fdn2	= AverageLuma(sdiff)
149
150
	global rvp2	= rvp1
151
	global rvp1	= rvc0
152
	global rvc0	= rvn1
153
	global rvn1	= rvn2
154
	global rvn2 	= AverageLuma(re_lut)
155
156
	bcalc	= rvc0<rvp2 && rvc0<rvp1 && rvc0<rvn1 && rvc0<rvn2 ? 
157
		\ (rvp2<rvp1 && rvp2<rvn1 && rvp2<rvn2 ? rvp2 : rvp1<rvn1 && rvp1<rvn2 ? rvp1 : rvn1<rvn2 ? rvn1 : rvn2) / rvc0 :
158
		\ rvc0<0.25*rvp1 && rvc0<0.25*rvn1 && (rvc0<0.5*rvp2 || rvc0<0.5*rvn2) ?
159
		\ -0.25 * (2*rvp2<rvp1 && 2*rvp2<rvn1 && rvp2>rvn2 ? 2*rvp2 : 2*rvn2<rvp1 && 2*rvn2<rvn1 && rvn2>rvp2 ? 2*rvn2 : rvp1<rvn1 ? rvp1 : rvn1) / rvc0 : 0
160
161
	global counter	= counter==-1 ? 1 : (abs(bcalc)>1.0 && rvc0<10*mthresh || abs(bcalc)>thresh) &&
162
			\ (counter>3 || bcalc>0) && (fdp1>mthresh || fdn1>mthresh || fdp1>0.5*fdc0 || fdn1>0.5*fdc0) ? 0 : counter+1
163
164
	global counter	= counter!=0 || sbd==false ? counter : fdp1<fdn1 && fdp1<mthresh ? -1 : fdn1<mthresh || fdc0<mthresh ? 1 : 0
165
		")
166
			
167
cache==-1 ? last.changefps(rate*2).changefps(rate,linear=true).addborders(8,0,0,0).crop(8,0,-0,-0) : \
168
            cache<0 ? last : last.RequestLinear(8, cache, 5, false, false)
169
170
return(last)  
171
}