I created a mask which marks most of the defects caused by MFlowFPS:
#AVISource("#2223 - cpadolf's SNES Super Metroid ''any%, glitched''.avi").ConvertToRGB32
AVIsource("test-blend.avi").ConvertToRGB32
v1 = TASBlend .PointResize(512, 448)
v2 = PointResize(512, 448).ConvertToYUY2.TASBlend_nanogyth.ConvertToRGB32
v3 = PointResize(512, 448).ConvertToYUY2.TASBlend_extendednanogyth2.ConvertToRGB32
v4 = TASBlend_Vit.PointResize(512, 448)
StackVertical( stackhorizontal(last.PointResize(512, 448).selecteven, last.PointResize(512, 448).selectodd), \
StackHorizontal(v1.Subtitle("TASBlend" ), v4.Subtitle("TASBlend_Vit" )), \
stackHorizontal(v2.Subtitle("TASBlend_nanogyth"), v3.Subtitle("TASBlend_extendednanogyth")))
function TASBlend_nanogyth(clip c) {
c
Assert(!IsRGB, "TASBlend_nanogyth: clip cannot be RGB")
Interleave(SelectEven.dbz.SelectEvery(4, 0),
\ SelectOdd .dbz.SelectEvery(4, 1))
}
function TASBlend_nanogyth_custom(clip c,int delta) {
c
Assert(!IsRGB, "TASBlend_nanogyth: clip cannot be RGB")
Interleave(SelectEven.dbz_custom(delta).SelectEvery(4, 0),
\ SelectOdd .dbz_custom(delta).SelectEvery(4, 1))
}
function differenceclip(clip a, clip b)
{
overlay( \
a.overlay(b.invert,mode="add",pc_range=true).invert, \
b.overlay(a.invert,mode="add",pc_range=true),mode="add",pc_range=true \
).invert.greyscale.levels(2,1,3,0,255)
}
function differenceclip_weak(clip a, clip b)
{
overlay( \
a.overlay(b.invert,mode="add",pc_range=true).invert, \
b.overlay(a.invert,mode="add",pc_range=true),mode="add",pc_range=true \
).invert.greyscale.levels(2,1,70,0,255)
}
function TASBlend_Vit(clip c, float "ratio") {
# reduces framerate to 1/2 but leaves flicker effects partly visible
# blends frame pairs with alternating opacity (default is 2/3 + 1/3;1/3 + 2/3)
# optional "ratio" is the opacity of the first frame out of the four
ratio = default(ratio, 2.0/3)
opacity = round(ratio * 257)
# blend flicker to half-rate
c.SelectEvery(4, 1, 0, 2, 3)
blend = Layer(SelectEven, SelectOdd, level=opacity)
# determine flicker is a simplistic way - compare each pixel with the previous and next two frames
similar2 = 1 # how similar current pixel must be to the same pixel 2 frames forwards and backwards
different1 = 8 # how different current pixel must be from the same pixel 1 frame forwards and backwards
mask_f2 = Overlay(c, c.SelectEvery(1, 2), mode="difference", pc_range=true).Greyscale.Levels(128 + similar2 , 1.0, 129 + similar2 , 0, 255, false).Invert
mask_f1 = Overlay(c, c.SelectEvery(1, 1), mode="difference", pc_range=true).Greyscale.Levels(128 + different1, 1.0, 129 + different1, 0, 255, false)
mask_b1 = Overlay(c, c.SelectEvery(1,-1), mode="difference", pc_range=true).Greyscale.Levels(128 + different1, 1.0, 129 + different1, 0, 255, false)
mask_b2 = Overlay(c, c.SelectEvery(1,-2), mode="difference", pc_range=true).Greyscale.Levels(128 + similar2 , 1.0, 129 + similar2 , 0, 255, false).Invert
mask_f = Overlay(mask_f1, mask_f2, mode="multiply", pc_range=true)
mask_b = Overlay(mask_b1, mask_b2, mode="multiply", pc_range=true)
mask = Overlay(mask_f, mask_b, mode="multiply", pc_range=true).SelectEven
# only use blend where detected flicker
Layer(c.SelectEven, blend.mask(mask))
}
function TASBlend_extendednanogyth(clip c) {
ng = TASBlend_nanogyth(c)
m=differenceclip(ng,TASBlend_nanogyth_custom(c,1))
m=overlay(m,differenceclip(ng,c.selecteven).invert,mode="add",pc_range=true)
m=overlay(m,differenceclip(ng,c.selecteven.deleteframe(0)).invert,mode="add",pc_range=true).converttorgb32.levels(250,1,251,0,255)
almostfinal = overlay(ng, c.selecteven, mask=m)
return almostfinal
return differenceclip(almostfinal, TASBlend_Vit(c.converttorgb32))
}
function TASBlend_extendednanogyth2(clip c) {
ng = TASBlend_nanogyth(c)
m = differenceclip(ng,TASBlend_nanogyth_custom(c,2))
m2 = differenceclip(ng,TASBlend_nanogyth_custom(c,3))
mask0 = overlay(m,m2,mode="add",pc_range=true)
ng2 = TASBlend_nanogyth(c.deleteframe(0))
m3 = differenceclip(ng,ng2.duplicateframe(0))
mask1 = overlay(mask0, m3, mode="add",pc_range=true)
#return overlay(ng, mask1, mask=mask1, pc_range=true)
#return overlay(c.selecteven, ng, mask=mask1.invert)
#return overlay(c.selecteven, mask1, mask=mask1)
mask2 = overlay(mask1.invert.greyscale.levels(127,1,128,0,255), differenceclip(ng, c.selecteven),mode="add")
mask3 = overlay(mask2, differenceclip(ng, c.selectodd), mode="subtract").greyscale
return ng.overlay(mask3.invert,mask=mask3.invert)
return overlay(mask3,mask4.invert,mode="add")
return overlay(ng, mask3.invert, mask=mask3.invert)
}
function dbz(clip c) {
super = c.MSuper(pel=2)
backward_vec = MAnalyse(super, isb=true)
forward_vec = MAnalyse(super, isb=false)
MFlowFps(c, super, backward_vec, forward_vec, num=60, den=1, ml=100)
}
function dbz_custom(clip c, int delta) {
super = c.MSuper(pel=2)
backward_vec = MAnalyse(super, isb=true,delta=delta)
forward_vec = MAnalyse(super, isb=false,delta=delta)
MFlowFps(c, super, backward_vec, forward_vec, num=60, den=1, ml=100)
}
function TASBlend(clip c) {
ratio = 2.0/3
opacity = round(ratio * 257)
c.SelectEvery(4, 1, 0, 2, 3)
blend = Layer(SelectEven, SelectOdd, level=opacity)
Layer(c.SelectEven, blend)
}
I tested this code with
this video which has fast movement and flicker at the same time .
edit: seems to be a bit too restrictive in the super metroid video...