Understanding sitk.Euler3DTransform convention

Hi,

I’m using sitk.Euler3DTransform to rotate my 3D image, but I am confused regarding which euler convention is used.

I found that sitk.Euler3DTransform uses the ZXY or ZYX convention. However, is this using extrinsic or intrinsic rotations?

According to wikipedia this:
R=X(\alpha )Y(\beta )Z(\gamma )
is a rotation matrix that may be used to represent a composition of extrinsic rotations about axes z, y, x, (in that order), or a composition of intrinsic rotations about axes x-y′-z″ (in that order).

So if sitk.Euler3DTransform uses extrinsic rotation convention, the ZYX convention would mean that it would rotate along the x (first), y (second) and z (third) axes intrinsically, right?

And secondly, if I would want to change the convention to ZYX from ZXY in my python script, what do I need to do? The code below doesn’t work.

euler_transform = sitk.Euler3DTransform ()
euler_transform.SetComputeZYX()

Thank you!

Hello @MMdeB,

SimpleITK/ITK support two ways for specifying a rotation matrix using Euler angles, ZXY order which is the default and ZYX. There are 12 possible Euler angle combinations but only these two are supported. As always, documentation and implementation may differ so we check that the code does what it claims (SimpleITK returns the matrix in row order):

import SimpleITK as sitk
import numpy as np

# angles are always in radians, but easier to specify in degrees
theta_x = np.deg2rad(20)
theta_y = np.deg2rad(30)
theta_z = np.deg2rad(40)

sitk_R = sitk.Euler3DTransform()
sitk_R.SetRotation(theta_x, theta_y, theta_z)

Rx = np.array([[1, 0, 0],
               [0, np.cos(theta_x), -np.sin(theta_x)],
               [0, np.sin(theta_x), np.cos(theta_x)]])

Ry = np.array([[np.cos(theta_y), 0, np.sin(theta_y)],
               [0, 1, 0],
               [-np.sin(theta_y), 0, np.cos(theta_y)]])

Rz = np.array([[np.cos(theta_z), -np.sin(theta_z), 0],
               [np.sin(theta_z), np.cos(theta_z), 0],
               [0, 0, 1]])

print('ZXY:')
print(Rz.dot(Rx).dot(Ry))
print(sitk_R.GetMatrix())

print('ZYX:')
sitk_R.SetComputeZYX(True)
print(Rz.dot(Ry).dot(Rx))
print(sitk_R.GetMatrix())
2 Likes