Log in

View Full Version : Using filters within ModifyFrame


zorr
3rd March 2019, 22:44
I need to perform per frame brightness adjustments so that every frame has different adjustment settings. In Avisynth this can be done with ScriptClip.

I tried this code (as a proof-of-concept) but it doesn't change the output.

def adjust_brightness(n, f):
fout = f.copy()
fout = core.std.Expr(clips=[fout], expr=['x 2 *', ''])
return fout

core.std.ModifyFrame(clip=v1, clips=v1, selector=adjust_brightness)

Is that kind of code supposed to work? I think comes down to whether you can call filters within ModifyFrame and have them return the modified frame.

If it's not supported what is a good workaround? Do I have to split the clip into len(clip) one frame length clips and process them individually without ModifyFrame?

[EDIT] I just noticed that there was an error:
Expr: argument clips was passed an unsupported type (expected clip[] compatible type but got VideoFrame)

So that can't work because f is a VideoFrame and not a clip. Is it possible to create a clip out of a VideoFrame?

WolframRhodium
4th March 2019, 04:34
It is convenient to use NumPy within std.ModifyFrame in this case.


from functools import partial
import numpy as np

base_clip = core.std.BlankClip(format=vs.GRAY8, length=2560, color=1)

def adjust_brightness_numpy(n, f, coeffs):
fout = f.copy()

frame_in = f.get_read_array(0) # only the first plane will be processed
frame_out = fout.get_write_array(0)

data_in = np.asarray(frame_in)
data_out = np.asarray(frame_out)

data_out[:] = data_in * coeffs[n % 16]
# or simply:
# np.multiply(data_in, coeffs[n % 16], out=data_out)

return fout

flt = core.std.ModifyFrame(base_clip, clips=base_clip, selector=partial(adjust_brightness_numpy, coeffs=[16 * i for i in range(16)]))


Or you can achieve it simply through std.FrameEval (http://www.vapoursynth.com/doc/functions/frameeval.html)


from functools import partial

base_clip = core.std.BlankClip(format=vs.GRAY8, length=2560, color=1)

def adjust_brightness(n, clip, coeffs):
return core.std.Expr(clip, [f'x {coeffs[n % 16]} *'])

flt = core.std.FrameEval(base_clip, eval=partial(adjust_brightness, clip=base_clip, coeffs=[16 * i for i in range(16)]))

zorr
4th March 2019, 15:16
Thanks Wolf. That latter example looks just what I need. I don't know why I didn't realize that myself, a similar example is right there in the FrameEval documentation (http://www.vapoursynth.com/doc/functions/frameeval.html). :o