How do I apply a transform to fiducial seeds from Slicer?

I have a list of fiducial seed points obtained through Slicer which correspond to locations in a reference image. I have registered this reference image with a fixed target image using an affine transform and now wish to apply the same transform to the seed points in order to get their corresponding locations in the target image.

I’m fairly new to ITK, however I know that Slicer uses the RAS coordinate system while ITK uses LPS. I also recently read that the transform you get from registration actually maps points from the fixed image to the moving image. This doesn’t make logical sense to me (since the whole idea of a transform is to move the points in the moving image to the fixed image), and I want to confirm that its true.

My main question however, is what steps can I take to transform the seed points? What is the simplest way to convert between the two coordinate systems and apply the transform?

transform->TransformPoint(point) seems like a useful function, however if what I read is true, then it would map the point to the moving image which is the opposite of what I want. Any help would be appreciated.



I managed to figure out the solution to my own problem. For those who are having similar difficulties, the solution is as follows.

In order to convert from RAS to LPS you simply invert (take the negative of) the first two indices ie. (-R, -A, S) == (L, P, S).

To apply a transform to a fiducial point and map it from the moving image to the fixed image you must get the inverse of the transform you are trying to apply. This is because, as I mentioned above, transform objects map points from the fixed image to the moving image. Since we want to map points in the opposite direction you need the inverse of the transform. Here is some example code:

itk::Point< double, Dimension > oldPoint;
itk::Point< double, Dimension > newPoint;

oldPoint[0] = -seedPointD1;
oldPoint[1] = -seedPointD2;
oldPoint[2] =  seedPointD3;

TransformType::InverseTransformBasePointer inverseTransform = transform->GetInverseTransform();
newPoint = inverseTransform->TransformPoint(oldPoint);

// To get the RAS coordinates again, remember to invert the first two indices
std::cout << -newPoint[0] << " ";
std::cout << -newPoint[1] << " ";
std::cout <<  newPoint[2] << std::endl;

Slicer’s seed files can also be written in LPS space. In that case, you don’t need the conversion. The property [coordinateSystem=“lps|ras|ijk”] controls that.

1 Like