Python - 使用由 X、Y 位置定义的 RGB 值创建颜色图
Python - Creating colormap with RGB values defined by X,Y position
我正在解决一个问题,我只解决了一半。
我正在使用 X、Y 坐标绘制二维绘图 space。我想在绘图上设置 4 个点 space,为每个点设置颜色并生成颜色图。
我能够生成具有 2 个点的颜色图 - 创建矢量并从一个点到另一个点。但是,此方法在几何意义上在点上创建 2D plane/1D 线。但是如果设置4个点,就需要生成面。所以换句话说,我需要在点中拟合曲面。
这是我想象的样子:
这是我的代码,用于生成从一个 X,Y,[RGB] 到另一个 X,Y,[RGB] 的直接变化。
import numpy as np
import colorsys
import cv2
a = np.array([100,0,0]) # Point one with x=0,y=0-max and rgb value
b = np.array([0,255,0]) # point two with x=max,y=0-max and rgb value
#in this case i loop from y=0 to y=max for corresponding point on the other side of drawing space - that is x=max
a = a[::-1]
b= b[::-1]
leds = 31 # just constant
h_color=100 # height of drawing space
t_lengt = (600/leds)*leds #recalculation of width (because I need integer)
vector = (b-a)*1.0/t_lengt
arr_texture = np.zeros(shape=[h_color, t_lengt, 3], dtype=np.uint8) #drawing space defined by x,y and 3d value
for i in range(t_lengt): # loop for all points in x=0 to x=max (that is y=0 to max)
for j in range(h_color):
arr_texture[j][i]=[a[0]+vector[0]*i,a[1]+vector[1]*i,a[2]+vector[2]*i]
cv2.imwrite('color_img.jpg', arr_texture)
cv2.imshow("image", arr_texture);
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
我对这个方法也很困惑,因为绘图 space 上的点是由 X,Y 坐标定义的,但它们带有 [R,G,B] 值。
所以总而言之,我需要将 3 到 更多 点放入创建颜色图表面,其中这些点具有 X、Y 坐标但携带 [R、G、B ] 值。
提前致谢
您知道四个角中每个角的 RGB 值,因此,为了能够创建颜色图,您只需要一个函数,该函数将采用坐标 (x,y)
(其中 x
和 y
在 0
到 1
的范围内)和 return 该坐标处的 RGB 值。
为此,我们需要实现 bilinear interpolation,这是线性插值到二维插值的扩展。
您通过在顶部两个角之间进行插值,然后将其结果与底部两个角之间的插值结果进行插值来执行双线性插值。
a ----|---- b
|
|
c ----|-----d
所以在我们编写 main 函数之前,我们首先需要一个助手来执行插值,因为我们将使用它九次。
这可能是线性的:
def lerp(x, a, b):
return a + x * (b-a)
或者更流畅的东西,比如 smoothstep 函数:
def serp(x, a, b):
return a + (3*x**2 - 2*x**3) * (b-a)
(事实证明,对于这种情况,我们只是去角落(而不是像柏林噪声发生器那样的山丘),线性产生更渐变的梯度!)
该函数将四个 RGB 值作为长度为 3
的四个 lists/numpy 数组(a
、b
、c
、d
) 和坐标 (x
, y
) 到 return 该坐标处的 RGB 值。
def get_color(x, y, a, b, c, d):
r = lerp(y, lerp(x, a[0], b[0]), lerp(x, c[0], d[0]))
g = lerp(y, lerp(x, a[1], b[1]), lerp(x, c[1], d[1]))
b = lerp(y, lerp(x, a[2], b[2]), lerp(x, c[2], d[2]))
return np.array([r, g, b])
或者,我们可以使用 list-comp 使其更加 Pythonic:
def get_color(x, y, a, b, c, d):
return np.array([lerp(y, lerp(x, a[i], b[i]),
lerp(x, c[i], d[i])) for i in range(3)])
现在我们只需要在一个 numpy 数组上对其进行评估,我们可以使用 np.meshgrid
for (see this question 作为替代方法)。
哦,我会用 matplotlib
绘图,因为我没有安装 OpenCV
!
import matplotlib.pyplot as plt
import numpy as np
w = h = 200
verts = [[255,0,0],[0,255,0],[0,0,255],[255,0,0]]
img = np.empty((h,w,3), np.uint8)
for y in range(h):
for x in range(w):
img[y,x] = get_color(x/w, y/h, *verts)
plt.imshow(img)
plt.show()
给出下图:
此技术也用于perlin noise which allowed me to create this terrain generator。
我正在解决一个问题,我只解决了一半。 我正在使用 X、Y 坐标绘制二维绘图 space。我想在绘图上设置 4 个点 space,为每个点设置颜色并生成颜色图。
我能够生成具有 2 个点的颜色图 - 创建矢量并从一个点到另一个点。但是,此方法在几何意义上在点上创建 2D plane/1D 线。但是如果设置4个点,就需要生成面。所以换句话说,我需要在点中拟合曲面。
这是我想象的样子:
这是我的代码,用于生成从一个 X,Y,[RGB] 到另一个 X,Y,[RGB] 的直接变化。
import numpy as np
import colorsys
import cv2
a = np.array([100,0,0]) # Point one with x=0,y=0-max and rgb value
b = np.array([0,255,0]) # point two with x=max,y=0-max and rgb value
#in this case i loop from y=0 to y=max for corresponding point on the other side of drawing space - that is x=max
a = a[::-1]
b= b[::-1]
leds = 31 # just constant
h_color=100 # height of drawing space
t_lengt = (600/leds)*leds #recalculation of width (because I need integer)
vector = (b-a)*1.0/t_lengt
arr_texture = np.zeros(shape=[h_color, t_lengt, 3], dtype=np.uint8) #drawing space defined by x,y and 3d value
for i in range(t_lengt): # loop for all points in x=0 to x=max (that is y=0 to max)
for j in range(h_color):
arr_texture[j][i]=[a[0]+vector[0]*i,a[1]+vector[1]*i,a[2]+vector[2]*i]
cv2.imwrite('color_img.jpg', arr_texture)
cv2.imshow("image", arr_texture);
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
我对这个方法也很困惑,因为绘图 space 上的点是由 X,Y 坐标定义的,但它们带有 [R,G,B] 值。
所以总而言之,我需要将 3 到 更多 点放入创建颜色图表面,其中这些点具有 X、Y 坐标但携带 [R、G、B ] 值。
提前致谢
您知道四个角中每个角的 RGB 值,因此,为了能够创建颜色图,您只需要一个函数,该函数将采用坐标 (x,y)
(其中 x
和 y
在 0
到 1
的范围内)和 return 该坐标处的 RGB 值。
为此,我们需要实现 bilinear interpolation,这是线性插值到二维插值的扩展。
您通过在顶部两个角之间进行插值,然后将其结果与底部两个角之间的插值结果进行插值来执行双线性插值。
a ----|---- b
|
|
c ----|-----d
所以在我们编写 main 函数之前,我们首先需要一个助手来执行插值,因为我们将使用它九次。
这可能是线性的:
def lerp(x, a, b):
return a + x * (b-a)
或者更流畅的东西,比如 smoothstep 函数:
def serp(x, a, b):
return a + (3*x**2 - 2*x**3) * (b-a)
(事实证明,对于这种情况,我们只是去角落(而不是像柏林噪声发生器那样的山丘),线性产生更渐变的梯度!)
该函数将四个 RGB 值作为长度为 3
的四个 lists/numpy 数组(a
、b
、c
、d
) 和坐标 (x
, y
) 到 return 该坐标处的 RGB 值。
def get_color(x, y, a, b, c, d):
r = lerp(y, lerp(x, a[0], b[0]), lerp(x, c[0], d[0]))
g = lerp(y, lerp(x, a[1], b[1]), lerp(x, c[1], d[1]))
b = lerp(y, lerp(x, a[2], b[2]), lerp(x, c[2], d[2]))
return np.array([r, g, b])
或者,我们可以使用 list-comp 使其更加 Pythonic:
def get_color(x, y, a, b, c, d):
return np.array([lerp(y, lerp(x, a[i], b[i]),
lerp(x, c[i], d[i])) for i in range(3)])
现在我们只需要在一个 numpy 数组上对其进行评估,我们可以使用 np.meshgrid
for (see this question 作为替代方法)。
哦,我会用 matplotlib
绘图,因为我没有安装 OpenCV
!
import matplotlib.pyplot as plt
import numpy as np
w = h = 200
verts = [[255,0,0],[0,255,0],[0,0,255],[255,0,0]]
img = np.empty((h,w,3), np.uint8)
for y in range(h):
for x in range(w):
img[y,x] = get_color(x/w, y/h, *verts)
plt.imshow(img)
plt.show()
给出下图:
此技术也用于perlin noise which allowed me to create this terrain generator。