Interpreting segmentation nrrd files

Hello,

I am segmenting prostates with Slicer and now I want to post-process my segmentations. So I read the nrrd segmentation files with my python code. I have a case where I have one file with one segmentation and two segments corresponding to two lesions. I notice that:

  1. in the nrrd file the data is 4-d array where the first dimension seems to correspond to the segment in a multi-segment segmentation. (is that the case?)

  2. The header dimension header is now 4 (instead of 3) I am assuming that is because each segment/lesion is stored in its own array.

  3. The spaces direction header is an array with 4 elements now, whereas the first element of the array is ‘none’ and the other three elements are 3-d vectors. I assume this is to match the fact that data is now a 4-d matrix (is that the case?)

  4. The sizes header is also 4-d and it seems that the first coordinate corresponds to the number of segments and the other three are the minimum common cube that contain the segments.

Are my assumptions correct?

Thanks,

D

Yes, all the above are correct. Segmentation is stored in a 4D array (segment index and 3 spatial dimensions) because segments may overlap.

1 Like

In case you haven’t seen it: pynrrd.

3 Likes

If you know the segments don’t overlap you could export to a labelmap (to store as a 3D nrrd or nifti which is sometimes more compatible with other software).

Let’s look at the following key value pair for a segment NRRD header:

Segment0_Extent:=7 110 376 473 383 572

What does the above key value pair mean? 7 should be the 7th volume, but what do the following numbers mean?

Again, what does the following imply?

Segmentation_ReferenceImageExtentOffset:=114 108 88

Is the Offset in IJK or world coordinates?

Reference to any TUTORIAL would be helpful.

Thanks for @fedorov. I guess part of the answer is here .

The segmentation 4D nrrd file is considered Slicer-specific, to enable single-file export/import of whole labelmap based segmentations. So there are no tutorials, because we don’t intend this to be used directly, but through the Slicer storage infrastructure.

The extent does not start at 0 because segments do not store the whole reference image geometry, only the non-empty part of the segment labelmap (“effective extent”).
(The vtkImageData::Extent variable that you linked just now explains what an extent is, but it does not explain the effective extent used for segments)

I suggest that instead of trying to read this 4D nrrd, you export the segmentation as a labelmap within Slicer and save that in a usual 3D nrrd. Of course any overlap information will be lost (if you’re concerned about this you can export the segments in individual labelmaps too with some python scripting).
There are many topics describing how to do this programmatically, such as this or this. If you want to do this from the UI then here’s the easiest way
image
but you can find more options in the Segmentations module

Thanks. I am loading the segmentation file (i.e. header) in Python. I need to apply transform (warp/affine) on your segmentation file which is why understanding each key-value pair is important to me.

In case missed, what does the following mean? Is it in IJK?

Segmentation_ReferenceImageExtentOffset:=114 108 88

Most private metadata fields in the 4D .seg.nrrd file is for performance improvement only (so that we don’t need to recompute effective extents of frames), so you can safely ignore them. But probably we should document them somewhere anyway. I’ll specify those fields and add a link here.

1 Like

I suggest it makes sense to do it here:

https://www.slicer.org/wiki/Documentation/4.10/SlicerApplication/SupportedDataFormat

I’ve added description here: https://github.com/Slicer/Slicer/blob/e7d91177d4873dfde90e47df336be8487bff6c5d/Libs/MRML/Core/vtkMRMLSegmentationStorageNode.h#L56-L122

I’ve added links from the https://www.slicer.org/wiki/Documentation/Nightly/SlicerApplication/SupportedDataFormat pages to the specification of the custom fields.

1 Like