7

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?

6
  • 2
    Can you describe the output as a image ? Commented Nov 14, 2016 at 13:19
  • 1
    What does "One image going from one colour to the other" mean? Commented Nov 14, 2016 at 13:20
  • 2
    Also, what is show_image() ? Commented Nov 14, 2016 at 13:24
  • Sure, @P.Camilleri The image should start with a pure colour eg red on the top of the image and as you look further down, the colour fades and slowly changes to another colour eg blue. A quick google search returned this. Thanks. Commented Nov 14, 2016 at 13:28
  • 1
    If it is a custom function, include the code in your question, for other users to be able to test your code. Even better, substitute a built in function like plt.imshow() Commented Nov 14, 2016 at 13:36

2 Answers 2

10

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Yes exactly what I'm looking for! Can you explain what c = np.linspace(0, 1, 50)[:, None, None] and gradient = x + (y - x) * c does if you can? for the gradient it looks like you're computing the difference between the two arrays and multiplying by the steps then adding to the first colour block, why does this work?
Also, would it be possible to somehow use np.outer(x,y) to get the outer product and use that to display the desired output?
@Boa I don't see how the outer product of x and y is going to help here. outer product could be used nevertheless, but between different arrays.
Thanks for the explanations, and apparently it is possible with np.outer by using gradient = np.outer(np.linspace(0,1,50),np.ones((50,))).reshape(50,50,1)
@Boa Nice to know. Please add a space after commas as PEP8 recommends :)
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.