使用numpy生成彩色图像渐变

7
我写了一个函数,可以生成两个有颜色的图像块:
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)

我希望将这两种颜色组合成渐变色,也就是一张图片从一种颜色渐变到另一种颜色。但我不知道该如何继续,有什么建议吗?我可以使用np.linspace()生成一个一维数组的步数,但之后呢?


2
你能否将输出描述为一张图片? - ZdaR
1
“一张图片从一种颜色变成另一种颜色”是什么意思? - P. Camilleri
2
还有,show_image() 是什么? - P. Camilleri
当然,@P.Camilleri。图片应该以纯色开始,例如在图像的顶部是红色,随着你向下看,颜色逐渐淡化并缓慢变成另一种颜色,例如蓝色。快速的谷歌搜索返回了这个链接:https://www.google.co.uk/search?q=gcolour+gradient&espv=2&biw=1920&bih=925&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjJtdnIrKjQAhViLsAKHZ7FBeIQ_AUIBigB#imgrc=uugXHrVp1HrN5M%3A。谢谢。 - Boa
据我所知,@P.Camilleri的show_image()函数将数组条目显示为像素,即一个填充了零的5x5数组通过show_image()将呈现为黑色正方形,如果这些值是1而不是0,则会呈现为白色正方形。 - Boa
1
如果这是一个自定义函数,请在您的问题中包含代码,以便其他用户能够测试您的代码。更好的方式是替换内建函数,例如plt.imshow()。 - P. Camilleri
2个回答

10

这是您正在寻找的吗?

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

根据你的建议,我使用了 np.linspace,它是numpy中非常强大的广播工具; 在这里了解更多。

c = np.linspace(0, 1, 50)创建一个形状为(50,)的数组,其中包含50个从0到1均匀间隔的数字。添加[:, None, None]将此数组变为三维形状,形状为(50, 1, 1)。在(x - y) * c中使用它时,由于x-y(50, 50, 3),因此最后两个维度会发生广播。c被视为一个我们称为d的数组,其形状为(50, 50, 3),使得对于范围内的i,d[i, :, :]是一个形状为(50, 3),填充有c[i]的数组。

因此,梯度的第一行是x[0,:,:] + c[0] *(x[0,:,:] - y [0,:,:]),它只是x[0,:,:]。 第二行是x[1,:,:] + c[1] *(x[1,:,:] - y [1,:,:]),以此类推。第 i 行是x [i]y[i]的重心,系数为1-c[i]c[i]

enter image description here

您可以在c的定义中使用[None,:,None]进行逐列变化。


是的,这正是我正在寻找的内容!如果您可以,请解释一下c = np.linspace(0, 1, 50)[:, None, None]gradient = x + (y - x) * c的作用?对于梯度而言,看起来您正在计算两个数组之间的差异,将其乘以步长然后添加到第一个颜色块中,为什么会有效呢? - Boa
另外,是否有可能以某种方式使用 np.outer(x,y) 来获取外积并将其用于显示所需的输出? - Boa
@Boa 我不明白在这里如何使用x和y的外积。 外积仍然可以用于不同数组之间。 - P. Camilleri
感谢您的解释,显然可以使用np.outer来实现,方法是使用gradient = np.outer(np.linspace(0,1,50),np.ones((50,))).reshape(50,50,1) - Boa
@Boa 很高兴知道。请像PEP8建议的那样在逗号后面添加一个空格 :) - P. Camilleri

1
感谢P. Camilleri提供的出色答案。我添加了一列变化的示例,生成大小为(HEIGHT_LIMIT, WIDTH_LIMIT)的图像,使用给定的RGB值和。最后,我将其转换为可以保存的图像。
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

示例输出: 渐变示例


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接