SHOW:
|
|
- or go back to the newest paste.
1 | - | function deblink4(clip clp, float "ratio", int "level") { |
1 | + | LoadPlugin("mvtools2.dll") |
2 | LoadPlugin("mt_masktools-26.dll") | |
3 | ||
4 | - | \ "[deblink4] 1.0 >= ratio >= 0.0, it was " + string(ratio)) |
4 | + | function ng_deblink(clip clp, |
5 | \ float "ratio", | |
6 | \ int "level", | |
7 | \ clip "blinkmask" | |
8 | - | \ "[deblink4] 257 >= level >= 0, it was " + string(level)) |
8 | + | \){ |
9 | #Version 10 2012.04.22 | |
10 | - | blink=clp.ng_blinkmask_new |
10 | + | |
11 | - | m01=mt_logic(blink.selectevery(4,0), |
11 | + | blink = default(blinkmask, clp.ng_blinkmask()) |
12 | - | \ blink.selectevery(4,1), |
12 | + | |
13 | - | \ mode="or").converttorgb32 |
13 | + | |
14 | - | m01=mt_logic(blink.selectevery(4,2), |
14 | + | |
15 | - | \ blink.selectevery(4,3), |
15 | + | \ "[ng_deblink] 1.0 >= ratio >= 0.0, it was " + string(ratio)) |
16 | - | \ mode="or").converttorgb32 |
16 | + | |
17 | level = default(level, round(ratio * 257)) | |
18 | - | f0=layer(clp.selectevery(4,0), |
18 | + | |
19 | - | \ clp.selectevery(4,1).mask(m01), |
19 | + | \ "[ng_deblink] 257 >= level >= 0, it was " + string(level)) |
20 | ||
21 | - | f1=layer(clp.selectevery(4,1), |
21 | + | m01=mt_logic(blink.SelectEvery(4,0), |
22 | - | \ clp.selectevery(4,0).mask(m01), |
22 | + | \ blink.SelectEvery(4,1), |
23 | \ mode="or").ConvertToRGB32() | |
24 | - | f2=layer(clp.selectevery(4,2), |
24 | + | m23=mt_logic(blink.SelectEvery(4,2), |
25 | - | \ clp.selectevery(4,3).mask(m23), |
25 | + | \ blink.SelectEvery(4,3), |
26 | \ mode="or").ConvertToRGB32() | |
27 | - | f3=layer(clp.selectevery(4,3), |
27 | + | |
28 | - | \ clp.selectevery(4,2).mask(m23), |
28 | + | f0=Layer(clp.SelectEvery(4,0), |
29 | \ clp.SelectEvery(4,1).Mask(m01), | |
30 | \ level=level) | |
31 | - | interleave(f0,f1,f2,f3) |
31 | + | f1=Layer(clp.SelectEvery(4,1), |
32 | \ clp.SelectEvery(4,0).Mask(m01), | |
33 | \ level=level) | |
34 | - | function deblink3(clip clp){ |
34 | + | f2=Layer(clp.SelectEvery(4,2), |
35 | - | blink=clp.ng_blinkmask_new |
35 | + | \ clp.SelectEvery(4,3).Mask(m23), |
36 | - | m01=mt_logic(blink.selectevery(4,0), |
36 | + | |
37 | - | \ blink.selectevery(4,1), |
37 | + | f3=Layer(clp.SelectEvery(4,3), |
38 | - | \ mode="or").converttorgb32 |
38 | + | \ clp.SelectEvery(4,2).Mask(m23), |
39 | - | f0=layer(clp.selectevery(4,0), |
39 | + | |
40 | - | \ clp.selectevery(4,1).mask(m01)) |
40 | + | |
41 | - | f1=layer(clp.selectevery(4,1), |
41 | + | Interleave(f0,f1,f2,f3) |
42 | - | \ clp.selectevery(4,0).mask(m01)) |
42 | + | |
43 | - | interleave(f0,f1, |
43 | + | |
44 | - | \ clp.selectevery(4,2),clp.selectevery(4,3)) |
44 | + | function ng_blinkmask(clip clp, |
45 | \ bool "TEST", | |
46 | \ bool "STABILIZE", | |
47 | - | function ng_blinkmask_new(clip c,int "ml"){ |
47 | + | \ bool "SHARP", |
48 | - | ml=default(ml,128) |
48 | + | \ bool "HYSTER", |
49 | - | src=c.ConvertToYv12 |
49 | + | \ int "inpand", |
50 | - | super=MSuper(src, pel=1) |
50 | + | \ int "expand", |
51 | - | fvec =MAnalyse(super, isb=false, blksize=4) |
51 | + | \ int "ml" |
52 | - | bvec =MAnalyse(super, isb=true , blksize=4) |
52 | + | \){ |
53 | - | fmask=Mmask(src,fvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) |
53 | + | #Version 10 2012.04.22 |
54 | - | bmask=Mmask(src,bvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) |
54 | + | |
55 | #BLINK | |
56 | - | eo0_to =fmask.selectevery(2,1) |
56 | + | # Blinking is a block that alternates on/off each frame |
57 | - | oe_from=bmask.selectevery(2,1) |
57 | + | # SelectEven would only see either the on or the off |
58 | - | front =mt_logic(eo0_to,oe_from,mode="and") |
58 | + | |
59 | #FLASH | |
60 | - | oe_to =fmask.selectevery(2,2) |
60 | + | # Flashing is a block that is only on for a single frame |
61 | - | eo_from=bmask.selectevery(2,2) |
61 | + | # SelectEven might miss the flash |
62 | - | back =mt_logic(oe_to,eo_from,mode="and") |
62 | + | |
63 | #SHAKE | |
64 | - | ee_src=src.selecteven |
64 | + | # Shaking is a block that moves back/forth each frame |
65 | - | ee_super=MSuper(ee_src, pel=1) |
65 | + | # SelectEven would only see one position |
66 | - | ee_fvec =MAnalyse(ee_super, isb=false, blksize=4) |
66 | + | |
67 | - | ee_bvec =MAnalyse(ee_super, isb=true , blksize=4) |
67 | + | # The goal of this function is to make a blink mask for use with |
68 | - | ee_fmask=Mmask(ee_src,ee_fvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) |
68 | + | # ng_deblink. For overly complicated scenes where a clean blinkmask |
69 | - | ee_bmask=Mmask(ee_src,ee_bvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) |
69 | + | # can't be found, just use TASBlend. Uniform softness looks better |
70 | # than sharp artifacts. | |
71 | - | ee_to =ee_fmask.trim(1,0) |
71 | + | |
72 | - | ee_from=ee_bmask |
72 | + | # This function calculates flash and shake info for the test script, |
73 | - | ee =mt_logic(ee_to,ee_from,mode="or") |
73 | + | # but those effects should be handled in different ways. |
74 | # Flash - choose frames to make sure the flash is in your final clip. | |
75 | - | oo_src=src.selectodd |
75 | + | # Shake - SelectEvery(4,0,2,1,3) or SelectEvery(4,1,0,2,3) |
76 | - | oo_super=MSuper(oo_src, pel=1) |
76 | + | # SelectEvery doesn't generally work because it messes with the fluidity |
77 | - | oo_fvec =MAnalyse(oo_super, isb=false, blksize=4) |
77 | + | # of motion. But that won't be noticable on a shaking screen. |
78 | - | oo_bvec =MAnalyse(oo_super, isb=true , blksize=4) |
78 | + | # Be careful if 2 frame blinking is present, as the selectevery can turn |
79 | - | oo_fmask=Mmask(oo_src,oo_fvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) |
79 | + | # it into 1 frame blinking. |
80 | - | oo_bmask=Mmask(oo_src,oo_bvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) |
80 | + | |
81 | TEST = default( TEST, false) | |
82 | - | oo_to =oo_fmask.trim(1,0) |
82 | + | STABILIZE = default(STABILIZE, true) |
83 | - | oo_from=oo_bmask |
83 | + | SHARP = default( SHARP, true) |
84 | - | oo =mt_logic(oo_to,oo_from,mode="or") |
84 | + | HYSTER = default( HYSTER, false) |
85 | inpand = default( inpand, 1) | |
86 | - | #to e0-o1, from o1-e2, nothing e0-e2 |
86 | + | expand = default( expand, 1) |
87 | - | even_blink=mt_logic(front,ee.mt_invert,mode="and") |
87 | + | ml = default( ml, 128) |
88 | ||
89 | - | #to o1-e2, from e2-o3, nothing o1-o3 |
89 | + | # The functions used to make the masks work in the YV12 colorspace. Once |
90 | - | odd_blink =mt_logic(back,oo.mt_invert,mode="and") |
90 | + | # the masks are created they can be used in the RGB32 colorspace direcly |
91 | src=clp.ConvertToYV12() | |
92 | - | interleave(even_blink, odd_blink).selectevery(1,-1) |
92 | + | |
93 | # Blinking is located by looking for blocks that don't exist in | |
94 | # consecutive frames. The motion vector will match blocks that exist in | |
95 | # both frames. The blocks that aren't in both will end up with huge | |
96 | # values that are picked out by the motion mask. | |
97 | super = MSuper(src, pel=1) | |
98 | fvec = MAnalyse(super, isb=false, blksize=4) | |
99 | bvec = MAnalyse(super, isb=true , blksize=4) | |
100 | fmask = Mmask(src, fvec, kind=1, ml=ml).mt_binarize() | |
101 | bmask = Mmask(src, bvec, kind=1, ml=ml).mt_binarize() | |
102 | blink = mt_logic(fmask, bmask, mode="and") | |
103 | ||
104 | # Blinking usually occurs against a stable background. This is found | |
105 | # by looking at blocks 2 frames apart. This distinguishes a blink from | |
106 | # blocks that are just changing every frame. | |
107 | ee_src = src.SelectEven() | |
108 | ee_super = MSuper(ee_src, pel=1) | |
109 | ee_fvec = MAnalyse(ee_super, isb=false, blksize=4) | |
110 | ee_bvec = MAnalyse(ee_super, isb=true , blksize=4) | |
111 | ee_fmask = Mmask(ee_src, ee_fvec, kind=1, ml=ml).mt_binarize() | |
112 | ee_bmask = Mmask(ee_src, ee_bvec, kind=1, ml=ml).mt_binarize() | |
113 | ||
114 | oo_src = src.SelectOdd() | |
115 | oo_super = MSuper(oo_src, pel=1) | |
116 | oo_fvec = MAnalyse(oo_super, isb=false, blksize=4) | |
117 | oo_bvec = MAnalyse(oo_super, isb=true , blksize=4) | |
118 | oo_fmask = Mmask(oo_src, oo_fvec, kind=1, ml=ml).mt_binarize() | |
119 | oo_bmask = Mmask(oo_src, oo_bvec, kind=1, ml=ml).mt_binarize() | |
120 | ||
121 | fmask_2 = Interleave(ee_fmask, oo_fmask) | |
122 | bmask_2 = Interleave(ee_bmask, oo_bmask) | |
123 | background = mt_logic(fmask_2.SelectEvery(1,1), | |
124 | \ bmask_2.SelectEvery(1,-1), | |
125 | \ mode="or") | |
126 | stable_blink = mt_hysteresis(background.mt_invert, blink) | |
127 | blink2 = (STABILIZE) ? stable_blink : blink | |
128 | ||
129 | # Shrinking the blink mask can get rid of noise, | |
130 | # too much will lose signal as well. | |
131 | blink3 = blink2.mt_inpand(mode=mt_diamond(inpand)) | |
132 | ||
133 | # Using just pixels that changed helps sharpen the mask | |
134 | diff = ng_diff(clp.SelectEvery(1,-1), clp) | |
135 | diff_2 = mt_logic(diff, diff.SelectEvery(1,1), mode="and") | |
136 | ||
137 | #Hysteresis | |
138 | # Matches continuous blocks of pixels. | |
139 | # Use with care, will match the whole screen on fades. | |
140 | hyster_blink = mt_hysteresis(blink3, diff_2) | |
141 | ||
142 | # Expand the mask to make up for shrinking it (or just use hysteresis) | |
143 | blink4 = blink3.mt_expand(mode=mt_circle(expand)) | |
144 | sharp_blink = mt_logic(blink4, diff_2, mode="and") | |
145 | ||
146 | blink5 = (HYSTER) ? hyster_blink : | |
147 | \ (SHARP) ? sharp_blink : blink4 | |
148 | ||
149 | ||
150 | # A flash won't match blocks 1 or 2 frames away. | |
151 | sub_flash = mt_logic(fmask_2, bmask_2, mode="and") | |
152 | flash = mt_logic(blink, sub_flash, mode="and") | |
153 | ||
154 | # A shake changes in one frame and changes back in the next. | |
155 | # This isn't detected by the motion vectors because the blocks exist in | |
156 | # both frames, they are just shifting around. | |
157 | same = ng_same(clp.SelectEvery(1,-1), clp.SelectEvery(1,1)) | |
158 | shake = mt_logic(same, diff_2, mode="and") | |
159 | ||
160 | (TEST) ? stackhorizontal(clp, mergeRGB(blink5, flash, shake)) | |
161 | \ : blink5.GreyScale() | |
162 | } | |
163 | ||
164 | function ng_diff(clip A, clip B, int "thr"){ | |
165 | thr=default(thr,0) | |
166 | TAD=ng_TAD(A,B) | |
167 | return mt_binarize(TAD, threshold=thr) | |
168 | } | |
169 | ||
170 | function ng_same(clip A, clip B, int "thr"){ | |
171 | thr=default(thr,0) | |
172 | TAD=ng_TAD(A,B) | |
173 | return mt_binarize(TAD, threshold=thr, upper=true) | |
174 | } | |
175 | ||
176 | function ng_TAD(clip A, clip B){ | |
177 | R=ng_AD(A .showRed("YV12"),B .showRed("YV12")) | |
178 | G=ng_AD(A.showGreen("YV12"),B.showGreen("YV12")) | |
179 | B=ng_AD(A .showBlue("YV12"),B .showBlue("YV12")) | |
180 | return ng_plus(R, ng_plus(G, B)) | |
181 | } | |
182 | ||
183 | function ng_AD(clip A, clip B){ | |
184 | return mt_lutxy(A,B,"x y - abs") | |
185 | } | |
186 | ||
187 | function ng_plus(clip A, clip B){ | |
188 | return mt_lutxy(A,B,"x y +") | |
189 | } |