15

我正在使用MayaVi Python 库来绘制 3d 点,使用points3d该类。文档指定每个点的颜色是通过第四个参数指定的s

此外,您可以传递与 x、y 和 z 形状相同的第四个数组 s,为每个点提供相关的标量值,或者传递一个函数 f(x,y,z) 返回标量值。此标量值可用于调制点的颜色和大小。

copper这为每个点指定了一个标量值,该值将点映射到颜色图,例如jethsv。例如从他们的文档中:

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元组数组替换 ,但抛出错误。

4

4 回答 4

17

在今天大部分时间都在努力解决这个问题之后,我找到了一种相对简单的方法来完全按照问题的要求进行操作——为每个点指定一个 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()
于 2015-05-15T18:16:36.473 回答
9

我找到了一种直接设置颜色的更好方法。

您可以非常轻松地创建自己的直接 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. <This is where you are storing your custom colors in RGB>
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, 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
于 2015-02-23T19:32:05.087 回答
6

您可以使用 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 值相对应的任何标量。

于 2013-09-03T14:49:04.710 回答
3

现在可以简单地使用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()

在此处输入图像描述

于 2017-07-26T11:56:15.817 回答