SuperElastix / SimpleElastix

Multi-lingual medical image registration library
http://simpleelastix.github.io
Apache License 2.0
514 stars 148 forks source link

"Spacing" transformation parameter can cause unexpected scaling #271

Open simon-bre opened 5 years ago

simon-bre commented 5 years ago

Hi, thanks for this nice wrapper! However, today I ran into an issue that i can't make any sense of:

I need to register a set of images to a reference image, using the same transformation. So first I register a "master image" to the reference:

filter = sitk.ElastixImageFilter()
filter.SetFixedImage(sitk.ReadImage(reffile))
filter.SetMovingImage(sitk.ReadImage(masterfile))
params = sitk.GetDefaultParameterMap("bspline")
params['MaximumNumberOfIterations'] = ['256']
params['FinalGridSpacingInPhysicalUnits'] = ['50']
filter.SetParameterMap(params)
filter.Execute()

When I now get the warped imaged with filter.GetResultImage(), it is perfectly registered, everything as expected.

However, when I try to apply the same transformation to the remaining images of my set using TransformixImageFilter, strange things happen:

transform_filter = sitk.TransformixImageFilter()
transform_filter.SetTransformParameterMap(filter.GetTransformParameterMap())
...
for f in imgfiles:
                transform_filter.SetMovingImage(sitk.ReadImage(os.path.join(dir_in, d, f)))
                transform_filter.Execute()
                resultimg_sitk = transform_filter.GetResultImage()

now my result image is scaled up by quite precisely a factor of 3:

expectation: a reality: b

Image resolution matches the reference image, so it is actually scaled, not cropped.

I tried:

..always same problem. Any ideas?

simon-bre commented 5 years ago

Ok, I think I found the source of the problem:

There is a transformation parameter called "Spacing", in the exported textfile in section "Image Specific": (Spacing 0.3527777778 0.3527777778)

Apparently my "master" images has some property that the others don't, causing this parameter to be set; however, the only difference I can see is that the "master" was edited and saved with photoshop. Dimensions, channels, bit-depth, format are the same; could not find any suspicious parameters in exif data either (images are tiffs).

My solution is to eliminate any meta-information that SimpleITK may come up with by converting the image to an array and then back to an image before using it. Works perfeclty fine.

So, problem solved for me, but it might be interesting why it happens and how to avoid it.

Cheers!

NHPatterson commented 5 years ago

You can also just set the spacing of the images once they are loaded into SimpleITK based on your own information rather than converting to an array which may cause you errors down the road. Sometimes with non-medical image formats (jpegs, tifs, etc), such resolution metadata gets changed or saved in odd ways by different softwares so it is better to manage it at execution than to expect it to be saved correctly.

moving = sitk.ReadImage('moving.png')
moving.GetSpacing() #prints spacing
moving.SetSpacing((0.1,0.1)) #sets spacing (or pixel/voxel resolution), needs a 3rd spacing term if the data is 3D.

#repeat for fixed

These parameters are really important in registration because the physical space defined by the spacing is to constrain transformation. The grid spacing is an example. If you have a spacing of (100,100) whatever units and the grid spacing of your b-spline model is 100.0 then not much is going to happen.