Is it possible to draw a image with 3 color channels using mayavi? According to the documentation for mayavi, mayavi.mlab.imshow
can only handle images of shape (n x m).
问题:
回答1:
Method
I had to make use of mayavi's custom colormaps, see http://docs.enthought.com/mayavi/mayavi/auto/example_custom_colormap.html .
I made a colormap that consists of all the pixles in the original (n x m x 3) image as rows. I also included an alpha channel so that transparent png's can be displayed correctly. Next I used a grayscale image as a lookup table, with pixle values as indices to the original pixles stored in the colormap. I created an imshow object with the lookup table as the input image and replaced the imshow object's colormap with my custom colormap.
Code
Here is some working code with a test case for those interested. Pylab can be replaced by Numpy (Pylab wraps Numpy) everywhere except in the testcase at pl.imread(...). Tested on Python2.7 with Mayavi 4.3.0 on Windows 7. (Unfortunately I had to first fix the following mayavi bug on Windows https://github.com/enthought/mayavi/pull/96/files).
import pylab as pl
from mayavi import mlab
def mlab_imshowColor(im, alpha=255, **kwargs):
"""
Plot a color image with mayavi.mlab.imshow.
im is a ndarray with dim (n, m, 3) and scale (0->255]
alpha is a single number or a ndarray with dim (n*m) and scale (0->255]
**kwargs is passed onto mayavi.mlab.imshow(..., **kwargs)
"""
try:
alpha[0]
except:
alpha = pl.ones(im.shape[0] * im.shape[1]) * alpha
if len(alpha.shape) != 1:
alpha = alpha.flatten()
# The lut is a Nx4 array, with the columns representing RGBA
# (red, green, blue, alpha) coded with integers going from 0 to 255,
# we create it by stacking all the pixles (r,g,b,alpha) as rows.
myLut = pl.c_[im.reshape(-1, 3), alpha]
myLutLookupArray = pl.arange(im.shape[0] * im.shape[1]).reshape(im.shape[0], im.shape[1])
#We can display an color image by using mlab.imshow, a lut color list and a lut lookup table.
theImshow = mlab.imshow(myLutLookupArray, colormap='binary', **kwargs) #temporary colormap
theImshow.module_manager.scalar_lut_manager.lut.table = myLut
mlab.draw()
return theImshow
def test_mlab_imshowColor():
"""
Test if mlab_imshowColor displays correctly by plotting the wikipedia png example image
"""
#load a png with a scale 0->1 and four color channels (an extra alpha channel for transparency).
from urllib import urlopen
url = 'http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png'
im = pl.imread(urlopen(url), format='png')
im *= 255
mlab_imshowColor(im[:, :, :3], im[:, :, -1])
mlab.points3d([-200, 300, -200, 300],
[-200, 300, 200, -300],
[300, 300, 300, 300])
mlab.show()
if __name__ == "__main__":
test_mlab_imshowColor()
Results
回答2:
Table was removed in 4.4.3
load_lut_from_file
does not seem to work as expected with imshow
though. Setting the color directly in the actor is the only method that worked for me.
import pylab as pl
import numpy as np
from mayavi import mlab
from urllib import urlopen
from tvtk.api import tvtk
def test_mlab_imshowColor():
"""
Test if mlab_imshowColor displays correctly by plotting the wikipedia png example image
"""
#load a png with a scale 0->1 and four color channels (an extra alpha channel for transparency).
url = 'http://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png'
im = pl.imread(urlopen(url), format='png') * 255
colors = tvtk.UnsignedCharArray()
colors.from_array(im.transpose((1,0,2)).reshape(-1, 4))
m_image = mlab.imshow(np.ones(im.shape[:2]))
m_image.actor.input.point_data.scalars = colors
mlab.points3d([-200, 300, -200, 300],
[-200, 300, 200, -300],
[300, 300, 300, 300])
mlab.draw()
mlab.show()
if __name__ == "__main__":
test_mlab_imshowColor()