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 | } |