Log in

View Full Version : Gradient Ramp function?


poisondeathray
15th September 2019, 07:10
Is there a function to generate a gradient ramp ?

e.g. a ramp from x1,y1 to x2,y2 coordinates. Values from a to b



Or how would you do it in python ?

I know you can do it in other programs, but I'm just wondering how to do it procedurally in vapoursynth

Thanks

_Al_
15th September 2019, 23:28
Do you work in RGB? You can then use numpy and use even opencv algorithms. Im sure you coul google some "opencv gradients" or better "numpy to gradient".
Just to demonstarate the process, here is some Eval function, where vs array is changed into numpy, opencv making gradients by some built in function and then using some numpy magic to paste that rectangle into original numpy array. Then numpy is going back to vs array.

import cv2
import numpy as np
import functools
import vshelper
import vapoursynth as vs
from vapoursynth import core
clip = core.ffms2.Source(r'C:/video.mp4')
clip = core.resize.Point(clip, matrix_in_s = '709', format = vs.RGB24)
X1,Y1 = (100,100)
X2,Y2 = (500,500)

def grad(n, clip):
list_of_arrays = [np.array(clip.get_frame(n).get_read_array(i), copy=False) for i in range(3)]
np_image = np.dstack(list_of_arrays)
rectangle = cv2.applyColorMap(np_image, cv2.COLORMAP_JET)[Y1:Y2, X1:X2]
np_image[Y1:Y2, X1:X2] = rectangle
out = vshelper.uint8_vsclip(np_image, clip=None)
out = core.resize.Bilinear(out, format = vs.RGB24)
return out

clip = core.std.FrameEval(clip, functools.partial(grad, clip=clip))

clip.set_output()

poisondeathray
16th September 2019, 00:47
Thanks _Al_

RGB yes

I can't find vshelper

How would you specify the values ? Lets start with something simple: Lets say you wanted RGB30 linear ramp. RGB [0,0,0 - 1023,1023,1023] , from 0,0 to 1023,0 . So it's a 1024x(something height) dimension rectangle

I already did this in another program, I'm just wondering programatically how it can be done in vapoursynth, or what the syntax would be

_Al_
16th September 2019, 02:10
https://github.com/KotoriCANOE/MyTF/blob/master/utils/vshelper.py

here is an example for floating point, vshelper can do floating point, going on from RGBS, not sure about RGB30, but RGB24 is ok too,
no opencv needed, just numpy

I'm not sure how that gradient suppose to be, one color changing into other from top to bottom then pasted into video:

import numpy as np
import functools
import vshelper
clip = core.ffms2.Source(r'C:/video.mp4')
clip = core.resize.Point(clip, matrix_in_s = '709', format = vs.RGBS)
X1,Y1 = (100,100)
X2,Y2 = (600,300)
WIDTH = X2-X1
HEIGHT = Y2-Y1
#https://stackoverflow.com/questions/4337902/how-to-fill-opencv-image-with-one-solid-color
def create_blank(width, height, color=(0, 0, 0)):
image = np.zeros((height, width, 3), np.uint8)
#color = tuple(reversed(color))
image[:] = color
return image

def pip(n, clip, rectangle):
list_of_arrays = [np.array(clip.get_frame(n).get_read_array(i), copy=False) for i in range(3)]
np_image = np.dstack(list_of_arrays)
np_image[Y1:Y2, X1:X2] = rectangle
pip = vshelper.float32_vsclip(np_image, clip=None)
return pip

color1 = (255, 0, 0)
color2 = (0, 0, 255)
img1 = create_blank(WIDTH, HEIGHT, color1).astype(np.float32)/255.0
img2 = create_blank(WIDTH, HEIGHT, color2).astype(np.float32)/255.0
c = np.linspace(0, 1, HEIGHT)[:, None, None]
gradient = img1 + (img2 - img1) * c
clip = core.std.FrameEval(clip, functools.partial(pip, clip=clip, rectangle = gradient))
clip.set_output()

_Al_
16th September 2019, 02:42
and for gradient from left to right that one line for c would be:
c = np.linspace(0, 1, WIDTH)[None,:, None]

poisondeathray
16th September 2019, 02:56
Thanks, it works well

_Al_
16th September 2019, 04:24
simple black & white gradient could be made something like this into vs.VideoNode , but to create pip might be timely using FrameEval, though did not try it, numpy is really fast, so those gradients created into numpy first makes sense, like above,
vapoursynth gradient (black&white for alpha or something):

import vapoursynth as vs
from vapoursynth import core
clip = core.ffms2.Source(r'C:/video.mp4')
clip = core.resize.Point(clip, matrix_in_s = '709', format = vs.RGB24) #RGBS, RGB30 ...

X1,Y1 = (100,100)
X2,Y2 = (600,300)
WIDTH = X2-X1
HEIGHT = Y2-Y1

gradient = core.std.BlankClip(width=1, height=HEIGHT, color=(0,0,0), format = clip.format.id)
if gradient.format.sample_type == vs.INTEGER:
size=2**gradient.format.bits_per_sample
else:
size=1 #vs.FLOAT

for part in range(1,WIDTH):
c = size/WIDTH*part
add = core.std.BlankClip(clip, width=1, height=HEIGHT, color=(c,c,c))
gradient = core.std.StackHorizontal([gradient, add])
del add
gradient.set_output()

poisondeathray
16th September 2019, 04:34
The 1st function is flexible enough for me; I just use blankclip for the video . It works well for my purposes