2013-08-30 107 views
11

我使用MayaVi Python庫來繪製3d點,使用points3d類。 The documentation指定每個點的顏色通過第四參數指定,s指定MayaVi中3D點的絕對顏色

此外,可以通過相同形狀的x,y, 和z給相關聯的標量值的第四數組S對於每個點,或函數f(x,y,z)返回標量值。此標量值可用於調整點的顏色和大小。

這指定的每個點,該點映射到colourmap標量值,如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) 

給出:

enter image description here

相反,我想爲每一個點作爲(R,G,B)的元組指定實際值。這在MayaVi中可能嗎?我試過用元組數組替換s,但是拋出了一個錯誤。

回答

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() 

enter image description here

3

您可以使用任何您想要的邏輯,使用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

有沒有辦法做到這一點,產生一個任意0-255 RGB值,而不指定用255x255x255種值的獨特色彩表? 換句話說,在解決方案中,有一個方法來表徵逆譜()函數,其中頻譜()是與域[0,1]和範圍的函數0-255,0-255,0- 255? 這種行爲一直激怒了我,我已經看到了一些應用程序在其周圍獲得(例如VTK程序trackvis,其所有者下降到源釋放給我,讓我可以看到他是如何做)。 – aestrivex

+0

您可以探索mayavi.core.lut_manager,尤其是mayavi.core.lut_manager中的pylab_luts,以瞭解它們是如何構建的(並且大概構建您自己的並將其與您期望的任何行爲一起分配) – Chrismit

+0

我玩過這些遊戲。使用自定義的luts來指定所需的顏色方案,與爲指定標量的每個頂點指定唯一的RGB值相比,其解決方案要少得多。 從計算的角度來看,這是不正確的,因爲可以指定一個具有唯一定義RGB色譜的256x256x256值的LUT。但實際上做到這一點非常痛苦。 我認爲這個問題的正確答案是「對不起,沒有正確的方法來做到這一點。」 – aestrivex

3

我發現了一個更好的方法來直接設置顏色。

你可以很容易地創建自己的直接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 
7

這種掙扎最後的今天,我發現了一個比較簡單的方法做的正是這個問題問什麼 - 指定每個點的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() 
+0

this運作良好,是最簡單的答案。 – chris

+0

對於任何人想在其他類型的地塊上做這個比顫動;它是最重要的第二行;即你也可以做'surf.module_manager.scalar_lut_manager.lut.table = colors'。 – RolKau