View Issue Details

IDProjectCategoryView StatusLast Update
0003664Slicer4Module Markupspublic2014-09-17 23:01
Reporterfedorov Assigned Tolassoan  
PriorityurgentSeveritymajorReproducibilityalways
Status closedResolutionfixed 
Product Version 
Target VersionSlicer 4.4.0Fixed in Version 
Summary0003664: Applying b-spline transformation to the fiducial list is inconsistent with image resampling
Description

I have one image (moving, Case10-MR-subvolume-scale_1.nrrd) registered to another one (reference, case10_US_resampled-subvolume-scale_1.nrrd) via a b-spline transform. See attached zip file with the scene and all images. Applying the same transform to the label and to fiducial results in inconsistent location. Steps to reproduce:

I have a fiducial defined in the moving image. I also have a blob in a label image that is centered on the fiducial.

1) drag the fiducial list under the b-spline transform.

2) use BRAINS Resample to resample label image.

3) Resampled label and the fiducial are in a very different locations (see screenshot).

TagsNo tags attached.

Relationships

related to 0003660 closedalexy Interaction with fiducials is broken when fiducials under a bspline transform 

Activities

2014-04-18 12:27

 

fedorov

fedorov

2014-04-18 12:28

developer   ~0011615

in the screenshot:

Top row: resampled image and resampled label
Middle: resampled image and transformed fiducial
Bottom: original image, original label, original fiducial

2014-04-18 12:28

 

FinalScene.zip (2,441,612 bytes)
lassoan

lassoan

2014-04-18 20:30

developer   ~0011618

The problem is that the approximation of the bspline inverse is very inaccurate for this particular transform. You can visualize this by loading the bspline transform twice, invert one instance, and apply it to the other instance. The transformed transform "to world" should be identity transform, so where this transform has non-zero displacement (can be visualized by enabling display in the Display section), the inverse was estimated inaccurately.

Probably the best option would be to use the vtkBSplineTransform class in VTK, which has a more sophisticated invert method than vtkITKBSplineTransform (when vtkITKBSplineTransform was created vtkBSplineTransform did not exist, but now, as a proper VTK class is available for BSpline, we should probably use it).

Another option is to precompute the inverse using http://www.itk.org/Doxygen/html/classitk_1_1InverseDeformationFieldImageFilter.html and store it in the transform node. The transform node can already store both the "fromParent" and the "toParent" transforms, so no significant redesign would be needed.

fedorov

fedorov

2014-04-20 06:54

developer   ~0011623

Andras, I think looking at just the inverse transform with the very helpful transform visualizer shows it is not correct. But I was not sure where the issue actually is.

Can someone confirm this is the right piece of code that calculates the inverse: https://github.com/Slicer/Slicer/blob/master/Libs/vtkITK/vtkITKBSplineTransform.cxx#L1070-L1119? How was that code validated? Number of iterations is fixed at 10, and tolerance at 1?... Who is "bess" that authored that code in 2008?

It seems that both ITK and VTK implementations have a lot more involved algorithms for inversion (see Modules/Compatibility/V3Compatibility/include/itkIterativeInverseDeformationFieldImageFilter.hxx in ITK and Hybrid/vtkBSplineTransform.cxx in VTK).

If we precompute the inverse, would this require inverting at bspline knots and recalculating the bspline coefficients, or creating an inverse deformation field?

Finally, are we in agreement this functionality should be disabled until implemented correctly? I think it is quite dangerous to keep it the way it is, since the result of inversion is not "obviously" wrong, and can mislead the user.

lassoan

lassoan

2014-04-20 16:45

developer   ~0011627

Last edited: 2014-04-20 17:17

I would not spend time with temporarily disabling this specific feature. Instead, we should switch to the vtkBSplineTransform, which has an inverse computation method that is guaranteed to be correct (see section 2.4 in http://www.vtkjournal.org/browse/publication/790).

I'll try to integrate this VTK class next week, it'll probably ready by the end of the week.

fedorov

fedorov

2014-04-20 17:05

developer   ~0011628

Andras, did you include the right link? That paper doesn't have section 2.4

lassoan

lassoan

2014-04-20 17:19

developer   ~0011629

sorry, link fixed

alexy

alexy

2014-04-21 04:34

developer   ~0011630

Andras, if you want to switch to vtkBSplineTransform, how you are going to handle file format, does vtkBSplineTransform support .tfm files? Otherwise you would need to convert from itkBSplineTransform to vtkBSplineTransform internally.

lassoan

lassoan

2014-04-21 04:52

developer   ~0011631

I've implemented instantiation of a vtkBSplineTransform from an ITK .tfm file :
https://github.com/lassoan/Slicer/tree/vtk-bspline-transform
(the writing is not ready yet, but can be implemented in a few hours)

Results: The inverse computation works very well. No problem with Andriy's data set anymore. The inverse computation only seem to fail in areas where no inverse exists (where the field is "folded": in regions where different points are mapped to the same position; typically at the boundary).

Although the inverse is not available only in irrelevant areas, we may still have to prepare certain modules to handle missing inverse properly. Fortunately, we know if the inverse is missing. For example, we could show in the markups module GUI if a transformed markup has unknown position and we could hide it from the 2D/3D views.

lassoan

lassoan

2014-05-12 08:49

developer   ~0011721

Fixed in rev 23148.

Problem:
vtkITKBSplineTransform incorrectly computed the 1. forward derivatives, 2. inverse displacement when there was a bulk transform component and rotated bspline grid, 3. the inverse displacement.

Analysis:
In the ITK bspline transform no inverse computation is available and in the current ITK bspline version no additive bulk transform is supported (therefore it is not backward-compatible with the old ITK bspline transform), ITK's transform support is very limited (compared to the powerful transform pipelines in VTK), and Slicer already uses VTK transforms (vtkGridTransform), therefore the ITK bspline is not usable in Slicer as is.
A bspline transform implementation is available in VTK, which is is efficient and well-tested (and equivalence with ITK's bspline implementation can be proven by testing).

Solution:
Replaced vtkITKBSplineTransform it with a vtkBSplineTransform-based transform, vtkOrientedBSplineTransform, which extends the original VTK class to handle arbitrarily oriented b-spline grids and supports an additive bulk transform.
Added test that verifies the vtkOrientedBSplineTransform's equivalence with the ITK BSpline transform implementation in the whole bspline grid (the differences are less than 1e-10).
Added test that verifies the correctness of the inverse and derivative computation.

Fixes:
http://www.na-mic.org/Bug/view.php?id=3664
http://www.na-mic.org/Bug/view.php?id=3659
http://www.na-mic.org/Bug/view.php?id=3614

jcfr

jcfr

2014-09-17 23:01

administrator   ~0012547

Closing resolved issues that have not been updated in more than 3 months.

Issue History

Date Modified Username Field Change
2014-04-18 12:27 fedorov New Issue
2014-04-18 12:27 fedorov Status new => assigned
2014-04-18 12:27 fedorov Assigned To => nicole
2014-04-18 12:27 fedorov File Added: Mismatch in label and fiducial.png
2014-04-18 12:28 fedorov Note Added: 0011615
2014-04-18 12:28 fedorov File Added: FinalScene.zip
2014-04-18 13:09 jcfr Relationship added related to 0003660
2014-04-18 13:09 jcfr Target Version => Slicer 4.4.0
2014-04-18 20:30 lassoan Note Added: 0011618
2014-04-19 04:47 alexy Assigned To nicole => alexy
2014-04-20 06:54 fedorov Note Added: 0011623
2014-04-20 16:45 lassoan Note Added: 0011627
2014-04-20 17:05 fedorov Note Added: 0011628
2014-04-20 17:17 lassoan Note Edited: 0011627
2014-04-20 17:19 lassoan Note Added: 0011629
2014-04-21 04:34 alexy Note Added: 0011630
2014-04-21 04:52 lassoan Note Added: 0011631
2014-05-12 08:15 lassoan Assigned To alexy => lassoan
2014-05-12 08:49 lassoan Note Added: 0011721
2014-05-12 08:49 lassoan Status assigned => resolved
2014-05-12 08:49 lassoan Resolution open => fixed
2014-09-17 22:59 jcfr Status resolved => closed
2014-09-17 23:01 jcfr Note Added: 0012547