diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp index b286e6589c..a1d2d23974 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp @@ -1,265 +1,272 @@ /*============================================================================ 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 "QmitkBooleanOperationsWidget.h" #include #include #include #include #include #include #include #include QmitkBooleanOperationsWidget::QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent) : QWidget(parent) { m_Controls = new Ui::QmitkBooleanOperationsWidgetControls; m_Controls->setupUi(this); m_Controls->label1st->setText(""); m_Controls->label1st->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); m_Controls->label2nd->setText(""); m_Controls->label2nd->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); 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 boolean operations.")); m_Controls->segNodeSelector->SetPopUpTitel(QStringLiteral("Select segmentation")); m_Controls->segNodeSelector->SetPopUpHint(QStringLiteral("Select the segmentation that should be used as source for boolean operations.")); m_Controls->labelInspector->SetMultiSelectionMode(true); connect(m_Controls->segNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkBooleanOperationsWidget::OnSegSelectionChanged); connect(m_Controls->labelInspector, &QmitkMultiLabelInspector::CurrentSelectionChanged, this, &QmitkBooleanOperationsWidget::OnLabelSelectionChanged); connect(m_Controls->differenceButton, &QToolButton::clicked, this, &QmitkBooleanOperationsWidget::OnDifferenceButtonClicked); connect(m_Controls->intersectionButton, &QToolButton::clicked, this, &QmitkBooleanOperationsWidget::OnIntersectionButtonClicked); connect(m_Controls->unionButton, &QToolButton::clicked, this, &QmitkBooleanOperationsWidget::OnUnionButtonClicked); m_Controls->segNodeSelector->SetAutoSelectNewNodes(true); this->ConfigureWidgets(); } QmitkBooleanOperationsWidget::~QmitkBooleanOperationsWidget() { m_Controls->labelInspector->SetMultiLabelNode(nullptr); } void QmitkBooleanOperationsWidget::OnSegSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/) { auto node = m_Controls->segNodeSelector->GetSelectedNode(); m_Controls->labelInspector->SetMultiLabelNode(node); this->ConfigureWidgets(); } void QmitkBooleanOperationsWidget::OnLabelSelectionChanged(mitk::LabelSetImage::LabelValueVectorType /*labels*/) { this->ConfigureWidgets(); } namespace { - std::string GenerateLabelHTML(const mitk::Label* label) + std::string GenerateLabelHTML(const mitk::Label* label, const mitk::LabelSetImage* segmentation) { std::stringstream stream; auto color = label->GetColor(); stream << "(color.GetRed()*255) << std::setw(2) << static_cast(color.GetGreen()*255) << std::setw(2) << static_cast(color.GetBlue()*255) << "; font-size: 20px '>■" << std::dec; - stream << " " << label->GetName()<< ""; + stream << " " << label->GetName(); + if (segmentation->GetLabelValuesByName(segmentation->GetGroupIndexOfLabel(label->GetValue()), label->GetName()).size() > 1) + { + stream << " [" << label->GetValue() << "]"; + } + stream << ""; return stream.str(); } } void QmitkBooleanOperationsWidget::ConfigureWidgets() { auto selectedLabelValues = m_Controls->labelInspector->GetSelectedLabels(); auto seg = m_Controls->labelInspector->GetMultiLabelSegmentation(); auto styleSheet = qApp->styleSheet(); m_Controls->line1stLabel->document()->setDefaultStyleSheet(styleSheet); m_Controls->lineOtherLabels->document()->setDefaultStyleSheet(styleSheet); if (selectedLabelValues.empty()) { m_Controls->line1stLabel->setHtml(QStringLiteral("Select 1st label to proceed.")); } else { mitk::Label::ConstPointer label = seg->GetLabel(selectedLabelValues.front()); if (label.IsNotNull()) - m_Controls->line1stLabel->setText(QString::fromStdString(GenerateLabelHTML(label))); + m_Controls->line1stLabel->setText(QString::fromStdString(GenerateLabelHTML(label,seg))); else m_Controls->line1stLabel->setText(QString("Unknown label ID ")+QString::number(selectedLabelValues.front())); } if (selectedLabelValues.size() < 2) { m_Controls->lineOtherLabels->setHtml(QStringLiteral("Select secondary label(s) to proceed.")); } else { + decltype(selectedLabelValues) otherLabelValues(selectedLabelValues.begin() + 1, selectedLabelValues.end()); + std::stringstream stream; - for (const auto& labelValue : selectedLabelValues) + for (const auto& labelValue : otherLabelValues) { mitk::Label::ConstPointer label = seg->GetLabel(labelValue); if (stream.rdbuf()->in_avail() != 0) stream << "; "; if (label.IsNotNull()) - stream << GenerateLabelHTML(label); + stream << GenerateLabelHTML(label,seg); else stream << "Unknown label ID " << labelValue; } m_Controls->lineOtherLabels->setText(QString::fromStdString(stream.str())); } m_Controls->differenceButton->setEnabled(selectedLabelValues.size()>1); m_Controls->intersectionButton->setEnabled(selectedLabelValues.size() > 1); m_Controls->unionButton->setEnabled(selectedLabelValues.size() > 1); } void QmitkBooleanOperationsWidget::OnDifferenceButtonClicked() { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); mitk::ProgressBar::GetInstance()->Reset(); mitk::ProgressBar::GetInstance()->AddStepsToDo(110); unsigned int currentProgress = 0; auto progressCallback = [¤tProgress](float filterProgress) { auto delta = (filterProgress * 100) - currentProgress; if (delta > 0) { currentProgress += delta; mitk::ProgressBar::GetInstance()->Progress(delta); } }; auto selectedLabelValues = m_Controls->labelInspector->GetSelectedLabels(); auto minuend = selectedLabelValues.front(); auto subtrahends = mitk::LabelSetImage::LabelValueVectorType(selectedLabelValues.begin() + 1, selectedLabelValues.end()); auto seg = m_Controls->labelInspector->GetMultiLabelSegmentation(); auto resultMask = mitk::BooleanOperation::GenerateDifference(seg, minuend, subtrahends, progressCallback); std::stringstream name; name << "Difference " << seg->GetLabel(minuend)->GetName() << " -"; for (auto label : subtrahends) { name << " " << seg->GetLabel(label)->GetName(); } this->SaveResultLabelMask(resultMask, name.str()); mitk::ProgressBar::GetInstance()->Reset(); QApplication::restoreOverrideCursor(); } void QmitkBooleanOperationsWidget::OnIntersectionButtonClicked() { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); mitk::ProgressBar::GetInstance()->Reset(); mitk::ProgressBar::GetInstance()->AddStepsToDo(110); unsigned int currentProgress = 0; auto progressCallback = [¤tProgress](float filterProgress) { auto delta = (filterProgress * 100) - currentProgress; if (delta > 0) { currentProgress += delta; mitk::ProgressBar::GetInstance()->Progress(delta); } }; auto selectedLabelValues = m_Controls->labelInspector->GetSelectedLabels(); auto seg = m_Controls->labelInspector->GetMultiLabelSegmentation(); auto resultMask = mitk::BooleanOperation::GenerateIntersection(seg, selectedLabelValues, progressCallback); std::stringstream name; name << "Intersection"; for (auto label : selectedLabelValues) { name << " " << seg->GetLabel(label)->GetName(); } this->SaveResultLabelMask(resultMask, name.str()); mitk::ProgressBar::GetInstance()->Reset(); QApplication::restoreOverrideCursor(); } void QmitkBooleanOperationsWidget::OnUnionButtonClicked() { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); mitk::ProgressBar::GetInstance()->Reset(); mitk::ProgressBar::GetInstance()->AddStepsToDo(110); unsigned int currentProgress = 0; auto progressCallback = [¤tProgress](float filterProgress) { auto delta = (filterProgress * 100) - currentProgress; if (delta > 0) { currentProgress += delta; mitk::ProgressBar::GetInstance()->Progress(delta); } }; auto selectedLabelValues = m_Controls->labelInspector->GetSelectedLabels(); auto seg = m_Controls->labelInspector->GetMultiLabelSegmentation(); auto resultMask = mitk::BooleanOperation::GenerateUnion(seg, selectedLabelValues, progressCallback); std::stringstream name; name << "Union"; for (auto label : selectedLabelValues) { name << " " << seg->GetLabel(label)->GetName(); } this->SaveResultLabelMask(resultMask, name.str()); mitk::ProgressBar::GetInstance()->Reset(); QApplication::restoreOverrideCursor(); } void QmitkBooleanOperationsWidget::SaveResultLabelMask(const mitk::Image* resultMask, const std::string& labelName) const { auto seg = m_Controls->labelInspector->GetMultiLabelSegmentation(); if (seg == nullptr) mitkThrow() << "Widget is in invalid state. Processing was triggered with no segmentation selected."; auto labels = m_Controls->labelInspector->GetSelectedLabels(); if (labels.empty()) mitkThrow() << "Widget is in invalid state. Processing was triggered with no label selected."; auto groupID = seg->AddLayer(); auto newLabel = mitk::LabelSetImageHelper::CreateNewLabel(seg, labelName, true); seg->AddLabelWithContent(newLabel, resultMask, groupID, 1); m_Controls->labelInspector->GetMultiLabelSegmentation()->Modified(); m_Controls->labelInspector->GetMultiLabelNode()->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); }