I'm currently working on some visualization to help figure out why artifacts happen. The results are worse than previous because the masks are so sharp.
FFVideoSource("sm.avi")
ConvertToRGB32
HalfWink(debug=true)
function HalfWink(clip c, bool "debug"){
debug=default(debug,false)
#The clip is made of even/odd frames and the simplest way to reduce
#framerate would be to just take the even frames. But some clips have
#blinking/shaking that alternates frame to frame. That could make a
#"transparent" object solid or disappear entirely. Or lock a shaking
#scene in a single position.
#e e e
# o^o o
#Every other even frame is taken as is. The other even frame is used
#as much as it can be. A mask is made of the blinking and the shaking.
#Those parts of the frame are simply replaced with data from one of the
#odd frames. NO BLENDING!!!
e0=c.selectevery(4,0)
o1=c.selectevery(4,1)
e2=c.selectevery(4,2)
o3=c.selectevery(4,3)
e2fix=overlay(e2,o1,mask=BlinkShake(c))
DebugMask=stackvertical(\
stackhorizontal(o1,e2,o3),\
stackhorizontal(Shaking(c,debug=true),e2fix,Blinking(c,debug=true)))
return debug ? DebugMask : interleave(e0,e2fix)
}
function BlinkShake(clip c){
return mt_logic(Blinking(c),Shaking(c),mode="or")
}
function Shaking(clip c, bool "debug"){
debug=default(debug,false)
c=c.ConvertToYv12 #.colorYUV(autogain=true)
#Shaking is the background moving at a regular rate.
#E e E
# o ^ o o
move=c.mt_motion
oe=move.selectevery(4,2)
eo=move.selectevery(4,3)
oo=c.selectodd.mt_motion.selectodd
#Motion will be seen between oe AND eo, AND NOT oo
Shaking=mt_logic(mt_logic(oe,eo,mode="and"),oo.mt_invert,mode="and")
DebugMask=mergeRGB(oe,eo,oo.mt_invert)
return debug ? DebugMask : Shaking
}
function Blinking(clip c, bool "debug"){
debug=default(debug,false)
c=c.ConvertToYv12 #.colorYUV(autogain=true)
#Blinking is an object that appears/disappears from the scene.
#If the object is blinking it will show crazy high motion since it doesn't
#exist frame to frame. Use mvtools to detect motion.
#Look for motion to and from. The vectors aren't symetric because it is
#easier to match the background than an object.
#The motion must be forward AND backward or it isn't a one-frame blink.
super=MSuper(c)
fvec =MAnalyse(super, isb=false, truemotion=false)
bvec =MAnalyse(super, isb=true , truemotion=false)
fmask=Mmask(c,fvec,kind=1).mt_binarize
bmask=Mmask(c,bvec,kind=1).mt_binarize
#f f f f
# b b b b
#f b f b f b f b
#f(bf)(bf)(bf)(bf)(b
# >2<
masks=interleave(fmask,bmask)
To=masks.selectevery(2,1)
From=masks.selectevery(2,2)
ToFrom=mt_logic(To,From,mode="or")
tfForward=ToFrom.selectevery(4,1)
tfBackward=ToFrom.selectevery(4,2)
Blinking=mt_logic(tfForward,tfBackward,mode="and")
DebugMask=mergeRGB(tfForward,tfBackward,blankclip(tfForward))
return debug ? DebugMask : Blinking
}