Get Affine Transformation Matrix from TransformParameters
See original GitHub issueI’m using ITK to perform a affine coregistration on 3D MRI scans. Now similar to what is suggested in https://github.com/InsightSoftwareConsortium/ITKElastix/blob/master/examples/ITK_Example08_SimpleTransformix.ipynb I would like to perform the affine transformation on another image but we are using another library for that.
So I would need a full affine matrix for the transformation that describes the affine coregistration.
I noticed that the registration returns the transform parameters:
result_image, result_transform_parameters = itk.elastix_registration_method( ...
parameter_map = transform_parameters.GetParameterMap(0)
transform_parameters = np.array(parameter_map['TransformParameters'], dtype=float)
From other GitHub issues I gathered that the last 3 values of the 12 values in transform_parameters
is for the translation and the first 9 are for the rotation. Not sure if that is correct.
Based on this I started playing around and got close to the correct affine transformation matrix (the resulting images are similar but not quite right).
rotation = transform_parameters[:9].reshape(3, 3)
translation = transform_parameters[-3:][..., np.newaxis]
translation = -np.flip(translation)
reg_affine: np.ndarray = np.append(rotation, translation, axis=1)
reg_affine = np.append(reg_affine, [[0,0 ,0,1]], axis=0)
The translation might be right but the rotation is slightly off. What am I missing / what is wrong? Also why do I need to flip and negate the translation? Do I need to do something similar with the rotation matrix?
Would really appreciate some insight. The ITK methods are a blackbox to me.
Not sure what example data I can share. Here some example values for the above variables:
transform_parameters = [ 9.98573286e-01, -3.92533565e-03, -7.45617495e-03, 6.11828178e-04,
9.98081930e-01, 7.21948277e-03, 2.74329272e-03, -1.22292851e-02,
1.00763651e+00, -1.52612188e-01, 8.89476641e-01, 2.55258072e+00]
with the resulting affine matrix:
reg_affine = [[ 1.00763651e+00, -1.22292851e-02, 2.74329272e-03, -2.55258072e+00],
[ 7.21948277e-03, 9.98081930e-01, 6.11828178e-04, -8.89476641e-01],
[-7.45617495e-03, -3.92533565e-03, 9.98573286e-01, 1.52612188e-01],
[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]
Issue Analytics
- State:
- Created 2 years ago
- Comments:28 (12 by maintainers)
Hi @Spenhouet, I undestand that it has been long since you raised this issue and maybe your project has moved forward by now. However, I just created a PR here https://github.com/InsightSoftwareConsortium/itk-torch-transform-bridge/pull/6 that seems to do what you were aiming to do. In particular, the
test_regisration()
function inside thetest_cases.py
file is tested (locally at my pc) using the data that you shared here (fixed_2mm.nii.gz
,moving_2mm.nii.gz
) and does a registration with Elastix and then transforms affinely using MONAI. Hopefully, this is helpful to you.Some notes:
real_fixed.nii.gz
,real_moving.nii.gz
using ITK for some reason, and that’s why I used the original images that you shared.Let me know if you have any comments, or if you happen to test the code and it works for you. Any feedback will help improve the PR as well.
@mstaring @dzenanz A classic happened: For the example sample our code works now, and the solution also makes sense but we did now run into a sample where it does not work. I’m expecting that you were both right that we do in fact need to also factor in the center of rotation. But we struggle again to get how. We already considered the formula you shared and also did more research. I did again post the full question here: https://stackoverflow.com/questions/71529039/how-factor-the-itk-centerofrotationpoint-in-a-affine-transformation-matrix
Maybe you could have a look if you see an obvious mistake or answer.