diff --git a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp index d07c107ce8..b5a37ba586 100644 --- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp +++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp @@ -1,110 +1,108 @@ /*============================================================================ 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. ============================================================================*/ // MITK #include "mitkOtsuTool3D.h" #include "mitkOtsuSegmentationFilter.h" #include #include // us #include #include #include #include namespace mitk { MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, OtsuTool3D, "Otsu Segmentation"); } mitk::OtsuTool3D::OtsuTool3D() : SegWithPreviewTool() { this->ResetsToEmptyPreviewOn(); this->UseSpecialPreviewColorOff(); } void mitk::OtsuTool3D::Activated() { Superclass::Activated(); m_NumberOfBins = 128; m_NumberOfRegions = 2; m_UseValley = false; this->SetLabelTransferScope(LabelTransferScope::AllLabels); this->SetLabelTransferMode(LabelTransferMode::AddLabel); } const char **mitk::OtsuTool3D::GetXPM() const { return nullptr; } us::ModuleResource mitk::OtsuTool3D::GetIconResource() const { us::Module *module = us::GetModuleContext()->GetModule(); us::ModuleResource resource = module->GetResource("Otsu.svg"); return resource; } const char* mitk::OtsuTool3D::GetName() const { return "Otsu"; } void mitk::OtsuTool3D::DoUpdatePreview(const Image* inputAtTimeStep, const Image* /*oldSegAtTimeStep*/, LabelSetImage* previewImage, TimeStepType timeStep) { int numberOfThresholds = m_NumberOfRegions - 1; mitk::OtsuSegmentationFilter::Pointer otsuFilter = mitk::OtsuSegmentationFilter::New(); otsuFilter->SetNumberOfThresholds(numberOfThresholds); otsuFilter->SetValleyEmphasis(m_UseValley); otsuFilter->SetNumberOfBins(m_NumberOfBins); otsuFilter->SetInput(inputAtTimeStep); otsuFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand); try { otsuFilter->Update(); } catch (...) { mitkThrow() << "itkOtsuFilter error (image dimension must be in {2, 3} and image must not be RGB)"; } - auto otsuResultImage = otsuFilter->GetOutput(); - - mitk::ImageReadAccessor newMitkImgAcc(otsuResultImage); + mitk::ImageReadAccessor newMitkImgAcc(otsuFilter->GetOutput()); previewImage->SetVolume(newMitkImgAcc.GetData(), timeStep); } void mitk::OtsuTool3D::UpdatePrepare() { Superclass::UpdatePrepare(); auto preview = this->GetPreviewSegmentation(); preview->RemoveLabels(preview->GetAllLabelValues()); for (unsigned int i = 0; i < m_NumberOfRegions; ++i) { - auto label = LabelSetImageHelper::CreateNewLabel(preview, "Otsu " + std::to_string(i)); + auto label = LabelSetImageHelper::CreateNewLabel(preview, "Otsu " + std::to_string(i), true); label->SetValue(i + 1); preview->AddLabel(label, preview->GetActiveLayer(), false, false); } } unsigned int mitk::OtsuTool3D::GetMaxNumberOfBins() const { const auto min = this->GetReferenceData()->GetStatistics()->GetScalarValueMin(); const auto max = this->GetReferenceData()->GetStatistics()->GetScalarValueMaxNoRecompute(); return static_cast(max - min) + 1; } diff --git a/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp index e199373c53..dcfb2bc540 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp @@ -1,143 +1,154 @@ /*============================================================================ 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 "QmitkOtsuTool3DGUI.h" #include "mitkOtsuTool3D.h" #include MITK_TOOL_GUI_MACRO(MITKSEGMENTATIONUI_EXPORT, QmitkOtsuTool3DGUI, "") QmitkOtsuTool3DGUI::QmitkOtsuTool3DGUI() : QmitkMultiLabelSegWithPreviewToolGUIBase(), m_SuperclassEnableConfirmSegBtnFnc(m_EnableConfirmSegBtnFnc) { auto enableMLSelectedDelegate = [this](bool enabled) { if (this->m_FirstPreviewComputation) { return false; } else { return this->m_SuperclassEnableConfirmSegBtnFnc(enabled); } }; m_EnableConfirmSegBtnFnc = enableMLSelectedDelegate; } void QmitkOtsuTool3DGUI::ConnectNewTool(mitk::SegWithPreviewTool* newTool) { Superclass::ConnectNewTool(newTool); newTool->IsTimePointChangeAwareOff(); m_FirstPreviewComputation = true; } void QmitkOtsuTool3DGUI::InitializeUI(QBoxLayout* mainLayout) { m_Controls.setupUi(this); mainLayout->addLayout(m_Controls.verticalLayout); connect(m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnPreviewBtnClicked())); connect(m_Controls.m_Spinbox, SIGNAL(valueChanged(int)), this, SLOT(OnRegionSpinboxChanged(int))); connect(m_Controls.advancedSettingsButton, SIGNAL(toggled(bool)), this, SLOT(OnAdvancedSettingsButtonToggled(bool))); this->OnAdvancedSettingsButtonToggled(false); Superclass::InitializeUI(mainLayout); } void QmitkOtsuTool3DGUI::OnRegionSpinboxChanged(int numberOfRegions) { // we have to change to minimum number of histogram bins accordingly int curBinValue = m_Controls.m_BinsSpinBox->value(); if (curBinValue < numberOfRegions) m_Controls.m_BinsSpinBox->setValue(numberOfRegions); } void QmitkOtsuTool3DGUI::OnAdvancedSettingsButtonToggled(bool toggled) { m_Controls.m_ValleyCheckbox->setVisible(toggled); m_Controls.binLabel->setVisible(toggled); m_Controls.m_BinsSpinBox->setVisible(toggled); auto tool = this->GetConnectedToolAs(); if (toggled && nullptr != tool) { int max = tool->GetMaxNumberOfBins(); if (max >= m_Controls.m_BinsSpinBox->minimum()) { m_Controls.m_BinsSpinBox->setMaximum(max); } } } void QmitkOtsuTool3DGUI::OnPreviewBtnClicked() { auto tool = this->GetConnectedToolAs(); if (nullptr != tool) { if (!m_FirstPreviewComputation && (tool->GetNumberOfRegions() == static_cast(m_Controls.m_Spinbox->value()) && tool->GetUseValley() == m_Controls.m_ValleyCheckbox->isChecked() && tool->GetNumberOfBins() == static_cast(m_Controls.m_BinsSpinBox->value()))) return; m_FirstPreviewComputation = false; try { int proceed; QMessageBox *messageBox = new QMessageBox(QMessageBox::Question, nullptr, "The otsu segmentation computation may take several minutes depending " "on the number of Regions you selected. Proceed anyway?", QMessageBox::Ok | QMessageBox::Cancel); if (m_Controls.m_Spinbox->value() >= 5) { proceed = messageBox->exec(); if (proceed != QMessageBox::Ok) return; } tool->SetNumberOfRegions(static_cast(m_Controls.m_Spinbox->value())); tool->SetUseValley(m_Controls.m_ValleyCheckbox->isChecked()); tool->SetNumberOfBins(static_cast(m_Controls.m_BinsSpinBox->value())); tool->UpdatePreview(); } + catch (const std::exception& e) + { + this->setCursor(Qt::ArrowCursor); + QMessageBox* messageBox = + new QMessageBox(QMessageBox::Critical, + nullptr, + e.what()); + messageBox->exec(); + delete messageBox; + return; + } catch (...) { this->setCursor(Qt::ArrowCursor); QMessageBox *messageBox = new QMessageBox(QMessageBox::Critical, nullptr, - "itkOtsuFilter error: image dimension must be in {2, 3} and no RGB images can be handled."); + "Unkown error while computing Otsu preview."); messageBox->exec(); delete messageBox; return; } this->SetLabelSetPreview(tool->GetPreviewSegmentation()); tool->IsTimePointChangeAwareOn(); this->ActualizePreviewLabelVisibility(); } } void QmitkOtsuTool3DGUI::EnableWidgets(bool enabled) { Superclass::EnableWidgets(enabled); m_Controls.m_ValleyCheckbox->setEnabled(enabled); m_Controls.binLabel->setEnabled(enabled); m_Controls.m_BinsSpinBox->setEnabled(enabled); m_Controls.previewButton->setEnabled(enabled); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkSimpleLabelSetListWidget.cpp b/Modules/SegmentationUI/Qmitk/QmitkSimpleLabelSetListWidget.cpp index bd18ca218b..7094b974ab 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSimpleLabelSetListWidget.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSimpleLabelSetListWidget.cpp @@ -1,164 +1,165 @@ /*============================================================================ 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 "QmitkSimpleLabelSetListWidget.h" #include "mitkMessage.h" #include QmitkSimpleLabelSetListWidget::QmitkSimpleLabelSetListWidget(QWidget* parent) : QWidget(parent), m_LabelList(nullptr), m_Emmiting(false) { QGridLayout* layout = new QGridLayout(this); this->setContentsMargins(0, 0, 0, 0); m_LabelList = new QListWidget(this); m_LabelList->setSelectionMode(QAbstractItemView::MultiSelection); m_LabelList->setResizeMode(QListView::Adjust); m_LabelList->setAutoScrollMargin(0); layout->addWidget(m_LabelList); connect(m_LabelList, SIGNAL(itemSelectionChanged()), this, SLOT(OnLabelSelectionChanged())); } QmitkSimpleLabelSetListWidget::~QmitkSimpleLabelSetListWidget() { if (m_LabelSetImage.IsNotNull()) { m_LabelSetImage->AfterChangeLayerEvent -= mitk::MessageDelegate( this, &QmitkSimpleLabelSetListWidget::OnLayerChanged); } } QmitkSimpleLabelSetListWidget::LabelVectorType QmitkSimpleLabelSetListWidget::SelectedLabels() const { auto selectedItems = m_LabelList->selectedItems(); LabelVectorType result; QList::Iterator it; for (it = selectedItems.begin(); it != selectedItems.end(); ++it) { auto labelValue = (*it)->data(Qt::UserRole).toUInt(); result.push_back(m_LabelSetImage->GetLabel(labelValue)); } return result; } const mitk::LabelSetImage* QmitkSimpleLabelSetListWidget::GetLabelSetImage() const { return m_LabelSetImage; } void QmitkSimpleLabelSetListWidget::SetLabelSetImage(const mitk::LabelSetImage* image) { if (image != m_LabelSetImage) { m_LabelAddedObserver.Reset(); m_LabelModifiedObserver.Reset(); m_LabelRemovedObserver.Reset(); m_LabelSetImage = image; if (m_LabelSetImage.IsNotNull()) { auto& widget = *this; m_LabelAddedObserver.Reset(m_LabelSetImage, mitk::LabelAddedEvent(), [&widget](const itk::EventObject& event) { auto labelEvent = dynamic_cast(&event); widget.OnLabelChanged(labelEvent->GetLabelValue()); }); m_LabelModifiedObserver.Reset(m_LabelSetImage, mitk::LabelModifiedEvent(), [&widget](const itk::EventObject& event) { auto labelEvent = dynamic_cast(&event); widget.OnLabelChanged(labelEvent->GetLabelValue()); }); m_LabelRemovedObserver.Reset(m_LabelSetImage, mitk::LabelRemovedEvent(), [&widget](const itk::EventObject& event) { auto labelEvent = dynamic_cast(&event); widget.OnLabelChanged(labelEvent->GetLabelValue()); }); m_LabelSetImage->AfterChangeLayerEvent += mitk::MessageDelegate( this, &QmitkSimpleLabelSetListWidget::OnLayerChanged); } } } void QmitkSimpleLabelSetListWidget::OnLayerChanged() { if (!this->m_Emmiting) { this->ResetList(); this->m_Emmiting = true; emit ActiveLayerChanged(); emit SelectedLabelsChanged(this->SelectedLabels()); this->m_Emmiting = false; } } void QmitkSimpleLabelSetListWidget::OnLabelChanged(mitk::LabelSetImage::LabelValueType lv) { - if (!this->m_Emmiting && m_LabelSetImage->GetGroupIndexOfLabel(lv)==m_LabelSetImage->GetActiveLayer()) + if (!this->m_Emmiting + && (!m_LabelSetImage->ExistLabel(lv) || m_LabelSetImage->GetGroupIndexOfLabel(lv)==m_LabelSetImage->GetActiveLayer())) { this->ResetList(); this->m_Emmiting = true; emit ActiveLayerChanged(); emit SelectedLabelsChanged(this->SelectedLabels()); this->m_Emmiting = false; } } void QmitkSimpleLabelSetListWidget::OnLabelSelectionChanged() { if (!this->m_Emmiting) { this->m_Emmiting = true; emit SelectedLabelsChanged(this->SelectedLabels()); this->m_Emmiting = false; } } void QmitkSimpleLabelSetListWidget::ResetList() { m_LabelList->clear(); auto activeLayerID = m_LabelSetImage->GetActiveLayer(); auto labels = m_LabelSetImage->GetConstLabelsByValue(m_LabelSetImage->GetLabelValuesByGroup(activeLayerID)); for (auto& label : labels) { auto color = label->GetColor(); QPixmap pixmap(10, 10); pixmap.fill(QColor(color[0] * 255, color[1] * 255, color[2] * 255)); QIcon icon(pixmap); QListWidgetItem* item = new QListWidgetItem(icon, QString::fromStdString(label->GetName())); item->setData(Qt::UserRole, QVariant(label->GetValue())); m_LabelList->addItem(item); } } void QmitkSimpleLabelSetListWidget::SetSelectedLabels(const LabelVectorType& selectedLabels) { for (int i = 0; i < m_LabelList->count(); ++i) { QListWidgetItem* item = m_LabelList->item(i); auto labelValue = item->data(Qt::UserRole).toUInt(); auto finding = std::find_if(selectedLabels.begin(), selectedLabels.end(), [labelValue](const mitk::Label* label) {return label->GetValue() == labelValue; }); item->setSelected(finding != selectedLabels.end()); } }