我有一个带有多个顶点的mayavi对象,我想直接为这些顶点设置RGB或RGBA值,而不是将自己限制为带有标量的单个色彩映射。如何实现这一目标?
答案 0 :(得分:4)
据我所知,没有这方面的文档,但我找到了一种方法,只需最少量的黑客攻击即可。这是一个最小的例子,可能需要对不同类型的来源进行一些修补:
from tvtk.api import tvtk; from mayavi import mlab; import numpy as np
x,y,z=np.random.random((3,nr_points)) #some data
colors=np.random.randint(256,size=(100,3)) #some RGB or RGBA colors
pts=mlab.points3d(x,y,z)
sc=tvtk.UnsignedCharArray()
sc.from_array(colors)
pts.mlab_source.dataset.point_data.scalars=sc
pts.mlab_source.dataset.modified()
有时候你必须确保映射器指向正确的东西。对于上面的示例,这不是必需的,但它可能适用于其他来源
pts.actor.mapper.input=pts.mlab_source.dataset
在某些时候,mayavi API应该更好地修复,以便有一个API暴露给所有管道功能只是这样做,但结果是一个相当复杂和彻底的变化,我目前没有有时间完成。
编辑:
用户eqzx
发布了另一个问题(Specify absolute colour for 3D points in MayaVi)的答案,这可能更简单,特别是对于某些难以与tvtk.UnsignedCharArray
合作的来源类型。
他的想法是创建一个跨越256x256x256 RGB值范围的LUT。请注意,此LUT具有16,777,216个条目。如果您想在许多vtk对象中使用它,如果您不小心,可能会浪费相当多的内存。
#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