2024-03-29 14:56:42 发布
网友
我想要实现的是以编程方式创建一个由256x256颜色值矩阵表示的二维颜色渐变。预期结果见附图。我的起点是矩阵的4个角点颜色,从中可以插值出中间剩余的254种颜色。虽然我在为一个轴插值颜色方面取得了一些成功,但是二维计算给我带来了一些令人头疼的问题。虽然图像似乎有一个非线性的颜色梯度,我会很高兴有一个线性的。在
如果您能给我一些提示,如何使用numpy或其他工具来实现这一点,我将不胜感激。在
这是一个使用scipy.ndimage中的zoom function的超短解决方案。我用初始颜色(这里是随机的)定义一个2x2的RGB图像,并简单地将其缩放到256x256,order=1使插值线性化。代码如下:
scipy.ndimage
order=1
import numpy as np import matplotlib.pyplot as plt im=(np.random.rand(2,2,3)*255).astype(np.uint8) from scipy.ndimage.interpolation import zoom zoomed=zoom(im,(128,128,1),order=1) plt.subplot(121) plt.imshow(im,interpolation='nearest') plt.subplot(122) plt.imshow(zoomed,interpolation='nearest') plt.show()
输出:
这里有三种方法来做这个双线性插值。第一个版本用纯Python完成所有的算法,第二个版本使用PIL图像合成,第三个版本使用Numpy来完成算法。正如预期的那样,纯Python比其他方法慢得多。Numpy版本(源于Andras Deak编写的代码)几乎与小图像的PIL版本一样快,但是对于较大的图像,PIL版本明显更快。在
我也尝试在PIL中使用jadsq的缩放技术,但结果并不理想-我怀疑PIL的插值代码有点缺陷。在
如果您想创建大量相同大小的双线性渐变图像,PIL技术还有另一个优势:一旦您创建了构图遮罩,就不需要为每个图像重建它们。在
#!/usr/bin/env python3 ''' Simple bilinear interpolation Written by PM 2Ring 2016.09.14 ''' from PIL import Image from math import floor import numpy as np def color_square0(colors, size): tl, tr, bl, br = colors m = size - 1 r = range(size) def interp_2D(tl, tr, bl, br, x, y): u0, v0 = x / m, y / m u1, v1 = 1 - u0, 1 - v0 return floor(0.5 + u1*v1*tl + u0*v1*tr + u1*v0*bl + u0*v0*br) data = bytes(interp_2D(tl[i], tr[i], bl[i], br[i], x, y) for y in r for x in r for i in (0, 1, 2)) return Image.frombytes('RGB', (size, size), data) # Fastest def color_square1(colors, size): #Make an Image of each corner color tl, tr, bl, br = [Image.new('RGB', (size, size), color=c) for c in colors] #Make the composition mask mask = Image.new('L', (size, size)) m = 255.0 / (size - 1) mask.putdata([int(m * x) for x in range(size)] * size) imgt = Image.composite(tr, tl, mask) imgb = Image.composite(br, bl, mask) return Image.composite(imgb, imgt, mask.transpose(Image.TRANSPOSE)) # This function was derived from code written by Andras Deak def color_square2(colors, size): tl, tr, bl, br = map(np.array, colors) m = size - 1 x, y = np.mgrid[0:size, 0:size] x = x[..., None] / m y = y[..., None] / m data = np.floor(x*y*br + (1-x)*y*tr + x*(1-y)*bl + (1-x)*(1-y)*tl + 0.5) return Image.fromarray(np.array(data, dtype = 'uint8'), 'RGB') color_square = color_square1 #tl = (255, 0, 0) #tr = (255, 255, 0) #bl = (0, 0, 255) #br = (0, 255, 0) tl = (108, 115, 111) tr = (239, 239, 192) bl = (124, 137, 129) br = (192, 192, 175) colors = (tl, tr, bl, br) size = 256 img = color_square(colors, size) img.show() #img.save('test.png')
输出
为了好玩,这里有一个使用Tkinter的简单GUI程序,可以用来生成这些渐变。在
这里有一个非常简单的方法来使用ImageMagick,它安装在大多数Linux发行版上,可用于OSX和Windows。还有Python绑定。不管怎样,只要在命令行中,在图像的4个角创建一个2x2的正方形,然后让ImageMagick展开并插值到全尺寸:
convert \( xc:"#59605c" xc:"#ebedb3" +append \) \ \( xc:"#69766d" xc:"#b3b3a0" +append \) \ -append -resize 256x256 result.png
第一行使左上角和右上角各一个1x1像素,并排附加两个。第二行为左下角和右下角各生成一个1x1像素,并排附加。最后一行将底行附加到顶行下方,并通过插值放大到256x256。在
如果您想更好地了解发生了什么,下面是相同的基本图像,但使用最近邻而不是插值进行缩放:
这是一个使用
scipy.ndimage
中的zoom function的超短解决方案。我用初始颜色(这里是随机的)定义一个2x2的RGB图像,并简单地将其缩放到256x256,order=1
使插值线性化。代码如下:输出:
这里有三种方法来做这个双线性插值。第一个版本用纯Python完成所有的算法,第二个版本使用PIL图像合成,第三个版本使用Numpy来完成算法。正如预期的那样,纯Python比其他方法慢得多。Numpy版本(源于Andras Deak编写的代码)几乎与小图像的PIL版本一样快,但是对于较大的图像,PIL版本明显更快。在
我也尝试在PIL中使用jadsq的缩放技术,但结果并不理想-我怀疑PIL的插值代码有点缺陷。在
如果您想创建大量相同大小的双线性渐变图像,PIL技术还有另一个优势:一旦您创建了构图遮罩,就不需要为每个图像重建它们。在
输出
为了好玩,这里有一个使用Tkinter的简单GUI程序,可以用来生成这些渐变。在
^{pr2}$这里有一个非常简单的方法来使用ImageMagick,它安装在大多数Linux发行版上,可用于OSX和Windows。还有Python绑定。不管怎样,只要在命令行中,在图像的4个角创建一个2x2的正方形,然后让ImageMagick展开并插值到全尺寸:
第一行使左上角和右上角各一个1x1像素,并排附加两个。第二行为左下角和右下角各生成一个1x1像素,并排附加。最后一行将底行附加到顶行下方,并通过插值放大到256x256。在
如果您想更好地了解发生了什么,下面是相同的基本图像,但使用最近邻而不是插值进行缩放:
^{pr2}$相关问题 更多 >
编程相关推荐