I would like to convert Matlab coordinates to Slicer.
I load Dicom images to Matlab and I get some coordinates.
Then, I try to load them on Slicer, but both are in a completely different position.
Could you please give me a hint?
Hi Eleni -
I don’t use matlab, but I understand the matlabbridge extension is a big help.
Also, maybe at the heart of your question, is that DICOM uses LPS coordinates and Slicer uses RAS. These are described on this wiki page.
Thanks for the clarifications. I am going to describe better what I am going to achieve. I load a set of images on Matlab and picking there 3 points (red cross). And I want to convert these into Slicer. I load the same set of images and I plot these 3 point (red dots). I am trying to register the points with the image on Slicer. I have tried the following solutions:
- Apply diag(-1. -1, 1,1) to the points
- regarding the coordinates systems that I have I imagine that I should rotate 180 around z axis and 90 degrees around x axis.
Unfortunately, none of these are working.
I guess in Matlab you use voxel indices as coordinates (IJK). You can see in this example how to convert between IJK and LPS (or RAS) coordinates by multiplying with ijkToLpsTransform.
By the way, why do you need to define points in Matlab? You can define points in Slicer using markups. If you have some function implemented in Matlab that automatically detects those points then you can call that function directly from Slicer using MatlabBridge (which provides convenience functions to pass images and point positions between Matlab and Slicer in various coordinate systems). Check out MatlabBridge tutorial and examples for details.
At some point it could make sense to remove dependency on Matlab, which should be much easier in recent Slicer-4.11 releases, as you can use any Python packages in Slicer.
@lassoan Which example exactly are you referring to?
Seems that the coordinates are in mm in Matlab.
Unfortunately, I do not have any control over that and I cannot run it through MatlabBridge.
There is a software that I am using and I don’t have the source code. The only thing that I can get are these points as I have plotted on Matlab.
FillAroundSeeds example shows how to convert between Matlab-style (1-based) IJK and LPS physical coordinate systems.
You use multiple coordinate systems in both Slicer and Matlab and you convert between them using homogeneous transformation matrices. To convert, you need to simply multiply the homogeneous coordinates vector by the appropriate homogeneous transformation matrix from the left.
In Slicer, we usually use RAS physical coordinate system and 0-based IJK voxel coordinate system. Most other software use LPS physical coordinate systems for images, so we save images using LPS as physical coordinate system, therefore you’ll get that in Matlab. Also, in Matlab array indexing is 1-based, so you need to add/subtract this 1 offset. This is all taken into consideration in nrrdread.m for computing ijkToLps transform, so you can convert between your Matlab-style IJK and physical LPS by multiplying with this transform (or its inverse).
What prevents you from running the processing through MatlabBridge? (it should be possible to use MatlabBridge for running any Matlab function). Also, if you can tell us what this black-box Matlab code does then we might be able to recommend potential open-source alternatives.
As a follow up, Eleni and I worked through the data and found a transformation that appears to be correct. For reference here’s the script that works for us, but it’s probably a one-off solution specific to the way this particular matlab program generates the data (x and y coordinates in pixel space, but z coordinate scaled by slice spacing).
fp = open('/Users/pieper/Dropbox/data/MRRobot/Accuracy Phantom/Matlab/x-coordinate.txt', "r")
data = fp.read()
xcoords = map(float, data.strip().replace('\r\n', '\t').split('\t'))
fp = open('/Users/pieper/Dropbox/data/MRRobot/Accuracy Phantom/Matlab/y-coordinate.txt', "r")
data = fp.read()
ycoords = map(float, data.strip().replace('\r\n', '\t').split('\t'))
volumeNode = slicer.util.getNode('901*')
ijkToRAS = vtk.vtkMatrix4x4()
markupNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLMarkupsFiducialNode())
for index in range(64):
out = [0,]*4
ijkToRAS.MultiplyPoint([ xcoords[index], ycoords[index], 21 , 1], out) # 21 = 52.5 zcoord / 2.5 slice spacing