I tried to invert a ScaleVersor3DTransform, but I get this error message:
>>> import SimpleITK as sitk
>>> tx = sitk.ScaleVersor3DTransform()
>>> tx.SetTranslation([1,2,3])
>>> tx.SetScale([0.9, 1.1, 1.2])
>>> tx.GetInverse()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "~/.local/lib/python3.7/site-packages/SimpleITK/SimpleITK.py", line 4628, in GetInverse
return _SimpleITK.Transform_GetInverse(self)
RuntimeError: Exception thrown in SimpleITK Transform_GetInverse: /tmp/SimpleITK-build/ITK-prefix/include/ITK-5.1/itkScaleVersor3DTransform.hxx:202:
itk::ERROR: itk::ERROR: ScaleVersor3DTransform(0x556225fcac90): Setting the matrix of a ScaleVersor3D transform is not supported at this time.
This error does not sound like it can not calculate the inverse but not set the inverted matrix?
Is there a caveat to inverting the ScaleVersor transform or could I simply invert scale, translation and rotation on my own?
It sounds like there is some missing functionality in the ITK class the should be added.
Inverting the scale, translation, and rotation with reguards to the center and the composition is certainly possible, but may be tricky to get the composition and computation correctly.
The easier solution may be to convert the transform to an affine matrix and invert it. There are many examples of this in the SimpleITK Transform Notebook. Specifically the following should work:
Is there a specific reason that you are using the ScaleVersor3DTransform? I suspect it isn’t what you want, it isn’t the standard composition of scaling and a rigid transformation represented as a versor+translation. See section titled Scale Versor in the notebook @blowekamp pointed you to .
If for some reason it is what you want to do, then @blowekamp’s solution above and then calling the GetInverse on the affine transform should allow you to move forward.
Unfortunately, the name ScaleVersor3DTransform is misleading and it is not a composition of anisotropic scaling and rigid, so it isn’t what you were looking for.
The closest transform is Affine, but it also admits shearing. In a multi-step registration, you could use rigid ( Euler3DTransform or VersorRigid3DTransform) followed by anisotropic scaling (ScaleTransform), or other way round as the order for these specific transformations doesn’t matter. This wouldn’t be equivalent to optimizing all of the parameters from the two transformations in one go but is often close enough.
IMHO and experience using this transform, it works well with the registration framework. And this transform does incorporate anisotropic scaling as you need.
However, the “scaling” parameters are an approximation because the following optimization was done to make the parameters independent for optimization.
S*R \approx (S-1)+R where R is the rotation matrix and S is the scaling matrix. As the rotational angle increases the scaling parameter will diverge from a true scaling factor.