I was wondering if we can convert a
CompositeTransformType to a
Here is my sample of code:
using TransformType = itk::Euler3DTransform< double >; TransformType::Pointer first_transformation = TransformType::New(); TransformType::Pointer second_transformation = TransformType::New(); CompositeTransformType::Pointer composite_transformation = CompositeTransformType::New(); composite_transformation->AddTransform( first_transformation ); composite_transformation->AddTransform( second_transformation ); TransformType::Pointer total_transformation = TransformType::New();
and I want to compute the following procedure:
total_transformation = composite_transformation;
total_transformation->SetTransform( composite_transformation )
Is there any mean to convert a
CompositeTransformType to a
Thank you for your patience…
By looking at the documentation of CompositeTransform, it cannot “flatten” the transform queue. You will have to compose the transforms yourself, by multiplying matrices or something similar. Perhaps VersorRigid3DTransform is more convenient for that?
Perhaps @hjmjohnson, @blowekamp or @zivy can provide more useful advice?
As @dzenanz pointed out, unfortunately there is no straightforward way to “flatten” a composite transform into a single basic transformation (rigid/affine/…/BSpline/DisplacementField).
This is primarily because the CompositeTransform can contain any of these transformation types some of which have a global domain (rigid/affine…) and some a local domain (BSpline/DisplacementField).
If you have a combination of transformations with global and local domains there is no way to flatten them into a single basic transformation type.
If all of your transformations have a global domain then you could convert them all into affine transformations and combine those, retaining the global nature. This will require you to access the internal data (matrix, center, translation) and manually do the computations.
If all of your transformations have a local domain, you could (a) identify the union of all those domains. (b) create a DisplacementFieldTransform with that domain from the CompositeTransformation (see TransformToDisplacementFieldFilter).
@pierrectl is trying to compose two
Euler3DTransforms, if I understood correctly. Those are two transforms with global domain. Computing internal data (matrix, center, translation) is probably easier with versor than affine.
Affine is the most general case and it’s straightforward, illustrated in the section titled CompositeTransform in this SimpleITK Jupyter notebook, flattening a rigid and affine transformations into a single affine. Different syntax from ITK C++, but similar semantics.
We implemented flattening of composite transforms and computing displacement field from an arbitrary complex transform hierarchy in 3D Slicer and everything works very nicely.
By “flattening” of composite transforms we mean creating a list of transforms from an arbitrary composite transform hierarchy (a composite transform can contain other composite transforms) and it is fairly simple, see implementation here.
Computing a displacement field is straightforward, too, we just require the user to specify an image grid (origin, spacing, and axis directions) and we fill it with displacement that is computed by applying all the transforms in the composite transform. See implementation here. All we needed for this is to define the transformation everywhere not just inside the domain (with a smooth transition at the domain boundary to ensure that the transform remains invertible, if possible).
Thanks to all of you.
@zivy I work with global transformations: I did the way you tell me, by accessing center and translation vectors and rotation matrix of each transformation and compute the composite one “by hand”.