Read mha metadata

Hi everyone,

I’m trying to extract information about a volume which is in .mha format.
I’m struggling to find examples on how to read metadata of images which aren’t DICOM and I would like to automatically extract information such as the Orientation Convention of the volume (e.g. ‘RAI’ ‘LPI’).
How should I proceed?

An inconsistency was spotted recently in MetaImage. There is a lot of discussion regarding orientation in that bug report.

But the most general approach is to infer the orientation based on direction matrix. Identity matrix would mean LPS (i goes right to left, j goes anterior to posterior, k goes inferior to superior). You can use the existing class SpatialOrientationAdapter.

1 Like

Hi @Gabriele_Belotti,

As far as I know there is no easy way to access these information without fully reading the volume through an ImageFileReader.
If you want to only read the metadata, I think you can read the .mha file with a standard stream in byte mode, fetch only the first part that correspond to the header (it should be of constant size i think?) and convert back to string to manipulate as you want.
Note also that if you are able to do so, you can convert all your .mha files in mhd format, which detach the header and the binary part (giving a .mhd text header file + a .raw binary file), then the header is way more accessible.

HTH,

Tim

If you call UpdateOutputInformation it should read the image’s meta-data from the header, and not the bulk data.

2 Likes

Identity matrix would mean LPS ( i goes right to left, j goes anterior to posterior, k goes inferior to superior).

Yes, convention is “DICOM LPS” always, for clarity, ITK-SNAP calls that 3 letters orientation code RAI Code, with RAI for identity matrix, the same convention is in AnatomicalOrientation of MetaImage file and in ITK Spatial Orientation. ITK-SNAP heavily uses this terminology, BTW.

I have tested all 48 orientations with MetaImage files again with both Slicer and ITK-Snap. Both show images absolute correctly. Will provide link to test results later, may be.

ObjectType = Image
NDims = 3
BinaryData = True
BinaryDataByteOrderMSB = False
CompressedData = False
TransformMatrix = 1 0 0 0 1 0 0 0 1
Offset = -90 -89.5778 -72
CenterOfRotation = 0 0 0
AnatomicalOrientation = RAI
ElementSpacing = 2.02222 2.42222 2.02222

Thanks for the heads up, I managed to extract such information.
However I have encountered another issue with my data which is not directly related to Anatomical Orientation.
What I have is a CBCT which displays Coronal view first, Axial second, and I would like to transform it in order to have the Axial view first, which is what you expect from a CT.
Any idea on how to do this? I think permutation and rotation filters would be a good guess

If swapping the axis is sufficient, go with PermuteImageFilter. If the transform is to be more complex, you can use the ResampleImageFilter.

2 Likes

Following your suggestion right now, thanks for your time

I ended up needing FlipImageFilter to flip axis, but I have the following problem: this filter imposes RAI orientation to the pipeline and I am unable to write the image with the correct direction matrix even if I set it using the image::SetDirection function…
Any tips on why is this so? Are there any workarounds?

What do you mean? ITK physical coordinates system is always like that (eq. to Dicom LPS, see previous posts).
Maybe a code snippet would help here :slight_smile:

\ input to flipFilter is an image with RAI orientation
flipFilter->GetOutput()->SetDirection(OutputDirection);
\ where OutputDirection has set the matrix at [-1, 0 ,0 ,0 ,-1, 0, 0, 0, 0]

If I purposely update the filter or write the output image it will be in RAI orientation.

1 Like

Try something like:

flipFilter->Update();
auto ImToWrite = flipFilter->GetOutput();
ImToWrite->DisconnectPipeline();
ImToWrite->SetDirection(OutputDirection);
[...]
Writer->SetInput(ImToWrite);
[...]
Writer->Write();
1 Like

I get the following error

Description: itk::ERROR: ImageFileWriter(0000021DAAE2F820): Largest possible region does not fully contain requested paste IO regionPaste IO region: ImageIORegion (00000030780FF680)
Dimension: 3
Index: 0 0 0
Size: 0 0 0
Largest possible region: ImageRegion (00000030780FF840)
Dimension: 3
Index: [0, 0, 0]
Size: [0, 0, 0]

The image is ill defined (0 sized). Either the pipeline wasn’t properly executed or the input image is faulty?

@Gabriele_Belotti you need to update the image, assign the filter output to a variable, then disconnect variable from the pipeline, then set properties (direction etc) and finally write the “variable” to a file. I suspect you did not follow @tim-evain’s code snippet well.

Yes, in the end I managed to make everything work using all of your suggestions, so thank you very much @tim-evain and @dzenanz.
Sorry for the late reply

2 Likes