diff --git a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp index 917451a48c..a04cb3e085 100644 --- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp +++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp @@ -1,277 +1,253 @@ /*============================================================================ 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 "mitkImageAccessByItk.h" #include "mitkLabelSetImage.h" #include "mitkOtsuSegmentationFilter.h" #include "mitkRenderingManager.h" #include "mitkToolManager.h" #include #include #include #include #include #include // ITK #include #include #include // us #include #include #include #include #include namespace mitk { MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, OtsuTool3D, "Otsu Segmentation"); } -mitk::OtsuTool3D::OtsuTool3D() +mitk::OtsuTool3D::OtsuTool3D() : AutoSegmentationWithPreviewTool(true) { } mitk::OtsuTool3D::~OtsuTool3D() { } +void mitk::OtsuTool3D::SetSelectedRegions(const SelectedRegionVectorType& regions) +{ + if (this->m_SelectedRegions != regions) + { + this->m_SelectedRegions = regions; + //Note: we do not call this->Modified() on puprose. Reason: changing the + //selected regions should not force to run otsu filter in DoUpdatePreview due to changed MTime. + } +} + +mitk::OtsuTool3D::SelectedRegionVectorType mitk::OtsuTool3D::GetSelectedRegions() const +{ + return this->m_SelectedRegions; +} + void mitk::OtsuTool3D::Activated() { Superclass::Activated(); - if (m_ToolManager) - { - m_OriginalImage = dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData()); - - m_BinaryPreviewNode = mitk::DataNode::New(); - m_BinaryPreviewNode->SetName("Binary_Preview"); - m_BinaryPreviewNode->SetProperty("color", ColorProperty::New(0.0, 1.0, 0.0)); - m_BinaryPreviewNode->SetProperty("opacity", FloatProperty::New(0.3)); - // m_BinaryPreviewNode->SetBoolProperty("helper object", true); - // m_BinaryPreviewNode->SetProperty("binary", mitk::BoolProperty::New(true)); - m_ToolManager->GetDataStorage()->Add(this->m_BinaryPreviewNode); - - m_MultiLabelResultNode = mitk::DataNode::New(); - m_MultiLabelResultNode->SetName("Otsu_Preview"); - // m_MultiLabelResultNode->SetBoolProperty("helper object", true); - m_MultiLabelResultNode->SetVisibility(true); - - m_MaskedImagePreviewNode = mitk::DataNode::New(); - m_MaskedImagePreviewNode->SetName("Volume_Preview"); - // m_MultiLabelResultNode->SetBoolProperty("helper object", true); - m_MaskedImagePreviewNode->SetVisibility(false); - - m_ToolManager->GetDataStorage()->Add(this->m_MultiLabelResultNode); - } + m_SelectedRegions = {}; + m_NumberOfBins = 128; + m_NumberOfRegions = 2; + m_UseValley = false; + + m_OtsuResultNode = mitk::DataNode::New(); + m_OtsuResultNode->SetName("Otsu_Preview"); + // m_MultiLabelResultNode->SetBoolProperty("helper object", true); + m_OtsuResultNode->SetVisibility(true); + m_OtsuResultNode->SetOpacity(1.0); + + m_ToolManager->GetDataStorage()->Add(this->m_OtsuResultNode); } void mitk::OtsuTool3D::Deactivated() { - m_ToolManager->GetDataStorage()->Remove(this->m_MultiLabelResultNode); - m_MultiLabelResultNode = nullptr; - m_ToolManager->GetDataStorage()->Remove(this->m_BinaryPreviewNode); - m_BinaryPreviewNode = nullptr; - m_ToolManager->GetDataStorage()->Remove(this->m_MaskedImagePreviewNode); - m_MaskedImagePreviewNode = nullptr; + m_ToolManager->GetDataStorage()->Remove(this->m_OtsuResultNode); + m_OtsuResultNode = nullptr; Superclass::Deactivated(); } 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_48x48.png"); return resource; } -void mitk::OtsuTool3D::RunSegmentation(int regions, bool useValley, int numberOfBins) +const char* mitk::OtsuTool3D::GetName() const { - int numberOfThresholds = regions - 1; + return "Otsu"; +} +void mitk::OtsuTool3D::UpdateCleanUp() +{ + if (m_OtsuResultNode.IsNotNull()) + m_OtsuResultNode->SetVisibility(m_SelectedRegions.empty()); - const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); - auto image3D = Get3DImageByTimePoint(m_OriginalImage, timePoint); + if (nullptr != this->GetPreviewSegmentationNode()) + this->GetPreviewSegmentationNode()->SetVisibility(!m_SelectedRegions.empty()); - if (nullptr == image3D) + if (m_SelectedRegions.empty()) { - MITK_WARN << "Cannot run segementation. Currently selected timepoint is not in the time bounds of the selected reference image. Time point: " << timePoint; - return; + this->ResetPreviewNode(); } +} - mitk::OtsuSegmentationFilter::Pointer otsuFilter = mitk::OtsuSegmentationFilter::New(); - otsuFilter->SetNumberOfThresholds(numberOfThresholds); - otsuFilter->SetValleyEmphasis(useValley); - otsuFilter->SetNumberOfBins(numberOfBins); - otsuFilter->SetInput(image3D); +void mitk::OtsuTool3D::DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep) +{ + int numberOfThresholds = m_NumberOfRegions - 1; - try + const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); + mitk::LabelSetImage::Pointer otsuResultImage = dynamic_cast(this->m_OtsuResultNode->GetData()); + + if (nullptr == m_OtsuResultNode->GetData() + || this->GetMTime() > m_OtsuResultNode->GetData()->GetMTime() + || this->m_LastOtsuTimeStep != timeStep //this covers the case where dynamic + //segmentations have to compute a preview + //for all time steps on confirmation + || this->GetLastTimePointOfUpdate() != timePoint //this ensures that static seg + //previews work with dynamic images + //with avoiding unnecessary other otsu computations + ) { - otsuFilter->Update(); + if (nullptr == inputAtTimeStep) + { + MITK_WARN << "Cannot run segementation. Currently selected input image is not set."; + return; + } + + this->m_LastOtsuTimeStep = timeStep; + + 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)"; + } + + otsuResultImage = mitk::LabelSetImage::New(); + otsuResultImage->InitializeByLabeledImage(otsuFilter->GetOutput()); + this->m_OtsuResultNode->SetData(otsuResultImage); + this->m_OtsuResultNode->SetProperty("binary", mitk::BoolProperty::New(false)); + mitk::RenderingModeProperty::Pointer renderingMode = mitk::RenderingModeProperty::New(); + renderingMode->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); + this->m_OtsuResultNode->SetProperty("Image Rendering.Mode", renderingMode); + mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); + mitk::LookupTableProperty::Pointer prop = mitk::LookupTableProperty::New(lut); + vtkSmartPointer lookupTable = vtkSmartPointer::New(); + lookupTable->SetHueRange(1.0, 0.0); + lookupTable->SetSaturationRange(1.0, 1.0); + lookupTable->SetValueRange(1.0, 1.0); + lookupTable->SetTableRange(-1.0, 1.0); + lookupTable->Build(); + lut->SetVtkLookupTable(lookupTable); + prop->SetLookupTable(lut); + this->m_OtsuResultNode->SetProperty("LookupTable", prop); + mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); + mitk::LevelWindow levelwindow; + levelwindow.SetRangeMinMax(0, numberOfThresholds + 1); + levWinProp->SetLevelWindow(levelwindow); + this->m_OtsuResultNode->SetProperty("levelwindow", levWinProp); } - catch (...) + + if (!m_SelectedRegions.empty()) { - mitkThrow() << "itkOtsuFilter error (image dimension must be in {2, 3} and image must not be RGB)"; + AccessByItk_n(otsuResultImage, CalculatePreview, (previewImage, timeStep)); } - - m_ToolManager->GetDataStorage()->Remove(this->m_MultiLabelResultNode); - m_MultiLabelResultNode = nullptr; - m_MultiLabelResultNode = mitk::DataNode::New(); - m_MultiLabelResultNode->SetName("Otsu_Preview"); - m_MultiLabelResultNode->SetVisibility(true); - m_ToolManager->GetDataStorage()->Add(this->m_MultiLabelResultNode); - m_MultiLabelResultNode->SetOpacity(1.0); - - mitk::LabelSetImage::Pointer resultImage = mitk::LabelSetImage::New(); - resultImage->InitializeByLabeledImage(otsuFilter->GetOutput()); - this->m_MultiLabelResultNode->SetData(resultImage); - m_MultiLabelResultNode->SetProperty("binary", mitk::BoolProperty::New(false)); - mitk::RenderingModeProperty::Pointer renderingMode = mitk::RenderingModeProperty::New(); - renderingMode->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); - m_MultiLabelResultNode->SetProperty("Image Rendering.Mode", renderingMode); - mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); - mitk::LookupTableProperty::Pointer prop = mitk::LookupTableProperty::New(lut); - vtkSmartPointer lookupTable = vtkSmartPointer::New(); - lookupTable->SetHueRange(1.0, 0.0); - lookupTable->SetSaturationRange(1.0, 1.0); - lookupTable->SetValueRange(1.0, 1.0); - lookupTable->SetTableRange(-1.0, 1.0); - lookupTable->Build(); - lut->SetVtkLookupTable(lookupTable); - prop->SetLookupTable(lut); - m_MultiLabelResultNode->SetProperty("LookupTable", prop); - mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); - mitk::LevelWindow levelwindow; - levelwindow.SetRangeMinMax(0, numberOfThresholds + 1); - levWinProp->SetLevelWindow(levelwindow); - m_MultiLabelResultNode->SetProperty("levelwindow", levWinProp); - - // m_BinaryPreviewNode->SetVisibility(false); - // m_MultiLabelResultNode->SetVisibility(true); - // this->m_OtsuSegmentationDialog->setCursor(Qt::ArrowCursor); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -void mitk::OtsuTool3D::ConfirmSegmentation() -{ - mitk::LabelSetImage::Pointer resultImage = mitk::LabelSetImage::New(); - resultImage->InitializeByLabeledImage(dynamic_cast(m_BinaryPreviewNode->GetData())); - GetTargetSegmentationNode()->SetData(resultImage); - - m_ToolManager->ActivateTool(-1); -} - -void mitk::OtsuTool3D::UpdateBinaryPreview(std::vector regionIDs) -{ - m_MultiLabelResultNode->SetVisibility(false); - mitk::Image::Pointer multiLabelSegmentation = dynamic_cast(m_MultiLabelResultNode->GetData()); - AccessByItk_1(multiLabelSegmentation, CalculatePreview, regionIDs); } template -void mitk::OtsuTool3D::CalculatePreview(itk::Image *itkImage, std::vector regionIDs) +void mitk::OtsuTool3D::CalculatePreview(itk::Image *itkImage, mitk::Image* segmentation, unsigned int timeStep) { typedef itk::Image InputImageType; typedef itk::Image OutputImageType; typedef itk::BinaryThresholdImageFilter FilterType; typename FilterType::Pointer filter = FilterType::New(); // InputImageType::Pointer itkImage; - typename OutputImageType::Pointer itkBinaryTempImage1; - typename OutputImageType::Pointer itkBinaryTempImage2; typename OutputImageType::Pointer itkBinaryResultImage; - // mitk::Image::Pointer multiLabelSegmentation = dynamic_cast(m_MultiLabelResultNode->GetData()); - // mitk::CastToItkImage(multiLabelSegmentation, itkImage); - filter->SetInput(itkImage); - filter->SetLowerThreshold(regionIDs[0]); - filter->SetUpperThreshold(regionIDs[0]); + filter->SetLowerThreshold(m_SelectedRegions[0]); + filter->SetUpperThreshold(m_SelectedRegions[0]); filter->SetInsideValue(1); filter->SetOutsideValue(0); + filter->AddObserver(itk::ProgressEvent(), m_ProgressCommand); filter->Update(); - itkBinaryTempImage2 = filter->GetOutput(); - - typename itk::OrImageFilter::Pointer orFilter = - itk::OrImageFilter::New(); + itkBinaryResultImage = filter->GetOutput(); + itkBinaryResultImage->DisconnectPipeline(); // if more than one region id is used compute the union of all given binary regions - for (auto it = regionIDs.begin(); it != regionIDs.end(); ++it) + for (const auto regionID : m_SelectedRegions) { - filter->SetLowerThreshold(*it); - filter->SetUpperThreshold(*it); - filter->SetInsideValue(1); - filter->SetOutsideValue(0); - filter->Update(); - itkBinaryTempImage1 = filter->GetOutput(); - - orFilter->SetInput1(itkBinaryTempImage1); - orFilter->SetInput2(itkBinaryTempImage2); - - orFilter->UpdateLargestPossibleRegion(); - itkBinaryResultImage = orFilter->GetOutput(); - itkBinaryTempImage2 = itkBinaryResultImage; + if (regionID != m_SelectedRegions[0]) + { + filter->SetLowerThreshold(regionID); + filter->SetUpperThreshold(regionID); + filter->SetInsideValue(1); + filter->SetOutsideValue(0); + filter->Update(); + + typename OutputImageType::Pointer tempImage = filter->GetOutput(); + + typename itk::OrImageFilter::Pointer orFilter = + itk::OrImageFilter::New(); + orFilter->SetInput1(tempImage); + orFilter->SetInput2(itkBinaryResultImage); + orFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand); + + orFilter->UpdateLargestPossibleRegion(); + itkBinaryResultImage = orFilter->GetOutput(); + } } //---------------------------------------------------------------------------------------------------- - mitk::Image::Pointer binarySegmentation; - mitk::CastToMitkImage(itkBinaryResultImage, binarySegmentation); - m_BinaryPreviewNode->SetData(binarySegmentation); - m_BinaryPreviewNode->SetVisibility(true); - m_BinaryPreviewNode->SetProperty("outline binary", mitk::BoolProperty::New(false)); - - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -const char *mitk::OtsuTool3D::GetName() const -{ - return "Otsu"; -} -void mitk::OtsuTool3D::UpdateVolumePreview(bool volumeRendering) -{ - if (volumeRendering) - { - m_MaskedImagePreviewNode->SetBoolProperty("volumerendering", true); - m_MaskedImagePreviewNode->SetBoolProperty("volumerendering.uselod", true); - } - else - { - m_MaskedImagePreviewNode->SetBoolProperty("volumerendering", false); - } - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -void mitk::OtsuTool3D::ShowMultiLabelResultNode(bool show) -{ - m_MultiLabelResultNode->SetVisibility(show); - m_BinaryPreviewNode->SetVisibility(!show); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + segmentation->SetVolume((void*)(itkBinaryResultImage->GetPixelContainer()->GetBufferPointer()), timeStep); } -int mitk::OtsuTool3D::GetNumberOfBins() +unsigned int mitk::OtsuTool3D::GetMaxNumberOfBins() const { - ScalarType min = m_OriginalImage.GetPointer()->GetStatistics()->GetScalarValueMin(); - ScalarType max = m_OriginalImage.GetPointer()->GetStatistics()->GetScalarValueMaxNoRecompute(); - return static_cast(max - min) + 1; + const auto min = this->GetReferenceData()->GetStatistics()->GetScalarValueMin(); + const auto max = this->GetReferenceData()->GetStatistics()->GetScalarValueMaxNoRecompute(); + return static_cast(max - min) + 1; } diff --git a/Modules/Segmentation/Interactions/mitkOtsuTool3D.h b/Modules/Segmentation/Interactions/mitkOtsuTool3D.h index f4e22cab62..7761ec60dd 100644 --- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.h +++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.h @@ -1,68 +1,80 @@ /*============================================================================ 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 MITKOTSUTOOL3D_H #define MITKOTSUTOOL3D_H #include "itkImage.h" -#include "mitkAutoSegmentationTool.h" +#include "mitkAutoSegmentationWithPreviewTool.h" +#include "mitkDataNode.h" #include namespace us { class ModuleResource; } namespace mitk { class Image; - class MITKSEGMENTATION_EXPORT OtsuTool3D : public AutoSegmentationTool + class MITKSEGMENTATION_EXPORT OtsuTool3D : public AutoSegmentationWithPreviewTool { public: - mitkClassMacro(OtsuTool3D, AutoSegmentationTool); + mitkClassMacro(OtsuTool3D, AutoSegmentationWithPreviewTool); itkFactorylessNewMacro(Self); itkCloneMacro(Self); - const char *GetName() const override; + const char *GetName() const override; const char **GetXPM() const override; us::ModuleResource GetIconResource() const override; void Activated() override; void Deactivated() override; - void RunSegmentation(int regions, bool useValley, int numberOfBins); - void ConfirmSegmentation(); - // void UpdateBinaryPreview(int regionID); - void UpdateBinaryPreview(std::vector regionIDs); - void UpdateVolumePreview(bool volumeRendering); - void ShowMultiLabelResultNode(bool); + itkSetMacro(NumberOfBins, unsigned int); + itkGetConstMacro(NumberOfBins, unsigned int); - int GetNumberOfBins(); + itkSetMacro(NumberOfRegions, unsigned int); + itkGetConstMacro(NumberOfRegions, unsigned int); + + itkSetMacro(UseValley, bool); + itkGetConstMacro(UseValley, bool); + itkBooleanMacro(UseValley); + + using SelectedRegionVectorType = std::vector; + void SetSelectedRegions(const SelectedRegionVectorType& regions); + SelectedRegionVectorType GetSelectedRegions() const; + + /**Returns the number of max bins based on the current input image.*/ + unsigned int GetMaxNumberOfBins() const; protected: OtsuTool3D(); ~OtsuTool3D() override; + void UpdateCleanUp() override; + void DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep) override; + template - void CalculatePreview(itk::Image *itkImage, std::vector regionIDs); + void CalculatePreview(itk::Image *itkImage, mitk::Image* segmentation, unsigned int timeStep); - itk::SmartPointer m_OriginalImage; - // holds the user selected binary segmentation - mitk::DataNode::Pointer m_BinaryPreviewNode; - // holds the multilabel result as a preview image - mitk::DataNode::Pointer m_MultiLabelResultNode; - // holds the user selected binary segmentation masked original image - mitk::DataNode::Pointer m_MaskedImagePreviewNode; + unsigned int m_NumberOfBins = 128; + unsigned int m_NumberOfRegions = 2; + bool m_UseValley = false; + SelectedRegionVectorType m_SelectedRegions = {}; + // holds the multilabel result as a preview image + mitk::DataNode::Pointer m_OtsuResultNode; + TimeStepType m_LastOtsuTimeStep = 0; }; // class } // namespace #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp index 2d9b8f8032..031b353dab 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp @@ -1,184 +1,214 @@ /*============================================================================ 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 "QmitkConfirmSegmentationDialog.h" #include #include #include #include #include #include MITK_TOOL_GUI_MACRO(MITKSEGMENTATIONUI_EXPORT, QmitkOtsuTool3DGUI, "") QmitkOtsuTool3DGUI::QmitkOtsuTool3DGUI() : QmitkToolGUI(), m_NumberOfRegions(0) { m_Controls.setupUi(this); connect(m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnSpinboxValueAccept())); connect(m_Controls.m_selectionListWidget, SIGNAL(itemSelectionChanged()), this, SLOT(OnRegionSelectionChanged())); connect(m_Controls.m_Spinbox, SIGNAL(valueChanged(int)), this, SLOT(OnRegionSpinboxChanged(int))); connect(m_Controls.m_ConfSegButton, SIGNAL(clicked()), this, SLOT(OnSegmentationRegionAccept())); connect(this, SIGNAL(NewToolAssociated(mitk::Tool *)), this, SLOT(OnNewToolAssociated(mitk::Tool *))); connect(m_Controls.advancedSettingsButton, SIGNAL(toggled(bool)), this, SLOT(OnAdvancedSettingsButtonToggled(bool))); this->OnAdvancedSettingsButtonToggled(false); } QmitkOtsuTool3DGUI::~QmitkOtsuTool3DGUI() { + if (m_OtsuTool3DTool.IsNotNull()) + { + m_OtsuTool3DTool->CurrentlyBusy -= + mitk::MessageDelegate1(this, &QmitkOtsuTool3DGUI::BusyStateChanged); + } } 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::OnRegionSelectionChanged() { m_SelectedItems = m_Controls.m_selectionListWidget->selectedItems(); - if (m_SelectedItems.size() == 0) - { - m_Controls.m_ConfSegButton->setEnabled(false); - m_OtsuTool3DTool->ShowMultiLabelResultNode(true); - return; - } - if (m_OtsuTool3DTool.IsNotNull()) { // update preview of region QList::Iterator it; std::vector regionIDs; for (it = m_SelectedItems.begin(); it != m_SelectedItems.end(); ++it) regionIDs.push_back((*it)->text().toInt()); - m_OtsuTool3DTool->UpdateBinaryPreview(regionIDs); - m_Controls.m_ConfSegButton->setEnabled(true); + + m_OtsuTool3DTool->SetSelectedRegions(regionIDs); + m_OtsuTool3DTool->UpdatePreview(); + + m_Controls.m_ConfSegButton->setEnabled(!regionIDs.empty()); } } void QmitkOtsuTool3DGUI::OnAdvancedSettingsButtonToggled(bool toggled) { m_Controls.m_ValleyCheckbox->setVisible(toggled); m_Controls.binLabel->setVisible(toggled); m_Controls.m_BinsSpinBox->setVisible(toggled); if (toggled) { - int max = m_OtsuTool3DTool->GetNumberOfBins(); + int max = m_OtsuTool3DTool->GetMaxNumberOfBins(); if (max >= m_Controls.m_BinsSpinBox->minimum()) { m_Controls.m_BinsSpinBox->setMaximum(max); } } } void QmitkOtsuTool3DGUI::OnNewToolAssociated(mitk::Tool *tool) { + if (m_OtsuTool3DTool.IsNotNull()) + { + m_OtsuTool3DTool->CurrentlyBusy -= + mitk::MessageDelegate1(this, &QmitkOtsuTool3DGUI::BusyStateChanged); + } + m_OtsuTool3DTool = dynamic_cast(tool); + + if (m_OtsuTool3DTool.IsNotNull()) + { + m_OtsuTool3DTool->CurrentlyBusy += + mitk::MessageDelegate1(this, &QmitkOtsuTool3DGUI::BusyStateChanged); + + m_OtsuTool3DTool->SetOverwriteExistingSegmentation(true); + m_OtsuTool3DTool->IsTimePointChangeAwareOff(); + m_Controls.m_CheckProcessAll->setVisible(m_OtsuTool3DTool->GetTargetSegmentationNode()->GetData()->GetTimeSteps() > 1); + } } void QmitkOtsuTool3DGUI::OnSegmentationRegionAccept() { QmitkConfirmSegmentationDialog dialog; QString segName = QString::fromStdString(m_OtsuTool3DTool->GetCurrentSegmentationName()); - dialog.SetSegmentationName(segName); - int result = dialog.exec(); - - switch (result) + if (m_OtsuTool3DTool.IsNotNull()) { - case QmitkConfirmSegmentationDialog::CREATE_NEW_SEGMENTATION: + if (this->m_Controls.m_CheckCreateNew->isChecked()) + { m_OtsuTool3DTool->SetOverwriteExistingSegmentation(false); - break; - case QmitkConfirmSegmentationDialog::OVERWRITE_SEGMENTATION: + } + else + { m_OtsuTool3DTool->SetOverwriteExistingSegmentation(true); - break; - case QmitkConfirmSegmentationDialog::CANCEL_SEGMENTATION: - return; - } + } - if (m_OtsuTool3DTool.IsNotNull() && m_Controls.m_selectionListWidget->currentItem() != nullptr) - { + m_OtsuTool3DTool->SetCreateAllTimeSteps(this->m_Controls.m_CheckProcessAll->isChecked()); + + this->m_Controls.m_ConfSegButton->setEnabled(false); m_OtsuTool3DTool->ConfirmSegmentation(); } } void QmitkOtsuTool3DGUI::OnSpinboxValueAccept() { if (m_NumberOfRegions == m_Controls.m_Spinbox->value() && m_UseValleyEmphasis == m_Controls.m_ValleyCheckbox->isChecked() && m_NumberOfBins == m_Controls.m_BinsSpinBox->value()) return; if (m_OtsuTool3DTool.IsNotNull()) { 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; } m_NumberOfRegions = m_Controls.m_Spinbox->value(); m_UseValleyEmphasis = m_Controls.m_ValleyCheckbox->isChecked(); m_NumberOfBins = m_Controls.m_BinsSpinBox->value(); + m_OtsuTool3DTool->SetNumberOfRegions(m_NumberOfRegions); + m_OtsuTool3DTool->SetUseValley(m_UseValleyEmphasis); + m_OtsuTool3DTool->SetNumberOfBins(m_NumberOfBins); - this->setCursor(Qt::WaitCursor); - m_OtsuTool3DTool->RunSegmentation(m_NumberOfRegions, m_UseValleyEmphasis, m_NumberOfBins); - this->setCursor(Qt::ArrowCursor); + m_OtsuTool3DTool->UpdatePreview(); } 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."); messageBox->exec(); delete messageBox; return; } + // insert regions into widget QString itemName; QListWidgetItem *item; m_Controls.m_selectionListWidget->clear(); for (int i = 0; i < m_Controls.m_Spinbox->value(); ++i) { itemName = QString::number(i); item = new QListWidgetItem(itemName); m_Controls.m_selectionListWidget->addItem(item); } // deactivate 'confirm segmentation'-button m_Controls.m_ConfSegButton->setEnabled(false); + m_OtsuTool3DTool->IsTimePointChangeAwareOn(); } } -void QmitkOtsuTool3DGUI::OnVolumePreviewChecked(int state) +void QmitkOtsuTool3DGUI::BusyStateChanged(bool value) { - if (state == 1) + if (value) + { + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + } + else { + QApplication::restoreOverrideCursor(); } + + m_Controls.m_ValleyCheckbox->setEnabled(!value); + m_Controls.binLabel->setEnabled(!value); + m_Controls.m_BinsSpinBox->setEnabled(!value); + m_Controls.m_ConfSegButton->setEnabled(!m_OtsuTool3DTool->GetSelectedRegions().empty() && !value); + m_Controls.m_CheckProcessAll->setEnabled(!value); + m_Controls.m_CheckCreateNew->setEnabled(!value); + m_Controls.previewButton->setEnabled(!value); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.h b/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.h index f562f73560..ce2ad862fe 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.h +++ b/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.h @@ -1,83 +1,83 @@ /*============================================================================ 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 QmitkOtsuTool3DGUI_h_Included #define QmitkOtsuTool3DGUI_h_Included #include "QmitkToolGUI.h" #include "mitkOtsuTool3D.h" #include "ui_QmitkOtsuToolWidgetControls.h" #include #include #include class QSpinBox; class QLabel; /** \ingroup org_mitk_gui_qt_interactivesegmentation_internal \brief GUI for mitk::. \sa mitk:: This GUI shows ... Last contributor: $Author$ */ class MITKSEGMENTATIONUI_EXPORT QmitkOtsuTool3DGUI : public QmitkToolGUI { Q_OBJECT public: mitkClassMacro(QmitkOtsuTool3DGUI, QmitkToolGUI); itkFactorylessNewMacro(Self); itkCloneMacro(Self); signals : public slots : protected slots : void OnNewToolAssociated(mitk::Tool *); void OnSpinboxValueAccept(); void OnSegmentationRegionAccept(); void OnRegionSelectionChanged(); void OnRegionSpinboxChanged(int); - void OnVolumePreviewChecked(int); - private slots: void OnAdvancedSettingsButtonToggled(bool toggled); protected: QmitkOtsuTool3DGUI(); ~QmitkOtsuTool3DGUI() override; + void BusyStateChanged(bool value) override; + mitk::OtsuTool3D::Pointer m_OtsuTool3DTool; Ui_QmitkOtsuToolWidgetControls m_Controls; int m_NumberOfRegions; bool m_UseValleyEmphasis; int m_NumberOfBins; QList m_SelectedItems; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkOtsuToolWidgetControls.ui b/Modules/SegmentationUI/Qmitk/QmitkOtsuToolWidgetControls.ui index e5484bf97b..d0f8af9c9e 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkOtsuToolWidgetControls.ui +++ b/Modules/SegmentationUI/Qmitk/QmitkOtsuToolWidgetControls.ui @@ -1,214 +1,234 @@ QmitkOtsuToolWidgetControls 0 0 192 - 293 + 300 0 0 100 0 100000 100000 QmitkOtsuToolWidget Move to adjust the segmentation QLayout::SetNoConstraint 0 0 Number of Regions: 0 0 40 16777215 2 32 0 0 0 32 Advanced settings Qt::ToolButtonTextBesideIcon true Use Valley Emphasis Number of Histogram Bins: 2 4096 128 0 0 10000000 100 0 QAbstractItemView::MultiSelection QListView::Adjust 0 0 100000 16777215 Preview false 0 0 100000 16777215 Confirm Segmentation + + + + "Add the confirmed segmentation as a new segmentation instead of overwriting the currently selected." + + + Process all time steps + + + + + + + Add the confirmed segmentation as a new segmentation instead of overwriting the currently selected. + + + Create as new segmentation + + + ctkExpandButton QToolButton
ctkExpandButton.h