The GetInverse()
method doesn’t actually modify the vectors in the grid. It simply sets a flag so that, internally, the InverseTransformPoint()
is used instead of the ForwardTransformPoint()
method. The details of this can be seen in the implementation of vtkWarpTransform, which is the base class of vtkGridTransform.
Actually creating a new grid that is the inverse of the original grid requires the use of vtkTransformToGrid. This class will take any input transform (linear, b-spline, thin-plate-spline, or grid) and will sample that transform onto a grid. So what you want to do is sample the inverse of the original grid transform onto a new grid of the same size.
Also, when doing this, it’s very important to call SetInterpolationModeToCubic()
on the original vtkGridTransform to ensure a good result.
Edit: the inversion can be further improved by using b-spline interpolation rather than cubic interpolation, but this requires an additional step:
// create b-spline coefficients for the displacement grid image_data_sptr
auto bspline_filter = vtkSmartPointer<vtkImageBSplineCoefficients>::New();
bspline_filter->SetInputData(image_data_sptr);
bspline_filter->Update();
// use these b-spline coefficients to create a transform
auto bspline_transform = vtkSmartPointer<vtkBSplineTransform>::New();
bspline_transform->SetCoefficientData(bspline_filter->GetOutput());
// invert the b-spline transform onto a new grid
auto grid_maker = vtkSmartPointer<vtkTransformToGrid>::New();
grid_maker->SetInput(bspline_transform->GetInverse());
grid_maker->SetGridOrigin(image_data_sptr->GetOrigin());
grid_maker->SetGridSpacing(image_data_sptr->GetSpacing());
grid_maker->SetGridExtent(image_data_sptr->GetExtent());
grid_maker->SetGridScalarTypeToFloat();
grid_maker->Update();
// grid_maker->GetOutput() is the new displacement grid, as a vtkImageData