Post subject: Setting up a deblinking workflow
Player (65)
Joined: 4/21/2011
Posts: 232
I've updated the deblink function http://pastebin.com/JNJQKHm9 ng_blinkmask(test=true) will show a side by side of the video with some motion vector information. Use that to tell when you have blinking. Decide how best to deal with the blinking you have. (some guidelines at the pastebin) Then tie it together with some ReplaceFramesSimple.
ReplaceFramesSimple(src, src.ng_deblink(),
\ mappings="
[2235 2266]
[3729 3760]
[4673 4688]
[5361 5374]")

ReplaceFramesSimple(last, src.ng_deblink(1.0),
\ mappings="
[1933 2002]
[5165 5266]")

ReplaceFramesSimple(last, src.SelectEvery(4,0,2,1,3),
\ mappings="
[6595 6800]
[7861 8175]")

ReplaceFramesSimple(last, src.SelectEvery(4,1,0,2,3),
\ mappings="
[19677 19864]")

SelectEven()
Player (65)
Joined: 4/21/2011
Posts: 232
This might more sense with examples, so I'll use a super mario bros 2 run that YoungJ1997lol mentioned on IRC last night. The linked youtube is 240p and just uses SelectEven. Young's attempt upsizes to 480p and applies TASBlend throughout. There is very little blinking in the run, so the TASBlend ends up blurring motion everywhere with little positive effect. SelectEven is the correct approach for most of the run. I put together a collection of some of the more complex parts and I'll try to explain how to use the test=true option to sort things out. Section 1 The first 100 frame are typical of most of the movie. Blues for pixel change. Greens and yellows for flashes. Nothing that needs to be corrected. With the shyguy at the bottom there is some real blinking which shows up as red/magenta. Section 2 The flashing at the beginning isn't very distinct, it might just be a sprite limit issue. Toad looking back and forth is definitely blinking. Section 3 The enemies are constantly swapping screen order as they fall. The shyguys at the end flash at odd intervals. Section 4 The fish at the beginning looks like it might be blinking, but a double check shows it is just complex motion tricking my filters. The logs are blinking, which seems strange, probably a sprite issue. Section 5 Flashing at the beginning with some blinking as Luigi lifts the egg. Section 6 Mostly flashing, some blinking while Luigi is invincible. Section 7 Health bar blinks with the mask a bit. Blinking egg, sprite issue. Section 8 Egg blinks, probably a sprite issue. Boss blinks. Toad blinks when invincible Section 9 When Toad looks back and forth at a 1 frame rate it is blinking, but the (2 left, 1 right) isn't. Section 10 Wings are blinking.
src=avisource("4.avs")

ReplaceFramesSimple(src, src.ng_deblink(),
\ mappings="
[2378 3071] #first boss
[28627 29181] #wings")

ReplaceFramesSimple(src.ng_deblink(1.0),
\ mappings="
[2025 2053] #shyguy twitching
[2564 2708] #toad twitching
[4254 4341] #falling creeps
[6137 6182] #falling logs
[17391 17439] #invinc
[18675 18679] #footsie
[19699 19746] #invinc
[22756 22803] #invinc
[25922 26137] #egg+invinc
[26596 26615] #toad twitch
[27401 27455] #toad twitch")
http://www.youtube.com/watch?v=itz8byBrfVA
Player (65)
Joined: 4/21/2011
Posts: 232
Bubble Bobble was giving my regular techniques some trouble, so I came up with a new method. ColorKeyMask is made for greenscreening and such. I'm using it here to pick out just the colors of the sprites that are blinking. This works fine on NES where the palette is limited, but probably wouldn't work on 16bit+ consoles. The blinking scores were tricky because the main character is the same color. When I first did it using just 1 frame forward/back the eyes got wonky. Searching 4 frames f/b cleans up most of the visible artifacts. http://pastebin.com/MbksNPiJ
Player (65)
Joined: 4/21/2011
Posts: 232
Link to video The blinking as the boss dies (1:25) gives ng_deblink trouble. It is blinking out, rather than blinking in, so the edges are matching the background. Nothing is moving, so selectevery works there. When getting the bomb bee (1:39), the blinking is only recognized when the sprites are a certain distance apart. As they get close together it is treated as motion instead of blinking.
Language: avisynth

avisource("M:\TAS\EMU\vba\avi\Megaman Xtreme 2 (USA, Europe).avi") src=trim(55565,62425) ReplaceFramesSimple(src.ng_deblink(1.0), src.selectevery(8,1,1,2,2,4,4,7,7), mappings=" [5186 5323] # 1/8, 1/4") yt=ReplaceFramesSimple(src.selectevery(4,0,0,3,3), mappings=" [5324 5461] # 1/2") stackhorizontal(src.TASBlend(), yt.selecteven())
Player (65)
Joined: 4/21/2011
Posts: 232
hum, ng_deblink is having a real hard time with the grayscale at the end of Link's Awakening.
creaothceann
He/Him
Editor
Joined: 4/7/2005
Posts: 1874
Location: Germany
nanogyth wrote:
hum, ng_deblink is having a real hard time with the grayscale at the end of Link's Awakening.
I'd use simple frameblending on that one.
Player (65)
Joined: 4/21/2011
Posts: 232
I'd blend the credits, they're pretty harsh without it. The rest looks ok using selectevery to blink it. Link to video
Language: avisynth

src=avisource("M:\TAS\Legend of Zelda, The - Link's Awakening (USA, Europe).avi").trim(0,29470) ReplaceFramesSimple(src, src.selectevery(4, 0,0,3,3), mappings=" [1211 1231] # blinking shadow [2158 2235] # chicken shadow [3589 3625] # shadow [5179 5270] # blinking key [5277 5392] # shake walk [5783 5812] # shake walk [9368 14589] # stars / chain [16417 16998] # stars") ReplaceFramesSimple(src.TASBlend().selectevery(1, 0,0), mappings=" [22272 28796] # credits") #stackhorizontal(src, last) selecteven()
Player (65)
Joined: 4/21/2011
Posts: 232
This function will target just the text. That will keep the cloud/whale motion crisp. The .55 can be changed depending on how blinky you want the credits to be. 0.0 or 1.0 would maximize the blinking, 0.5 would minimize it.
Language: avisynth

function shake(clip clp){ diff = ng_diff(clp.SelectEvery(1,-1), clp) same = ng_same(clp.SelectEvery(1,-1), clp.SelectEvery(1,1)) mt_logic(same, diff, mode="and") } src=avisource("M:\TAS\Legend of Zelda, The - Link's Awakening (USA, Europe).avi").trim(0,29470) ReplaceFramesSimple(src, src.selectevery(4, 0,0,3,3), mappings=" [1211 1231] # blinking shadow [2158 2235] # chicken shadow [3589 3625] # shadow [5179 5270] # blinking key [5277 5392] # shake walk [5783 5812] # shake walk [9368 14589] # stars / chain [16417 16998] # stars") ReplaceFramesSimple(src.ng_deblink(.55, blinkmask=src.shake()), mappings=" [22272 28796] # credits") #stackhorizontal(src, last) selecteven()
Joined: 8/3/2012
Posts: 10
hi nanogyth, since I'm interested in speedruns and also avisynth and video editing I've come to see this thread and your script. I must say, pretty amazing work there. But I noticed that the detection of shakes and global flashes is not working pretty well (well that's probably the reason you put it in test mode). I came up with a pretty good solution for this problem. basically it doesn't use the local motion (like you did with mmask) but the global motion compensation aka the camera pan or scrolling. here is the function for 1frame-flashes:
function sfx_flash(clip clp, int "thr"){
	
   thr = default(thr, 64)
   src = clp.ConvertToYV12()
	
   super = MSuper(src, pel=1)
   fvec  = MAnalyse(super, isb=false, blksize=4)
   
   gmc  = MDepan(src, fvec)
   fgmc = Depan(src, data=gmc, offset=-1)
   bgmc = Depan(src, data=gmc, offset=1)

   fflash = mt_lutxy(fgmc,src,expr="x y - abs 2 *").mt_binarize(thr)
   bflash = mt_lutxy(bgmc,src,expr="x y - abs 2 *").mt_binarize(thr)
   flash  = mt_logic(fflash,bflash,mode="and")

   mt_lutf(flash,flash,"avg",expr="x").mt_binarize(thr).GreyScale()
}
litte explanation: let's say (c)urrent is our reference frame, (f)orward and (b)ackward the neighbor frames and diff(x,y) the difference between frames x and y. we eliminate the scrolling effect (which distorts the difference calculation) by analyzing the global motion (with MDepan() and Depan()) and shifting the frame to the postion of the reference frame. the rest is simple: we move f and b with depan to the position of c. if c is a single frame flash then diff(c,f) and diff(c,b) is pretty big and we set the mask to 255. otherwise it's zero. the threshold maybe needs adjustment from game to game. and now the code for 1frame-shakes:
function sfx_shake(clip clp, int "thr"){

   thr = default(thr, 32)
   src = clp.ConvertToYV12()
	
   super = MSuper(src, pel=1)
   fvec  = MAnalyse(super, isb=false, blksize=4)
   
   gmc  = MDepan(src, fvec)
   b1gmc = Depan(src, data=gmc, offset=1)
   b2gmc = Depan(src, data=gmc, offset=2)

   b1shake = mt_lutxy(src.selectevery(1,-1),b1gmc,expr="x y - abs 2 *").mt_binarize()
   b2shake = mt_lutxy(src.selectevery(1,-1),b2gmc.selectevery(1,1),expr="x y - abs 2 *").mt_binarize()

   b1shkavg = mt_lutf(b1shake,b1shake,"avg",expr="x")
   b2shkavg = mt_lutf(b2shake,b2shake,"avg",expr="x")

   mt_lutxy(b1shkavg,b2shkavg,"x y -").mt_binarize(thr).GreyScale()
}
explanation: if c is a single frame flash then diff(b,c) should be greater than diff(b,f) otherwise the camera is standing still or we have normal motion. to compensate for the differences inside the actual frames we don't compare the given frames but again using the global motion analysis. we shift b to the position of c and compare to the original position of b. then we do the same with b and f. the rest is just building the differences and comparing the results. the problem I have now is that I don't really now how I use the information of these masks, especially when there are many flashes/shakes in a row. here is my code so far, which works good if the source only has single flashes/shakes. maybe you have some ideas (should've add parameters for the new threshold values):
function sfx_deblinkmod(clip clp,
\ float "ratio",
\ int "level",
\ clip "blinkmask"
\){

    deblink = ng_deblink(clp, ratio, level, blinkmask)
    
    sfx = mt_lutxy(sfx_flash(deblink),sfx_shake(deblink),"x y +").ConvertToRGB32()

    f0=Layer(deblink.SelectEvery(2,0),
\            deblink.SelectEvery(2,1).Mask(sfx.SelectEvery(2,1)),
\            level=257)
    f1=Layer(deblink.SelectEvery(2,1),
\            deblink.SelectEvery(2,0).Mask(sfx.SelectEvery(2,0)),
\            level=257)

    interleave(f0,f1)
}
you can easily add the 3 functions to your script and it should work. of course you can optimize the code by eliminating the additional msuper and manalyze calls. but this would have required a rewrite of a great part of your script which had made my changes incomprehensible. tested the script modification with castlevania3, super metroid, bionic commando and contra3.
Player (65)
Joined: 4/21/2011
Posts: 232
I like the idea here. But I didn't get anything useful from the masks on the super metroid clip I tried. (I might have an out of date plugin)
Sp00kyFox wrote:
tested the script modification with castlevania3, super metroid, bionic commando and contra3.
Can you point out specific sections where it is working as intended?
Joined: 8/3/2012
Posts: 10
well I had the problem that I couldn't find many 1frame-shake scenes. it was often at least 2 frames (and these need no fixing). the flashes were easier to find. I had to selecteven() the source for some scenes to get 1frame-flashes/shakes for testing. 1frame-flashes: castlevania3 http://tasvideos.org/764M.html ~ 2:00 where the hero picks up the holy cross bionic comando http://tasvideos.org/1396M.html ~ 4:32 flashing sky ~ 12:32 ship boss super metroid http://tasvideos.org/1368M.html ~ 4:22 lightning behind samus ship ~ 33:42 mother brain boss part 1 (selecteven()) 1frame-shakes (probably have to lower the threshold value): contra3 http://tasvideos.org/787M.html ~ 1:21 destroying midstage boss (selecteven()) super metroid (same tas as above) ~ 3:18 escape intro ~ 32:25 disappearing boss statue (selecteven()) bionic commando (same tas as above) ~ 13:05 dialogue (selecteven()) just look at the masks. the deblinkmod function is not working properly for flashes/shakes in a row. well the shake detection script could probably be improved. if you imagine the 3 frames (b,c,f) as a triangle we only tested 2 edges. if we include the third edge (which is c-f) in the determination it could make it more accurate. suggestion (with corresponding variable names):
function sfx_shake2(clip clp, int "thr"){

   thr = default(thr, 0)
   src = clp.ConvertToYV12()
	
   super = MSuper(src, pel=1)
   fvec  = MAnalyse(super, isb=false, blksize=4)
   
   gmc  = MDepan(src, fvec)
   b1gmc = Depan(src, data=gmc, offset=1)
   b2gmc = Depan(src, data=gmc, offset=2)

   bcshake = mt_lutxy(src.selectevery(1,-1),b1gmc,expr="x y - abs 2 *").mt_binarize()
   cfshake = mt_lutxy(src.selectevery(1,1),b1gmc.selectevery(1,1),expr="x y - abs 2 *").mt_binarize()
   bfshake = mt_lutxy(src.selectevery(1,-1),b2gmc.selectevery(1,1),expr="x y - abs 2 *").mt_binarize()

   bcshkavg = mt_lutf(bcshake,bcshake,"avg",expr="x")
   cfshkavg = mt_lutf(cfshake,cfshake,"avg",expr="x")
   bfshkavg = mt_lutf(bfshake,bfshake,"avg",expr="x")

   minshk = mt_lutxy(bcshkavg,cfshkavg,expr="x y <= x y ?")
	
   mt_lutxy(minshk,bfshkavg,"x y -").mt_binarize(thr).GreyScale()
}
edit: noticed some luma issues with the masks and the yuv->rgb conversion. substituded tweak with greyscale function call. also fixed the other post.
creaothceann
He/Him
Editor
Joined: 4/7/2005
Posts: 1874
Location: Germany
Would be nice if every plugin author would provide RGB functionality...
Editor, Emulator Coder, Site Developer
Joined: 5/11/2011
Posts: 1108
Location: Murka
creaothceann wrote:
Would be nice if every plugin author would provide RGB functionality...
ahh, yes. one of the biggest strengths of avisynth (the large library of quick native code plugins) is also one of the biggest weaknesses... most of them are crusty old crap
Site Admin, Skilled player (1235)
Joined: 4/17/2010
Posts: 11264
Location: RU
How to disable single frame flashes detection? Kills console's interlaced vids.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Player (65)
Joined: 4/21/2011
Posts: 232
Try this ng_deblink(blinkmask=ng_blinkmask(NOFLASH=true)) Do you have a sample?
Joined: 11/29/2010
Posts: 8
Hello all, I'm struggling to know what correct order of filters to conversion 60 to 30. My script below: Download spoiler.avs
Language: avs

Import("C:\Program Files (x86)\AviSynth 2.5\plugins\deblink4.avs") LoadPlugin("C:\Program Files (x86)\AviSynth 2.5\plugins\ExactDedup.dll") LoadPlugin("C:\Program Files (x86)\AviSynth 2.5\plugins\mvtools2.dll") LoadPlugin("C:\Program Files (x86)\AviSynth 2.5\plugins\mt_masktools-26.dll") AVISource("video.avi").ConvertToRGB32().AssumeFPS(60,1).deblink4.ChangeFPS(30) deblink4.avs=function deblink4(clip clp, float "ratio", int "level") { ratio = default(ratio, 2.0 /3) assert(ratio >= 0.0 && 1.0 >= ratio, \ "[deblink4] 1.0 >= ratio >= 0.0, it was " + string(ratio)) level = default(level, round(ratio * 257)) assert(level >= 0 && 257 >= level, \ "[deblink4] 257 >= level >= 0, it was " + string(level)) blink=clp.ng_blinkmask_new m01=mt_logic(blink.selectevery(4,0),blink.selectevery(4,1),mode="or").converttorgb32 m23=mt_logic(blink.selectevery(4,2),blink.selectevery(4,3),mode="or").converttorgb32 f0=layer(clp.selectevery(4,0),clp.selectevery(4,1).mask(m01),level=level) f1=layer(clp.selectevery(4,1),clp.selectevery(4,0).mask(m01),level=level) f2=layer(clp.selectevery(4,2),clp.selectevery(4,3).mask(m23),level=(257-level) ) f3=layer(clp.selectevery(4,3),clp.selectevery(4,2).mask(m23),level=(257-level) ) interleave(f0,f1,f2,f3) } function deblink3(clip clp){ blink=clp.ng_blinkmask_new m01=mt_logic(blink.selectevery(4,0),blink.selectevery(4,1),mode="or").converttorgb32 f0=layer(clp.selectevery(4,0),clp.selectevery(4,1).mask(m01)) f1=layer(clp.selectevery(4,1),clp.selectevery(4,0).mask(m01)) interleave(f0,f1,clp.selectevery(4,2),clp.selectevery(4,3)) } function ng_blinkmask_new(clip c,int "ml"){ ml=default(ml,128) src=c.ConvertToYv12 super=MSuper(src, pel=1) fvec =MAnalyse(super, isb=false, blksize=4) bvec =MAnalyse(super, isb=true , blksize=4) fmask=Mmask(src,fvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) bmask=Mmask(src,bvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) eo0_to =fmask.selectevery(2,1) oe_from=bmask.selectevery(2,1) front =mt_logic(eo0_to,oe_from,mode="and") oe_to =fmask.selectevery(2,2) eo_from=bmask.selectevery(2,2) back =mt_logic(oe_to,eo_from,mode="and") ee_src=src.selecteven ee_super=MSuper(ee_src, pel=1) ee_fvec =MAnalyse(ee_super, isb=false, blksize=4) ee_bvec =MAnalyse(ee_super, isb=true , blksize=4) ee_fmask=Mmask(ee_src,ee_fvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) ee_bmask=Mmask(ee_src,ee_bvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) ee_to =ee_fmask.trim(1,0) ee_from=ee_bmask ee =mt_logic(ee_to,ee_from,mode="or") oo_src=src.selectodd oo_super=MSuper(oo_src, pel=1) oo_fvec =MAnalyse(oo_super, isb=false, blksize=4) oo_bvec =MAnalyse(oo_super, isb=true , blksize=4) oo_fmask=Mmask(oo_src,oo_fvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) oo_bmask=Mmask(oo_src,oo_bvec,kind=1,ml=ml).mt_binarize(u=-128,v=-128) oo_to =oo_fmask.trim(1,0) oo_from=oo_bmask oo =mt_logic(oo_to,oo_from,mode="or") #to e0-o1, from o1-e2, nothing e0-e2 even_blink=mt_logic(front,ee.mt_invert,mode="and") #to o1-e2, from e2-o3, nothing o1-o3 odd_blink =mt_logic(back,oo.mt_invert,mode="and") interleave(even_blink, odd_blink).selectevery(1,-1) }
and Download spoiler.avs
Language: avs

Import("C:\Program Files (x86)\AviSynth 2.5\plugins\ng_deblink.avs") LoadPlugin("C:\Program Files (x86)\AviSynth 2.5\plugins\ExactDedup.dll") LoadPlugin("C:\Program Files (x86)\AviSynth 2.5\plugins\mvtools2.dll") LoadPlugin("C:\Program Files (x86)\AviSynth 2.5\plugins\mt_masktools-26.dll") AviSource("video.avi").ConvertToRGB32().ng_deblink(0.5).Selectodd ng_deblink.avs=function ng_deblink(clip clp, \ float "ratio", \ int "level", \ clip "blinkmask" \){ #Version 10 2012.04.22 blink = default(blinkmask, clp.ng_blinkmask()) ratio = default(ratio, 2.0 /3) assert(ratio >= 0.0 && 1.0 >= ratio, \ "[ng_deblink] 1.0 >= ratio >= 0.0, it was " + string(ratio)) level = default(level, round(ratio * 257)) assert(level >= 0 && 257 >= level, \ "[ng_deblink] 257 >= level >= 0, it was " + string(level)) m01=mt_logic(blink.SelectEvery(4,0), \ blink.SelectEvery(4,1), \ mode="or").ConvertToRGB32() m23=mt_logic(blink.SelectEvery(4,2), \ blink.SelectEvery(4,3), \ mode="or").ConvertToRGB32() f0=Layer(clp.SelectEvery(4,0), \ clp.SelectEvery(4,1).Mask(m01), \ level=level) f1=Layer(clp.SelectEvery(4,1), \ clp.SelectEvery(4,0).Mask(m01), \ level=level) f2=Layer(clp.SelectEvery(4,2), \ clp.SelectEvery(4,3).Mask(m23), \ level=(257-level) ) f3=Layer(clp.SelectEvery(4,3), \ clp.SelectEvery(4,2).Mask(m23), \ level=(257-level) ) Interleave(f0,f1,f2,f3) } function ng_blinkmask(clip clp, \ bool "TEST", \ bool "STABILIZE", \ bool "SHARP", \ bool "HYSTER", \ int "inpand", \ int "expand", \ int "ml" \){ #Version 10 2012.04.22 #BLINK # Blinking is a block that alternates on/off each frame # SelectEven would only see either the on or the off #FLASH # Flashing is a block that is only on for a single frame # SelectEven might miss the flash #SHAKE # Shaking is a block that moves back/forth each frame # SelectEven would only see one position # The goal of this function is to make a blink mask for use with # ng_deblink. For overly complicated scenes where a clean blinkmask # can't be found, just use TASBlend. Uniform softness looks better # than sharp artifacts. # This function calculates flash and shake info for the test script, # but those effects should be handled in different ways. # Flash - choose frames to make sure the flash is in your final clip. # Shake - SelectEvery(4,0,2,1,3) or SelectEvery(4,1,0,2,3) # SelectEvery doesn't generally work because it messes with the fluidity # of motion. But that won't be noticable on a shaking screen. # Be careful if 2 frame blinking is present, as the selectevery can turn # it into 1 frame blinking. TEST = default( TEST, false) STABILIZE = default(STABILIZE, true) SHARP = default( SHARP, true) HYSTER = default( HYSTER, false) inpand = default( inpand, 1) expand = default( expand, 1) ml = default( ml, 128) # The functions used to make the masks work in the YV12 colorspace. Once # the masks are created they can be used in the RGB32 colorspace direcly src=clp.ConvertToYV12() # Blinking is located by looking for blocks that don't exist in # consecutive frames. The motion vector will match blocks that exist in # both frames. The blocks that aren't in both will end up with huge # values that are picked out by the motion mask. super = MSuper(src, pel=1) fvec = MAnalyse(super, isb=false, blksize=4) bvec = MAnalyse(super, isb=true , blksize=4) fmask = Mmask(src, fvec, kind=1, ml=ml).mt_binarize() bmask = Mmask(src, bvec, kind=1, ml=ml).mt_binarize() blink = mt_logic(fmask, bmask, mode="and") # Blinking usually occurs against a stable background. This is found # by looking at blocks 2 frames apart. This distinguishes a blink from # blocks that are just changing every frame. ee_src = src.SelectEven() ee_super = MSuper(ee_src, pel=1) ee_fvec = MAnalyse(ee_super, isb=false, blksize=4) ee_bvec = MAnalyse(ee_super, isb=true , blksize=4) ee_fmask = Mmask(ee_src, ee_fvec, kind=1, ml=ml).mt_binarize() ee_bmask = Mmask(ee_src, ee_bvec, kind=1, ml=ml).mt_binarize() oo_src = src.SelectOdd() oo_super = MSuper(oo_src, pel=1) oo_fvec = MAnalyse(oo_super, isb=false, blksize=4) oo_bvec = MAnalyse(oo_super, isb=true , blksize=4) oo_fmask = Mmask(oo_src, oo_fvec, kind=1, ml=ml).mt_binarize() oo_bmask = Mmask(oo_src, oo_bvec, kind=1, ml=ml).mt_binarize() fmask_2 = Interleave(ee_fmask, oo_fmask) bmask_2 = Interleave(ee_bmask, oo_bmask) background = mt_logic(fmask_2.SelectEvery(1,1), \ bmask_2.SelectEvery(1,-1), \ mode="or") stable_blink = mt_hysteresis(background.mt_invert, blink) blink2 = (STABILIZE) ? stable_blink : blink # Shrinking the blink mask can get rid of noise, # too much will lose signal as well. blink3 = blink2.mt_inpand(mode=mt_diamond(inpand)) # Using just pixels that changed helps sharpen the mask diff = ng_diff(clp.SelectEvery(1,-1), clp) diff_2 = mt_logic(diff, diff.SelectEvery(1,1), mode="and") #Hysteresis # Matches continuous blocks of pixels. # Use with care, will match the whole screen on fades. hyster_blink = mt_hysteresis(blink3, diff_2) # Expand the mask to make up for shrinking it (or just use hysteresis) blink4 = blink3.mt_expand(mode=mt_circle(expand)) sharp_blink = mt_logic(blink4, diff_2, mode="and") blink5 = (HYSTER) ? hyster_blink : \ (SHARP) ? sharp_blink : blink4 # A flash won't match blocks 1 or 2 frames away. sub_flash = mt_logic(fmask_2, bmask_2, mode="and") flash = mt_logic(blink, sub_flash, mode="and") # A shake changes in one frame and changes back in the next. # This isn't detected by the motion vectors because the blocks exist in # both frames, they are just shifting around. same = ng_same(clp.SelectEvery(1,-1), clp.SelectEvery(1,1)) shake = mt_logic(same, diff_2, mode="and") (TEST) ? stackhorizontal(clp, mergeRGB(blink5, flash, shake)) \ : blink5.GreyScale() } function ng_diff(clip A, clip B, int "thr"){ thr=default(thr,0) TAD=ng_TAD(A,B) return mt_binarize(TAD, threshold=thr) } function ng_same(clip A, clip B, int "thr"){ thr=default(thr,0) TAD=ng_TAD(A,B) return mt_binarize(TAD, threshold=thr, upper=true) } function ng_TAD(clip A, clip B){ R=ng_AD(A .showRed("YV12"),B .showRed("YV12")) G=ng_AD(A.showGreen("YV12"),B.showGreen("YV12")) B=ng_AD(A .showBlue("YV12"),B .showBlue("YV12")) return ng_plus(R, ng_plus(G, B)) } function ng_AD(clip A, clip B){ return mt_lutxy(A,B,"x y - abs") } function ng_plus(clip A, clip B){ return mt_lutxy(A,B,"x y +") }
Its ok? I'm also sending a video sample to know which filters to use. SAMPLE.AVI Thank you Claudio
Player (65)
Joined: 4/21/2011
Posts: 232
I'm struggling to know what correct order of filters to conversion 60 to 30.
Are you having a particular problem or just looking for general advice? AviSource("video.avi") ConvertToRGB32() ng_deblink(0.5) changefps(30) Use the emulator output (RGB) if you have it.
Joined: 11/29/2010
Posts: 8
Thanks for fast reply nano. Yes. My encodes aren't "fluid" (fighting games suffering) looks like various videos in forum. Its chopiness/stuttering Yep. I upload in H264 because size, my sources are RGB (Lagarith codec or UT video), all files 60.00 fps in default resolutions. Claudio
Player (65)
Joined: 4/21/2011
Posts: 232
There is a noticeable difference between 60 and 30fps, but it shouldn't be choppiness/stuttering. While running the avs you will often see choppiness because it is hard for most computers to do all the processing in real time. So do a test render and see if it that fixes the problem. For a side-by-side compare you can do something like this. src = avisource("sample.avi").converttorgb32() stackhorizontal(src, src.ng_deblink(0.5).selectevery(2,0,0))
Joined: 11/29/2010
Posts: 8
After your tip, I did several tests and found the problem is in Youtube encode, not the script (MP4 files are very good to watch). Comparing videos side by side the difference is really smallest. Thank you man Claudio