InsightSoftwareConsortium / ITKElastix

An ITK Python interface to elastix, a toolbox for rigid and nonrigid registration of images
Apache License 2.0
201 stars 22 forks source link

[Elastix Parameters --> ITK Transforms] Provide function to convert Elastix's TransformParameter.txt to ITK transforms #79

Open prerakmody opened 3 years ago

prerakmody commented 3 years ago

Context

Is there a roadmap to include these kind of Elastix -> ITK Transform helper functions in ITKElastix?

mstaring commented 3 years ago

In the CZI project there are plans to write the elastix TransformParameters also as itk::Transform classes with the help of the itk::TransformFileWriter class, into an hdf5 format. Perhaps the tfm format can be considered also.

dzenanz commented 3 years ago

Writing an ITK transform into .tfm file should be no different from writing into .h5.

mstaring commented 3 years ago

I already hoped that it would work the same as with images

thewtex commented 3 years ago

Note that with itk-5.2rc3, we can read and write itk.Transform's with itk.transformread and itk.transformwrite. These functions work with a Python list (an ordered sequence of transforms), supporting both tfm and h5 files.

thewtex commented 3 years ago

Discussed more in https://github.com/InsightSoftwareConsortium/ITKElastix/issues/110#issuecomment-794333942

dzenanz commented 3 years ago

Has there been some progress on this front? I now need ITK<->Elastix transform equivalence, see simplified code below:

# use manually placed landmarks to initialize the registration
case_landmarks = read_slicer_fiducials('case.fcsv')
case_transform = register_landmarks(case_landmarks, atlas_landmarks)
print(composite_transform)
case_image = itk.imread('case.nrrd')

# Construct elastix parameter map
parameter_object = itk.ParameterObject.New()
resolutions = 4
parameter_map_rigid = parameter_object.GetDefaultParameterMap('rigid', resolutions)
parameter_object.AddParameterMap(parameter_map_rigid)
parameter_map_bspline = parameter_object.GetDefaultParameterMap("bspline", resolutions, 1.0)
parameter_object.AddParameterMap(parameter_map_bspline)
parameter_object.SetParameter("DefaultPixelValue", "-1024")  # we are dealing with CTs

# how do I add case_transform as the initial rigid transform? Inverse operations in @prerakmody's script?

registered, elastix_transform = itk.elastix_registration_method(case_image, atlas_image,
                                                                parameter_object=parameter_object)

final_composite_rigid_and_bspline_transform = ...  # is there anything newer/better than @prerakmody's script?
itk.tranformwrite(final_composite_rigid_and_bspline_transform, 'case-reg.tfm')  # save it to disk in ITK format

# now use the tranform to transfer atlast labels to the case under observation
nearest_interpolator = itk.NearestNeighborInterpolateImageFunction.New(atlas_label)
atlas_labels_transformed = itk.resample_image_filter(atlas_label,
                                                     use_reference_image=True,
                                                     reference_image=case_image,
                                                     transform=final_composite_rigid_and_bspline_transform,
                                                     interpolator=nearest_interpolator)
itk.imwrite(atlas_labels_transformed, 'case-label.nrrd', compression=True)

# continue processing
roi = # construct from atlas_labels_transformed by choosing only some labels
morphometry_filter = itk.BoneMorphometryFeaturesFilter.New(case_image)
morphometry_filter.SetMaskImage(roi)
morphometry_filter.Update()

With this output:

VersorRigid3DTransform (0000029684D682A0)
  RTTI typeinfo:   class itk::VersorRigid3DTransform<double>
  Reference Count: 1
  Modified Time: 18
  Debug: Off
  Object Name: 
  Observers: 
    none
  Matrix: 
    -0.868953 -0.49029 -0.0673497 
    0.472869 -0.782407 -0.405259 
    0.146 -0.383999 0.911718 
  Offset: [24.3469, 32.3288, 1.86287]
  Center: [0, 0, 0]
  Translation: [24.3469, 32.3288, 1.86287]
  Inverse: 
    -0.868953 0.472869 0.146 
    -0.49029 -0.782407 -0.383999 
    -0.0673497 -0.405259 0.911718 
  Singular: 0
  Versor: [ 0.0208332, -0.209063, 0.943806, 0.255126 ]
thewtex commented 3 years ago

Reference: https://github.com/SuperElastix/elastix/tree/develop/Testing/Data/Translation(1%2C-2)

N-Dekker commented 3 years ago

@thewtex

Reference: https://github.com/SuperElastix/elastix/tree/develop/Testing/Data/Translation(1%2C-2)

Explanation: The current "develop" branch of elastix supports elastix transform parameter files that link to an ITK generated HDF5 or TFM file. For example, this is a supported elastix transform parameters file: https://github.com/SuperElastix/elastix/blob/develop/Testing/Data/Translation(1%2C-2)/TransformParameters-link-to-ITK-tfm-file.txt In this case, it links to the following ITK transform file: https://github.com/SuperElastix/elastix/blob/develop/Testing/Data/Translation(1%2C-2)/ITK-Transform.tfm

(Such an elastix transform parameters file may be used as input for both Elastix (as initial transform parameter file) and Transformix.)

At the moment, four ITK transform types are actively tested as input to elastix: Translation, Affine, Euler, and Similarity. I'm still busy preparing to add tests for BSpline.

dzenanz commented 3 years ago

Here is a WIP branch which I uses Elastix's ability to load ITK transform from a file: https://github.com/dzenanz/HASI/commit/f5ebf57864f991716a2f0076e0ee4ea4816c4129.

N-Dekker commented 3 years ago

BTW Elastix (develop branch) also has an experimental option to produce an ITK format TFM or a HDF5 file, as added by https://github.com/SuperElastix/elastix/pull/358

dzenanz commented 2 years ago

A lot of work seems to have been done last year regarding this. What it the latest update here?

NHPatterson commented 2 years ago

Just a quick Q, do these transforms also store output spacing, size, etc. as elastix transforms do?

dzenanz commented 2 years ago

ITK transforms operate in physical space. As such, they are unrelated to spacing or size of any particular image.

NHPatterson commented 2 years ago

Of course, my concern is more convenience of storing this information when doing elastix registrations.

thewtex commented 1 year ago

@N-Dekker perhaps we can have a notebook based on 0.16.0 that demonstrates how to do this?