Export Segmentation as Labeled LabelMap

Hi everyone!
I´m trying to export a segmentation with some segments labed as:


And I exported:
image

If I close scene and try to import again this file as a segmentation:


Original label is not preserved…

I have some other NonSlicerMade labelmaps and if I import them:
image

So I undertand that:

  • Slicer always add string “Segment_” to labelmap labels
  • Slicer save labelmaps always without original label (just as a ColorTable second file)

Is there any way to change this behaviour, or just the second issue?
Thanks on advance.

Slicer Stable 5.0.3 r30893

Slice allows round-trip editing and exporting and importing with preserving all the segment names.

I would recommend to save the segmentation file as usual, in a seg.nrrd file, because it contains a regular 3D labelmap that any software can read (if you have overlapping segments, then it will be a 4D volume containing a few non-overlapping 3D volumes) and the segment names, in a single file. You can edit these files and the segment names are preserved, just make sure all the custom fields in the .nrrd file header are preserved.

If you want to save the segment names in a separate file (because the file you use for segment editing cannot preserve custom fields in the nrrd file header) then you can export the segmentation into a labelmap and save the resulting color table file. You can use this color table file to specify segment names when you load a labemap volume.

Is there a way to output those label maps as colored masks? By default, Slicer3D outputs them all as binary masks.

I agree with you @lassoan but I´m working on a dataset to train Monai so I need the labelmap in nii format to work with. That is the reason fot not to work directly with segmentations (much better for almost everthing…).
I´m trying to mix my own cases with others form VerSe Dataset and I need to export as nii.gz labelmaps but it´s been impossible to me to get labelmaps with segments with the right label…

Thanks in advance !!!

Labelmaps are not meant to preserve segmentation labels, just the indices. You need to create a color table, and when converting the labelmap to segmentation you need to apply this: this section might be useful:

the associate color table looks like this: First column is the label index, second column is the segment label to be applied, followed by the RGB code (and alpha).

I think i´m not explain properly…
I want to make labelmaps as they are in VerSe Dataset but my labelmaps exported with Slicer are not the same. Verse ones have labels inside because i you import them in Slicer and you send them to an empty Segmentation, segments are correctly labeled (first vertebra is “8” because it is T1, not “1” because it´s the first indice).
I need to add my cases to VerSe Dataset to retrain a Monai Pipeline with them.
It´s strange that Segmentation Module ask you for a ColorTable during export task and labels are not added to the labelmap and output labelmap have no color as @Dolzodmaa_D said.

Thanks @muratmaga for your explain about labelmap import task into a Segmentation.

Because labelmap format does not have a field to store actual labels, only indices. The labels are preserved in the color table that was saved during the export.

See this thread on how to correctly load the labelmap as a segmentation using the color table from the UI. Copying segment names/colors from one segmentation to another - #7 by lassoan

The example I sent you is the programmatic approach to the same thing.

This may or may not be relevant for you, but we encountered an issue when using a labelmaps with non-contiguous numbers, and not starting from 1. We were training a multilabel model, and the source we used had for training had labelmaps that go from 1-50 (with couple gaps) and then 101-103. Monai didn’t like that so we ended having to reorder the labels in a continuous fashion from 1-50. So if your first label has an index of 8, you may or may not encounter the same issue. FYI.

Many MONAI examples use NIFTI format, but you should be able to use NRRD file format just as well. If you have trouble with that then you can post it as a question and @mention some MONAILabel people.

If some of the data is already in NIFTI format then it may be indeed simpler to add more data to it in the same format.

To make things easier for you, I’ve created a color table for the Verse data set. You can download it from here. Simply load this color table then select it when you load a labelmap volume or export a segmentation.

2 Likes

Thanks a lot @lassoan and @muratmaga for your kind explanations and the Verse ColorTable.
It’s a pity you can’t export slicers segmentations as NIFTI as other software do it because split labels and color in a diferent file is a bit tricky for sharing masks with other users in multilabel AI pipelines.

You can save segmentation in NIFTI file format, exactly for interoperability with other software. The color table ensures consistent label values <-> segment names mapping when importing or exporting NIFTI files.

1 Like

Do you know of a software that actually embeds segments names into NIFTI? Because I don’t think it is possible with that format. I never encountered one.

1 Like

I find the way to do it in Segmentations Module but it works the same as export to labelmap and save it as nifti. Thanks

I´ve been looking for a software to review NIFTI files metadata but I can´t find it. I don´t know what software were used to made VerSe masks and review documentation about.
I think I was in a mistake about labels in labelmaps file. Probably these VerSe masks don´t have labels but they are saved with “altered indexes”. I mean that first segment is not index 1 but has a higher index correlated with the vertebra level. They really don´t save label, they change first index in the labelmap.
Other issue is they have color info for each segment, but this is not critical for me.
Is there any way to save labelmap with this kind of “altered index” o edit indexes in labelmaps?

You can use nibabel Python package (you can run pip_install('nibabel') in the Slicer Python console to install it):

import nibabel
f = nibabel.load(r'path/to/some/segmentation.nii')
print(f)

It will provide an output like this:

<class 'nibabel.nifti1.Nifti1Image'>
data shape (256, 256, 130)
affine: 
[[ -0.           0.           1.29999542 -86.64489746]
 [ -1.          -0.          -0.         133.92860413]
 [  0.          -1.           0.         116.78569794]
 [  0.           0.           0.           1.        ]]
metadata:
<class 'nibabel.nifti1.Nifti1Header'> object, endian='<'
sizeof_hdr      : 348
data_type       : b''
db_name         : b''
extents         : 0
session_error   : 0
regular         : b'r'
dim_info        : 0
dim             : [  3 256 256 130   1   1   1   1]
intent_p1       : 0.0
intent_p2       : 0.0
intent_p3       : 0.0
intent_code     : none
datatype        : int16
bitpix          : 16
slice_start     : 0
pixdim          : [1.        1.        1.        1.2999954 0.        0.        0.
 0.       ]
vox_offset      : 0.0
scl_slope       : nan
scl_inter       : nan
slice_end       : 0
slice_code      : unknown
xyzt_units      : 2
cal_max         : 0.0
cal_min         : 0.0
slice_duration  : 0.0
toffset         : 0.0
glmax           : 0
glmin           : 0
descrip         : b''
aux_file        : b''
qform_code      : scanner
sform_code      : scanner
quatern_b       : -0.5
quatern_c       : 0.5
quatern_d       : -0.5
qoffset_x       : -86.6449
qoffset_y       : 133.9286
qoffset_z       : 116.7857
srow_x          : [ -0.          0.          1.2999954 -86.6449   ]
srow_y          : [ -1.      -0.      -0.     133.9286]
srow_z          : [  0.      -1.       0.     116.7857]
intent_name     : b''
magic           : b'n+1'

Yes, exactly. NIFTI files have a very limited and rigid header structure. It cannot store label values, but it entirely relies on external label description files to specify which label value correspond to what segment.

I provided you the correct label description file for the VerSe data set, which is all you need for importing and exporting with correct segment names / label values, but I give it one more try to explain every click you need to make.

Import

All you need to import a segmentation from NIFTI file with the correct segment names are these two simple steps:

  1. Load the label file into Slicer

image

  1. Load the NIFTI file, choosing: Description → Segmentation, Color node → VerseLabels

image

Result of the loaded CT volume and vertebra segmentation:

Export

To export a segmentation with the chosen label values in NIFTI format, use “Export to file” section in Segmentations module:

2 Likes

Hi @lassoan ,
Thanks for your export manual… Really clear what to do step by step!

I´ve been talking with @diazandr3s from MonaiLabel and we have reach another approach to the issue.
I´m going to add empty segments at the begining of segmentation till first vertebra has the same index as label. It´s supposed not to be a problem for MonaiLabel to manage empty segments…

I will give you fedback, maybe be intersting for anyone else because can fix many other problems with multilabel pipelines.

Thank you very much for your support…

1 Like

Hi @lassoan,
Sorry to be again over this old topic put I´m trying to follow your export method in a script and I´ve found some trouble.

Import color table code:

labelmapNodePath = ‘path_to_labelmap.nii.gz’ (labelmap is in NIFTI format)
labelmapNode = slicer.util.loadLabelVolume(labelmapNodePath)
importColorTable = slicer.util.loadColorTable(importColorTablePath)
labelmapNode.GetDisplayNode().SetAndObserveColorNodeID(importColorTable.GetID())
segmentationNode = slicer.mrmlScene.AddNewNodeByClass(“vtkMRMLSegmentationNode”)
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapNode,segmentationNode)

This is working fine but I don´t know how to make the export task.

exportLabelmapNode = slicer.mrmlScene.AddNewNodeByClass(“vtkMRMLLabelMapVolumeNode”)
segmentsIDs = segmentationNode.GetSegmentation().GetSegmentIDs()
slicer.modules.segmentations.logic().ExportSegmentsToLabelmapNode(segmentationNode, segmentsIDs, exportLabelmapNode , volumeNode)

If I try to SetAndObserveColorNodeID to exportLabelmapNodeDisplayNode or segmentationNodeDisplayNode, both sends error of (“vtkSegmentation::SetSegmentIndex failed: index 17 is out of range [0,10]”)

Could you bring me some light about this?
Thanks in advance!!!

You can use this method: Slicer: vtkSlicerSegmentationsModuleLogic Class Reference

Leave segment list empty to export all the segments. Set the color node as input. If you encounter problems try with latest Slicer Preview Release.

1 Like

Hi @lassoan , thanks for your quick answare!!

It works perfect…

1 Like