Display a segmentation in color over the segmented volume - loadable module

Operating system: MAC
Slicer version: 4.6.2

Hi everyone,

I am currently writting my own loadable module and I would need to segment a volume (for example by thresholding it) and display the segmentation in color over the segmented volume, as it is done in the “Segmentations” module (“Segment Editor”, the threshold effect).

To do so, I read the code of this loadable module (mostly qSlicerSegmentEditorAbstractEffect.cxx and SegmentEditorThresholdEffect.py) and I managed to extract some of the things I would need but I’m missing things and I’m a bit lost in the two files mentionned.
Thanks for any answer that could help me understand how to do this.

Here is what I have for the moment:

///////////////////////////////////////////////////////////////////////////

vtkMRMLScalarVolumeNode* volumeNode = … ;
vtkImageData* image = … ;

vtkNew thresholdFilter;
thresholdFilter->SetInValue(255);
thresholdFilter->SetOutValue(0);
thresholdFilter->SetInputData(image);
thresholdFilter->ThresholdBetween(min,max);

qSlicerLayoutManager* layoutManager = qSlicerApplication::application()->layoutManager();
foreach (QString sliceViewName, layoutManager->sliceViewNames())
{
qMRMLSliceWidget* sliceWidget = layoutManager->sliceWidget(sliceViewName);

    vtkNew<vtkLookupTable> lookupTable;
    vtkNew<vtkImageMapToRGBA> colorMapper;
    vtkNew<vtkImageMapper> mapper;
    vtkNew<vtkActor2D> actor;

    lookupTable->SetRampToLinear();
    lookupTable->SetNumberOfTableValues(2);
    lookupTable->SetTableRange(0,255);
    lookupTable->SetTableValue(0,0,0,0,0);
    lookupTable->SetTableValue(1,0.5,0.7,0.5,0.8);

    colorMapper->SetOutputFormatToRGBA();
    colorMapper->SetLookupTable(lookupTable.GetPointer());

    actor->VisibilityOn();
    actor->SetMapper(mapper.GetPointer());

    mapper->SetColorWindow(255);
    mapper->SetColorLevel(128);

    colorMapper->SetInputConnection(thresholdFilter->GetOutputPort());

    mapper->SetInputConnection(colorMapper->GetOutputPort());
   
    vtkRenderWindow* renderWindow = sliceWidget->sliceView()->renderWindow();
    vtkRenderer* renderer = vtkRenderer::SafeDownCast(renderWindow->GetRenderers()->GetItemAsObject(0));
    renderer->AddActor2D(actor.GetPointer());
   
    sliceWidget->sliceView()->scheduleRender();
}

vtkSlicerApplicationLogic* slicerAppLogic = this->module()->appLogic();
vtkMRMLSelectionNode* selectionNode = slicerAppLogic->GetSelectionNode();
selectionNode->SetReferenceActiveVolumeID(volumeNode->GetID());
slicerAppLogic->PropagateVolumeSelection();

/////////////////////////////////////////////////////////////////////////////////////////////////

Regards,

Sandra.

Probably the simplest is to create a segment editor widget, set its inputs (scene, input volume, segmentation), activate an effect, set parameters, and apply the effect.

Here is an example in Python (the same works in C++ with some trivial changes in syntax):

# 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)
segmentEditorWidget.setSegmentationNode(segmentationNode)
segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

# Run segmentation
segmentEditorWidget.setActiveEffectByName("Grow from seeds")
effect = segmentEditorWidget.activeEffect()
# You can change parameters by calling: effect.setParameter("MyParameterName", someValue)
# Most effect don't have onPreview, you can just call onApply
effect.self().onPreview()
effect.self().onApply()

# Clean up and show results
################################################

# Clean up
slicer.mrmlScene.RemoveNode(segmentEditorNode)

# Make segmentation results nicely visible in 3D
segmentationDisplayNode = segmentationNode.GetDisplayNode()
segmentationDisplayNode.SetSegmentVisibility(backgroundSegmentId, False)

You can find some more examples here: https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#How_to_run_segment_editor_effects_from_a_script

Hi Sandra, I do something like that here:

Specifically:

I guess it is possible to clean, by removing the initialization of the segment editor node (and just creating a segmentation node). However, in my case I inizialize the segment editor, and, then, I use the segmentation node create from the segmentation editor. This because I want that the segments that I create by thresholding the volumes will appear in the Segmentation editor module immediatly, so the user has already everything settled for modifying the selection done by thresholding.

Thank you very much both for your answers !

I would need to do my own segmentation after (and not use an already existing one like thresholding or growing from seeds in slicer) so I guess with your solution Andras it might not be possible ? or I would need to create my own effect in order to activate it ?

I believe I won’t have this issue with your solution Davide, so I’ll try to work from the code you gave me and come back to you if necessary.

Thank you,
Regards,
Sandra.

If there is already an effect that does what you need then follow this example: https://subversion.assembla.com/svn/slicerrt/trunk/SlicerRt/samples/PythonScripts/SegmentGrowCut/SegmentGrowCutSimple.py

If you want to do segmentation by using VTK, ITK, etc. classes then follow this example:
https://subversion.assembla.com/svn/slicerrt/trunk/SlicerRt/samples/PythonScripts/SegmentGrowCut/SegmentGrowCut.py
If it works well and you want to use it using a graphical user interface, share it with others, etc. then put it into a Segment editor effect (use the Extension wizard in Slicer to create a new scriptededitoreffect module). See example of extending Segment editor with new effects in this extension: https://github.com/lassoan/SlicerSegmentEditorExtraEffects

Thank you, it seems to be what I needed, I’ll look into it and come back to you if I have more questions

Davide, with your solution, would it be possible to display two segments of the same volume with two different colors ? I think that’s what you did with your SegmentTwo and SegmentThree both done on volumeTwo but if I follow your example only the first segment is displayed.

You can set the color of any segments independently. You can also have as many segments in the segmentation as you want and show them as the same time. If you need overlapping segments, set masking option Overwrite other segments to None.

I’ve already tried adding this line at the end:
SegmentationDisplayNode->SetSegmentOverrideColor(SegmentTwoID, 0.7, 0.5, 0.5);
And I get only the first segment displayed with the new color (0.7,0.5,0.5)

And even without trying to modify the color of any segment, I only get the first segment displayed

Add your segment to the scene and check if all segments shows up in the Segmentations module. If you still have problems then save the segmentation node to file and share it with us so that we can have a look (upload to Dropbox or OneDrive and attach the link).

Indeed I had only one segment showing up in the Segmentations module, I found my error (the two segments ended havind the same ID so I only got one segment).

Thank you very much for your help :slight_smile:

sorry I didn’t see your messages. Glad that you managed it!

Dr. Lassoan,
Hello.Recently, I have been writing modules in C + +, and I have also studied a lot about the call of segmenteditor. I want to know how to apply effects in C + +, such as threshold apply.
Best wishes to you.Thank you in advance.