Python - Создание цветовой карты со значениями RGB, определенными позициями X, Y - PullRequest
0 голосов
/ 06 июля 2018

Я решаю проблему, которую я решил только наполовину. Я работаю в 2D-пространстве с координатами X, Y. Я хочу установить 4 точки в области рисования, задать цвет для каждой точки и создать цветовую карту.

Мне удалось сгенерировать карту цветов с 2 точками - создать вектор и перейти из одной точки в другую. Однако этот метод создает в геометрическом смысле 2D плоскость / 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()

результат:

Также я очень запутался в методе, потому что точки на пространстве рисования определяются координатами X, Y, но они имеют значения [R, G, B].

Итак, чтобы подвести итог, мне нужно вложить от 3 до больше точек в создание поверхности карты цветов, где точки имеют координаты X, Y, но имеют значения [R, G, B].

Заранее спасибо

1 Ответ

0 голосов
/ 08 июля 2018

Вы знаете значения RGB в каждом из четырех углов, поэтому, чтобы иметь возможность создавать цветовую карту, все, что вам нужно, это функция, которая будет принимать координаты (x,y) (где x и y находятся в диапазон 0 до 1) и возвращает значение RGB по этой координате.

Для этого нам нужно реализовать билинейную интерполяцию , которая является расширением линейной интерполяции до интерполяции в 2d.


Вы выполняете билинейную интерполяцию, интерполируя между двумя верхними углами, а затем интерполируя результат этого с результатом интерполяции между двумя нижними углами.

a ----|---- b
      |
      |
c ----|-----d

Итак, прежде чем писать нашу основную функцию, нам сначала понадобится помощник для выполнения интерполяции, поскольку мы будем использовать ее девять раз.

Это может быть линейно:

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 (a, b, c, d) и координаты (x, y ), чтобы вернуть значение 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])

или мы могли бы сделать его более 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)])

Теперь нам просто нужно оценить это по массиву, для которого мы можем использовать np.meshgrid (см. этот вопрос для альтернативных методов).

О, и я начну с 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()

, который дает следующее изображение:

colormap.jpg


Этот метод также используется в перлин-шуме , что позволило мне создать этот генератор местности .

...