Hi,
I was trying to convert a euler 3D transform parameter file to a transform matrix to manually compute deformation field, by SimpleITK Euler3DTransform. I also used elastix command line to generate a deformation field. However, my manually computed results were always a little bit different from elastix generated.
I was wondering if you would know the possible reasons?
I thought for Euler transform, it only transforms the coordinates by the transform matrix, and no interpolation or other operations is needed, do I understand correctly?
My code and result:
image_origin = np.array([0, -239, 0])
theta_x = -0.094891
theta_y = 0.006870
theta_z = 0.031377
translation = np.array([-9.053901, -23.358420, -8.338770])
rotation_center = np.array([119.5, -119.5, 77])
rigid_euler = sitk.Euler3DTransform(rotation_center, theta_x, theta_y, theta_z, translation)
A1 = np.asarray(rigid_euler.GetMatrix()).reshape(3,3)
c1 = np.asarray(rigid_euler.GetCenter())
t1 = np.asarray(rigid_euler.GetTranslation())
p = np.array([100, 200, 200])
truec = rotation_center - image_origin
p_transform = np.dot(A1, p - truec) + t1 + truec
p_displacement = p_transform - p
result:
p_displacement = array([-11.0793279 , -12.68448335, -16.38891453])
p_displacement_byelastix = DVF[100, 200, 200] = array([-11.518286, -19.103964, -16.620592], dtype=float32)
their difference is: array([-0.43895785, -6.4194805 , -0.23167759])
The transform file:
(Transform "EulerTransform")
(NumberOfParameters 6)
(TransformParameters -0.094891 0.006870 0.031377 -9.053901 -23.358420 -8.338770)
(InitialTransformParametersFileName "NoInitialTransform")
(UseBinaryFormatForTransformationParameters "false")
(HowToCombineTransforms "Compose")
// Image specific
(FixedImageDimension 3)
(MovingImageDimension 3)
(FixedInternalImagePixelType "float")
(MovingInternalImagePixelType "float")
(Size 240 240 155)
(Index 0 0 0)
(Spacing 1.0000000000 1.0000000000 1.0000000000)
(Origin 0.0000000000 -239.0000000000 0.0000000000)
(Direction 1.0000000000 0.0000000000 0.0000000000 0.0000000000 1.0000000000 0.0000000000 0.0000000000 0.0000000000 1.0000000000)
(UseDirectionCosines "true")
// EulerTransform specific
(CenterOfRotationPoint 119.5000000000 -119.5000000000 77.0000000000)
(ComputeZYX "false")
// ResampleInterpolator specific
(ResampleInterpolator "FinalBSplineInterpolator")
(FinalBSplineInterpolationOrder 3)
// Resampler specific
(Resampler "DefaultResampler")
(DefaultPixelValue 0.000000)
(ResultImageFormat "nii.gz")
(ResultImagePixelType "short")
(CompressResultImage "false")
I will appreciate any of your ideas!
Thank you so much!
Hi Xiaoxiao,
On first glance your code looks right. The only thing I can still see if the ComputeZYX flag is set the same as in elastix, which specifies the order of the rotations. Other than that I think it is a case of debugging!
Best regards,
Marius Staring
Knowing that the convention is Euler angles with YXZ, explain how the resulting matrix is computed from the parameters.
Dear Xiaoxiao,
I have no further hints for you except to do a step by step debugging of your python code.
Good luck bug hunting!
Best, Marius
Dear Xiaoxiao,
Here you can find exactly what elastix does: