【问题标题】:Specify absolute colour for 3D points in MayaVi在 MayaVi 中指定 3D 点的绝对颜色
【发布时间】:2013-09-03 10:26:25
【问题描述】:

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

另外,你可以传递第四个数组s,其形状与x、y、 z 为每个点给出一个相关的标量值,或者一个函数 f(x, y, z) 返回标量值。这个标量值可以使用 调制点的颜色和大小。

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

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,但抛出错误。

【问题讨论】:

    标签: python point-clouds mayavi color-mapping


    【解决方案1】:

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

    【讨论】:

    • 有没有办法生成任意 0-255 RGB 值,而无需指定具有 256x256x256 值的唯一颜色图?换句话说,在您的解决方案中,是否有一种方法可以表征逆 Spectral() 函数,其中 Spectral() 是域 [0,1] 且范围为 0-255,0-255,0-255 的函数?这种行为一直让我感到厌烦,我看到一些应用程序绕过它(例如 vtk 程序 trackvis,其所有者拒绝向我发布源代码,以便我了解他是如何做到的)。
    • 您可以探索 mayavi.core.lut_manager,尤其是 mayavi.core.lut_manager 中的 pylab_luts,以了解它们是如何构建的(并可能构建您自己的并分配您想要的任何行为)跨度>
    • 我玩过这些。使用自定义 luts 来指定所需的配色方案远不如为指定标量的每个顶点指定唯一的 RGB 值那样通用。从计算上讲,这不是真的,因为可以指定一个具有 256x256x256 值的 LUT,它唯一地定义了 RGB 色谱。但实际上这样做会非常痛苦。我认为这个问题的正确答案是“对不起,没有正确的方法可以做到这一点。”
    • 这让我有点想哭。有没有其他包可以做到这一点?
    • 我同意 Andreas 的观点,在我意识到 API 没有任何明确/默认的自定义颜色方式后,我也采取了胎儿的立场并开始哭泣。这是我的解决方案:stackoverflow.com/questions/24471210/…
    【解决方案2】:

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

    您可以非常轻松地创建自己的直接 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
    

    【讨论】:

    • 感谢您提供这个伟大而笼统的回答!
    【解决方案3】:

    在今天大部分时间都在为此苦苦挣扎之后,我找到了一种相对简单的方法来完全按照问题的要求进行操作——为每个点指定一个 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()
    

    【讨论】:

    • 对于任何想要在 quiver 以外的其他类型的地块上执行此操作的人;倒数第二行是重要的;即您也可以使用surf.module_manager.scalar_lut_manager.lut.table = colors
    【解决方案4】:

    现在可以通过 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 2022-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多