Ответ 1
Теперь это можно просто сделать с помощью аргумента color
from mayavi import mlab
import numpy as np
c = np.random.rand(200, 3)
r = np.random.rand(200) / 10.
mlab.points3d(c[:, 0], c[:, 1], c[:, 2], r, color=(0.2, 0.4, 0.5))
mlab.show()
Я использую MayaVi библиотеку Python для построения трехмерных точек с использованием класса points3d
. В документации указано, что цвет каждой точки задается с помощью четвертого аргумента, s
:
Кроме того, вы можете передать четвертый массив s той же формы, что и x, y, и z задает связанное скалярное значение для каждой точки или функцию f (x, y, z) возвращает скалярное значение. Это скалярное значение может быть использовано для модуляции цвета и размера точек.
Указывает скалярное значение для каждой точки, которое отображает точку в цветовую карту, например copper
, jet
или hsv
. Например. из их документации:
import numpy
from mayavi.mlab import *
def test_points3d():
t = numpy.linspace(0, 4*numpy.pi, 20)
cos = numpy.cos
sin = numpy.sin
x = sin(2*t)
y = cos(t)
z = cos(2*t)
s = 2+sin(t)
return points3d(x, y, z, s, colormap="copper", scale_factor=.25)
дает:
Вместо этого я хотел бы указать фактическое значение для каждой точки как (r, g, b) кортеж. Возможно ли это в MayaVi? Я попытался заменить s
на массив кортежей, но выдается ошибка.
Теперь это можно просто сделать с помощью аргумента color
from mayavi import mlab
import numpy as np
c = np.random.rand(200, 3)
r = np.random.rand(200) / 10.
mlab.points3d(c[:, 0], c[:, 1], c[:, 2], r, color=(0.2, 0.4, 0.5))
mlab.show()
После борьбы с этим в течение большей части сегодняшнего дня я нашел относительно простой способ сделать именно то, что задает вопрос - укажите кортеж RGB для каждой точки. Трюк состоит только в том, чтобы определить цветовую карту с точно таким же количеством записей, что и точки для построения графика, а затем установить аргумент как список индексов:
# Imports
import numpy as np
from mayavi.mlab import quiver3d, draw
# Primitives
N = 200 # Number of points
ones = np.ones(N)
scalars = np.arange(N) # Key point: set an integer for each point
# Define color table (including alpha), which must be uint8 and [0,255]
colors = (np.random.random((N, 4))*255).astype(np.uint8)
colors[:,-1] = 255 # No transparency
# Define coordinates and points
x, y, z = colors[:,0], colors[:,1], colors[:,2] # Assign x, y, z values to match color
pts = quiver3d(x, y, z, ones, ones, ones, scalars=scalars, mode='sphere') # Create points
pts.glyph.color_mode = 'color_by_scalar' # Color by scalar
# Set look-up table and redraw
pts.module_manager.scalar_lut_manager.lut.table = colors
draw()
Вы можете использовать таблицу поиска rgb и сопоставлять свои значения rgb с ней, используя любую логику, которую вы хотите. Вот простой пример:
import numpy, random
from mayavi.mlab import *
def cMap(x,y,z):
#whatever logic you want for colors
return [random.random() for i in x]
def test_points3d():
t = numpy.linspace(0, 4*numpy.pi, 20)
cos = numpy.cos
sin = numpy.sin
x = sin(2*t)
y = cos(t)
z = cos(2*t)
s = cMap(x,y,z)
return points3d(x, y, z, s, colormap="spectral", scale_factor=0.25)
test_points3d()
Я понятия не имею, какую цветовую схему вы хотите, но вы можете оценить позиции x, y, z и вернуть любой скаляр, соответствующий требуемому значению rgb.
Я нашел лучший способ напрямую установить цвета.
Вы можете легко создать свой собственный прямой LUT. Пусть говорят, что мы хотим 256 ** 3 гранулярности:
#create direct grid as 256**3 x 4 array
def create_8bit_rgb_lut():
xl = numpy.mgrid[0:256, 0:256, 0:256]
lut = numpy.vstack((xl[0].reshape(1, 256**3),
xl[1].reshape(1, 256**3),
xl[2].reshape(1, 256**3),
255 * numpy.ones((1, 256**3)))).T
return lut.astype('int32')
# indexing function to above grid
def rgb_2_scalar_idx(r, g, b):
return 256**2 *r + 256 * g + b
#N x 3 colors
colors = numpy.array([_.color for _ in points])
#N scalars
scalars = numpy.zeros((colors.shape[0],))
for (kp_idx, kp_c) in enumerate(colors):
scalars[kp_idx] = rgb_2_scalar_idx(kp_c[0], kp_c[1], kp_c[2])
rgb_lut = create_8bit_rgb_lut()
points_mlab = mayavi.mlab.points3d(x, y, z
keypoint_scalars,
mode = 'point')
#magic to modify lookup table
points_mlab.module_manager.scalar_lut_manager.lut._vtk_obj.SetTableRange(0, rgb_lut.shape[0])
points_mlab.module_manager.scalar_lut_manager.lut.number_of_colors = rgb_lut.shape[0]
points_mlab.module_manager.scalar_lut_manager.lut.table = rgb_lut