Boa - 19 days ago 14
Python Question

# Generating colour image gradient using numpy

I wrote a function which generates 2 coloured image blocks:

``````def generate_block():
x = np.ones((50, 50, 3))
x[:,:,0:3] = np.random.uniform(0, 1, (3,))
show_image(x)

y = np.ones((50, 50, 3))
y[:, :, 0:3] = np.random.uniform(0, 1, (3,))
show_image(y)
``````

I would then like to combine those two colours to form a gradient, ie 1 image going from one colour to the other. I'm not sure how to continue, any advice? Using np.linspace() I can form a 1D array of steps but what then?

Is this what you are looking for ?

``````def generate_block():
x = np.ones((50, 50, 3))
x[:, :, 0:3] = np.random.uniform(0, 1, (3,))
plt.imshow(x)
plt.figure()

y = np.ones((50, 50, 3))
y[:,:,0:3] = np.random.uniform(0, 1, (3,))
plt.imshow(y)

plt.figure()
c = np.linspace(0, 1, 50)[:, None, None]
gradient = x + (y - x) * c
To use `np.linspace` as you suggested, I've used broadcasting which is a very powerful tool in numpy; read more here.
`c = np.linspace(0, 1, 50)` creates an array of shape `(50,)` with 50 numbers from 0 to 1, evenly spaced. Adding `[:, None, None]` makes this array 3D, of shape `(50, 1, 1)`. When using it in `(x - y) * c`, since `x - y` is `(50, 50, 3)`, broadcasting happens for the last 2 dimensions. c is treated as an array we'll call d of shape `(50, 50, 3)`, such that for i in range(50), `d[i, :, :]` is an array of shape `(50, 3)` filled with `c[i]`.
so the first line of gradient is `x[0, :, :] + c[0] * (x[0, :, :] - y[0, :, :])`, which is just `x[0, :, :]` The second line is `x[1, :, :] + c[1] * (x[1, :, :] - y[1, :, :])`, etc. The `i`th line is the barycenter of `x[i]` and `y[i]` with coefficients `1 - c[i]` and `c[i]`