diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.cpp index 605a9163f9..f03346674e 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.cpp +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.cpp @@ -1,156 +1,156 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkExtractFromMultiLabelSegmentationWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include QmitkExtractFromMultiLabelSegmentationWidget::QmitkExtractFromMultiLabelSegmentationWidget(mitk::DataStorage* dataStorage, QWidget* parent) : QWidget(parent), m_DataStorage(dataStorage) { m_Controls = new Ui::QmitkExtractFromMultiLabelSegmentationWidgetControls; m_Controls->setupUi(this); m_Controls->segNodeSelector->SetDataStorage(dataStorage); m_Controls->segNodeSelector->SetNodePredicate(mitk::GetMultiLabelSegmentationPredicate()); m_Controls->segNodeSelector->SetSelectionIsOptional(false); m_Controls->segNodeSelector->SetInvalidInfo(QStringLiteral("Please select segmentation for extraction.")); m_Controls->segNodeSelector->SetPopUpTitel(QStringLiteral("Select segmentation")); m_Controls->segNodeSelector->SetPopUpHint(QStringLiteral("Select the segmentation that should be used as source for extraction.")); m_Controls->checkExtractSelected->setChecked(false); m_Controls->checkClassMap->setChecked(false); m_Controls->checkInstanceMap->setChecked(true); m_Controls->checkInstanceMask->setChecked(true); this->ConfigureWidgets(); connect (m_Controls->btnExtract, &QAbstractButton::clicked, this, &QmitkExtractFromMultiLabelSegmentationWidget::OnExtractPressed); connect(m_Controls->segNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkExtractFromMultiLabelSegmentationWidget::OnSegSelectionChanged); auto widget = this; connect(m_Controls->checkInstanceMap, &QCheckBox::toggled, this, [widget](bool checked) {widget->ConfigureWidgets(); }); connect(m_Controls->checkClassMap, &QCheckBox::toggled, this, [widget](bool checked) {widget->ConfigureWidgets(); }); connect(m_Controls->checkInstanceMask, &QCheckBox::toggled, this, [widget](bool checked) {widget->ConfigureWidgets(); }); connect(m_Controls->checkExtractSelected, &QCheckBox::toggled, this, [widget](bool checked) {widget->ConfigureWidgets(); }); m_Controls->segNodeSelector->SetAutoSelectNewNodes(true); } QmitkExtractFromMultiLabelSegmentationWidget::~QmitkExtractFromMultiLabelSegmentationWidget() { m_Controls->labelInspector->SetMultiLabelNode(nullptr); } void QmitkExtractFromMultiLabelSegmentationWidget::ConfigureWidgets() { m_InternalEvent = true; m_Controls->labelInspector->setVisible(m_Controls->checkExtractSelected->isChecked()); bool isOK = (m_Controls->checkInstanceMap->isChecked() || m_Controls->checkInstanceMask->isChecked() || m_Controls->checkClassMap->isChecked()); m_Controls->btnExtract->setEnabled(isOK); m_InternalEvent = false; } void QmitkExtractFromMultiLabelSegmentationWidget::OnSegSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/) { if (!m_InternalEvent) { m_Controls->labelInspector->SetMultiLabelNode(m_Controls->segNodeSelector->GetSelectedNode()); this->ConfigureWidgets(); } } void QmitkExtractFromMultiLabelSegmentationWidget::StoreToDataStorage(mitk::Image* image, const std::string& name, mitk::DataNode* parent) { auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNull()) { mitkThrow() << "QmitkExtractFromMultiLabelSegmentationWidget is in invalid state. No datastorage is set."; } mitk::DataNode::Pointer outNode = mitk::DataNode::New(); outNode->SetName(name); outNode->SetData(image); dataStorage->Add(outNode, parent); } void QmitkExtractFromMultiLabelSegmentationWidget::OnExtractPressed() { auto node = m_Controls->segNodeSelector->GetSelectedNodes().front(); auto seg = dynamic_cast(node->GetData()); auto selectedLabelValues = seg->GetAllLabelValues(); if (m_Controls->checkExtractSelected->isChecked()) selectedLabelValues = m_Controls->labelInspector->GetSelectedLabels(); auto groupLabelValueMap = mitk::LabelSetImageHelper::SplitLabelValuesByGroup(seg,selectedLabelValues); unsigned int numSteps = 0; if (m_Controls->checkInstanceMap->isChecked()) numSteps += groupLabelValueMap.size(); if (m_Controls->checkInstanceMask->isChecked()) numSteps += selectedLabelValues.size(); if (m_Controls->checkClassMap->isChecked()) numSteps += groupLabelValueMap.size(); mitk::ProgressBar::GetInstance()->Reset(); mitk::ProgressBar::GetInstance()->AddStepsToDo(numSteps); for (auto& [groupID, labelValues] : groupLabelValueMap) { if (m_Controls->checkInstanceMap->isChecked()) { auto image = seg->GetGroupImageWorkarround(groupID)->Clone(); std::string name = "InstanceMap group "+std::to_string(groupID); this->StoreToDataStorage(image, name, node); mitk::ProgressBar::GetInstance()->Progress(); } if (m_Controls->checkClassMap->isChecked()) { auto [image,lookup] = mitk::CreateLabelClassMap(seg, groupID, labelValues); std::string name = "ClassMap group " + std::to_string(groupID); this->StoreToDataStorage(image, name, node); mitk::ProgressBar::GetInstance()->Progress(); } if (m_Controls->checkInstanceMask->isChecked()) { for (auto& labelValue : labelValues) { - auto image = mitk::CreateLabelMask(seg,labelValue); + auto image = mitk::CreateLabelMask(seg,labelValue,false); std::string name = "LabelMask " + seg->GetLabel(labelValue)->GetName() + " [" + std::to_string(labelValue) + "]"; this->StoreToDataStorage(image, name, node); mitk::ProgressBar::GetInstance()->Progress(); } } } mitk::ProgressBar::GetInstance()->Reset(); } diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox index a55ac22c09..731dd23efb 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox +++ b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox @@ -1,84 +1,99 @@ /** \page org_mitk_views_segmentationutilities The Segmentation Utilities View \imageMacro{segmentation_utilities-dox.svg,"Icon of the Segmentation Utilities View",5.00} \imageMacro{QmitkSegmentationUtilities_Overview.png,"The Segmentation Utilities View",16.00} \tableofcontents \section org_mitk_views_segmentationUtilitiesManualOverview Overview The Segmentation Utilities View allows to postprocess existing segmentations. Currently five different operations exist:
  • \ref org_mitk_views_segmentationUtilitiesBooleanOperations -
  • \ref org_mitk_views_segmentationUtilitiesContourToImage
  • \ref org_mitk_views_segmentationUtilitiesImageMasking
  • \ref org_mitk_views_segmentationUtilitiesMorphologicalOperations -
  • \ref org_mitk_views_segmentationUtilitiesSurfaceToImage +
  • \ref org_mitk_views_segmentationUtilitiesConvertToSegmentation +
  • \ref org_mitk_views_segmentationUtilitiesExtractFromSegmentation
\section org_mitk_views_segmentationUtilitiesDataSelection Data Selection All postprocessing operations provide one or more selection widgets, which allow to select the data for the operation. \section org_mitk_views_segmentationUtilitiesBooleanOperations Boolean operations Boolean operations allows to perform the following fundamental operations on two segmentations:
  • Difference: Subtracts the second segmentation from the first segmentation.
  • Intersection: Extracts the overlapping areas of the two selected segmentations.
  • Union: Combines the two existing segmentations.
The selected segmentations must have the same geometry (size, spacing, ...) in order for the operations to work correctly. The result will be stored in a new data node as a child node of the first selected segmentation. \imageMacro{QmitkSegmentationUtilities_BooleanOperations.png,"Boolean operations",6.00} -\section org_mitk_views_segmentationUtilitiesContourToImage Contour to image - -Contour to image allows to create a segmentation out of a given contour-model. -The operation requires a contour model set and a reference image. -The created segmentation image will have the same geometrical properties like the reference image (dimension, size and Geometry3D). - -\imageMacro{QmitkSegmentationUtilities_ContourToImage.png,"Contour to image",6.00} - \section org_mitk_views_segmentationUtilitiesImageMasking Image masking Image masking allows to mask an image with either an existing segmentation or a surface. The operation requires an image and a segmentation or a surface. The result will be an image containing only the pixels that are covered by the respective mask. The default background pixel value is zero. It can be changed to the minimum existing pixel value of the image or to a custom pixel value. If the custom pixel value is out of the valid bounds of the pixel type, it is optionally clamped accordingly. \imageMacro{QmitkSegmentationUtilities_ImageMasking.png,"Image masking",6.00} \section org_mitk_views_segmentationUtilitiesMorphologicalOperations Morphological operations Morphological operations are applied to a single segmentation image. Based on a given structuring element the underlying segmentation will be modified. The plugin provides a ball and a cross as structuring elements. The follow operations are available:
  • Dilation: Each labeled pixel within the segmentation will be dilated based on the selected structuring element.
  • Erosion: Each labeled pixel within the segmentation will be eroded based on the selected structuring element.
  • Opening: A dilation followed by an erosion, used for smoothing edges or eliminating small objects.
  • Closing: An erosion followed by an dilation, used for filling small holes.
  • Fill Holes: Fills bigger holes within a segmentation.
\imageMacro{QmitkSegmentationUtilities_MorphologicalOperations.png,"Morphological operations",6.00} -\section org_mitk_views_segmentationUtilitiesSurfaceToImage Surface to image +\section org_mitk_views_segmentationUtilitiesConvertToSegmentation Convert to Segmentation + +Convert to segmentation allows to convert one or multiple input data into a multi-label segmentation. The supported input data types are surfaces, contour models and images. Surfaces and contour models will be converted into a new label (with the same color then the respective input data). Input images will be analyzed for their pixel content. Each pixel value (different to 0; which marks unlabeled pixels) will be associated with the new label. +The conversion can have the following outputs: +
    +
  • Convert to new segmentation: The inputs will be converted and integrated in a new segmentation. The geometry of the output segmentation is determined by the largest geometry of the input images. If no images are selected as input, one has to specify an image or segmentation as reference. If sub mode "Convert inputs separately" is selected, each input will be converted into its own multi-label segmentation output. +
  • Add to existing segmentation: The inputs will be converted and integrated as new group(s) in a selected segmentation. +
-Surface to image allows to create a segmentation out of a given surface. -The operation requires a surface and a reference image. -The created segmentation image will have the same geometrical properties like the reference image (dimension, size and Geometry3D). +For the output the following grouping modes can be selected (if the output is not new separate segmentation): +
    +
  • Merge all inputs ...: All inputs will be merged into a new group. Remark: If inputs overlap the inputs might overwrite each other. +
  • New group per input: Each input will be added as a new group to the multi-label segmentation. +
-\imageMacro{QmitkSegmentationUtilities_SurfaceToImage.png,"Surface to image",6.00} +Remark on label values: when converting inputs into a multi-labels segmentation the conversion process tries to keep the label value the same like the original value. In cases of surfaces or contour models it would be 1. In case of images it would be the respective pixel value. In cases of the label value collision (the label value is already used in the segmentation) a new value will be assigned to resolve the conflict. Therefore it is only guaranteed that values are kept, if you convert only one input into a new or empty segmentation. + +Remark unsupported geometries: if you select images as input, these images have to have either the same geometry or must be a sub geometry. If an reference is defined or you want to add them to an existing segmentation, the imports images also have to have the same geometry like the target or be a sub geometry of it. + + +\section org_mitk_views_segmentationUtilitiesExtractFromSegmentation Extract from Segmentation + +Extract from segmentation allows to extract the content of a multi-label segmentation (either all labeled or a selection of labels) in various ways and stores it as simple images in the data storage. + +The following output options are available (at least one must be selected): +
    +
  • label class map(s): This generates an image where each pixel value (different from 0, which indicates unlabeled pixels) indicates a label class. Label class comprises all label instances that have the same label name. One can also see that has the semantic segmentation result. This mode will generate an output for each group indicated by the selected labels (or all groups). +
  • Label instance map(s): This generates an image where each pixel value (different from 0, which indicates unlabeled pixels) indicates a label instance. The used pixel values are equivalent to the label value of each instance. This mode will generate an output for each group indicated by the selected labels (or all groups). +
  • Label instance mask(s): This generates an image for one label instance where each pixel value (different from 0, which indicates unlabeled pixels) indicates the label instance. The used pixel value is equivalent to the label value of the label instance. +
**/