Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 744
Boa Avatar asked Nov 14 '16 13:11

Boa


People also ask

How does NumPy calculate gradient?

The gradient is computed using second order accurate central differences in the interior points and either first or second order accurate one-sides (forward or backwards) differences at the boundaries. The returned gradient hence has the same shape as the input array.

How do you work out the gradient of an image?

The gradient of a pixel is the difference between an adjacent pixel and the current pixel. In the y direction, dI/dy = I(y+1) - I(y) .

What is the use of NumPy in image processing?

We can also use NumPy for transforming the image into a grayscale image. By Taking the weighted mean of the RGB value of the image we can perform this. Output: Here is the image of the output of our grayscale conversion process.


2 Answers

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
    plt.imshow(gradient)
    return x, y, gradient

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 ith line is the barycenter of x[i] and y[i] with coefficients 1 - c[i] and c[i]

enter image description here

You can do column-wise variation with [None, :, None] in the definition of c.

like image 140
P. Camilleri Avatar answered Sep 18 '22 10:09

P. Camilleri


Thanks to P. Camilleri for the great answer. I add an example of column-wise variation, that generates Image in (HEIGHT_LIMIT, WIDTH_LIMIT) size, using a given RGB value and . Finally, I transform it to an image you can save.

WIDTH_LIMIT = 3200
HEIGHT_LIMIT = 4800
def generate_grad_image(rgb_color=(100,120,140)): # Example value
    x = np.ones((HEIGHT_LIMIT, WIDTH_LIMIT, 3)) 
    x[:, :, 0:3] = rgb_color
    y = np.ones((HEIGHT_LIMIT, WIDTH_LIMIT, 3))
    y[:,:,0:3] = [min(40 + color, 255) for color in rgb_color]
    c = np.linspace(0, 1, WIDTH_LIMIT)[None,:, None]
    gradient = x + (y - x) * c
    im = Image.fromarray(np.uint8(gradient))
    return im

Example output: gradient example

like image 23
Gil Gvirts Avatar answered Sep 22 '22 10:09

Gil Gvirts