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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > VapourSynth

Reply
 
Thread Tools Search this Thread Display Modes
Old 23rd May 2015, 13:35   #1  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
vmulti/compensateMulti/degrainN/writevec/readvec for vsmvtools

Code:
def getvectors (src, supersearch, tr=6, pel=4, dct=5, thsad=400):
    core        = vs.get_core ()
    supersoft   = core.mv.Super (src, pel=pel, chroma=False, hpad=32, vpad=32, pelclip=supersearch, sharp=2, rfilter=4, levels=0)
    supersharp  = core.mv.Super (src, pel=pel, chroma=False, hpad=32, vpad=32, pelclip=supersearch, sharp=2, rfilter=2, levels=0)
    def search (isb, delta):
        vectors = core.mv.Analyse (supersoft, isb=isb, overlap=16, blksize=32, search=3, chroma=False, truemotion=True, delta=delta, trymany=True, searchparam=16, pelsearch=16, dct=0, levels=0, divide=2, badrange=-24)
        vectors = core.mv.Recalculate (supersoft, vectors, overlap=8, blksize=16, thsad=thsad//2, chroma=False, truemotion=True, search=3, searchparam=16, dct=dct, smooth=1, divide=2)
        vectors = core.mv.Recalculate (supersharp, vectors, overlap=4, blksize=8, thsad=thsad//2, chroma=False, truemotion=True, search=3, searchparam=16, dct=dct, smooth=1, divide=2)
        vectors = core.mv.Recalculate (supersharp, vectors, overlap=2, blksize=4, thsad=thsad//2, chroma=False, truemotion=True, search=3, searchparam=16, dct=dct, smooth=1, divide=0)
        return vectors
    bv          = [search (True, i) for i in range (tr, 0, -1)]
    fv          = [search (False, i) for i in range (1, tr+1)]
    vmulti      = bv + fv
    vmulti      = core.std.Interleave (vmulti)
    return vmulti

def compensatemulti (src, comp, superclip, vmulti, tr=6, pel=4, thsad=400, thscd1=248, thscd2=130):
    core        = vs.get_core ()
    super       = core.mv.Super (comp, pel=pel, chroma=False, hpad=32, vpad=32, pelclip=superclip, sharp=2, rfilter=2, levels=0)
    def compensate (delta):
        vectors = core.std.SelectEvery (vmulti, tr*2, delta)
        filter  = core.mv.Compensate (src, super, vectors, thsad=thsad, thscd1=thscd1, thscd2=thscd2)
        return filter
    bcomp       = [compensate (i) for i in range (0, tr)]
    fcomp       = [compensate (i) for i in range (tr, 2*tr)]
    compmulti   = bcomp + [src] + fcomp
    compmulti   = core.std.Interleave (compmulti)
    return compmulti

def degrainn (src, comp, superclip, vmulti, tr=6, pel=4, thsad=400, thscd1=248, thscd2=130, full=True):
    core        = vs.get_core ()
    super       = core.mv.Super (comp, pel=pel, chroma=False, hpad=32, vpad=32, pelclip=superclip, sharp=2, rfilter=2, levels=0)
    def MDG1 (a):
        bv      = core.std.SelectEvery (vmulti, tr*2, tr-1-a)
        fv      = core.std.SelectEvery (vmulti, tr*2, tr+a)
        MDG     = core.mv.Degrain1 (src, super, bv, fv, thsad=thsad, thscd1=thscd1, thscd2=thscd2, plane=0)
        return MDG
    MDGMulti    = [MDG1 (i) for i in range (0, tr)]
    MDGMulti    = core.fmtc.bitdepth (core.std.Interleave (MDGMulti), bits=32, flt=True, fulls=full, fulld=full, dmode=1)
    def MDGMerge (start=None, a=2):
        start   = core.std.Merge (core.std.SelectEvery (MDGMulti, tr, 0), core.std.SelectEvery (MDGMulti, tr, 1), 0.5) if start is None else start
        merge   = core.std.Merge (start, core.std.SelectEvery (MDGMulti, tr, a), 1/(a+1))
        a       = a+1
        clip    = merge if a == tr else MDGMerge (start=merge, a=a)
        return clip
    return MDGMerge ()

def writevec (vec, logout):
    core = vs.get_core ()
    w    = vec.get_frame (0).width
    with open (logout, "w") as f:
         print (w, file=f)
    vec  = core.std.CropAbs (vec, width=w, height=1)
    return vec

def readvec (vec, login):
    core = vs.get_core ()
    with open (login, "r") as f:
         w = int (f.readline ())
    vec  = core.raws.Source (vec, w, 1, src_fmt="Y8")
    return vec
works with a "tr" parameter, like in avisynth mvtools
degrainN takes tr >= 3 only, go mv.Degrain1/2 if tr<3, and degrainN ain't the exact extension of degrain1/2/3, it's a more convolved (averaged) variant, but gets you very similar results compared to the original one.

writevec=MStoreVec in avisynth MVTools
readvec=MRestoreVec in avisynth MVTools
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated

Last edited by feisty2; 30th May 2015 at 06:46.
feisty2 is offline   Reply With Quote
Old 23rd May 2015, 16:22   #2  |  Link
Myrsloik
Professional Code Monkey
 
Myrsloik's Avatar
 
Join Date: Jun 2003
Location: Ikea Chair
Posts: 1,870
This is where you simplify the script to figure out what's causing it.
__________________
VapourSynth - proving that scripting languages and video processing isn't dead yet
Myrsloik is offline   Reply With Quote
Old 24th May 2015, 12:03   #3  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
bump after update
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 25th May 2015, 06:04   #4  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
update: rewrote the merging part of degrainn, it won't lose precision for nothing now
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 26th May 2015, 09:17   #5  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
update:
new: writevec/readvec
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 26th May 2015, 12:14   #6  |  Link
MonoS
Registered User
 
Join Date: Aug 2012
Posts: 170
I suggest you to add something like that
Code:
def writevecs(vecs, files, log):
	w = vecs[0].get_frame(0).width
	
	f = [0 for x in range(len(files))]
	for numFile in range(len(files)):
		f[numFile] = open(files[numFile], "wb")

	for i in range(vecs[0].num_frames):
		if (i+1) % 100 == 0:
			print(i+1, "/", vecs[0].num_frames)
		
		for numVec in range(len(vecs)):
			frame = vecs[numVec].get_frame(i)
			view = frame.get_read_array(0)
			
			for y in range(len(view)):
				f[numVec].write(view[y])
	
	for numFile in range(len(files)):
		f[numFile].close()
	
	open (log, "w").write (repr(w))
I made a little test and this gave me about 2x speedup to the single write version.
I don't know how to optimize python code, but maybe it can be further improved.

The function seems to works properly, tried saving the vector file with the single file version, reading it with rawsource and saving 4 vector files using this function [if you try to compare it saving the vector twice you get different md5 due to some initialized memory]
MonoS is offline   Reply With Quote
Old 26th May 2015, 12:18   #7  |  Link
Myrsloik
Professional Code Monkey
 
Myrsloik's Avatar
 
Join Date: Jun 2003
Location: Ikea Chair
Posts: 1,870
Actually there's another trick you can use to make it doable with vspipe which will definitely beat any python based solution.

1. Get the width of the vector clip from the first frame
2. Use CropAbs(vector_clip, width=frame0width, height=1)
3. vspipe script.vpy vectors.bin -p

alternative 3. Use clip.output() which should also be faster at this point


The key here is that CropAbs can make a variable dimension clip have fixed dimensions (as long as the input frames are big enough to not leave blank parts in the output).
__________________
VapourSynth - proving that scripting languages and video processing isn't dead yet
Myrsloik is offline   Reply With Quote
Old 26th May 2015, 13:15   #8  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
done, looks super
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 26th May 2015, 18:04   #9  |  Link
splinter98
Registered User
 
Join Date: Oct 2010
Posts: 36
I'd tweak the single readvecs and writevecs to the following, you want to ensure you close the files after writing otherwise someone may have issues with too many files open (by using a context manager, the the file closes automatically when you exit the with block).

Code:
def writevec(vec, logout):
    core = vs.get_core()
    w = vec.get_frame(0).width
    vec = core.std.CropAbs(vec, width=w, height=1)
    with open(logout, "w") as f:
        f.write(repr(w))
    return vec

def readvec(vec, login):
    core = vs.get_core()
    with open(login, "r") as f:
        w = int(f.read())
    vec = core.raws.Source(vec, w, 1, src_fmt="Y8")
    return vec
Personally I'd also swap f.write(repr(w)) with print(w, file=f) as then you get a new line in the file and f.read() with f.readline() as if the file provided is incorrect and is large you won't fill your memory with nearly as much data before int returns an error.

Last edited by splinter98; 26th May 2015 at 18:12.
splinter98 is offline   Reply With Quote
Old 26th May 2015, 19:51   #10  |  Link
MonoS
Registered User
 
Join Date: Aug 2012
Posts: 170
Using Myrsloik suggestion i created this.
It's about 25% faster than my previous writevecs [i didn't made any test]

The resulting clip must be saved as a raw file.

ReadVecs works using the same indexes used writing.
Maybe opening the vecs file outside of the function could improve performance, i didn't made extensive testing [and don't appear to be faster than feisty2 readvec implementation]

Code:
def WriteVecs(vecs, prefix):
	core = vs.get_core()
	
	w = vecs[0].get_frame(0).width
	
	for numVec in range(len(vecs)):
		vecs[numVec] = core.std.CropAbs(vecs[numVec], width=w, height=1)
	
	v = core.std.StackVertical(vecs)
	
	log = open(prefix + ".len", "w")
	log.write(repr(w))
	
	return v

def ReadVecs(index, prefix, h):
	core = vs.get_core()
	
	f = open(prefix + ".len", "r")
	w = int(f.read())
	f.close()
	
	vecs = core.raws.Source(prefix + ".vec", w, h, src_fmt="Y8")
	
	v = core.std.CropAbs(vecs, y=index, height=1, width=w)
	
	return v
MonoS is offline   Reply With Quote
Old 27th May 2015, 06:15   #11  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
@MonoS
why putting all that extra work to make the 1xn clip mxn,
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 27th May 2015, 08:46   #12  |  Link
MonoS
Registered User
 
Join Date: Aug 2012
Posts: 170
Quote:
Originally Posted by feisty2 View Post
@MonoS
why putting all that extra work to make the 1xn clip mxn,
Because i wanted an easy way to save all the vector in 1 call and have a nice speedup [this last one was not expected]

If you want to save only one vector clip than your method is the best [simple code, no strange modification to the clip, etc], but if you want to save more vector clips you must do it by hand and imho it's annoying
MonoS is offline   Reply With Quote
Old 27th May 2015, 11:31   #13  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
update: degrainn always outputs float point clips now, to minimize the rounding error of the merging process
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 27th May 2015, 17:54   #14  |  Link
splinter98
Registered User
 
Join Date: Oct 2010
Posts: 36
Quote:
Originally Posted by MonoS View Post
Using Myrsloik suggestion i created this.
It's about 25% faster than my previous writevecs [i didn't made any test]

...

Code:
def WriteVecs(vecs, prefix):
	core = vs.get_core()
	
	w = vecs[0].get_frame(0).width
	
	for numVec in range(len(vecs)):
		vecs[numVec] = core.std.CropAbs(vecs[numVec], width=w, height=1)
	
	v = core.std.StackVertical(vecs)
	
	log = open(prefix + ".len", "w")
	log.write(repr(w))
	
	return v
...
You can squeeze even more performance out of this function by making it a little more pythonic, and also removes the mutation of vecs.

Code:
def WriteVecs(vecs, prefix):
    core = vs.get_core()
    w = vecs[0].width
    v = core.std.StackVertical([core.std.CropAbs(vec, width=w, height=1) for vec in vecs])
    with open(prefix + ".len", "w") as f:
        print(w, file=f)
    return v
splinter98 is offline   Reply With Quote
Old 27th May 2015, 23:40   #15  |  Link
MonoS
Registered User
 
Join Date: Aug 2012
Posts: 170
Quote:
Originally Posted by splinter98 View Post
You can squeeze even more performance out of this function by making it a little more pythonic, and also removes the mutation of vecs.
Oh, that nice, thanks [i hope that my supreme skillfulness on python come through my code]
MonoS is offline   Reply With Quote
Old 29th May 2015, 16:17   #16  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
update: fixed a "limit" bug, just found out not like in avisynth mvtools, "no limit" in mv.degrain does not stay constant as "255", actually bit depth related (2 ^ bitdepth - 1), simplified the merging expression, should run a little bit faster now
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Old 29th May 2015, 16:31   #17  |  Link
Myrsloik
Professional Code Monkey
 
Myrsloik's Avatar
 
Join Date: Jun 2003
Location: Ikea Chair
Posts: 1,870
Quote:
Originally Posted by feisty2 View Post
update: fixed a "limit" bug, just found out not like in avisynth mvtools, "no limit" in mv.degrain does not stay constant as "255", actually bit depth related (2 ^ bitdepth - 1), simplified the merging expression, should run a little bit faster now
Generally speaking Expr is slower than anything else that does similar things. Its only advantage is that it can do things no other filter can sometimes...

start = core.std.Expr ([core.std.SelectEvery (MDGMulti, tr, 0), core.std.SelectEvery (MDGMulti, tr, 1)], ["x y + 2 /"]) if start is None else start
is faster if written as
core.std.Merge(core.std.SelectEvery (MDGMulti, tr, 0), clipb=core.std.SelectEvery (MDGMulti, tr, 1))

Likewise
merge = core.std.Expr ([start, core.std.SelectEvery (MDGMulti, tr, a)], ["x {a} * y + {a} 1 + /".format (a=a)])
can be accomplished faster by fiddling with the weight of the merge.
__________________
VapourSynth - proving that scripting languages and video processing isn't dead yet
Myrsloik is offline   Reply With Quote
Old 30th May 2015, 06:47   #18  |  Link
feisty2
I'm Siri
 
feisty2's Avatar
 
Join Date: Oct 2012
Location: Los Angeles, California
Posts: 2,119
update: replaced Expr with Merge, should work faster now
__________________
If I got new ideas, will post here: https://github.com/IFeelBloated
feisty2 is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 21:26.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.