# Automatize model generation from segmentation

**URL:** <https://discourse.slicer.org/t/automatize-model-generation-from-segmentation/35355>\
**Category:** Support\
**Tags:** segmentation, 3d-model, automation\
**Created:** [April 8, 2024, 3:33pm UTC](https://discourse.slicer.org/t/automatize-model-generation-from-segmentation/35355 "2024-04-08T15:33:28Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![MrMarkus](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MrMarkus](https://discourse.slicer.org/u/MrMarkus)\
**Post date:** [April 8, 2024, 3:33pm UTC](https://discourse.slicer.org/t/automatize-model-generation-from-segmentation/35355/1 "2024-04-08T15:33:28Z")

</div>

Hi,

I would like to automatically generate 3D-models from segmented 3D-data. The  
segmented data is stored as \*.nrrd, and the segmentation was performed with  
an external program.

The idea is to store the segmented data in a folder and use “slicerpipelines” to  
automatize the task. But I am not exactly sure how to set up the pipeline.

The following steps need to be covered:

- load the data as “segmentation”
- select only segment1 and segment2
- keep largest element of segment1, keep largest element of segment2
- generate model of segment1 and of segment2
- store model\_segment1 and model\_segment2 → file names should be derived from  
the loaded segmentation-data

Any hint / tutorial how to set-up the “SlicerPipeline” for this workflow?

Thanks!

Any help is greatly appreciated!

Best,  
Markus

---

<div class="post-metadata">

**Author:** ![muratmaga](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/muratmaga/32/3622_2.png) [@muratmaga](https://discourse.slicer.org/u/muratmaga)\
**Post date:** [April 8, 2024, 6:02pm UTC](https://discourse.slicer.org/t/automatize-model-generation-from-segmentation/35355/2 "2024-04-08T18:02:11Z")

</div>

I am not sure if all of this is possible through SlicerPipelines, but it is definitely possible via python scripting. See the script repository, specifically segmentations section for examples.

[https://slicer.readthedocs.io/en/latest/developer\_guide/script\_repository.html#segmentations](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#segmentations)

---

<div class="post-metadata">

**Author:** ![MrMarkus](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MrMarkus](https://discourse.slicer.org/u/MrMarkus)\
**Post date:** [April 9, 2024, 11:16am UTC](https://discourse.slicer.org/t/automatize-model-generation-from-segmentation/35355/3 "2024-04-09T11:16:35Z")

</div>

Thanks for the hint!

Looks promising.

Best,  
Markus

---

<div class="post-metadata">

**Author:** ![Matteboo](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/matteboo/32/66548_2.png) [@Matteboo](https://discourse.slicer.org/u/Matteboo)\
**Post date:** [April 9, 2024, 11:33am UTC](https://discourse.slicer.org/t/automatize-model-generation-from-segmentation/35355/4 "2024-04-09T11:33:21Z")

</div>

There’s a functiun that should be very useful for you in the [ablation planner module](https://github.com/naterex23/SlicerAblationPlanner/blob/main/AblationPlanner/AblationPlanner.py) line 793

```auto
convertSegmentToModel(segmentNode, folderName="Folder")

```

---

<div class="post-metadata">

**Author:** ![MrMarkus](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MrMarkus](https://discourse.slicer.org/u/MrMarkus)\
**Post date:** [April 24, 2024, 7:48am UTC](https://discourse.slicer.org/t/automatize-model-generation-from-segmentation/35355/5 "2024-04-24T07:48:46Z")

</div>

Hi,

once again thanks for the link.

I tried to find & use the code snippets which looked promising to me.  
And it worked out, starting from the segmentation models were generated and  
also filtered using the “Islands” - Operation.

An nice example of how to apply the filter-effects is given here:

> <https://gist.github.com/lassoan/0f45db8bae792ea19ccad36ceefbf52d>

BUT. While testing I found out that the model generation / exporting is  
introducing a “transformation” / or change of the coordinate system.

→ in comparison to the position of the segmentation is the position of the  
model now changed.

Any idea how this is caused and how it could be solved?

I am using:

Export model to Blender, including color by scalar

[https://slicer.readthedocs.io/en/latest/developer\_guide/script\_repository.html#export-model-to-blender-including-color-by-scalar](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#export-model-to-blender-including-color-by-scalar)

Maybe there is a better way how to export “Segment” → “Model” ?

Thanks!  
Best,  
Markus

---

<div class="post-metadata">

**Author:** ![MrMarkus](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MrMarkus](https://discourse.slicer.org/u/MrMarkus)\
**Post date:** [April 29, 2024, 4:20pm UTC](https://discourse.slicer.org/t/automatize-model-generation-from-segmentation/35355/6 "2024-04-29T16:20:30Z")

</div>

Hi again,

meanwhile I discoverd similar topics, e.g.

> [@Export volume (or segment?) to stl file with python](https://discourse.slicer.org/t/export-volume-or-segment-to-stl-file-with-python/25111):
>
> Hi there, Currently I’ve been working on automating a work flow in python that goes like the following: Load CT scans (as .tiffs) Create a segmentation and threshold to identify air in the scans Automate a mouse click in a known location and use the “Remove selected island” feature Apply the “Keep largest island” feature Calculate and report statistics I’d like to add a 6th step that saves the final resulting volume as an STL file so users could easily open up a visual artifact at a later da…

and an example how to export the Model to disk:

[https://github.com/SlicerMorph/Scripts#2-run-an-image-processing-pipeline-on-a-folder-of-volumes](https://github.com/SlicerMorph/Scripts#2-run-an-image-processing-pipeline-on-a-folder-of-volumes)

One question remains on how is the order in setting up the segmentEditorWidget.  
Not sure if the code is “fine” like it is applied, because after all files in the folder  
are processed the “KEEP\_LARGEST\_ISLAND” filter is still “active” → the mouse pointer has this typical “icon”…

```auto
# Load CurrentSegmentation
    CurrentSegmentation = os.path.join(ProjectFolder, FilesInFolder[sampleIndex])
    slicer.util.loadSegmentation(CurrentSegmentation)
    segmentationNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLSegmentationNode")
    
    sampleID = segmentationNode.GetName()
    
    # storage of the segment volume 
    volumeSegment[sampleIndex][0] = sampleID 
    
    # masterVolume for segmentation
    masterVolumeNode = segmentationNode.GetNodeReference(segmentationNode.GetReferenceImageGeometryReferenceRole())
    
    # Create segment editor to get access to effects
    segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
    
    # To show segment editor widget (useful for debugging):
    # segmentEditorWidget.show()
    segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
    segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
    slicer.mrmlScene.AddNode(segmentEditorNode)
    segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
    
    # actual segmentation
    segmentEditorWidget.setSegmentationNode(segmentationNode)
    segmentEditorWidget.setSourceVolumeNode(masterVolumeNode)
    
    # Visible segments will be processed
    inputSegmentIDs = vtk.vtkStringArray()
    segmentationNode.GetDisplayNode().GetVisibleSegmentIDs(inputSegmentIDs)
    
    segmentationNode.GetDisplayNode().SetSegmentVisibility(inputSegmentIDs.GetValue(2), False)
    
    # apply filter: Keep_Largest_Island / get rid of "particles"
    for index in range(inputSegmentIDs.GetNumberOfValues()-1):
        segmentID = inputSegmentIDs.GetValue(index)
        segmentEditorWidget.setCurrentSegmentID(segmentID)
        
        # Remove islands in inverted segment (these are the holes inside the segment)
        segmentEditorWidget.setActiveEffectByName("Islands")
        effect = segmentEditorWidget.activeEffect()
        effect.setParameter("Operation", "KEEP_LARGEST_ISLAND")
        effect.self().onApply()

    # prepare: Export segment -> to model
    shNode = slicer.mrmlScene.GetSubjectHierarchyNode()
    exportFolderItemId = shNode.CreateFolderItem(shNode.GetSceneItemID(), sampleID)
    slicer.modules.segmentations.logic().ExportAllSegmentsToModels(segmentationNode, exportFolderItemId)
itemList=[]
    shNode.GetItemChildren(exportFolderItemId,itemList)
    if itemList is []:
      print("Error: no model node exported for ", volumeNode.GetName())
      continue
    
    # export skull = Segment_1
    modelNode = shNode.GetItemDataNode(itemList[0])
    # Decimate the model 80%
    slicer.modules.SurfaceToolboxWidget.logic.decimate(modelNode, modelNode, 0.8)
    slicer.util.saveNode(modelNode, plyFilePathSkull)

  # Delete temporary segment editor
    slicer.mrmlScene.RemoveNode(segmentEditorNode)
    del segmentEditorWidget

  slicer.mrmlScene.Clear(0) # EMPTY scene

```

Maybe one could comment on the lines above.

THANKS!

Best,  
Markus
