Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
|
12th April 2007, 09:55 | #1 | Link |
Registered User
Join Date: Apr 2002
Location: Germany
Posts: 5,391
|
Well, since the thread is there now, I reserve this "toplevel" post to possibly add a general survey. (Not too soon - somewhen later this year...)
__________________
- We´re at the beginning of the end of mankind´s childhood - My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!) Last edited by Didée; 12th April 2007 at 09:57. |
12th April 2007, 15:38 | #2 | Link |
AviSynth plugger
Join Date: Nov 2003
Location: Russia
Posts: 2,183
|
mcbob was firstly posted here:
http://forum.doom9.org/showthread.ph...383#post891383
__________________
My Avisynth plugins are now at http://avisynth.org.ru and mirror at http://avisynth.nl/users/fizick I usually do not provide a technical support in private messages. Last edited by Fizick; 25th December 2007 at 22:17. Reason: first |
12th April 2007, 18:53 | #3 | Link | |
Moderator
Join Date: Nov 2001
Location: Netherlands
Posts: 6,364
|
Quote:
Anyway, v0.3c is the latest i could find and is posted below. Are there any posts discussing mcbob? If so, please point me to them, then i will add them as references. Code:
# MCBob v0.3: # # Another approach to motion compensated bobbing, build by Didée. # # ( Between-all-chairs version with some quick hacks ) # ( v0.3c: as stated above, but worse ;-) ) # # Features: # # - No residual combing, due to STT (Shape Transposition Technology) # - Works without thresholds (with adaptive thresholds instead of fixed ones) # - Motion Search between fields of same parity, for maximum flicker/bob reduction in motion areas # - Motion Masking adaptive to local complexity, for maximum flicker/bob reduction in static areas # - spatial Interpolation overweights spatio-temporal interpolation # ( in areas where the information obtained from temporal neighbors in itself was only spatially # interpolated, use a mix of spatial and spatio-temporal interpolation ) # - error correction for temporal interpolation is fully self adaptive # # Prerequisites: # # - MVTools, preferably v1.4.13 (or newer) # - MaskTools v2.0 # - EEDI2 # - RemoveGrain/Repair package # - ReduceFlicker (if temp-NR for ME is used) # - MedianBlur by tsp |
|
12th April 2007, 18:53 | #4 | Link |
Moderator
Join Date: Nov 2001
Location: Netherlands
Posts: 6,364
|
Code:
function MCBob(clip clp, float "EdiPre", int "EdiPost", int "blocksize", int "MEdepth", float "sharpness", int "mtnmode", float "mtnth1", float "mtnth2", float "errth1", float "errth2", float "MEspatNR", float "MEtempNR") { EdiPre = default( EdiPre, 1.0 ) # What bob to start with: 0.0 = dumbbob, 1.0 = EEdiBob, inbetween = mix of both EdiPost = default( EdiPost, 1 ) # 0 = no EEDI PP / 1 = Framesized EEdi PP / Average two Fieldbased EEdi PP's bs = default( blocksize, 16 ) # Blocksize for motion search me = default( MEdepth, 2 ) # Search effort of motion search sharpness = (EdiPost==2) \ ? default( sharpness, 0.7 ) \ : default( sharpness, 1.0 ) # use slight sharpening before STT routine mtnmode = default( mtnmode, 0 ) # 0 = use only same-parity motion check, 1|2 use an additional # inter-parity check: 1 = on vertical edges / 2 = not on horizontal edges mtnth1 = default( mtnth1, 0.20 ) # below this %age of local min/max is static mtnth2 = default( mtnth2, 0.40 ) # above this %age of local min/max is motion errth1 = default( errth1, 0.40 ) # similar for error detection errth2 = default( errth2, 0.60 ) # of motion interpolation errors MEspatNR = default( MEspatNR, 0.00 ) # amount of spatial NR (for motion search only) MEtempNR = default( MEtempNR, 0.00 ) # amount of temporal NR (for motion search only) order = (clp.GetParity == True) ? 0 : 1 ORDR = (order==0) ? "TFF" : "BFF" ox = clp.width() oy = clp.height() ERTH1 = string(errth1) ERTH2 = string(errth2) MNTH1 = string(mtnth1) MNTH2 = string(mtnth2) SSTR = string(sharpness) idx_1 = 10 idx_2 = (MEspatNR==0.0 && MEtempNR==0.0) ? idx_1 : idx_1+2 idx_3 = idx_2 + 2 # Create basic operations that we will work with # ============================================== # Basic Field & Bob clips # ----------------------- flatbob = clp.Bob(1,0) normbob = clp.Bob(0.0,0.5) ofields = clp.SeparateFields() oweave = clp.DoubleWeave() edibobbed = clp.EEDIbob() bobbed = (EdiPre == 0.0) ? normbob \ : (EdiPre == 1.0) ? edibobbed \ : normbob.merge(edibobbed,EdiPre) # Mask to check if motion compensation has delivered only the neighbor's spatial interpolated part # ------------------------------------------------------------------------------------------------ black = Blankclip(ofields).mt_lut("0").Trim(1,1).Loop(Framecount(clp)) white = Blankclip(ofields).mt_lut("255").Trim(1,1).Loop(Framecount(clp)) interpol = Interleave(black,white,white,black).AssumeFieldbased().AssumeParity(ORDR).Weave() # Vertical Edge mask, needed for more safe motion masking # ------------------------------------------------------- Vedge = bobbed.mt_Edge("1 0 -1 2 0 -2 1 0 -1",0,255,0,255,U=1,V=1) Vedge2 = Vedge.mt_Inpand(mode="vertical").mt_Inpand(mode="vertical").mt_Expand(mode="vertical").mt_Expand(mode="vertical") Vedge = mt_Lutxy(Vedge,Vedge2,yexpr="y 2 - 2 * x > x y 2 - 2 * ?") #.mt_Expand() Hedge = bobbed.mt_Edge("1 2 1 0 0 0 -1 -2 -1",0,255,0,255,U=1,V=1) Hedge = Hedge.mt_logic(Hedge.temporalsoften(1,255,0,255,2),"max") # If requested, do flicker reduction before searching motion vectors # ------------------------------------------------------------------- (MEspatNR==0.0) ? bobbed : bobbed.Merge(bobbed.minblur(2,uv=3),MEspatNR) (MEtempNR==0.0) ? last : last.Merge(reduceflicker(2),MEtempNR) srch=last # Perform Motion Search # --------------------- lmbda = 128 pnw = 40 bw_vec2 = srch.SelectEven().MVAnalyse(isb=true, truemotion=false,delta=1,lambda=lmbda,pel=2,searchparam=me,sharp=2,blksize=bs,overlap=1*bs/2,pnew=pnw,idx=idx_1) fw_vec2 = srch.SelectEven().MVAnalyse(isb=false,truemotion=false,delta=1,lambda=lmbda,pel=2,searchparam=me,sharp=2,blksize=bs,overlap=1*bs/2,pnew=pnw,idx=idx_1) bw_vec3 = srch.SelectOdd() .MVAnalyse(isb=true, truemotion=false,delta=1,lambda=lmbda,pel=2,searchparam=me,sharp=2,blksize=bs,overlap=1*bs/2,pnew=pnw,idx=idx_1+1) fw_vec3 = srch.SelectOdd() .MVAnalyse(isb=false,truemotion=false,delta=1,lambda=lmbda,pel=2,searchparam=me,sharp=2,blksize=bs,overlap=1*bs/2,pnew=pnw,idx=idx_1+1) # Create RAW motion interpolation # ------------------------------- alt_1 = bobbed.SelectEven().MVFlowInter(bw_vec2,fw_vec2,time=50.0,thSCD1=64*18,thSCD2=227,idx=idx_2) alt_2 = bobbed.SelectOdd() .MVFlowInter(bw_vec3,fw_vec3,time=50.0,thSCD1=64*18,thSCD2=227,idx=idx_2+1).DuplicateFrame(0) alt = Interleave(alt_2,alt_1) # Create motion interpolation of "nothing new" mask # ------------------------------------------------- interpol_1 = interpol.SelectEven().MVFlowInter(bw_vec2,fw_vec2,time=50.0,thSCD1=64*8,thSCD2=127,idx=idx_3) interpol_2 = interpol.SelectOdd() .MVFlowInter(bw_vec3,fw_vec3,time=50.0,thSCD1=64*8,thSCD2=127,idx=idx_3+1).DuplicateFrame(0) interpol_comp= Interleave(interpol_2,interpol_1) nothing_new = mt_lutxy(interpol,interpol_comp,"x y * 255 / 255 / 1 2 / ^ 160 *") # Error check of motion interpolation # =================================== # Errors that are neutralized by errors in direct vertical neighborhood are not considered, because bob-typical. # Remaining error is checked against [min,max] of local error to decide if it's valid or not. # # Build error mask, neutralize vertical-only errors # --------------------------------------------------- altD = mt_Makediff(bobbed,alt,U=3,V=3) altDmin = altD.mt_Inpand(mode="vertical",U=3,V=3) altDmin = altDmin.mt_Deflate().mt_Merge(altDmin,Vedge,U=4,V=4) altDmax = altD.mt_Expand(mode="vertical",U=3,V=3) altDmax = altDmax.mt_Inflate().mt_Merge(altDmax,Vedge,U=4,V=4) altDmm = mt_Lutxy(altDmax.mt_Expand(mode="horizontal",U=3,V=3),altDmin.mt_Inpand(mode="horizontal",U=3,V=3),"x y -",U=3,V=3) altDmm = altDmm.mt_Inflate().mt_Merge(altDmm,Vedge,U=4,V=4) altD1 = altD .mt_Lutxy(altDmin,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=3,V=3) altD1 = altD1.mt_Lutxy(altDmax,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=3,V=3) altD2 = altD.Repair(altD1,1) # Build correction mask by combining: error mask + "nothing new" mask + a scenechange mask # --------------------------------------------------------------------------------------------- corrmask = mt_Lutxy(altD2,altDmm,"x 128 - abs 2 - y 2 + / "+ERTH1+" - "+ERTH2+" "+ERTH1+" - / 255 *",U=3,V=3).mt_Expand(U=3,V=3) sc = corrmask.BilinearResize(64,64) sc = mt_LutF(sc,sc,mode="average",expr="x 255 0.6 * > 255 0 ?").PointResize(ox,oy) corrmask = corrmask.mt_Logic(nothing_new,"max",U=2,V=2) corrmask = corrmask.mt_Logic(sc,"max",U=2,V=2) # Create a first bob from motion interpolation, not yet error corrected ... # ------------------------------------------------------------------------- # ***( temporarily changed ... yet unsure what works best )*** Interleave(bobbed,alt).AssumeParity(ORDR) SeparateFields().SelectEvery(8,0,3,5,6).Weave() naked= last naked2 = last.vinverse(1.6) # flatbob # naked_mm = naked.mt_Edge("min/max",0,255,0,255,U=1,V=1) edibb_mm = edibobbed.mt_Edge("min/max",0,255,0,255,U=1,V=1).mt_Expand(mode="vertical") check2 = mt_LutXY(naked_mm,edibb_mm,"x y / 3 - 5 3 - / 255 *") corrmask = corrmask.mt_Logic(check2,"max",U=2,V=2) # ... and build a motion mask from this one. # ------------------------------------------ # ***( temporarily changed ... tickertapes might suffer. )*** stc = bobbed .removegrain(2)# oweave.removegrain(11) mm = stc.mt_Edge("min/max",0,255,0,255,U=3,V=3) # mm = mm .mt_Logic(mm.DuplicateFrame(0),"max",U=3,V=3).mt_Logic(mm.DeleteFrame(0),"max",U=3,V=3) # max = stc.mt_expand(U=3,V=3) # max = max.mt_logic(max.Duplicateframe(0),"max",U=3,V=3).mt_logic(max.Duplicateframe(0).Duplicateframe(0),"max",U=3,V=3) # min = stc.mt_inpand(U=3,V=3) # min = min.mt_logic(min.Duplicateframe(0),"min",U=3,V=3).mt_logic(min.Duplicateframe(0).Duplicateframe(0),"min",U=3,V=3) # mm = mt_LutXY(max,min,"x y -",U=3,V=3) diff2prev1 = mt_LutXY(stc,stc.DuplicateFrame(0),"x y - abs",U=3,V=3) diff2prev2 = mt_LutXY(stc,stc.DuplicateFrame(0).DuplicateFrame(0),"x y - abs",U=3,V=3) diff2prev12 = (mtnmode==0) ? diff2prev2 : \ (mtnmode==1) ? diff2prev2 .mt_Merge(diff2prev1,Vedge,U=2,V=2) \ : diff2prev1 .mt_Merge(diff2prev2,Hedge,U=2,V=2) motn = diff2prev12.mt_Logic(diff2prev12.DeleteFrame(0),"max",U=3,V=3).mt_Logic(diff2prev12.DeleteFrame(0).DeleteFrame(0),"max",U=3,V=3) notstatic = mt_LutXY(motn,mm,"x 1 - y 1 + / "+MNTH1+" - "+MNTH2+" "+MNTH1+" - / 255 *",U=3,V=3).mt_Expand(U=3,V=3).mt_Inpand(U=3,V=3) # notstatic = notstatic.mt_Logic(notstatic.RemoveGrain(4),"max",U=3,V=3).mt_Expand(U=3,V=3).mt_Inpand(U=3,V=3) # Now do the error correction of the "naked" MC-bob # ------------------------------------------------- naked .mt_Merge(edibobbed,corrmask,luma=false,U=3,V=3) .Vinverse(2.7-sharpness) repaired = last # If requested, sharpen the corrected MC-bob up a little # ( pre-sharpen for EdiPost = 0 | 1 ) # ------------------------------------------------------ shrpbase = last#.MinBlur(1,1).Merge(RemoveGrain(12,-1),0.23) shrp = mt_LutXY(shrpbase,shrpbase.RemoveGrain(11,-1),"x x y - abs 16 / 1 1 x y - abs 1 4 / ^ + / ^ 16 * "+SSTR+" * x y - x y - abs 1.3 + / * 1 x y - abs 16 / 1 4 / ^ + / +",U=2,V=2) # \ .Repair(repaired,1,0) shrpD = mt_Makediff(shrpbase,shrp) (sharpness==0.0 || EdiPost==2) ? last : last .mt_Makediff(MergeLuma(shrpD.MinBlur(1,uv=1),shrpD.RemoveGrain(12,-1),0.24),U=2,V=2) # If requested, do additional PP via EEDI2 # ---------------------------------------- oweave.mt_merge(last,notstatic,luma=false,U=3,V=3) AssumeTFF() edisingle = eedi2().LanczosResize(ox,oy,0,-0.5,ox,2*oy+0.001,taps=3) edidouble = merge(SeparateFields().SelectEven().eedi2(field=1),SeparateFields().SelectOdd().EEDI2(field=0),0.5) edidoubleD = mt_makediff(last,edidouble,U=3,V=3) (EdiPost==1) ? edisingle : \ (EdiPost==2) ? edidouble : last # ( post-sharpen for EdiPost = 2 ) # ------------------------------------------------------ edidoubleshrpD = mt_makediff(edidouble,sharpness==1.0?edidouble.removegrain(20):edidouble.removegrain(20).merge(edidouble,1.0-sharpness),U=3,V=3) edidoubleshrpD = edidoubleshrpD.repair(edidoubleD,13) (EdiPost==2) ? edidouble.mt_adddiff(edidoubleshrpD,U=3,V=3) : last # STT (Shape Transposition Technology) Routine: # ============================================= # Simply weaving the corrected output with the original fields is bad, because the risk of # creating unwanted residual combing is too high. # Instead, the vertical "shape" is taken off the corrected output, and transposed # onto the fixed "poles" of the original fields' scanlines. Et Voila. # ---------------------------------------------------------------------------------------- synthbob = last.AssumeParity(ORDR).SeparateFields().SelectEvery(4,0,3).Weave().Bob(1,0) mapped_new = flatbob.mt_makediff(mt_makediff(synthbob,last,U=3,V=3),U=3,V=3) newfields = mapped_new.AssumeParity(ORDR).SeparateFields().SelectEvery(4,1,2) mappedbob = Interleave(ofields,newfields).SelectEvery(4,0,1,3,2).AssumeParity(ORDR).Weave() # Finally, for static areas use just original fields # -------------------------------------------------- mappedbob #bobbed oweave.mt_merge(last,notstatic.mt_inpand(Y=2,U=2,V=2),luma=false,U=3,V=3) # Lastly, set correct parity for the bobbed clip # ---------------------------------------------- (order==0) ? AssumeTFF() : AssumeBFF() return(last) } # =============================================== ############################ # Helper functions below # ############################ ## Function EEDIbob, courtesty of scharfis_brain: # slow, but accurate EEDI-bob, always dumb ;) # altering maxd changes the search radius for connecting diagonal lines Function EEDIbob(clip Input, int "maxd") { #GetParity(Input) ? Input.SeparateFields().EEDI2(Field = 3, maxd = maxd, pp = 0, estr = 0, dstr = 0, mthresh = 0, vthresh = 0, lthresh = 0) : Input.SeparateFields().EEDI2(Field = 2, maxd = maxd, pp = 0, estr = 0, dstr = 0, mthresh = 0, vthresh = 0, lthresh = 0) GetParity(Input) ? Input.SeparateFields().EEDI2(Field = 3, maxd = maxd) : Input.SeparateFields().EEDI2(Field = 2, maxd = maxd) AssumeFrameBased() GetParity(Input) ? AssumeTFF() : AssumeBFF() } # Helper to simplify script function AssumeParity(clip clp, string "order") { order == "TFF" ? clp.assumeTFF() : clp.assumeBFF() return(last) } # Kill Combing Function function Vinverse(clip clp, float "sstr", int "amnt", int "uv") { uv = default(uv,3) sstr = default(sstr,2.7) amnt = default(amnt,255) uv2 = (uv==2) ? 1 : uv STR = string(sstr) AMN = string(amnt) vblur = clp.mt_convolution("1","50 99 50",U=uv,V=uv) vblurD = mt_makediff(clp,vblur,U=uv2,V=uv2) Vshrp = mt_lutxy(vblur,vblur.mt_convolution("1","1 4 6 4 1",U=uv2,V=uv2),expr="x x y - "+STR+" * +",U=uv2,V=uv2) VshrpD = mt_makediff(Vshrp,vblur,U=uv2,V=uv2) VlimD = mt_lutxy(VshrpD,VblurD,expr="x 128 - y 128 - * 0 < x 128 - abs y 128 - abs < x y ? 128 - 0.25 * 128 + x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2) mt_adddiff(Vblur,VlimD,U=uv,V=uv) (amnt>254) ? last : (amnt==0) ? clp : mt_lutxy(clp,last,expr="x "+AMN+" + y < x "+AMN+" + x "+AMN+" - y > x "+AMN+" - y ? ?",U=uv,V=uv) return(last) } # Nifty Gauss/Median combination function MinBlur(clip clp, int r, int "uv") { uv = default(uv,3) uv2 = (uv==2) ? 1 : uv rg4 = (uv==3) ? 4 : -1 rg11 = (uv==3) ? 11 : -1 rg20 = (uv==3) ? 20 : -1 medf = (uv==3) ? 1 : -200 RG11D = (r==1) ? mt_makediff(clp,clp.removegrain(11,rg11),U=uv2,V=uv2) \ : (r==2) ? mt_makediff(clp,clp.removegrain(11,rg11).removegrain(20,rg20),U=uv2,V=uv2) \ : mt_makediff(clp,clp.removegrain(11,rg11).removegrain(20,rg20).removegrain(20,rg20),U=uv2,V=uv2) RG4D = (r==1) ? mt_makediff(clp,clp.removegrain(4,rg4),U=uv2,V=uv2) \ : (r==2) ? mt_makediff(clp,clp.medianblur(2,2*medf,2*medf),U=uv2,V=uv2) \ : mt_makediff(clp,clp.medianblur(3,3*medf,3*medf),U=uv2,V=uv2) DD = mt_lutxy(RG11D,RG4D,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2) clp.mt_makediff(DD,U=uv,V=uv) return(last) } |
13th April 2007, 05:47 | #5 | Link |
Doom9ing since 2001
Join Date: Oct 2001
Location: Seattle, WA, USA
Posts: 2,002
|
Though it's in a language I can't read, I've often found this page very useful in collecting all the necessary plugins for MCBob:
http://www.avisynth.info/?MCBob It'd be nice to see a similar list of links in this thread's top post. |
12th October 2007, 02:41 | #7 | Link |
Registered User
Join Date: Sep 2004
Location: Near LA, California, USA
Posts: 1,545
|
Just bought a QX6850 Quad-Core CPU with 4 gigs of DDR-2 RAM. I decided to use NNEDI+mcbob on a 1 hour 44 minute basketball game capped with Huffyuv and encode it to Lagarith. I trimmed each section of the video into 4 parts and assigned each part to each core. It took a total of about 16 hours to complete, so basically I got a combined total of about 5-6FPS. That's faster than what mvbob ran on my Athlon X2 4600+. Anyhoo, it's great to finally be able to use the best bobber on the planet at pretty reasonable speeds.
__________________
Pirate: Now how would you like to die? Would you like to have your head chopped off or be burned at the stake? Curly: Burned at the stake! Moe: Why? Curly: A hot steak is always better than a cold chop. |
15th October 2007, 07:39 | #9 | Link |
Registered User
Join Date: Sep 2004
Location: Near LA, California, USA
Posts: 1,545
|
Ah! But wait until Didee releases MCBob 2.0
I won't be so lucky anymore.
__________________
Pirate: Now how would you like to die? Would you like to have your head chopped off or be burned at the stake? Curly: Burned at the stake! Moe: Why? Curly: A hot steak is always better than a cold chop. |
14th October 2007, 03:06 | #10 | Link | |
Fighting spam with a fish
Join Date: Sep 2005
Posts: 2,699
|
NNEDI + MCBOB
Quote:
|
|
14th October 2007, 03:06 | #11 | Link |
Fighting spam with a fish
Join Date: Sep 2005
Posts: 2,699
|
Cont.
Code:
function MCBob(clip clp, float "EdiPre", int "EdiPost", int "blocksize", int "MEdepth", float "sharpness", int "mtnmode", float "mtnth1", float "mtnth2", float "errth1", float "errth2", float "MEspatNR", float "MEtempNR") { EdiPre = default( EdiPre, 1.0 ) # What bob to start with: 0.0 = dumbbob, 1.0 = nnEdiBob, inbetween = mix of both EdiPost = default( EdiPost, 2 ) # 0 = no nnEDI PP / 1 = Framesized nnEdi PP / Average two Fieldbased nnEdi PP's bs = default( blocksize, 16 ) # Blocksize for motion search me = default( MEdepth, 2 ) # Search effort of motion search sharpness = (EdiPost==2) \ ? default( sharpness, 0.7 ) \ : default( sharpness, 1.0 ) # use slight sharpening before STT routine mtnmode = default( mtnmode, 1 ) # 0 = use only same-parity motion check, 1|2 use an additional # inter-parity check: 1 = on vertical edges / 2 = not on horizontal edges mtnth1 = default( mtnth1, 0.20 ) # below this %age of local min/max is static mtnth2 = default( mtnth2, 0.40 ) # above this %age of local min/max is motion errth1 = default( errth1, 0.40 ) # similar for error detection errth2 = default( errth2, 0.60 ) # of motion interpolation errors MEspatNR = default( MEspatNR, 0.00 ) # amount of spatial NR (for motion search only) MEtempNR = default( MEtempNR, 0.00 ) # amount of temporal NR (for motion search only) order = (clp.GetParity == True) ? 0 : 1 ORDR = (order==0) ? "TFF" : "BFF" ox = clp.width() oy = clp.height() ERTH1 = string(errth1) ERTH2 = string(errth2) MNTH1 = string(mtnth1) MNTH2 = string(mtnth2) SSTR = string(sharpness) idx_1 = 10 idx_2 = (MEspatNR==0.0 && MEtempNR==0.0) ? idx_1 : idx_1+2 idx_3 = idx_2 + 2 # Create basic operations that we will work with # ============================================== # Basic Field & Bob clips # ----------------------- flatbob = clp.Bob(1,0) normbob = clp.Bob(0.0,0.5) ofields = clp.SeparateFields() oweave = clp.DoubleWeave() nnedibobbed = clp.nnEDIbob() bobbed = (EdiPre == 0.0) ? normbob \ : (EdiPre == 1.0) ? nnedibobbed \ : normbob.merge(nnedibobbed,EdiPre) # Mask to check if motion compensation has delivered only the neighbor's spatial interpolated part # ------------------------------------------------------------------------------------------------ black = Blankclip(ofields).mt_lut("0").Trim(1,1).Loop(Framecount(clp)) white = Blankclip(ofields).mt_lut("255").Trim(1,1).Loop(Framecount(clp)) interpol = Interleave(black,white,white,black).AssumeFieldbased().AssumeParity(ORDR).Weave() # Vertical Edge mask, needed for more safe motion masking # ------------------------------------------------------- Vedge = bobbed.mt_Edge("1 0 -1 2 0 -2 1 0 -1",0,255,0,255,U=1,V=1) Vedge2 = Vedge.mt_Inpand(mode="vertical").mt_Inpand(mode="vertical").mt_Expand(mode="vertical").mt_Expand(mode="vertical") Vedge = mt_Lutxy(Vedge,Vedge2,yexpr="y 2 - 2 * x > x y 2 - 2 * ?") #.mt_Expand() Hedge = bobbed.mt_Edge("1 2 1 0 0 0 -1 -2 -1",0,255,0,255,U=1,V=1) Hedge = Hedge.mt_logic(Hedge.temporalsoften(1,255,0,255,2),"max") # If requested, do flicker reduction before searching motion vectors # ------------------------------------------------------------------- (MEspatNR==0.0) ? bobbed : bobbed.Merge(bobbed.minblur(2,uv=3),MEspatNR) (MEtempNR==0.0) ? last : last.Merge(reduceflicker(2),MEtempNR) srch=last # Perform Motion Search # --------------------- lmbda = 128 pnw = 40 bw_vec2 = srch.SelectEven().MVAnalyse(isb=true, truemotion=false,delta=1,lambda=lmbda,pel=2,searchparam=me,sharp=2,blksize=bs,overlap=1*bs/2,pnew=pnw,idx=idx_1) fw_vec2 = srch.SelectEven().MVAnalyse(isb=false,truemotion=false,delta=1,lambda=lmbda,pel=2,searchparam=me,sharp=2,blksize=bs,overlap=1*bs/2,pnew=pnw,idx=idx_1) bw_vec3 = srch.SelectOdd() .MVAnalyse(isb=true, truemotion=false,delta=1,lambda=lmbda,pel=2,searchparam=me,sharp=2,blksize=bs,overlap=1*bs/2,pnew=pnw,idx=idx_1+1) fw_vec3 = srch.SelectOdd() .MVAnalyse(isb=false,truemotion=false,delta=1,lambda=lmbda,pel=2,searchparam=me,sharp=2,blksize=bs,overlap=1*bs/2,pnew=pnw,idx=idx_1+1) # Create RAW motion interpolation # ------------------------------- alt_1 = bobbed.SelectEven().MVFlowInter(bw_vec2,fw_vec2,time=50.0,thSCD1=64*18,thSCD2=227,idx=idx_2) alt_2 = bobbed.SelectOdd() .MVFlowInter(bw_vec3,fw_vec3,time=50.0,thSCD1=64*18,thSCD2=227,idx=idx_2+1).DuplicateFrame(0) alt = Interleave(alt_2,alt_1) # Create motion interpolation of "nothing new" mask # ------------------------------------------------- interpol_1 = interpol.SelectEven().MVFlowInter(bw_vec2,fw_vec2,time=50.0,thSCD1=64*8,thSCD2=127,idx=idx_3) interpol_2 = interpol.SelectOdd() .MVFlowInter(bw_vec3,fw_vec3,time=50.0,thSCD1=64*8,thSCD2=127,idx=idx_3+1).DuplicateFrame(0) interpol_comp= Interleave(interpol_2,interpol_1) nothing_new = mt_lutxy(interpol,interpol_comp,"x y * 255 / 255 / 1 2 / ^ 160 *") # Error check of motion interpolation # =================================== # Errors that are neutralized by errors in direct vertical neighborhood are not considered, because bob-typical. # Remaining error is checked against [min,max] of local error to decide if it's valid or not. # # Build error mask, neutralize vertical-only errors # --------------------------------------------------- altD = mt_Makediff(bobbed,alt,U=3,V=3) altDmin = altD.mt_Inpand(mode="vertical",U=3,V=3) altDmin = altDmin.mt_Deflate().mt_Merge(altDmin,Vedge,U=4,V=4) altDmax = altD.mt_Expand(mode="vertical",U=3,V=3) altDmax = altDmax.mt_Inflate().mt_Merge(altDmax,Vedge,U=4,V=4) altDmm = mt_Lutxy(altDmax.mt_Expand(mode="horizontal",U=3,V=3),altDmin.mt_Inpand(mode="horizontal",U=3,V=3),"x y -",U=3,V=3) altDmm = altDmm.mt_Inflate().mt_Merge(altDmm,Vedge,U=4,V=4) altD1 = altD .mt_Lutxy(altDmin,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=3,V=3) altD1 = altD1.mt_Lutxy(altDmax,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=3,V=3) altD2 = altD.Repair(altD1,1) # Build correction mask by combining: error mask + "nothing new" mask + a scenechange mask # --------------------------------------------------------------------------------------------- corrmask = mt_Lutxy(altD2,altDmm,"x 128 - abs 2 - y 2 + / "+ERTH1+" - "+ERTH2+" "+ERTH1+" - / 255 *",U=3,V=3).mt_Expand(U=3,V=3) sc = corrmask.BilinearResize(64,64) sc = mt_LutF(sc,sc,mode="average",expr="x 255 0.6 * > 255 0 ?").PointResize(ox,oy) corrmask = corrmask.mt_Logic(nothing_new,"max",U=2,V=2) corrmask = corrmask.mt_Logic(sc,"max",U=2,V=2) # Create a first bob from motion interpolation, not yet error corrected ... # ------------------------------------------------------------------------- # ***( temporarily changed ... yet unsure what works best )*** Interleave(bobbed,alt).AssumeParity(ORDR) SeparateFields().SelectEvery(8,0,3,5,6).Weave() naked= last naked2 = last.vinverseD(1.6) # flatbob # naked_mm = naked.mt_Edge("min/max",0,255,0,255,U=1,V=1) edibb_mm = nnedibobbed.mt_Edge("min/max",0,255,0,255,U=1,V=1).mt_Expand(mode="vertical") check2 = mt_LutXY(naked_mm,edibb_mm,"x y / 3 - 5 3 - / 255 *") corrmask = corrmask.mt_Logic(check2,"max",U=2,V=2) # ... and build a motion mask from this one. # ------------------------------------------ # ***( temporarily changed ... tickertapes might suffer. )*** stc = bobbed .removegrain(2)# oweave.removegrain(11) mm = stc.mt_Edge("min/max",0,255,0,255,U=3,V=3) # mm = mm .mt_Logic(mm.DuplicateFrame(0),"max",U=3,V=3).mt_Logic(mm.DeleteFrame(0),"max",U=3,V=3) # max = stc.mt_expand(U=3,V=3) # max = max.mt_logic(max.Duplicateframe(0),"max",U=3,V=3).mt_logic(max.Duplicateframe(0).Duplicateframe(0),"max",U=3,V=3) # min = stc.mt_inpand(U=3,V=3) # min = min.mt_logic(min.Duplicateframe(0),"min",U=3,V=3).mt_logic(min.Duplicateframe(0).Duplicateframe(0),"min",U=3,V=3) # mm = mt_LutXY(max,min,"x y -",U=3,V=3) diff2prev1 = mt_LutXY(stc,stc.DuplicateFrame(0),"x y - abs",U=3,V=3) diff2prev2 = mt_LutXY(stc,stc.DuplicateFrame(0).DuplicateFrame(0),"x y - abs",U=3,V=3) diff2prev12 = (mtnmode==0) ? diff2prev2 : \ (mtnmode==1) ? diff2prev2 .mt_Merge(diff2prev1,Vedge,U=2,V=2) \ : diff2prev1 .mt_Merge(diff2prev2,Hedge,U=2,V=2) motn = diff2prev12.mt_Logic(diff2prev12.DeleteFrame(0),"max",U=3,V=3).mt_Logic(diff2prev12.DeleteFrame(0).DeleteFrame(0),"max",U=3,V=3) notstatic = mt_LutXY(motn,mm,"x 1 - y 1 + / "+MNTH1+" - "+MNTH2+" "+MNTH1+" - / 255 *",U=3,V=3).mt_Expand(U=3,V=3).mt_Inpand(U=3,V=3) # notstatic = notstatic.mt_Logic(notstatic.RemoveGrain(4),"max",U=3,V=3).mt_Expand(U=3,V=3).mt_Inpand(U=3,V=3) # Now do the error correction of the "naked" MC-bob # ------------------------------------------------- naked .mt_Merge(nnedibobbed,corrmask,luma=false,U=3,V=3) .VinverseD(2.7-sharpness) repaired = last # If requested, sharpen the corrected MC-bob up a little # ( pre-sharpen for EdiPost = 0 | 1 ) # ------------------------------------------------------ shrpbase = last#.MinBlur(1,1).Merge(RemoveGrain(12,-1),0.23) shrp = mt_LutXY(shrpbase,shrpbase.RemoveGrain(11,-1),"x x y - abs 16 / 1 1 x y - abs 1 4 / ^ + / ^ 16 * "+SSTR+" * x y - x y - abs 1.3 + / * 1 x y - abs 16 / 1 4 / ^ + / +",U=2,V=2) # \ .Repair(repaired,1,0) shrpD = mt_Makediff(shrpbase,shrp) (sharpness==0.0 || EdiPost==2) ? last : last .mt_Makediff(MergeLuma(shrpD.MinBlur(1,uv=1),shrpD.RemoveGrain(12,-1),0.24),U=2,V=2) # If requested, do additional PP via nnEDI2 # ---------------------------------------- oweave.mt_merge(last,notstatic,luma=false,U=3,V=3) AssumeTFF() edisingle = nnedi(dh=true,field=1).LanczosResize(ox,oy,0,-0.5,ox,2*oy+0.001,taps=3) edidouble = merge(nnedi(field=1),nnedi(field=0),0.5) edidoubleD = mt_makediff(last,edidouble,U=3,V=3) (EdiPost==1) ? edisingle : \ (EdiPost==2) ? edidouble : last # ( post-sharpen for EdiPost = 2 ) # ------------------------------------------------------ edidoubleshrpD = mt_makediff(edidouble,sharpness==1.0?edidouble.removegrain(20):edidouble.removegrain(20).merge(edidouble,1.0-sharpness),U=3,V=3) edidoubleshrpD = edidoubleshrpD.repair(edidoubleD,13) (EdiPost==2) ? edidouble.mt_adddiff(edidoubleshrpD,U=3,V=3) : last # STT (Shape Transposition Technology) Routine: # ============================================= # Simply weaving the corrected output with the original fields is bad, because the risk of # creating unwanted residual combing is too high. # Instead, the vertical "shape" is taken off the corrected output, and transposed # onto the fixed "poles" of the original fields' scanlines. Et Voila. # ---------------------------------------------------------------------------------------- synthbob = last.AssumeParity(ORDR).SeparateFields().SelectEvery(4,0,3).Weave().Bob(1,0) mapped_new = flatbob.mt_makediff(mt_makediff(synthbob,last,U=3,V=3),U=3,V=3) newfields = mapped_new.AssumeParity(ORDR).SeparateFields().SelectEvery(4,1,2) mappedbob = Interleave(ofields,newfields).SelectEvery(4,0,1,3,2).AssumeParity(ORDR).Weave() # Finally, for static areas use just original fields # -------------------------------------------------- mappedbob #bobbed oweave.mt_merge(last,notstatic.mt_inpand(Y=2,U=2,V=2),luma=false,U=3,V=3) # Lastly, set correct parity for the bobbed clip # ---------------------------------------------- (order==0) ? AssumeTFF() : AssumeBFF() return(last) } # =============================================== ############################ # Helper functions below # ############################ ## Function nnEDIbob, courtesty of tritical: # slow, but accurate nnEDI-bob, always dumb ;) Function nnEDIbob(clip Input) { Input.nnedi(field=-2) } # Helper to simplify script function AssumeParity(clip clp, string "order") { order == "TFF" ? clp.assumeTFF() : clp.assumeBFF() return(last) } # Kill Combing Function function VinverseD(clip clp, float "sstr", int "amnt", int "uv") { uv = default(uv,3) sstr = default(sstr,2.7) amnt = default(amnt,255) uv2 = (uv==2) ? 1 : uv STR = string(sstr) AMN = string(amnt) vblur = clp.mt_convolution("1","50 99 50",U=uv,V=uv) vblurD = mt_makediff(clp,vblur,U=uv2,V=uv2) Vshrp = mt_lutxy(vblur,vblur.mt_convolution("1","1 4 6 4 1",U=uv2,V=uv2),expr="x x y - "+STR+" * +",U=uv2,V=uv2) VshrpD = mt_makediff(Vshrp,vblur,U=uv2,V=uv2) VlimD = mt_lutxy(VshrpD,VblurD,expr="x 128 - y 128 - * 0 < x 128 - abs y 128 - abs < x y ? 128 - 0.25 * 128 + x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2) mt_adddiff(Vblur,VlimD,U=uv,V=uv) (amnt>254) ? last : (amnt==0) ? clp : mt_lutxy(clp,last,expr="x "+AMN+" + y < x "+AMN+" + x "+AMN+" - y > x "+AMN+" - y ? ?",U=uv,V=uv) return(last) } # Nifty Gauss/Median combination function MinBlur(clip clp, int r, int "uv") { uv = default(uv,3) uv2 = (uv==2) ? 1 : uv rg4 = (uv==3) ? 4 : -1 rg11 = (uv==3) ? 11 : -1 rg20 = (uv==3) ? 20 : -1 medf = (uv==3) ? 1 : -200 RG11D = (r==1) ? mt_makediff(clp,clp.removegrain(11,rg11),U=uv2,V=uv2) \ : (r==2) ? mt_makediff(clp,clp.removegrain(11,rg11).removegrain(20,rg20),U=uv2,V=uv2) \ : mt_makediff(clp,clp.removegrain(11,rg11).removegrain(20,rg20).removegrain(20,rg20),U=uv2,V=uv2) RG4D = (r==1) ? mt_makediff(clp,clp.removegrain(4,rg4),U=uv2,V=uv2) \ : (r==2) ? mt_makediff(clp,clp.medianblur(2,2*medf,2*medf),U=uv2,V=uv2) \ : mt_makediff(clp,clp.medianblur(3,3*medf,3*medf),U=uv2,V=uv2) DD = mt_lutxy(RG11D,RG4D,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2) clp.mt_makediff(DD,U=uv,V=uv) return(last) } Last edited by Adub; 14th October 2007 at 03:11. |
14th October 2007, 16:26 | #13 | Link |
Registered User
Join Date: Apr 2002
Location: Germany
Posts: 5,391
|
For mpeg sources loaded with DGDecode, there is (usually) no need to specify field order. Field order is flagged in the source stream, and DGDecode passes the flag through to Avisynth.
For other types of sources, you should always specify the correct field order manually. E.g. AviSource will always flag the stream as being BFF, regardless whether it's actually TFF or BFF.
__________________
- We´re at the beginning of the end of mankind´s childhood - My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!) |
16th October 2007, 21:05 | #15 | Link |
Registered User
Join Date: Sep 2004
Location: Near LA, California, USA
Posts: 1,545
|
I was joking.
I don't know if he is or not.
__________________
Pirate: Now how would you like to die? Would you like to have your head chopped off or be burned at the stake? Curly: Burned at the stake! Moe: Why? Curly: A hot steak is always better than a cold chop. |
16th October 2007, 23:03 | #17 | Link |
Registered User
Join Date: Sep 2004
Location: Near LA, California, USA
Posts: 1,545
|
You'd want MCBob 2.0?
IMO, it would be too slow for anybody if it was made. Well, maybe not for David Hermann and his special cluster computing avisynth plugin. Too each his own I guess.
__________________
Pirate: Now how would you like to die? Would you like to have your head chopped off or be burned at the stake? Curly: Burned at the stake! Moe: Why? Curly: A hot steak is always better than a cold chop. Last edited by Revgen; 16th October 2007 at 23:05. |
17th October 2007, 22:03 | #18 | Link | |
Formerly davidh*****
Join Date: Jan 2004
Posts: 2,496
|
Quote:
But, back on topic, who's to say mcbob 2.0 couldn't be faster and better? If some of the external plugins and functions could be rewritten to implement only the functionality that mcbob requires, that could happen. For instance, as I understand it, mcbob currently uses EEDI/NNEDI (in "post", as opposed to "pre") on the whole image before masking in those sections it needs to use. If there was an EEDI/NNEDI that could understand the mask, it could be applied to only a fraction of the image. David |
|
13th November 2007, 02:05 | #19 | Link |
Registered User
Join Date: Oct 2007
Posts: 66
|
Hi, This is my first post - hope I'm in the right place.
I want to use MCBob, but I can't figure out how to apply it to a given clip. Could somebody gently take me through the steps? I work daily with simple AVISynth scripts, but nothing as complex as MCBob. Thanks! |
15th June 2008, 17:48 | #20 | Link |
Sleepy overworked fellow
Join Date: Feb 2008
Location: Maple syrup's homeland
Posts: 933
|
Do you have the latest removegrain?
__________________
AnimeIVTC() - v2.00 -http://boinc.berkeley.edu/- Let all geeks use their incredibly powerful comps for the greater good (no, no, it won't slow your filtering/encoding :p) |
|
|