Log in

View Full Version : Using MVTools for repair broken frames.


D3C0D3R
10th May 2011, 00:32
So i have some condition to detect bad frames and in that case i want to replace (obviously via ScriptClip) this bad frames by MVFlowFps function results.

But i cant get into writing sane avs-script.

Mug Funky
10th May 2011, 00:36
function morph (clip c, int in, int "out", int "blksize")
{

Function fill_loop(string s, int stop, int count)
{
return (stop == 0) ? s : string("tofill.mflowinter(morph_spr,fill_vb,fill_vf,time=" + string(100*(count - stop)/float(count))) + ",thscd1=255,thscd2=255).selectevery(tofill.framecount(),0)," + fill_loop(s,stop-1,count)
}

out=default(out, 0)
blksize=default(blksize,16)

d=c.trim(in,out)# in-1?

numframes=d.framecount-2
tofill=d.selectevery(c.framecount(),0,c.framecount()-1)
global morph_spr=tofill.msuper()
fill_vf=morph_spr.manalyse(truemotion=true,blksize=blksize,isb=false,overlap=blksize/2)
fill_vb=morph_spr.manalyse(truemotion=true,blksize=blksize,isb=true,overlap=blksize/2)
filled=eval("interleave(" + fill_loop("" ,d.framecount()-1,d.framecount()-1) + "tofill.selectevery(tofill.framecount(),tofill.framecount())).assumefps(c.framerate())")
c.trim(0,in-1)++filled++c.trim(out+1,0)
}

try this.

usage:

if you have, say, frames 21 and 22 bad, then use "morph(20,23)"

beware - this is old and i'm not sure if i got round to adapting it to mtools2. i think i've used it recently though, so it's probably fine.

Gavino
10th May 2011, 12:43
function morph (clip c, int in, int "out", int "blksize")
That's a pretty mean function, but it has a couple of flaws.
Because of the behaviour of Trim (http://forum.doom9.org/showthread.php?t=58358), it doesn't work when 'in' is 0 or 1, or when 'out' is the last frame.
This can be fixed by replacing the last line
c.trim(0,in-1)++filled++c.trim(out+1,0)
by
c.trim(0,-(in+1))++filled.trim(1,numframes)++c.trim(out,0)
Also, it doesn't work with the default 'out' of 0 - I think in+2 would be a more useful default (or make 'out' mandatory).

Other observations are that 'morph_spr' needn't be global and that 'numframes' was not used (but is now, in my fix).

TheRyuu
10th May 2011, 13:11
I don't know how much this applies to what you're trying to do but I had it lying around.

# QQfix v0.1
# This function tries to identify corrupted (blocky) frames and fix them by interpolating previous and next frames
# By: Kuukunen

function qqfix(clip v, int "blockthres", float "messthres", int "delta",bool "debug") {

blockthres=default(blockthres, 20) # how likely an edge is to be counted as a block edge
messthres=default(messthres,3.0) # how much block edges there needs to be to be considered corrupted (VERY dependent on blockthres)
delta=default(delta,1) # how far to calculate fixes from: more = longer corruptions handled, but
debug=default(debug,false) #instead of fixing anything, show debugging information

vedge2 = v.mt_LutSpa(relative=false, expr="x 8 % 1 < 255 0 ?")
vedge1 = v.mt_LutSpa(relative=false, expr="1 x + 8 % 1 < 255 0 ?")
hedge2 = v.mt_LutSpa(relative=false, expr="y 8 % 1 < 255 0 ?")
hedge1 = v.mt_LutSpa(relative=false, expr="1 y + 8 % 1 < 255 0 ?")

vm1=v.converttorgb().GeneralConvolution(0, "0 0 0 0 -1 1 0 0 0 ", 1)
vm1=blankclip(v).overlay(vm1,mask=vedge1).mt_binarize(blockthres)
vm1=vm1.bilinearresize(vm1.width,vm1.height/8).mt_binarize(220).pointresize(vm1.width,vm1.height)

vm2=v.converttorgb().GeneralConvolution(0, "0 0 0 1 -1 0 0 0 0 ", 1)
vm2=blankclip(v).overlay(vm2,mask=vedge2).mt_binarize(blockthres)
vm2=vm2.bilinearresize(vm2.width,vm2.height/8).mt_binarize(220).pointresize(vm2.width,vm2.height)


hm1=v.converttorgb().GeneralConvolution(0, "0 0 0 0 -1 0 0 1 0 ", 1)
hm1=blankclip(v).overlay(hm1,mask=hedge1).mt_binarize(blockthres)
hm1=hm1.bilinearresize(hm1.width/8,hm1.height).mt_binarize(220).pointresize(hm1.width,hm1.height)

hm2=v.converttorgb().GeneralConvolution(0, "0 1 0 0 -1 0 0 0 0 ", 1)
hm2=blankclip(v).overlay(hm2,mask=hedge2).mt_binarize(blockthres)
hm2=hm2.bilinearresize(hm2.width/8,hm2.height).mt_binarize(220).pointresize(hm2.width,hm2.height)

vm=mt_logic(vm1,vm2,"or")
hm=mt_logic(hm1,hm2,"or")
m=mt_logic(vm,hm,"or")
v
super = MSuper()
backward_vectors = MAnalyse(super, isb = true, delta=delta)
forward_vectors = MAnalyse(super, isb = false, delta=delta)
inter = MFlowInter(super, backward_vectors, forward_vectors, time=50, ml=70)
v
debug?Eval("""
v=conditionalfilter(m,inter,v,"averageluma()",">","3.0",debug)
blankclip(v).overlay(v,mask=m)
v=v.tweak(cont=0.5).overlay(m,mask=m)
#v=ScriptClip("Subtitle(String(m.Averageluma))")
"""):Eval("""
v=conditionalfilter(m,inter,v,"averageluma()",">","3.0",debug)
""")
return v
}

Mug Funky
12th May 2011, 05:08
ha! thanks for that, Gavino.

never was a problem for me because splats rarely occur and only ever happen on the first frame if there's a deck problem.

i've no idea what numframes was about - probably an abandoned earlier attempt to fix the behaviour you describe.

i generally stop scripting when my test case works, then fix later when some other clip breaks it :)

D3C0D3R
8th June 2011, 18:35
thats all is very helpful.
thank everyone of you guys.

laserfan
28th July 2011, 13:27
function morph (clip c, int in, int "out", int "blksize")
...

try this. usage:

if you have, say, frames 21 and 22 bad, then use "morph(20,23)"

Or in my case, frames 87336 and 87337!

I found two bad frames in an otherwise perfect movie source, and am astonished at how well this function worked for me! Never having tried a custom function like this before, I didn't know how to do it and guessed at inserting the above code into my otherwise simple avs script, and, after getting an "msuper" error, downloading mvtools and placing into Avisynth plugins, the thing ran right off.

I've had to step forward-and-backward thru the repaired section of video a dozen times to make sure I was seeing-what-I-was-seeing because it performs like magic--sensational. Almost can't believe how easy this was.

There are some days when doom9 makes me happy, and this is one of those. Thanks Mug Funky, brilliant! Thread deserves a bump...

:thanks:

Emulgator
17th December 2011, 17:17
Unipolator 1.15.
I decided to release it into the wild today, Santa is close and 2011 ran as hell.

Can do motion-based interpolation of 0-7 consequent missing frames in 0-52 places at once.
Especially designed for in-place repair of heavily damaged frames and/or recalculation and reinsertion of missing frames.

http://forum.doom9.org/showthread.php?p=1545489#post1545489

sven_x
29th February 2012, 19:06
@Mug Funky, Gavino:
Is there anything more needed than mvtools2.dll to run the morph function?
I tried to use it, but placing morph(130,131) after the function still gives back my original source video. No error messages, no interpolation.

Gavino
29th February 2012, 20:14
@Mug Funky, Gavino:
Is there anything more needed than mvtools2.dll to run the morph function?
I tried to use it, but placing morph(130,131) after the function still gives back my original source video. No error messages, no interpolation.
It replaces frames between the two numbers, so with morph(130,131) there are no frames to replace!
To replace both 130 and 131, for example, you would use morph(129,132), the logic being that it morphs from 129 to 132, replacing everything in-between by interpolation.
Another way of looking at it is you have to supply the numbers of the nearest good frames, not the bad ones.

sven_x
8th March 2012, 12:44
Many thanks, Gavino. Now I have written a script, that searches for duplicate frames. From the result it generates a second script, that is using calls to Mug Funkys Morph function.
MorphDups - replace duplicate frames by interpolations (http://forum.doom9.org/showthread.php?p=1563921)

Jenyok
22nd March 2013, 20:18
There are some changes to morph() function.
.

#
# morph() function...
#
# Usage:
# if you say frames 21, 22, 23, 24 and 25 are bad, then use "morph(20, 26)"
#
function morph(clip clp, int FrameIn, int "FrameOut")
{
# Constants
# MSuper()
#
hpad = 8 # Maybe 4, 8, 16, 32, !!! Change this constant for best tuning !!!
vpad = 8 # Maybe 4, 8, 16, 32, !!! Change this constant for best tuning !!!
pel = 2 # default=2
sharp = 2 # default=2 !!!
rfilter = 4 # default=2
chroma = true # default=true
isse = true # default=true
planar = false # default=false
levels = 0 # default=0

# Constants
# MAnalyse()
#
blkh = 32 # Maybe 4, 8, 16, 32, !!! Change this constant for best tuning !!!
blkv = 32 # Maybe 4, 8, 16, 32, !!! Change this constant for best tuning !!!
overlap = 4 # Maybe 2, 4, 8, 16, !!! maybe blkh/2 or litle !!! Change this constant for best tuning !!!
overlapV = 4 # Maybe 2, 4, 8, 16, !!! maybe blkv/2 or litle !!! Change this constant for best tuning !!!
search = 3 # default=4 !!! DO NOT CHANGE =3
searchparam = 1 # default=2 !!! DO NOT CHANGE =1
dct = 5 # default=0
plevel = 2 # default=0
badsad = 10000 # default=10000
badrange = (-24) # default=24
divide = 0 # default=0
sadx264 = 0 # default=0
truemotion = true # default=true

lambda = (truemotion == false) ? 0 : (1000 * blkh * blkv / 64) # default=0 truemotion=false, default=1000*blksize*blksizeV/64 truemotion=true
lsad = (truemotion == false) ? 400 : 1200 # default=400 truemotion=false, default=1200 truemotion=true
pnew = (truemotion == false) ? 0 : 50 # default=0 truemotion=false, default=50 truemotion=true
pzero = pnew # default pzero=pnew

# Constants
# MRecalculate()
#
blkhR = 8 # Maybe 4, 8, 16, 32, !!! Change this constant for best tuning !!!
blkvR = 8 # Maybe 4, 8, 16, 32, !!! Change this constant for best tuning !!!
overlapR = 4 # Maybe 2, 4, 8, 16, !!! maybe blkhR/2 or litle !!! Change this constant for best tuning !!!
overlapVR = 4 # Maybe 2, 4, 8, 16, !!! maybe blkvR/2 or litle !!! Change this constant for best tuning !!!
searchR = 3 # default=4
searchparamR = 1 # default=2
thSAD = 400 # default=200 !!! DO NOT CHANGE =400

lambdaR = (truemotion == false) ? 0 : (1000 * blkhR * blkvR / 64) # default=0 truemotion=false, default=1000*blksize*blksizeV/64 truemotion=true

# Constants
# MFlowInter()
#
thSCD1 = 800 # default=400 !!! DO NOT CHANGE =800
thSCD2 = 255 # default=130
ml = 70 # default=100
blend = true # default=true


# Defaults
#
FrameOut = Default(FrameOut, 0)


# Local Fill_Loop() function...
#
function Fill_Loop(string s, int stop, int count, int ml, int thSCD1, int thSCD2, bool isse, bool planar, bool blend)
{
return ((stop == 0) ? \
s : String("MFlowInter(tofill, morph_spr, fill_vb, fill_vf" + \
", time=" + String(100.0 * Float(count - stop) / Float(count))) + \
", ml=" + String(ml) + \
", thSCD1=" + String(thSCD1) + \
", thSCD2=" + String(thSCD2) + \
", isse=" + String(isse) + \
", planar=" + String(planar) + \
", blend=" + String(blend) + \
").SelectEvery(tofill.FrameCount(), 0)," + \
Fill_Loop(s, stop-1, count, ml, thSCD1, thSCD2, isse, planar, blend))
}


# Here is code of function...
#
d = clp.Trim(FrameIn, FrameOut) # in - 1 ?
tofill = d.SelectEvery(clp.FrameCount(), 0, clp.FrameCount()-1)

# function MSuper(clip, int "hpad", int "vpad", int "pel", int "levels", bool "chroma", \
# int "sharp", int "rfilter", clip "pelclip", bool "isse", bool "planar")
#
morph_spr = MSuper(tofill, \
hpad = hpad, \
vpad = vpad, \
pel = pel, \
chroma = chroma, \
sharp = sharp, \
rfilter = rfilter, \
isse = isse, \
planar = planar, \
levels = levels)

# function MAnalyse(clip super, int "blksize", int "blksizeV", int "level", int "search", int "searchparam", \
# int "pelsearch", bool "isb", int "lambda", bool "chroma", int "delta", bool "truemotion", \
# int "lsad", int "plevel", bool "global", int "pnew", int "pzero", int "pglobal", int "overlap", \
# int "overlapV", string "outfile", int "dct", int "divide", int "sadx264", int "badSAD", \
# int "badrange", bool "isse", int "full", bool "meander", bool "temporal")
#
fill_vb = MAnalyse(morph_spr, \
delta = 1, \
isb = true, \
blksize = blkh, \
blksizeV = blkv, \
overlap = overlap, \
overlapV = overlapV, \
search = search, \
searchparam = searchparam, \
pelsearch = pel, \
lambda = lambda, \
chroma = chroma, \
truemotion = truemotion, \
lsad = lsad, \
dct = dct, \
plevel = plevel, \
pnew = pnew, \
pzero = pzero, \
divide = divide, \
sadx264 = sadx264, \
badSAD = badsad, \
badrange = badrange, \
isse = isse, \
levels = levels, \
global = true, \
pglobal = 0, \
meander = true, \
temporal = false, \
trymany = false)

# function MAnalyse(clip super, int "blksize", int "blksizeV", int "level", int "search", int "searchparam", \
# int "pelsearch", bool "isb", int "lambda", bool "chroma", int "delta", bool "truemotion", \
# int "lsad", int "plevel", bool "global", int "pnew", int "pzero", int "pglobal", int "overlap", \
# int "overlapV", string "outfile", int "dct", int "divide", int "sadx264", int "badSAD", \
# int "badrange", bool "isse", int "full", bool "meander", bool "temporal")
#
fill_vf = MAnalyse(morph_spr, \
delta = 1, \
isb = false, \
blksize = blkh, \
blksizeV = blkv, \
overlap = overlap, \
overlapV = overlapV, \
search = search, \
searchparam = searchparam, \
pelsearch = pel, \
lambda = lambda, \
chroma = chroma, \
truemotion = truemotion, \
lsad = lsad, \
dct = dct, \
plevel = plevel, \
pnew = pnew, \
pzero = pzero, \
divide = divide, \
sadx264 = sadx264, \
badSAD = badsad, \
badrange = badrange, \
isse = isse, \
levels = levels, \
global = true, \
pglobal = 0, \
meander = true, \
temporal = false, \
trymany = false)

# MRecalculate(clip super, clip vectors, int "thSAD", int "smooth", int "blksize", int "blksizeV", \
# int "search", int "searchparam", int "lambda", bool "chroma", bool "truemotion", \
# int "pnew", int "overlap", int "overlapV", string "outfile", int "dct", int "divide", \
# int "sadx264", bool "isse")
#
fill_vb = MRecalculate(morph_spr, \
fill_vb, \
blksize = blkhR, \
blksizeV = blkvR, \
overlap = overlapR, \
overlapV = overlapVR, \
search = searchR, \
searchparam = searchparamR, \
lambda = lambdaR, \
dct = dct, \
truemotion = truemotion, \
thSAD = thSAD, \
isse = isse, \
chroma = chroma, \
pnew = pnew, \
divide = divide, \
sadx264 = sadx264, \
smooth = 1)

# MRecalculate(clip super, clip vectors, int "thSAD", int "smooth", int "blksize", int "blksizeV", \
# int "search", int "searchparam", int "lambda", bool "chroma", bool "truemotion", \
# int "pnew", int "overlap", int "overlapV", string "outfile", int "dct", int "divide", \
# int "sadx264", bool "isse")
#
fill_vf = MRecalculate(morph_spr, \
fill_vf, \
blksize = blkhR, \
blksizeV = blkvR, \
overlap = overlapR, \
overlapV = overlapVR, \
search = searchR, \
searchparam = searchparamR, \
lambda = lambdaR, \
dct = dct, \
truemotion = truemotion, \
thSAD = thSAD, \
isse = isse, \
chroma = chroma, \
pnew = pnew, \
divide = divide, \
sadx264 = sadx264, \
smooth = 1)

filled = Eval("Interleave(" + \
Fill_Loop("", d.FrameCount()-1, d.FrameCount()-1, ml, thSCD1, thSCD2, isse, planar, blend) + \
"tofill.SelectEvery(tofill.FrameCount(), tofill.FrameCount())).AssumeFps(clp.Framerate())")

return (clp.Trim(0, (-1 * (FrameIn + 1))) ++ filled.Trim(1, d.FrameCount - 2) ++ clp.Trim(FrameOut, 0))
}

Jenyok
23rd March 2013, 07:02
There are some functions to interpolate and replace broken and bad frames, gathered togather, lol.
Functions are described in code section, see below.
See attached RAR file.
.

#
# File: InterpolateFrames.avsi
#
# various functions to interpolate and replace BAD FRAMES
#
#
# Last editing date: 23.03.2013 year
#
#
#
# function InterpolateFrames(clip clp, int FrameNumber, int FrameCount) using MFlowInter(), GScript
# function InterpolateFrames2(clip clp, int FrameNumber, int FrameCount) using MFlowInter(), MRecalculate(), GScript
# function RXOriginal(clip clp, int FrameNumber, int FrameCount) using MFlowFps()
# function RX(clip clp, int FrameNumber, int FrameCount) using MFlowFps(), MRecalculate()
# function IX(clip clp, int FrameNumber, int FrameCount)
# function ReplaceFrames(clip clp, int FrameNumber, int FrameCount) using MBlockFps(), MRecalculate() two times (twice)
# function InsertFrames(clip clp, int FrameNumber, int FrameCount)
# function morph(clip clp, int FrameIn, int "FrameOut") using MFlowInter(), MRecalculate()
#
#
# function OneFrame(clip clp, int N) using MFlowInter(), MRecalculate()
# function OneFrames(clip clp, int N) the same as OneFrame() function
# function TwoFrames(clip clp, int N) using MFlowInter(), MRecalculate()
# function PairFrames(clip clp, int N) the same as TwoFrames() function
# function ThreeFrames(clip clp, int N) using MFlowInter(), MRecalculate()
# function FourFrames(clip clp, int N) using MFlowInter(), MRecalculate()
# function FiveFrames(clip clp, int N) using MFlowInter(), MRecalculate()
# function SixFrames(clip clp, int N) using MFlowInter(), MRecalculate()
# function SevenFrames(clip clp, int N) using MFlowInter(), MRecalculate()
# function EightFrames(clip clp, int N) using MFlowInter(), MRecalculate()
# function NineFrames(clip clp, int N) using MFlowInter(), MRecalculate()
# function TenFrames(clip clp, int N) using MFlowInter(), MRecalculate()
#
#

.
Did some improvment changes more...
.