View difference between Paste ID: 6hStBeaN and pQLKaECS
SHOW: | | - or go back to the newest paste.
1
###                                                      #
2
###                                                      #
3
### Stabilization Tools Pack 2.1 by Dogway (16-09-2015)  #
4-
###                   mod 2.5 by A.SONY in (19-02-2019)  #
4+
###                  mod 2.51 by A.SONY in (08-01-2020)  #
5
###                                                      #
6
##########################################################
7
###
8
### FilmGateFix()
9
###
10
###  (http://forum.videohelp.com/threads/371336)
11
###
12
### Function to fix frames ( by means of FreezeFrame() ) with film gate issues after a scene change.
13
### This is aimed at animation, for live footage frame interpolation should be desired.
14
###
15
### Rationale:
16
### Film Gate is about non-linear vertical stretching, thus we compare
17
### current and next frames in two blocks, a 1/5 block of top and bottom.
18
### The difference in both should be very high for film gate artifacts
19
### between the 2nd and 3rd frame after a Scene Change (also 1st and 2nd are compared).
20
### We mask this through a Scene Detection filter, motion masks, etc.
21
###
22
###  EXPERIMENTAL:
23
###  It still grabs too many false-positives, and leaves many positives-positives undone
24
###  a better approach would be to automatically bookmark every scene change and manually freezeframe them
25
###
26
###
27
### Dependencies:
28
###
29
### Required:
30
### ------------
31
###
32
###   MVTools       (v2.5.11.3 or higher)               (http://avisynth.org.ru/mvtools/mvtools2.html)
33
###   masktools     (v2a48 or higher)                   (http://forum.doom9.org/showthread.php?t=98985)
34
###   Average       (v0.92 or higher)                   (http://forum.doom9.org/showthread.php?t=169832)
35
###   GRunT         (v1.0.1 or higher)                  (http://forum.doom9.org/showthread.php?t=139337)
36
###
37
####################################
38
39
function FilmGateFix(clip c,  float "thr", int "window", int "thSCD1", int "thSCD2", bool "debug") {
40
41
thr     = Default(thr,1.2)      # Main tweak setting, use debug and tweak according 2nd frame after Scene Change
42
window  = Default(window,5)     # Enlarges/reduces detection area, "height()/window"
43
thSCD1  = Default(thSCD1,500)   # Increase to reduce number of scenes detected
44
thSCD2  = Default(thSCD2,145)   # Increase to reduce number of scenes detected
45
Debug   = Default(Debug,false)  # Check what frames will be fixed and the difference value of frames for tweaking "thr"
46
thr2    = 5.0                   # central part of frame must change less than this to consider static scene to fix.
47
48
c
49
w=width()
50
h=height()
51
52
# Block for Scene Change detection and Motion Mask
53
kind   = 0
54
gam    = 1.2 # Could probably be exposed
55
mvthr  = 30  # Threshold, heavily dependent on gamma value above
56
super  = MSuper  (pel=1, sharp=0,vpad=0,hpad=0)
57
b1v    = MAnalyse(super,isb=true, blksize=16,overlap=8,search=0)
58
f1v    = MAnalyse(super,isb=false, blksize=16,overlap=8,search=0)
59
SADbv1 = MMask   (b1v,kind=kind,gamma=gam,thSCD1=thSCD1,thSCD2=thSCD2)
60
SADfv1 = MMask   (f1v,kind=kind,gamma=gam,thSCD1=thSCD1,thSCD2=thSCD2)
61
62
SceneChange = MSCDetection (f1v,thSCD1=thSCD1,thSCD2=thSCD2)
63
mvmask      = Average(SADbv1,1./2,SADfv1,1./2)
64
65
66
# Film Gate happens commonly between 2nd and 3rd frame after SC
67
# 1st frame is commonly garbage
68
add  = round(w/(window*1.0))
69
T    = crop(0,0,0,((-h+add)/8)*8)
70
B    = crop(0,((h-add)/8)*8,0,0)
71
72
L    = crop(0,0,((-w+add)/8)*8,0)
73
R    = crop(((w-add)/8)*8,0,0,0)
74
75
CTB  = crop(0,((add)/8)*8,0,-((add)/8)*8)
76
CLR  = crop(round(((add*1.5)/8)*8),0,round(-((add*1.5)/8)*8),0)
77
78
SC2  = mt_logic(SceneChange,selectevery(SceneChange,1,-1),"max",U=3,V=3)
79
80
# Here, if after SC top area changes more than "thr" compared to bottom area
81
# then apply one FreezeFrame() for first SC frame, and another FreezeFrame() for the 2nd one,
82
# they (1st and 2nd) compute individually. There is a motionmask on top to rule out false positives.
83
scriptclip("""(abs(YDifferenceToNext(T)-YDifferenceToNext(B))>"""+string(thr)+""" && abs(YDifferenceToNext(CTB))<"""+
84
            \ string(thr2)+""") || (abs(YDifferenceToNext(L)-YDifferenceToNext(R))>"""+string(thr)+
85
            \ """ && abs(YDifferenceToNext(CLR))<"""+string(thr2)+""") ?"""+
86
            \ """(YplaneMax(SC2)>254?(YDifferenceFromPrevious(SC2)>250?(AverageLuma(mvmask)<"""+string(mvthr)+
87
            \ """?(LumaDifference(c,d)<3.7?freezeframe(current_frame,current_frame,current_frame+2):(YDifferenceToNext()<8.0?freezeframe(current_frame,current_frame,current_frame+1):c)):c):"""+
88
            \ """(AverageLuma(mvmask)<"""+string(mvthr)+"""?freezeframe(current_frame,current_frame,current_frame+1):c)):c):c""",
89
            \ args="T,B,L,R,c,SC2,CTB,CLR,mvmask,d=Trim(2,0)")
90
91
# Debug block
92
debug ? +\
93
eval("""stackhorizontal(scriptclip("Subtitle(c,"+Chr(34)+" Top & Bottom:"+Chr(34)+"+String(YDifferenceToNext(T)-YDifferenceToNext(B))+
94
       \ "+Chr(34)+"\n Left & Right:  "+Chr(34)+"+String(YDifferenceToNext(L)-YDifferenceToNext(R))+
95
       \ "+Chr(34)+"\n Center Horiz:  "+Chr(34)+"+String(YDifferenceToNext(CTB))+
96
       \ "+Chr(34)+"\n Center Vert:    "+Chr(34)+"+String(YDifferenceToNext(CLR))+
97
       \ "+Chr(34)+"\n AvgLuma:    "+Chr(34)+"+String(LumaDifference(c,d)),
98
       \ align=7,size=30,lsp=10)",args="T,B,L,R,c,CTB,CLR,d=Trim(2,0)"),
99
       \ scriptclip("AverageLuma(mvmask)<"""+string(mvthr)+"""?((abs(YDifferenceToNext(T)-YDifferenceToNext(B))>"+string(thr)+
100
           \ " && abs(YDifferenceToNext(CTB))<"+string(thr2)+") || (abs(YDifferenceToNext(L)-YDifferenceToNext(R))>"+
101
           \ string(thr)+" && abs(YDifferenceToNext(CLR))<"+string(thr2)+") ? "+
102
           \ "(YplaneMax(SC2)>254?(LumaDifference(c,d)<3.7?mt_lut(c,"+Chr(34)+"255"+Chr(34)+",U=128,V=128):(YDifferenceToNext()<8.0?mt_lut(c,"+Chr(34)+"255"+Chr(34)+",U=128,V=128):mt_lut(c,"+Chr(34)+"0"+Chr(34)+
103
           \ ",U=128,V=128))):mt_lut(c,"+Chr(34)+"0"+Chr(34)+",U=128,V=128)):mt_lut(c,"+Chr(34)+"0"+Chr(34)+",U=128,V=128)):mt_lut(c,"+Chr(34)+"0"+
104
           \ Chr(34)+",U=128,V=128)",args="T,B,L,R,c,CTB,CLR,SC2,mvmask,d=Trim(2,0)"))
105
           \ crop(0,0,-(round(w/1.1)/2)*2,0).Subtitle("Frame to Freeze",align=9,size=40)""") : last }
106
107
108
109
110
111
####################################
112
###
113
### FillBorders()
114
###
115
###  (http://forum.videohelp.com/threads/371336)
116
###
117
### Function to fill dark (use threshold) borders, in the vein of old FillMargins() function.
118
### But instead of mirroring or other approaches like resizing, this function fills/interpolates
119
### missing data from surrounding pixels.
120
### Useful to use as a clean pass after stab() and crop(x1,y1,x2,y2)
121
### for the remaining thin black borders (up to 3px)
122
###
123
### For borders of 4px and more you can enable FixFalPos, there you supply a clip
124
### without black borders (ie. before stab() ). It automatically replaces the offended frames.
125
### Some thick black borders aren't "0" black at all, they show garbage and the 3+1 pixel border
126
### may not average to 0, so a "thr2" setting is added as threshold, default 7 should be enough.
127
###
128
### Below you can still use the the FindBlackBorders() function for manual handling of thick black borders.
129
### Use ClipClop() for the stab() results according to the statistics file of FindBlackBorders()
130
###
131
### Mind you, for FillBorders() you need to manually load the AVSInpaint plugin:
132
### LoadCPlugin("AVSInpaint.dll")
133
###
134
###  EXPERIMENTAL:
135
###  Some thick black borders aren't value 0 at all, sometimes they average to 16, so one would
136
###  need to set thr2 to >16 which will basically bypass the Stab'ed clip in a lot of dark scenes.
137
###  So probably you might still want to use this for only <4px borders and FindBlackBorders() to
138
###  manually find the most offending borders and problematic areas.
139
###
140
###
141
### Dependencies:
142
###
143
###   masktools     (v2a48 or higher)                   (http://forum.doom9.org/showthread.php?t=98985)
144
###   GRunT         (v1.0.1 or higher)                  (http://forum.doom9.org/showthread.php?t=139337)
145
###   AVSInpaint    (v2008.02.23 or higher)             (http://forum.doom9.org/showthread.php?t=133682)
146
###
147
####################################
148
149-
function FillBorders(clip c, int "thr", int "pad", bool "blur", bool "debug", clip "FixFalPos", int "thr2", bool "mirror", float "PAR", bool "subsample" ) {
149+
function FillBorders(clip c, int "thr", int "pad", bool "blur", bool "debug", clip "FixFalPos", int "thr2", bool "mirror", float "PAR", bool "subsample", bool "maskonly", clip "FillBordersc" ) {
150
151
thr      = Default(thr, 1)       # Threshold, pixel values below this will be considered borders
152
pad      = Default(pad, 0)       # Pixels, you can expand the replacement area adding more pixels
153
                                 # (to deal with dirty borders) (use "1" to deal with 1px b/w chroma, due to the chroma subsampling nature of video)
154
mirror   = Default(mirror, false)
155
blur     = Default(blur, mirror) # Blurs the masking for the replacement area. Currently not supported for InpaintLogo()
156
debug    = Default(debug,false)  # Show the borders that are going to be filled
157
FalPos   = Defined(FixFalPos)    # If you supply a reference clip borders with 4 or more
158
                                 # average thr2 pixels will be replaced with the clip's frame
159
thr2     = Default(thr2, 7)      # Threshold for FalPos, FalPos frames sometimes have garbage borders so you need to increase threshold 
160
mskonly  = Default(maskonly, false) 
161
subsampl = Default(subsample,false) 
162
163
sisphbd = AvsPlusVersionNumber > 2294
164
165
c
166
contoy = sisphbd ? !isy() : !isy8()
167
contoy ? sisphbd ? converttoy() : converttoy8() : last
168
yclip=last
169
w=width()
170
h=height()
171
172
# 4px or greater
173
L4=FalPos ? crop(0,0,-w+4,0) : nop()
174
R4=FalPos ? crop(w-4,0,0 ,0) : nop()
175
T4=FalPos ? crop(0,0,0,-h+4) : nop()
176
B4=FalPos ? crop(0,h-4,0 ,0) : nop()
177
# 3px
178
L3=crop(0,0,-w+3,0)
179
R3=crop(w-3,0,0 ,0)
180
T3=crop(0,0,0,-h+3)
181
B3=crop(0,h-3,0 ,0)
182
# 2px
183
L2=crop(L3,0,0,-1, 0)
184
R2=crop(R3,1,0,0 , 0)
185
T2=crop(T3,0,0,0 ,-1)
186
B2=crop(B3,0,1,0 , 0)
187
# 1px
188
L1=crop(L3,0,0,-2,0 )
189
R1=crop(R3,2,0,0 ,0 )
190
T1=crop(T3,0,0,0 ,-2)
191
B1=crop(B3,0,2,0 ,0 )
192
193
c
194
Fill = gScriptClip("""
195
yclip
196
pad= blur ? pad+2 : pad
197
198
L1A = AverageLuma(L1)
199
R1A = AverageLuma(R1)
200
T1A = AverageLuma(T1)
201
B1A = AverageLuma(B1)
202
203
x1o = L1A < thr ? (AverageLuma(L2) < thr ? (AverageLuma(L3) < thr ? 3 : 2) : 1) : 0
204
x1  = L1A < thr ? x1o+pad : x1o
205
x2o = R1A < thr ? (AverageLuma(R2) < thr ? (AverageLuma(R3) < thr ? 3 : 2) : 1) : 0
206
x2  = R1A < thr ? x2o+pad : x2o
207
y1o = T1A < thr ? (AverageLuma(T2) < thr ? (AverageLuma(T3) < thr ? 3 : 2) : 1) : 0
208
y1  = T1A < thr ? y1o+pad : y1o
209
y2o = B1A < thr ? (AverageLuma(B2) < thr ? (AverageLuma(B3) < thr ? 3 : 2) : 1) : 0
210
y2  = B1A < thr ? y2o+pad : y2o
211-
FalPos = FalPos ? ((x1-pad > 2 || x2-pad > 2 || y1-pad > 2 || y2-pad > 2 )
211+
212-
              \ ? ((AverageLuma(L4) < thr2) || (AverageLuma(R4) < thr2) || (AverageLuma(T4) < thr2) || (AverageLuma(B4) < thr2)
212+
FalPos = !mskonly && FalPos ? ((x1-pad > 2 || x2-pad > 2 || y1-pad > 2 || y2-pad > 2 )
213-
              \ ? true : false) : false) : false
213+
                          \ ? ((AverageLuma(L4) < thr2) || (AverageLuma(R4) < thr2) || (AverageLuma(T4) < thr2) || (AverageLuma(B4) < thr2)
214
                          \ ? true : false) : false) : false
215
216
217
cropnpad = (x1+y1+x2+y2>0)
218
ter = !FalPos && cropnpad
219
220
x1inp=cropnpad && subsampl ? int(round(x1o/2.0)*2) : x1
221
x2inp=cropnpad && subsampl ? int(round(x2o/2.0)*2) : x2
222
y1inp=cropnpad && subsampl ? int(round(y1o/2.0)*2) : y1
223
y2inp=cropnpad && subsampl ? int(round(y2o/2.0)*2) : y2
224-
PaCl = mirror && !ter ? c.crop(x1inp,y1inp,-x2inp,-y2inp,align=true).Padding(x1inp,y1inp,x2inp,y2inp) : c
224+
225
PaCl = mskonly ? nop() : mirror && !ter ? c.crop(x1inp,y1inp,-x2inp,-y2inp,align=true).Padding(x1inp,y1inp,x2inp,y2inp) : c
226
227
msk  = LetterBox(BlankClip(last, Color_yuv=$000000),y1,y2,x1,x2,$ffffff)
228
msk  = !mirror ? msk.mt_lut("x 128 > 255 x ?") : msk
229
msk  = !mirror && blur ? msk.mt_convolution("1 1 1 1 1", "1 1 1 1 1") : msk
230
msk  = contoy ? sisphbd ? CombinePlanes(msk,c,planes="YUV",sample_clip=c) : YToUV(c.UToY8(),c.VToY8(),msk) : msk
231-
fill = FalPos ? trim(c,0,current_frame-1)++trim(FixFalPos,current_frame,-1)++trim(c,current_frame+1,0) : \
231+
232-
         (ter ? InpaintLogo(c, radius=max(x1,y1,x2,y2)+max(2,pad), mask=msk,ChromaTensor=subsampl,PixelAspect=PAR,PreBlur=mirror && blur ? 2.5 : undefined) : PaCl)
232+
fill = mskonly ? msk : FalPos ? trim(c,0,current_frame-1)++trim(FixFalPos,current_frame,-1)++trim(c,current_frame+1,0) : \
233
                       (ter ? Defined(FillBordersc) ? FillBordersc : InpaintLogo(c, radius=max(x1,y1,x2,y2)+max(2,pad), mask=msk,ChromaTensor=subsampl,PixelAspect=PAR,PreBlur=mirror && blur ? 2.5 : undefined) : PaCl)
234
sub  = debug  ? subtitle(msk,"Bordered",align=3,size=round(h/20.0)) : nop()
235
236-
""",args="yclip,c,sisphbd,contoy,thr,thr2,L4,R4,T4,B4,L3,R3,T3,B3,L2,R2,T2,B2,L1,R1,T1,B1,pad,blur,debug,FalPos,FixFalPos,mirror,subsampl,PAR")
236+
237
""",args="yclip,c,sisphbd,contoy,thr,thr2,L4,R4,T4,B4,L3,R3,T3,B3,L2,R2,T2,B2,L1,R1,T1,B1,pad,blur,debug,FalPos,FixFalPos,mirror,subsampl,PAR,mskonly,FillBordersc")
238
239
!debug ? Fill : \
240
eval("""
241
 box    = h/4.0
242
 m      = 2
243
244
 corner = crop(mt_lut("255"),round((w-box)/m)*m,round((h-box)/m)*m,0,0,align=true)
245
 corner = corner.addborders(0,0,round((w/2.0-box)/m)*m,round(box/m)*m).mt_lut("x 255 < 0 255 ?")
246
247
 horiz  = stackhorizontal(corner,corner.fliphorizontal())
248
 verti  = stackvertical(horiz,horiz.flipvertical())
249
250
 mt_merge(c,Fill.pointresize(w,h),verti,luma=true)""") }
251
252
253
####################################
254
###
255
### FindBlackBorders()
256
###
257
###  (http://forum.videohelp.com/threads/371336)
258
###
259
### Script to find sources with black borders for example as a result of bad deshaking, run on analysis pass
260
### The output file is formatted to be imported to avspmod as bookmarks
261
### use ClipClop() afterwards on a scene by scene basis to fix this.
262
###
263
### "width" is border thickness for detection
264
### "thr" is threshold, pixel values below this will be considered borders
265
### "path" is the path to store the statistics file, with end backslash. Default is "C:"
266
### "filename" is the statistics file name. In case you don't want to overwrite old ones
267
###
268
### Dependencies:
269
###
270
### Required:
271
### ------------
272
###
273
###   masktools     (v2a48 or higher)                   (http://forum.doom9.org/showthread.php?t=98985)
274
###   Dither        (v1.26.5 or higher)                 (http://forum.doom9.org/showthread.php?p=1386559#post1386559)
275
###
276
####################################
277
278
function FindBlackBorders(clip c, int "width", int "thr", string "path", string "filename") {
279
280
add      = Default(width,1)     # Width for detection, normally 1 should suffix to most situations
281
thr      = Default(thr,1)       # Threshold for detection, pixels lower than this value will be considered a border
282
path     = Default(path, "C:")  # This is the path to store the statistics file
283
filename = Default(filename, "FindBlackBorders - Statistics.log") # Filename of the statistics file
284
285
c
286
converttoy8()
287
w=width()
288
h=height()
289
290
L1=crop(0,0,-w+add,0)
291
R1=crop(w-add,0,0 ,0)
292
T1=crop(0,0,0,-h+add)
293
B1=crop(0,h-add,0 ,0)
294
295
ScriptClip("""
296
x1 = AverageLuma(L1) < thr ? true : false
297
x2 = AverageLuma(R1) < thr ? true : false
298
y1 = AverageLuma(T1) < thr ? true : false
299
y2 = AverageLuma(B1) < thr ? true : false
300
function IsBorder(clip c, bool x1, bool x2, bool y1, bool y2) {return (x1||y1||x2||y2)?true:false}
301
302
q = chr(34)chr(34)chr(34)
303
WriteFileIf(""+path+"\"+filename+"", " "+string(IsBorder(x1,y1,x2,y2))+" ", q+"CHAPTER00="+q,
304
        \ "FFFormatTime_stabi(round((current_frame * 1000) / framerate()))", "", "")
305
""",args="thr,L1,R1,T1,B1,path,filename")
306
307
converttoyv12()
308
309
# Bug or limitations of 8-bit masktools with Overlay or...
310
# mt_merge (masking PC Range masks) so use Dither tools
311
Dither_merge16_8(Dither_convert_8_to_16(),Dither_convert_8_to_16(c),mt_lut("255"),luma=true)
312
ditherpost(mode=-1) }
313
314
315
316
####################################
317
###
318
### Stab2()
319
###
320
###  (http://forum.videohelp.com/threads/371336)
321
###
322
### For completeness I'm going to list all the shortcomings of Depan plugin
323
### maybe a programmer realises the urge of an avisynth bug-free stabilizer:
324
### -Color tint (hue shift to green) when subpixel>0 to stablizated frames --> addressed here
325
### -Artifacts occasionally on frame borders (1px skew) --> crop out, check example
326
### -No advanced border fill --> addressed above ( FillBorders() )
327
### -Some false-positives when people clapping, trembling...
328
### -Requires mod 4 inputs?
329
### -No medium jitter fix
330
### -Some thick borders (false positives) aren't 0 black on the inner side
331
###
332
#######################################
333
###
334
### What I improved over original Stab() was to work around the first issue by
335
### 	counter fixing the planes hue deviation on a frame by frame basis with float point precision
336
### Implemented a FixPalPos to replace frames that present black borders of 3 or more pixels
337
### 	with source frames, check output just in case, since some borders don't average to 0 black (rare).
338
### Also supplied a more contrasty clip version for more subtle global motion analysis
339
### Prefilter is for the prefilter clip, in case the clip is very grainy/noisy
340
### Finally a few more things were introduced by testing and checking other script versions.
341
###
342
###
343
### Required (*Optional):
344
### ------------
345
###   Depan         (v1.10.1 or higher)                 (http://avisynth.org.ru/depan/depan.html)
346
###   DePanEstimate (v1.10.1 or higher)                 (http://avisynth.org.ru/depan/depan.html)
347
###   Dither        (v1.26.5 or higher)                 (http://forum.doom9.org/showthread.php?p=1386559#post1386559)
348
###   SmoothAdjust* (v3.0 or higher)                    (http://forum.doom9.org/showthread.php?t=154971)
349
###   AutoAdjust    (v2.50 or higher)                   (http://forum.doom9.org/showthread.php?t=167573)
350
###   GRunT         (v1.0.1 or higher)                  (http://forum.doom9.org/showthread.php?t=139337)
351
###   Repair        (vanilla or tp7's branch)           (http://avisynth.nl/index.php/Removegrain)
352
###
353
### Example:
354
###
355
### stab2(UVfix=true,FixFalPos=true)
356
### crop(2,2,-2,-2) # to remove garbage around borders
357
###
358
####################################
359
360
function Stab2 (clip clp, int "ts", int "range", int "dxmax", int "dymax", bool "UVfix", bool "FixFalPos", float "zoom", int "mirror", float "PAR", clip "Prefilter") {
361
362
ts     = default(ts, 7)        #frames to temporal average for better motion estimation (max. 7)
363
range  = default(range, 3)     #frames before/after to estimate motion
364
dxmax  = default(dxmax, 15)    #maximum deviation in pixels (use at least 8 for SD)
365
dymax  = default(dymax, 15)    #x, and y should be the same
366
zoom   = default(zoom, 1)      #maximum zoom factor (1 disabled)
367
mirror = default(mirror, 0)    #Edge filling. 0 off, 15 everything on
368
PAR    = default(PAR, 1.0)     #PAR of your source
369
UVfix  = default(UVfix, true)  # Fixes the bug of change of HUE in Depan,
370
FixFalPos  = default(FixFalPos, true) # Fixes borders of 3 or more pixels wide. Use along crop(2,2,-2,-2)...
371
									  # ...after stab2() to get rid of border issues entirely
372
373
Pref   = Defined(Prefilter) ? Prefilter : clp
374
temp   = Pref.TemporalSoften(ts,255,255,25,2) # SC thr to 25 otherwise pans will stutter
375
rep    = temp.Repair(Pref.TemporalSoften(1,255,255,25,2))
376
inter  = Interleave(rep,Pref)
377
378
# temporal stable auto-contrast (better subpixel detection)
379
Luma_Expa = AutoAdjust(inter,temporal_radius=10,auto_balance=false,auto_gain=true,use_interp=true,\
380
           avg_safety=0.25,dark_limit=10,bright_limit=10,gamma_limit=1.0,dark_exclude=0.05,bright_exclude=0.05,\
381
           chroma_process=0,scd_threshold=16,input_tv=false,output_tv=false,high_bitdepth=false,debug_view=false)
382
383
mdata = DePanEstimate(Luma_Expa,range=range,pixaspect=PAR,trust=0,dxmax=dxmax,dymax=dymax,zoommax=zoom,improve=true)
384
385
DePan(Defined(Prefilter)?Interleave(rep,clp):inter,data=mdata,offset=-1,mirror=mirror,pixaspect=PAR,matchfields=false,subpixel=2)
386
SelectEvery(2,0)
387
388
# from depansafe() function
389
FixFalPos ? eval("""
390
thick = 2.0  # removing >2px wide borders
391
cropx = ceil(dxmax)*2
392
ratiox = "YPlaneMax("+string(ceil(99-thick/cropx*100))+")"
393
394
crop(0,0,0,cropx).conditionalfilter(last,clp,ratiox,">","0")
395
crop(0,height-cropx,0,0).conditionalfilter(last,clp,ratiox,">","0")
396
crop(0,0,cropx,0).conditionalfilter(last,clp,ratiox,">","0")
397
crop(width-cropx,0,0,0).conditionalfilter(last,clp,ratiox,">","0")""") : last
398
399
400
UVfix ? eval("""
401
ScriptClip ("
402
blue=round((AverageChromaU(clp) - AverageChromaU()) * 256.0)
403
red=round((AverageChromaV(clp) - AverageChromaV()) * 256.0)
404
405
Dither_convert_8_to_16()
406
SmoothTweak16(saturation=1.0,hue1=min(384,blue),hue2=min(384,red),HQ=true)
407
DitherPost(stacked=true,prot=false,mode=6)
408
", args="clp" ) """) : last
409
410
}
411
412
413
####################################
414
###
415
### Stab3()
416
###
417
### same as Stab2 but with some changes
418
###
419
####################################
420-
function Stab3 (clip clp, int "ts", int "range", int "dxmax", int "dymax", bool "UVfix", bool "FixFalPos", float "zoom", int "mirror", float "PAR", clip "Prefilter", int "Luma_Exp", bool "Fill3pBorders", clip "FalPosclip") {
420+
421
function Stab3 (clip clp, int "ts", int "range", int "dxmax", int "dymax", bool "UVfix", bool "FixFalPos", float "zoom", int "mirror", float "PAR", clip "Prefilter", int "Luma_Exp", int "FillBorders", clip "FalPosclip") {
422
423
ts     = default(ts, 7)        #frames to temporal average for better motion estimation (max. 7)
424
range  = default(range, 1)     #frames before/after to estimate motion
425
dxmax  = default(dxmax, Round(clp.width()/180.0)) #maximum deviation in pixels
426
dymax  = default(dymax, dxmax) #x, and y should be the same
427
zoom   = default(zoom, 1)      #maximum zoom factor (1 disabled)
428
mirror = default(mirror, 0)    #Edge filling. 0 off, 15 everything on
429
PAR    = default(PAR, 1.0)     #PAR of your source
430-
b3fix  = default(Fill3pBorders, true) # Fixes borders of 3 or less pixels wide.
430+
431
bfix   = default(FillBorders, 1) # 1=Fixes borders of 3 or less pixels wide.
432
b3fix  = bfix > 0
433
FixFalPos  = default(FixFalPos, true) # Fixes borders of 3 or more pixels wide. Use along crop(2,2,-2,-2)...
434
									  # ...after stab2() to get rid of border issues entirely
435
Lumae  = default(Luma_Exp, 1) #Luma Rebuild
436
437
Pref   = Defined(Prefilter) ? Prefilter : clp
438
temp   = Pref.TemporalSoften(ts,255,255,25,2) # SC thr to 25 otherwise pans will stutter
439
rep    = temp.Repair(Pref.TemporalSoften(1,255,255,25,2))
440
inter  = Interleave(rep,Pref)
441
442
# temporal stable auto-contrast (better subpixel detection)
443
Luma_Expa = Lumae==2 ? AutoAdjust(inter,temporal_radius=10,auto_balance=false,auto_gain=true,use_interp=true,\
444
           avg_safety=0.25,dark_limit=10,bright_limit=10,gamma_limit=1.0,dark_exclude=0.05,bright_exclude=0.05,\
445
           chroma_process=0,scd_threshold=16,input_tv=false,output_tv=false,high_bitdepth=false,debug_view=false) : \
446
            Lumae==1 ? inter.ColorYUV(levels="TV->PC") : inter
447
448
mdata = DePanEstimate(Luma_Expa,range=range,pixaspect=PAR,trust=0,dxmax=dxmax,dymax=dymax,zoommax=zoom)
449
450
DePan(Defined(Prefilter)?Interleave(rep,clp):inter,data=mdata,offset=-1,mirror=b3fix ? 0 : mirror,pixaspect=PAR,matchfields=false,subpixel=2)
451
SelectEvery(2,0)
452
453
stabclip=last
454
FalPosclip = !defined(FalPosclip) && FixFalPos && mirror==15 && b3fix ? clp : FalPosclip
455
456
# from depansafe() function
457
b3fix && defined(FalPosclip) ? FalPosclip : FixFalPos ? eval("""
458
thick = b3fix ? 3.0 : 2.0  # removing >2px wide borders
459
cropx = dxmax*2
460
ratiox = "YPlaneMax("+string(ceil(99-thick/cropx*100))+")"
461
462
crop(0,0,0,cropx).conditionalfilter(last,clp,ratiox,">","0")
463
crop(0,height-cropx,0,0).conditionalfilter(last,clp,ratiox,">","0")
464
crop(0,0,cropx,0).conditionalfilter(last,clp,ratiox,">","0")
465-
subsampl = b3fix ? Findstr(VersionString(), "AviSynth+") != 0 && Findstr(VersionString(), "r1576") == 0 ? !(clp.is444() || clp.isy()) : VersionNumber() < 2.60 ? clp.isyv12() : !(clp.isyv24() || clp.isy8()) : nop()
465+
466
467-
b3fix ? stabclip.FillBorders(pad=subsampl && mirror!=15 ? 1 : 0,subsample=subsampl,FixFalPos=defined(FalPosclip) || FixFalPos ? last : Undefined, mirror=mirror==15,PAR=PAR) : last
467+
subsampl = b3fix ? AvsPlusVersionNumber > 2294 ? !(clp.is444() || clp.isy()) : VersionNumber() < 2.60 ? clp.isyv12() : !(clp.isyv24() || clp.isy8()) : nop()
468
469
bfixc = bfix > 0 ? stabclip.FillBorders(pad=subsampl && mirror!=15 ? 1 : 0,subsample=subsampl,FixFalPos=defined(FalPosclip) || FixFalPos ? last : Undefined, mirror=mirror==15,PAR=PAR, maskonly=bfix > 1) : last
470
bfix > 1 ? stabclip.FillBorders(pad=subsampl && mirror!=15 ? 1 : 0,subsample=subsampl,FixFalPos=defined(FalPosclip) || FixFalPos ? last : Undefined, mirror=mirror==15,PAR=PAR, FillBordersc=mt_merge(stabclip,clp,bfixc,luma=true).ExInpaint(bfixc)) : bfixc
471
472
UVfix ? eval("""
473
lumaf=last
474
ScriptClip ("
475
blue=round((AverageChromaU(clp) - AverageChromaU()) * 256.0)
476
red=round((AverageChromaV(clp) - AverageChromaV()) * 256.0)
477
478
Dither_convert_8_to_16()
479
SmoothTweak16(saturation=1.0,hue1=min(384,blue),hue2=min(384,red),HQ=true)
480
DitherPost(stacked=true,prot=false,mode=6,y=1,slice=false)
481
", args="clp" )
482
Mergeluma(lumaf)
483
""") : last
484
485
}
486
487
488
######### HELPER FUNCTIONS #########
489
490
# Helper function for FindBlackBorders() from FFMS2.avsi
491
function FFFormatTime_stabi(int ms) {
492
    s = ms / 1000
493
    ms = ms % 1000
494
    m = s / 60
495
    s = s % 60
496
    h = m / 60
497
    m = m % 60
498
    return string(h) + ":" + string(m,"%02.0f") + ":" + string(s,"%02.0f") + "." + string(ms,"%03.0f")}