View difference between Paste ID: 8KSTcJ0C and 4hXcg8jk
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 or Decomb for decimating (external)
15+
##      - TIVTC	(for cache>-1, not default. or for decimating (external))
16
##		- Decomb (if you want to use the function decimate for decimating)
17-
##		- v0.9b  - 29.08.2016 for new Average
17+
18
##		- v0.91b  - 11.11.2017
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-
##		The (s)ingle(b)lend(d)etection value is a boolean, Set it true for 12fps animations and so on.	[bool  ->false]
56+
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-
Function FixBlendIVTC(clip input, "post", float "bthresh", "mthresh", bool "sbd", clip "dclip") 
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-
global thresh	= 1.01
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
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()
90
sislumaonly = ssispmt ? 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) : \
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)
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-
last.changefps(rate*2).changefps(rate,linear=true).addborders(8,0,0,0).crop(8,0,-0,-0)
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
}