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