Slicer Segmentation inverted normals for closed surface representation

Hi everyone,

We have recently noticed a problem when exporting STL and OBJ from segmentations in Slicer. Depending on the Volume’s affine, the generated normals can point inside instead of outside.

This doesn’t cause any problems for Slicer’s rendering as backface culling is disabled, but it can cause multiple problems including when trying to perform boolean operations or exporting to other softwares.

The problem is easily reproducible by creating a sphere brush segmentation in the following volumes :

import numpy as np
inverted_volume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode")

m = np.eye(4)
m[0,0] = -1
m[1,1] = -1
m[2,2] = -1
inverted_volume.SetSpacing([1, 1, 1])
slicer.util.updateVolumeFromArray(inverted_volume, np.zeros((256,256,256)))

not_inverted_volume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode")

m = np.eye(4)
m[0,0] = -1
m[1,1] = -1
not_inverted_volume.SetSpacing([1, 1, 1])
slicer.util.updateVolumeFromArray(not_inverted_volume, np.zeros((256,256,256)))

Exporting to STL and displaying the face orientation in Blender yields the following results :


@jcfr and @lassoan what do you think of this issue?


IJK coordinate system of the image must be right-handed (IJK to Physicial transformation matrix must have positive determinant). Left-handed coordinate system is currently not supported, because it would be hard to ensure that every algorithms are prepared to deal with it.

It would be nice if Slicer reported a warning and offer to fix it (reorder slices and invert the K axis). But until then, we rely on users to generate valid images (or resample them to a valid geometry after they are generated, before doing any further processing).

@lassoan Thanks for the information!

In all the cases we saw, these images were loaded from NIFTI or other import file formats. So I think that handling the inversion when loading the files would be the best to address 99.9% of our needs.

For developers, a warning mechanism would be sufficient.

Do you know where would be the best places to implement these fixes?

Inverting the slice order and flipping the K axis direction could be done right after reading the image into a VTK image in vtkMRMLVolumeArchetypeStorageNode:

1 Like

Thanks for the link! I’ll have a look!