Is it possible to directly apply an affine transformation matrix to a Mayavi ImageActor object?

PythonTransformationMayavi

Python Problem Overview


I'm using Mayavi to render some imaging data that consists of multiple 2D planes within a 3D volume, the position, orientation, and scale of which are defined by 4x4 rigid body affine transformation matrices. Each plane consists of:

  • An array of 2D image data, which I display using mayavi.mlab.imshow
  • A set of ROIs consisting of lines and points that I draw using mayavi.mlab.points3d and mayavi.mlab.plot3d respectively.

I transform my points and line vertices from a 2D reference plane into the 3D space by dotting their coordinates with my affine matrix. Based on my previous question/answer here, I figured out that I could set the positions and orientations of the ImageActor objects individually, using:

obj = mlab.imshow(img)
obj.actor.orientation = [pitch, roll, yaw] # the required orientation (deg)
obj.actor.position = [dx, dy, dz] # the required position 
obj.actor.scale = [sx, sy, sz] # the required scale

Now the plot looks like this:

enter image description here

Everything lines up nicely, but it's very difficult to interpret because the planes are so densely spaced in z. What I'd now like to be able to do is 'stretch out' the z-axis by some scaling factor. In the case of the points and lines, this is very easy to do - all I do is multiply all of the transformed z-coordinates by a scaling factor.

However, I can't figure out how to apply the same transformation to the images. If I just scale the z-position, the rotation and scaling of the images will of course be wrong, and my plotted points/lines will no longer fall on the same plane as the image:

enter image description here

What I need to do is apply a non-rigid affine transformation that incorporates shear as well as rotation, translation, and scaling to my images.

Is there any way I can manually apply shear to an ImageActor, or even better just directly apply an arbitrary 4x4 affine matrix that I've precomputed?

Python Solutions


Solution 1 - Python

ImageActor, which ultimately is a wrapper for tvtk.ImageActor, has a user_matrix property, which lets you assign a 4D transformation matrix.

Starting with a random image,

    import numpy as np
    from mayavi.mlab import imshow
    s = np.random.random((10, 10))
    image = imshow(s, colormap='gist_earth', interpolate=False)

gives us the following ...

Random image

Creating a transformation matrix and setting a term to give it some shear ...

    from tvtk.api import tvtk
    transform_matrix = tvtk.Matrix4x4()
    transform_matrix.set_element(0, 1, 2.5)
    image.actor.user_matrix = transform_matrix

gives us ...

Random image with shear

set_element has the signature (row, col, value), so you should be able to set elements on that matrix as needed.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionali_mView Question on Stackoverflow
Solution 1 - PythonWillie ConradView Answer on Stackoverflow