How to draw a color image in mayavi (imshow)

2020-07-24 06:20发布

问题:

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