# Python segmentation conversion - specifying geometry for binary labelmap

**URL:** <https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364>\
**Category:** Support\
**Created:** [May 24, 2024, 6:35am UTC](https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364 "2024-05-24T06:35:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![LRAnti](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lranti/32/78502_2.png) [@LRAnti](https://discourse.slicer.org/u/LRAnti)\
**Post date:** [May 24, 2024, 6:35am UTC](https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364/1 "2024-05-24T06:35:35Z")

</div>

Operating system: Windows  
Slicer version: 5.2.2

Hello! I’m trying to alter an existing python script which converts segmentations from an RT Struct dataset to binary labelmaps for export as stls. I’ve found that when I do this manually through the GUI, I get the best result when I use “Advanced Create” in Segmentations, choose the Planar Contour \> Closed Surface \> Binary Labelmap path, and click “Specify geometry” (it doesn’t matter whether I select the source geometry or not - as long as the spacing is set to 1mm on all axes).

I am trying to replicate this in my script but have had no luck primarily because I have no idea what I’m doing. The current script does this, but it gives me a large stl with a rough surface:

def convert\_to\_model():  
log\_info(“Generate Binary Label Map”)  
segmentations = slicer.util.getNodesByClass(‘vtkMRMLSegmentationNode’)  
segmentations[0].CreateBinaryLabelmapRepresentation()  
segmentations[0].SetMasterRepresentationToBinaryLabelmap()

```
seg = getNode('*RTSTRUCT*')
segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()

slicer.mrmlScene.AddNode(segmentEditorNode)
segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
segmentEditorWidget.setSegmentationNode(seg)

# export segmentation to a model
shNode = slicer.mrmlScene.GetSubjectHierarchyNode()
exportFolderItemId = shNode.CreateFolderItem(shNode.GetSceneItemID(), "Segments")

log_info("Export all segments to models")
slicer.modules.segmentations.logic().ExportAllSegmentsToModels(seg, exportFolderItemId)

```

Would anyone be able to point me in the direction of what I might do to modify this to use the conversion path/parameters as described above? I’ve spent a long time going through documentation but I’m not quite sure what I’m looking for. I tried using this:

segmentationNode = getNode(“Segmentation”)  
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass(“vtkMRMLLabelMapVolumeNode”)  
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(segmentationNode, labelmapVolumeNode, slicer.vtkSegmentation.EXTENT\_REFERENCE\_GEOMETRY)

but didn’t get the same result as I did from the UI. Any help would be greatly appreciated!

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [May 27, 2024, 9:13am UTC](https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364/2 "2024-05-27T09:13:22Z")

</div>

If you want to skip the direct Planar contour → Closed surface conversion path so that the Planar contour → Ribbon model → Binary labelmap path is used, you can do this:

```auto
factory = slicer.vtkSegmentationConverterFactory.GetInstance()
factory.DisableConverterRule('Planar contour', 'Closed surface')

```

---

<div class="post-metadata">

**Author:** ![LRAnti](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lranti/32/78502_2.png) [@LRAnti](https://discourse.slicer.org/u/LRAnti)\
**Post date:** [May 27, 2024, 9:21am UTC](https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364/3 "2024-05-27T09:21:08Z")

</div>

Thank you! The main issue is that I can’t find a way to specify the reference image geometry when creating the binary label map. I have noticed that when I click “specify geometry”, I don’t need to choose a segment, as long as it populates the reference image geometry with generic values like this:

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/c/2/c294492d8ebf85d344f0ca20f0e66320d740c2ac.png)  
then the conversion works as expected. I haven’t been able to find a way to replicate this with my python script however. I tried making a dummy volume node, adding spacing values to this and setting reference geometry of the segment I’m trying to convert, but it still doesn’t work. Do you have any suggestions for this?

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [May 27, 2024, 11:17am UTC](https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364/4 "2024-05-27T11:17:55Z")

</div>

This is how you can specify reference geometry from Python:

```auto
referenceGeometryMatrix = #TODO: Specify your direction matrix
extent = [0, 1, 0, 1, 0, 1] # Arbitrary extent, the "effective extent" will be determined automatically
geometryString = slicer.vtkSegmentationConverter.SerializeImageGeometry(referenceGeometryMatrix, extent)
segmentationNode.GetSegmentation().SetConversionParameter(
  slicer.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), geometryString)

```

---

<div class="post-metadata">

**Author:** ![LRAnti](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lranti/32/78502_2.png) [@LRAnti](https://discourse.slicer.org/u/LRAnti)\
**Post date:** [May 27, 2024, 1:02pm UTC](https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364/5 "2024-05-27T13:02:19Z")

</div>

Thank you so much, I really appreciate the help! I tried using that but am still getting output that is different to what happens when clicking specify geometry on the UI:

This is what I used:  
extent = [0,1,0,1,0,1]  
matrix = vtk.vtkMatrix4x4()  
referenceGeometryMatrix = matrix.Identity()  
geometryString = slicer.vtkSegmentationConverter.SerializeImageGeometry(referenceGeometryMatrix, extent)  
segmentationNode = getNode(‘_RTSTRUCT_’)  
segmentationNode.GetSegmentation().SetConversionParameter(slicer.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), geometryString)  
segmentationNode.CreateBinaryLabelmapRepresentation()

the console output was:  
[VTK] CalculateOutputGeometry: No image geometry specified, default geometry is calculated (0.366345130101627;0;0;-83.49600219726562;0;0.366345130101627;0;355.9289855957031;0;0;0.366345130101627;-47.14999771118164;0;0;0;1;0;299;0;215;0;241;)

[VTK] CalculateOutputGeometry: No image geometry specified, default geometry is calculated (0.8751702253519644;0;0;-128.906005859375;0;0.8751702253519644;0;200.16799926757812;0;0;0.8751702253519644;-114.75;0;0;0;1;0;232;0;253;0;265;)

The resulting representation was still very stepped (it is smooth when specifying geometry with the button on the ui). Do you have any suggestions?

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [May 27, 2024, 2:35pm UTC](https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364/6 "2024-05-27T14:35:30Z")

</div>

The problem is that you don’t actually set a geometry.

After the call

```auto
referenceGeometryMatrix = matrix.Identity()

```

referenceGeometryMatrix is `None`. I strongly suggest that you try to run these lines in the Python console and see the output. It is very easy but super important to see the content of the variables, and unfortunately the `Identity()` function has no return value.

Do you want to set an identity matrix? Then try

```auto
referenceGeometryMatrix = vtk.vtkMatrix4x4()

```

---

<div class="post-metadata">

**Author:** ![LRAnti](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lranti/32/78502_2.png) [@LRAnti](https://discourse.slicer.org/u/LRAnti)\
**Post date:** [May 28, 2024, 3:05am UTC](https://discourse.slicer.org/t/python-segmentation-conversion-specifying-geometry-for-binary-labelmap/36364/7 "2024-05-28T03:05:00Z")

</div>

Oh right I see!

That worked perfectly to replicate setting the geometry from the UI (just using an identity matrix). Details for anyone experiencing the same problem:

extent = [0,1,0,1,0,1]  
referenceGeometryMatrix = vtk.vtkMatrix4x4()  
geometryString = slicer.vtkSegmentationConverter.SerializeImageGeometry(referenceGeometryMatrix, extent)  
segmentationNode.GetSegmentation().SetConversionParameter(slicer.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), geometryString)  
segmentationNode.CreateBinaryLabelmapRepresentation()

Thank you SO much for your help, I have been battling this for quite some time!
