I\'m trying to make a 3D plot that consists of a series of 2D planes through an RGB stack, like this:
Big thanks to aestrivex for providing working solutions using Mayavi/VTK - it's useful info that I may need for doing more complicated things in the future.
In the end I actually chose to go with cgohlke's suggestion of using visvis, which turned out to be a lot simpler to implement:
import visvis as vv
vv.use('wx')
import numpy as np
from matplotlib.image import imread
from matplotlib.cbook import get_sample_data
imgdata = imread(get_sample_data('lena.png'))
nr, nc = imgdata.shape[:2]
x,y = np.mgrid[:nr, :nc]
z = np.ones((nr, nc))
for ii in xrange(5):
vv.functions.surf(x, y, z*ii*100, imgdata, aa=3)
I don't know about other libraries -- volshow looks neat but I havent tested it -- but you can do this in vtk.
I have been working on doing this generally in mayavi (see How to directly set RGB/RGBA colors in mayavi) but for certain image sources mayavi structures the vtk pipeline in a way that was not designed to deal with this at all. My efforts to convert a 2D vtk.ImageData to true color starting with mlab.imshow were met with resistance at every step, but I managed it.
First, here is how I have managed to do it in mayavi using mlab. This is far too hacky and "magic"-reliant even for my standards:
from mayavi import mlab
import numpy as np
from tvtk.api import tvtk
k=mlab.imshow(np.random.random((10,10)),colormap='bone')
colors=tvtk.UnsignedCharArray()
colors.from_array(np.random.randint(256,size=(100,3)))
k.mlab_source.dataset.point_data.scalars=colors
k.actor.input.point_data.scalars=colors
#the latter set of scalars is what is actually used in the VTK pipeline in this
#case, but if they don't play nice with the mayavi source then tvtk will
#complain because we are circumventing the structure it expects
k.actor.input.scalar_type='unsigned_char'
k.actor.input.number_of_scalar_components=3
k.image_map_to_color.lookup_table=None
k.actor.input.modified()
mlab.draw()
#this draw fails. As it fails, there is an interaction here, somewhere deep in
#tvtk, causing the ImageData to partially reset.. I have not been able to track
#it down yet. ignore the error output
k.actor.input.scalar_type='unsigned_char'
k.actor.input.number_of_scalar_components=3
#now after we reset these back to what they should be, it works
mlab.draw()
mlab.show()
But in pure tvtk it's not nearly so bad:
import numpy as np
from tvtk.api import tvtk
colors=np.random.randint(256,size=(100,3))
an_image=tvtk.ImageData()
an_image.number_of_scalar_components=3
an_image.scalar_type='unsigned_char'
an_image.point_data.scalars=tvtk.UnsignedCharArray()
an_image.point_data.scalars.from_array(colors)
an_image.dimensions=np.array((10,10,1))
an_actor=tvtk.ImageActor()
an_actor.input=an_image
an_actor.interpolate=False
ren=tvtk.Renderer()
renWin=tvtk.RenderWindow()
renWin.add_renderer(ren)
ren.add_actor2d(an_actor)
iren=tvtk.RenderWindowInteractor()
iren.render_window=renWin
iren.interactor_style=tvtk.InteractorStyleTrackballCamera()
renWin.render()
iren.start()
Of course, doing it in vtk is more work. You might even be able to wrap this nicely so that it's pretty reasonable.
I want to fix mayavi to handle this properly, but as you can see from my snippet it is not straightforward and could take a while.