diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.cpp new file mode 100644 index 0000000000..bf60382daa --- /dev/null +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.cpp @@ -0,0 +1,536 @@ +/*============================================================================ + +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 "QmitkConvertToMultiLabelSegmentationWidget.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static const char* const HelpText = "Select an image and a surface above"; + +mitk::NodePredicateBase::Pointer GetInputPredicate() +{ + auto isImage = mitk::TNodePredicateDataType::New(); + auto isNotSeg = mitk::NodePredicateNot::New(mitk::GetMultiLabelSegmentationPredicate()); + + auto isSurface = mitk::TNodePredicateDataType::New(); + auto isContourModel = mitk::TNodePredicateDataType::New(); + auto isContourModelSet = mitk::TNodePredicateDataType::New(); + + auto isData = mitk::NodePredicateOr::New(isImage, isContourModel, isContourModelSet); + isData->AddPredicate(isSurface); + + auto isValidInput = mitk::NodePredicateAnd::New(isNotSeg, isData); + isValidInput->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); + isValidInput->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object"))); + return isValidInput.GetPointer(); +} + +const mitk::DataNode* GetNodeWithLargestImageGeometry(const QmitkNodeSelectionDialog::NodeList& nodes) +{ + mitk::BaseGeometry::ConstPointer refGeometry; + mitk::DataNode* result; + + for (auto& node : nodes) + { + auto castedData = dynamic_cast(node->GetData()); + if (castedData != nullptr) + { + if (refGeometry.IsNull() || mitk::IsSubGeometry(*refGeometry, *(castedData->GetGeometry()))) + { + refGeometry = castedData->GetGeometry(); + result = node; + } + } + } + return result; +} + +QmitkNodeSelectionDialog::NodeList GetNoneImageNodes(const QmitkNodeSelectionDialog::NodeList& nodes) +{ + QmitkNodeSelectionDialog::NodeList result; + + for (auto& node : nodes) + { + auto castedData = dynamic_cast(node->GetData()); + if (castedData == nullptr) + { + result.push_back(node); + } + } + return result; +} + +QmitkNodeSelectionDialog::NodeList GetImageNodes(const QmitkNodeSelectionDialog::NodeList& nodes) +{ + QmitkNodeSelectionDialog::NodeList result; + + for (auto& node : nodes) + { + auto castedData = dynamic_cast(node->GetData()); + if (castedData != nullptr) + { + result.push_back(node); + } + } + return result; +} + +QmitkNodeSelectionDialog::SelectionCheckFunctionType CheckForSameGeometry(const mitk::DataNode* refNode) +{ + mitk::DataNode::ConstPointer refNodeLambda = refNode; + + auto lambda = [refNodeLambda](const QmitkNodeSelectionDialog::NodeList& nodes) + { + if (nodes.empty()) + { + return std::string(); + } + + mitk::BaseGeometry::ConstPointer refGeometry; + bool usedExternalGeo = false; + std::string refNodeName; + + if (refNodeLambda.IsNotNull() && nullptr != refNodeLambda->GetData()) + { + refGeometry = refNodeLambda->GetData()->GetGeometry(); + usedExternalGeo = true; + refNodeName = refNodeLambda->GetName(); + } + + if (refGeometry.IsNull()) + { + auto imageNode = GetNodeWithLargestImageGeometry(nodes); + if (nullptr != imageNode) + { + refGeometry = imageNode->GetData()->GetGeometry(); + refNodeName = imageNode->GetName(); + } + } + + auto geoPredicate = mitk::NodePredicateSubGeometry::New(refGeometry); + + for (auto& node : nodes) + { + auto castedImageData = dynamic_cast(node->GetData()); + + if (nullptr != castedImageData) + { + if (!geoPredicate->CheckNode(node)) + { + std::stringstream ss; + ss << "

Invalid selection: All selected images must have the same geometry or a sub geometry "; + if (usedExternalGeo) ss << "of the selected reference/output"; + ss << ".< / p>

Uses reference data: \""; + ss << refNodeName << "\"

"; + ss << "

Differing data selections i.a.: \""; + ss << node->GetName() << "\"

"; + return ss.str(); + } + } + } + + return std::string(); + }; + + return lambda; +} + +QmitkConvertToMultiLabelSegmentationWidget::QmitkConvertToMultiLabelSegmentationWidget(mitk::DataStorage* dataStorage, QWidget* parent) + : QWidget(parent), m_DataStorage(dataStorage) +{ + m_Controls = new Ui::QmitkConvertToMultiLabelSegmentationWidgetControls; + m_Controls->setupUi(this); + + m_Controls->inputNodesSelector->SetDataStorage(dataStorage); + m_Controls->inputNodesSelector->SetNodePredicate(GetInputPredicate()); + m_Controls->inputNodesSelector->SetSelectionCheckFunction(CheckForSameGeometry(nullptr)); + m_Controls->inputNodesSelector->SetSelectionIsOptional(false); + m_Controls->inputNodesSelector->SetInvalidInfo(QStringLiteral("Please select inputs (images, surfaces or contours) for conversion")); + m_Controls->inputNodesSelector->SetPopUpTitel(QStringLiteral("Select inputs")); + m_Controls->inputNodesSelector->SetPopUpHint(QStringLiteral("You may select multiple inputs for conversion. But all selected images must have the same geometry or a sub geometry.")); + + m_Controls->outputSegSelector->SetDataStorage(dataStorage); + m_Controls->outputSegSelector->SetNodePredicate(mitk::GetMultiLabelSegmentationPredicate()); + m_Controls->outputSegSelector->SetSelectionIsOptional(false); + m_Controls->outputSegSelector->SetInvalidInfo(QStringLiteral("Please select the target segmentation")); + m_Controls->outputSegSelector->SetPopUpTitel(QStringLiteral("Select target segmentation")); + m_Controls->outputSegSelector->SetPopUpHint(QStringLiteral("Select the segmentation where the converted inputs should be added.")); + m_Controls->outputSegSelector->SetAutoSelectNewNodes(true); + + this->ConfigureWidgets(); + + connect (m_Controls->btnConvert, &QAbstractButton::clicked, this, &QmitkConvertToMultiLabelSegmentationWidget::OnConvertPressed); + connect(m_Controls->inputNodesSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, + this, &QmitkConvertToMultiLabelSegmentationWidget::OnInputSelectionChanged); + auto widget = this; + connect(m_Controls->radioAddToSeg, &QRadioButton::toggled, + m_Controls->outputSegSelector, [widget](bool checked) {widget->ConfigureWidgets(); }); + connect(m_Controls->checkMultipleOutputs, &QCheckBox::toggled, + m_Controls->outputSegSelector, [widget](bool checked) {widget->ConfigureWidgets(); }); +} + +QmitkConvertToMultiLabelSegmentationWidget::~QmitkConvertToMultiLabelSegmentationWidget() +{ +} + +void QmitkConvertToMultiLabelSegmentationWidget::ConfigureWidgets() +{ + m_InternalEvent = true; + + if (m_Controls->radioAddToSeg->isChecked()) + { + auto selectedNode = m_Controls->outputSegSelector->GetSelectedNode(); + m_Controls->inputNodesSelector->SetSelectionCheckFunction(CheckForSameGeometry(selectedNode)); + } + m_Controls->outputSegSelector->setVisible(m_Controls->radioAddToSeg->isChecked()); + + if (m_Controls->radioNewSeg->isChecked()) + { + auto selectedNode = m_Controls->refNodeSelector->GetSelectedNode(); + } + m_Controls->checkMultipleOutputs->setVisible(m_Controls->radioNewSeg->isChecked()); + bool refNeeded = m_Controls->radioAddToSeg->isChecked() && !m_Controls->inputNodesSelector->GetSelectedNodes().empty() && nullptr == GetNodeWithLargestImageGeometry(m_Controls->inputNodesSelector->GetSelectedNodes()); + m_Controls->refNodeSelector->setVisible(refNeeded); + + if (refNeeded) m_Controls->inputNodesSelector->SetSelectionCheckFunction(CheckForSameGeometry(m_Controls->refNodeSelector->GetSelectedNode())); + + m_Controls->groupGrouping->setVisible(m_Controls->radioAddToSeg->isChecked() || !(m_Controls->checkMultipleOutputs->isChecked())); + + bool inputIsOK = !m_Controls->inputNodesSelector->GetSelectedNodes().empty() && + !m_Controls->inputNodesSelector->CurrentSelectionViolatesCheckFunction(); + bool outputIsOK = !m_Controls->radioAddToSeg->isChecked() || m_Controls->outputSegSelector->GetSelectedNode().IsNotNull(); + bool refIsOK = !m_Controls->radioNewSeg->isChecked() || !m_Controls->refNodeSelector->isVisible() || m_Controls->refNodeSelector->GetSelectedNode().IsNotNull(); + + m_Controls->btnConvert->setEnabled(inputIsOK && outputIsOK && refIsOK); + m_InternalEvent = false; +} + +void QmitkConvertToMultiLabelSegmentationWidget::OnInputSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/) +{ + if (!m_InternalEvent) this->ConfigureWidgets(); +} + +void QmitkConvertToMultiLabelSegmentationWidget::OnOutputSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/) +{ + if (!m_InternalEvent) this->ConfigureWidgets(); +} + +void QmitkConvertToMultiLabelSegmentationWidget::OnRefSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/) +{ + if (!m_InternalEvent) this->ConfigureWidgets(); +} + + +void QmitkConvertToMultiLabelSegmentationWidget::OnConvertPressed() +{ + auto dataStorage = m_DataStorage.Lock(); + if (dataStorage.IsNull()) + { + mitkThrow() << "QmitkConvertToMultiLabelSegmentationWidget is in invalid state. No datastorage is set."; + } + + auto nodes = m_Controls->inputNodesSelector->GetSelectedNodes(); + mitk::ProgressBar::GetInstance()->Reset(); + mitk::ProgressBar::GetInstance()->AddStepsToDo(3 * nodes.size() + 1); + + if (m_Controls->radioNewSeg->isChecked() && m_Controls->checkMultipleOutputs->isChecked()) + { + for (auto& node : nodes) + { + this->ConvertNodes({ node }); + } + } + else + { + this->ConvertNodes(nodes); + } +} + + +mitk::Image::Pointer ConvertSurfaceToImage(const mitk::Image* refImage, const mitk::Surface* surface) +{ + mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New(); + surfaceToImageFilter->MakeOutputBinaryOn(); + surfaceToImageFilter->UShortBinaryPixelTypeOn(); + surfaceToImageFilter->SetInput(surface); + surfaceToImageFilter->SetImage(refImage); + try + { + surfaceToImageFilter->Update(); + } + catch (itk::ExceptionObject& excpt) + { + MITK_ERROR << excpt.GetDescription(); + return nullptr; + } + + return surfaceToImageFilter->GetOutput(); +} + +mitk::Image::Pointer ConvertContourModelSetToImage(mitk::Image* refImage, mitk::ContourModelSet* contourSet) +{ + // Use mitk::ContourModelSetToImageFilter to fill the ContourModelSet into the image + mitk::ContourModelSetToImageFilter::Pointer contourFiller = mitk::ContourModelSetToImageFilter::New(); + contourFiller->SetImage(refImage); + contourFiller->SetInput(contourSet); + contourFiller->MakeOutputLabelPixelTypeOn(); + + try + { + contourFiller->Update(); + } + catch (const std::exception& e) + { + MITK_ERROR << "Error while converting contour model. " << e.what(); + } + catch (...) + { + MITK_ERROR << "Unknown error while converting contour model."; + } + + return contourFiller->GetOutput(); +} + +void QmitkConvertToMultiLabelSegmentationWidget::ConvertNodes(const QmitkNodeSelectionDialog::NodeList& nodes) +{ + auto noneImageNodes = GetNoneImageNodes(nodes); + auto imageNodes = GetImageNodes(nodes); + + mitk::LabelSetImage::Pointer outputSeg; + mitk::Image::Pointer refImage; + const mitk::DataNode* refNode; + + if (m_Controls->radioAddToSeg->isChecked()) + { + outputSeg = dynamic_cast(m_Controls->outputSegSelector->GetSelectedNode()->GetData()); + + if (outputSeg->GetNumberOfLayers() > 0) + { + refImage = outputSeg->GetGroupImage(0); + } + else + { + //in case we work with a output seg, we need to generate a template image + //reason is that the conversion filters used for surfaces or contours need images + //as reference and MultiLabelSegmentations is currently empty. + refImage = mitk::Image::New(); + refImage->Initialize(mitk::MakePixelType(), *(outputSeg->GetTimeGeometry())); + } + } + else + { + outputSeg = mitk::LabelSetImage::New(); + + auto inputNode = GetNodeWithLargestImageGeometry(m_Controls->inputNodesSelector->GetSelectedNodes()); + if (nullptr != inputNode) + { + refNode = inputNode; + refImage = dynamic_cast(inputNode->GetData()); + outputSeg->Initialize(refImage); + } + else + { + refNode = m_Controls->refNodeSelector->GetSelectedNode(); + refImage = dynamic_cast(refNode->GetData()); + outputSeg->Initialize(refImage); + } + } + + //convert none image nodes to images + std::map preparedImageMap; + std::map foundLabelsMap; + for (const auto& node : noneImageNodes) + { + mitk::ProgressBar::GetInstance()->Progress(); + mitk::Image::Pointer convertedImage; + + auto surface = dynamic_cast(node->GetData()); + auto contourModel = dynamic_cast(node->GetData()); + auto contourModelSet = dynamic_cast(node->GetData()); + if (nullptr != surface) + { + convertedImage = ConvertSurfaceToImage(refImage, surface); + } + else if (nullptr != contourModelSet) + { + convertedImage = ConvertContourModelSetToImage(refImage, contourModelSet); + } + else if (nullptr != contourModel) + { + auto contourModelSet = mitk::ContourModelSet::New(); + contourModelSet->AddContourModel(contourModel); + convertedImage = ConvertContourModelSetToImage(refImage, contourModelSet); + } + else + { + mitkThrow() << "Invalid state of QmitkConvertToMultiLabelSegmentationWidget. At least one input is of invalid type, that should not be possible to select. Invalid node: " << *(node.GetPointer()); + } + + if (convertedImage.IsNotNull()) + { + preparedImageMap.emplace(node, convertedImage); + //all none image data is converted to binary maps + foundLabelsMap.emplace(node, mitk::LabelSetImage::LabelValueVectorType({ 1 })); + } + else + { + mitkThrow() << "Failed to convert an input. Failed node: " << *(node.GetPointer()); + } + } + + //prepare image nodes and get contained labels + for (const auto& node : imageNodes) + { + mitk::ProgressBar::GetInstance()->Progress(); + mitk::LabelSetImage::LabelValueVectorType foundLabels; + + mitk::ProgressBar::GetInstance()->Progress(); + mitk::Image::Pointer convertedImage = mitk::ConvertImageToGroupImage(dynamic_cast(node->GetData()), foundLabels); + preparedImageMap.emplace(node, convertedImage); + foundLabelsMap.emplace(node, foundLabels); + } + + //check for label collision and fix if needed + mitk::LabelSetImage::LabelValueVectorType usedLabelValues = outputSeg->GetAllLabelValues(); + std::map labelsMappingMap; + for (const auto& node : imageNodes) + { + mitk::ProgressBar::GetInstance()->Progress(); + + const auto& foundLabels = foundLabelsMap[node]; + mitk::LabelSetImage::LabelValueVectorType correctedLabelValues; + bool correctionNeeded = mitk::CheckForLabelValueConflictsAndResolve(foundLabels, usedLabelValues, correctedLabelValues); + + mitk::LabelValueMappingVector mapping; + std::transform(foundLabels.begin(), foundLabels.end(), correctedLabelValues.begin(), std::back_inserter(mapping), + [](mitk::LabelSetImage::LabelValueType a, mitk::LabelSetImage::LabelValueType b) { return std::make_pair(a, b); }); + labelsMappingMap.emplace(node, mapping); + } + + for (const auto& node : noneImageNodes) + { + mitk::ProgressBar::GetInstance()->Progress(); + + const auto& foundLabels = foundLabelsMap[node]; + mitk::LabelSetImage::LabelValueVectorType correctedLabelValues; + bool correctionNeeded = mitk::CheckForLabelValueConflictsAndResolve(foundLabels, usedLabelValues, correctedLabelValues); + + mitk::LabelValueMappingVector mapping; + std::transform(foundLabels.begin(), foundLabels.end(), correctedLabelValues.begin(), std::back_inserter(mapping), + [](mitk::LabelSetImage::LabelValueType a, mitk::LabelSetImage::LabelValueType b) { return std::make_pair(a, b); }); + labelsMappingMap.emplace(node, mapping); + } + + + //Ensure that we have the first layer to add + mitk::LabelSetImage::GroupIndexType currentGroupIndex = 0; + if (m_Controls->radioAddToSeg->isChecked() || 0 == outputSeg->GetNumberOfLayers()) + { + currentGroupIndex = outputSeg->AddLayer(); + } + + //Transfer content and add labels + for (const auto& node : imageNodes) + { + mitk::ProgressBar::GetInstance()->Progress(); + + if (m_Controls->radioSingleGroup->isChecked() && node != imageNodes.front()) + currentGroupIndex = outputSeg->AddLayer(); + + const auto& labelsMapping = labelsMappingMap.at(node); + for (auto [oldV, correctedV] : labelsMapping) + { + std::string name = "Value " + std::to_string(oldV); + if (m_Controls->radioMergeGroup->isChecked()) + name = node->GetName() + " " + name; + + auto label = mitk::LabelSetImageHelper::CreateNewLabel(outputSeg, name, true); + label->SetValue(correctedV); + + outputSeg->AddLabel(label, currentGroupIndex, false, false); + } + + mitk::TransferLabelContent(preparedImageMap.at(node), outputSeg->GetGroupImage(currentGroupIndex), + outputSeg->GetConstLabelsByValue(outputSeg->GetLabelValuesByGroup(currentGroupIndex)), + mitk::LabelSetImage::UNLABELED_VALUE, mitk::LabelSetImage::UNLABELED_VALUE, false, labelsMapping); + } + + for (const auto& node : noneImageNodes) + { + mitk::ProgressBar::GetInstance()->Progress(); + + if (m_Controls->radioSingleGroup->isChecked() && (node != noneImageNodes.front() || !imageNodes.empty())) + currentGroupIndex = outputSeg->AddLayer(); + + const auto& labelsMapping = labelsMappingMap.at(node); + for (auto [oldV, correctedV] : labelsMapping) + { + auto label = mitk::LabelSetImageHelper::CreateNewLabel(outputSeg, node->GetName(), true); + label->SetValue(correctedV); + mitk::ColorProperty::ConstPointer colorProp = dynamic_cast(node->GetConstProperty("color").GetPointer()); + if (colorProp.IsNotNull()) + label->SetColor(colorProp->GetColor()); + + outputSeg->AddLabel(label, currentGroupIndex, false, false); + } + + mitk::TransferLabelContent(preparedImageMap.at(node), outputSeg->GetGroupImage(currentGroupIndex), + outputSeg->GetConstLabelsByValue(outputSeg->GetLabelValuesByGroup(currentGroupIndex)), + mitk::LabelSetImage::UNLABELED_VALUE, mitk::LabelSetImage::UNLABELED_VALUE, false, labelsMapping); + } + + if (m_Controls->radioAddToSeg->isChecked()) + { + m_Controls->outputSegSelector->GetSelectedNode()->Modified(); + } + else + { + mitk::DataNode::Pointer outNode = mitk::DataNode::New(); + std::stringstream stream; + stream << "ConvertedSeg"; + if (nodes.size() == 1) + { + stream << "_" << nodes.front()->GetName(); + } + outNode->SetName(stream.str()); + outNode->SetData(outputSeg); + + auto dataStorage = m_DataStorage.Lock(); + dataStorage->Add(outNode); + } + mitk::ProgressBar::GetInstance()->Reset(); +} diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.h new file mode 100644 index 0000000000..4647d906c7 --- /dev/null +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.h @@ -0,0 +1,82 @@ +/*============================================================================ + +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. + +============================================================================*/ + +#ifndef QmitkConvertToMultiLabelSegmentationWidget_h +#define QmitkConvertToMultiLabelSegmentationWidget_h + +#include +#include +#include + +#include "itkSmartPointer.h" + +#include + +namespace Ui +{ + class QmitkConvertToMultiLabelSegmentationWidgetControls; +} + +namespace mitk +{ + class DataNode; + class DataStorage; + class Surface; + class Image; + class LabelSetImage; +} + +/*! + \brief QmitkConvertToMultiLabelSegmentationWidget + + Widget that offers the GUI and logic to convert different inputs (images, surfaces and contour models) + into a multi label segmentation (by generating a new or adding the converted inputs to an existing + segmentation). +*/ +class MITKSEGMENTATIONUI_EXPORT QmitkConvertToMultiLabelSegmentationWidget : public QWidget +{ + Q_OBJECT + +public: + + /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */ + explicit QmitkConvertToMultiLabelSegmentationWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr); + + /** @brief Default destructor. */ + ~QmitkConvertToMultiLabelSegmentationWidget() override; + +private slots: + + /** @brief This slot is called if the selection in the workbench is changed. */ + void OnInputSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/); + + void OnOutputSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/); + + void OnRefSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/); + + + /** @brief This slot is called if user activates the button to convert a surface into a binary image. */ + void OnConvertPressed(); + +private: + void ConvertNodes(const QmitkNodeSelectionDialog::NodeList& nodes); + + bool m_InternalEvent = false; + mitk::WeakPointer m_DataStorage; + + /** @brief Enable buttons if data selection is valid. */ + void ConfigureWidgets(); + + Ui::QmitkConvertToMultiLabelSegmentationWidgetControls* m_Controls; +}; + +#endif diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidgetControls.ui b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidgetControls.ui new file mode 100644 index 0000000000..91296e98e4 --- /dev/null +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidgetControls.ui @@ -0,0 +1,157 @@ + + + QmitkConvertToMultiLabelSegmentationWidgetControls + + + + 0 + 0 + 408 + 316 + + + + + + + Inputs; + + + + + + + + + + Output: + + + + + + Convert to new segmentation + + + true + + + + + + + 20 + + + + + + + + If activated, the conversion will generate separate multi label segmentations for each input instead of joining all inputs in one multi label segmentation. + + + Convert inputs separatly + + + + + + + + + Add to existing segmentation + + + + + + + + + + + + + Grouping: + + + + 4 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + Merge all inputs in new group + + + true + + + + + + + New group per input + + + + + + + + + + Convert + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + label + inputNodesSelector + groupGrouping + btnConvert + groupOutput + + + + QmitkMultiNodeSelectionWidget + QWidget +
QmitkMultiNodeSelectionWidget.h
+ 1 +
+ + QmitkSingleNodeSelectionWidget + QWidget +
QmitkSingleNodeSelectionWidget.h
+ 1 +
+
+ + +
diff --git a/Modules/SegmentationUI/files.cmake b/Modules/SegmentationUI/files.cmake index d230e65769..fca289c644 100644 --- a/Modules/SegmentationUI/files.cmake +++ b/Modules/SegmentationUI/files.cmake @@ -1,126 +1,129 @@ set(CPP_FILES Qmitk/QmitkSegWithPreviewToolGUIBase.cpp Qmitk/QmitkMultiLabelSegWithPreviewToolGUIBase.cpp Qmitk/QmitkBinaryThresholdToolGUIBase.cpp Qmitk/QmitkBinaryThresholdToolGUI.cpp Qmitk/QmitkBinaryThresholdULToolGUI.cpp Qmitk/QmitkConfirmSegmentationDialog.cpp Qmitk/QmitkCopyToClipBoardDialog.cpp Qmitk/QmitkDrawPaintbrushToolGUI.cpp Qmitk/QmitkErasePaintbrushToolGUI.cpp Qmitk/QmitkEditableContourToolGUIBase.cpp Qmitk/QmitkGrowCutToolGUI.cpp Qmitk/QmitkLiveWireTool2DGUI.cpp Qmitk/QmitkLassoToolGUI.cpp Qmitk/QmitkOtsuTool3DGUI.cpp Qmitk/QmitkPaintbrushToolGUI.cpp Qmitk/QmitkPickingToolGUI.cpp Qmitk/QmitkSlicesInterpolator.cpp Qmitk/QmitkToolGUI.cpp Qmitk/QmitkToolGUIArea.cpp Qmitk/QmitkToolSelectionBox.cpp Qmitk/QmitknnUNetFolderParser.cpp Qmitk/QmitknnUNetToolGUI.cpp Qmitk/QmitknnUNetWorker.cpp Qmitk/QmitknnUNetGPU.cpp Qmitk/QmitkSurfaceStampWidget.cpp Qmitk/QmitkMaskStampWidget.cpp Qmitk/QmitkStaticDynamicSegmentationDialog.cpp Qmitk/QmitkSimpleLabelSetListWidget.cpp Qmitk/QmitkSegmentationTaskListWidget.cpp Qmitk/QmitkTotalSegmentatorToolGUI.cpp Qmitk/QmitkSetupVirtualEnvUtil.cpp Qmitk/QmitkMultiLabelInspector.cpp Qmitk/QmitkMultiLabelManager.cpp Qmitk/QmitkMultiLabelTreeModel.cpp Qmitk/QmitkMultiLabelTreeView.cpp Qmitk/QmitkMultiLabelPresetHelper.cpp Qmitk/QmitkLabelColorItemDelegate.cpp Qmitk/QmitkLabelToggleItemDelegate.cpp Qmitk/QmitkFindSegmentationTaskDialog.cpp Qmitk/QmitkSegmentAnythingToolGUI.cpp SegmentationUtilities/QmitkBooleanOperationsWidget.cpp SegmentationUtilities/QmitkContourModelToImageWidget.cpp SegmentationUtilities/QmitkImageMaskingWidget.cpp SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp SegmentationUtilities/QmitkSurfaceToImageWidget.cpp SegmentationUtilities/QmitkDataSelectionWidget.cpp + SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.cpp ) set(H_FILES Qmitk/QmitkMultiLabelPresetHelper.h ) set(MOC_H_FILES Qmitk/QmitkSegWithPreviewToolGUIBase.h Qmitk/QmitkMultiLabelSegWithPreviewToolGUIBase.h Qmitk/QmitkBinaryThresholdToolGUIBase.h Qmitk/QmitkBinaryThresholdToolGUI.h Qmitk/QmitkBinaryThresholdULToolGUI.h Qmitk/QmitkConfirmSegmentationDialog.h Qmitk/QmitkCopyToClipBoardDialog.h Qmitk/QmitkDrawPaintbrushToolGUI.h Qmitk/QmitkErasePaintbrushToolGUI.h Qmitk/QmitkEditableContourToolGUIBase.h Qmitk/QmitkGrowCutToolGUI.h Qmitk/QmitkLiveWireTool2DGUI.h Qmitk/QmitkLassoToolGUI.h Qmitk/QmitkOtsuTool3DGUI.h Qmitk/QmitkPaintbrushToolGUI.h Qmitk/QmitkPickingToolGUI.h Qmitk/QmitkSlicesInterpolator.h Qmitk/QmitkToolGUI.h Qmitk/QmitkToolGUIArea.h Qmitk/QmitkToolSelectionBox.h Qmitk/QmitknnUNetFolderParser.h Qmitk/QmitknnUNetToolGUI.h Qmitk/QmitknnUNetGPU.h Qmitk/QmitknnUNetWorker.h Qmitk/QmitknnUNetEnsembleLayout.h Qmitk/QmitkSurfaceStampWidget.h Qmitk/QmitkMaskStampWidget.h Qmitk/QmitkStaticDynamicSegmentationDialog.h Qmitk/QmitkSimpleLabelSetListWidget.h Qmitk/QmitkSegmentationTaskListWidget.h Qmitk/QmitkTotalSegmentatorToolGUI.h Qmitk/QmitkSetupVirtualEnvUtil.h Qmitk/QmitkMultiLabelInspector.h Qmitk/QmitkMultiLabelManager.h Qmitk/QmitkMultiLabelTreeModel.h Qmitk/QmitkMultiLabelTreeView.h Qmitk/QmitkLabelColorItemDelegate.h Qmitk/QmitkLabelToggleItemDelegate.h Qmitk/QmitkFindSegmentationTaskDialog.h Qmitk/QmitkSegmentAnythingToolGUI.h SegmentationUtilities/QmitkBooleanOperationsWidget.h SegmentationUtilities/QmitkContourModelToImageWidget.h SegmentationUtilities/QmitkImageMaskingWidget.h SegmentationUtilities/QmitkMorphologicalOperationsWidget.h SegmentationUtilities/QmitkSurfaceToImageWidget.h SegmentationUtilities/QmitkDataSelectionWidget.h + SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.h ) set(UI_FILES Qmitk/QmitkConfirmSegmentationDialog.ui Qmitk/QmitkGrowCutToolWidgetControls.ui Qmitk/QmitkOtsuToolWidgetControls.ui Qmitk/QmitkSurfaceStampWidgetGUIControls.ui Qmitk/QmitkMaskStampWidgetGUIControls.ui Qmitk/QmitknnUNetToolGUIControls.ui Qmitk/QmitkEditableContourToolGUIControls.ui Qmitk/QmitkSegmentationTaskListWidget.ui Qmitk/QmitkTotalSegmentatorGUIControls.ui Qmitk/QmitkMultiLabelInspectorControls.ui Qmitk/QmitkMultiLabelManagerControls.ui Qmitk/QmitkFindSegmentationTaskDialog.ui Qmitk/QmitkSegmentAnythingGUIControls.ui SegmentationUtilities/QmitkBooleanOperationsWidgetControls.ui SegmentationUtilities/QmitkContourModelToImageWidgetControls.ui SegmentationUtilities/QmitkImageMaskingWidgetControls.ui SegmentationUtilities/QmitkMorphologicalOperationsWidgetControls.ui SegmentationUtilities/QmitkSurfaceToImageWidgetControls.ui SegmentationUtilities/QmitkDataSelectionWidgetControls.ui + SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidgetControls.ui ) set(QRC_FILES resources/SegmentationUI.qrc )