diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp index c1e2aa0412..58d982de3f 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.cpp @@ -1,158 +1,157 @@ /*============================================================================ 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 static const char* const HelpText = "Select two different segmentations above"; namespace { static std::string GetPrefix(mitk::BooleanOperation::Type type) { switch (type) { case mitk::BooleanOperation::Difference: return "DifferenceFrom_"; case mitk::BooleanOperation::Intersection: return "IntersectionWith_"; case mitk::BooleanOperation::Union: return "UnionWith_"; default: assert(false && "Unknown boolean operation type"); return "UNKNOWN_BOOLEAN_OPERATION_WITH_"; } } static void AddToDataStorage(mitk::DataStorage::Pointer dataStorage, mitk::Image::Pointer segmentation, const std::string& name, mitk::DataNode::Pointer parent = nullptr) { if (dataStorage.IsNull()) { std::string exception = "Cannot add result to the data storage. Data storage invalid."; MITK_ERROR << "Boolean operation failed: " << exception; QMessageBox::information(nullptr, "Boolean operation failed", QString::fromStdString(exception)); } auto dataNode = mitk::DataNode::New(); dataNode->SetName(name); dataNode->SetData(segmentation); dataStorage->Add(dataNode, parent); } } -QmitkBooleanOperationsWidget::QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent) - : QmitkSegmentationUtilityWidget(timeNavigationController, parent) +QmitkBooleanOperationsWidget::QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent) + : QWidget(parent) { m_Controls = new Ui::QmitkBooleanOperationsWidgetControls; m_Controls->setupUi(this); m_Controls->dataSelectionWidget->SetDataStorage(dataStorage); m_Controls->dataSelectionWidget->AddDataSelection("", "Select 1st segmentation", "Select 1st segmentation", "", QmitkDataSelectionWidget::SegmentationPredicate); m_Controls->dataSelectionWidget->AddDataSelection("", "Select 2nd segmentation", "Select 2nd segmentation", "", QmitkDataSelectionWidget::SegmentationPredicate); m_Controls->dataSelectionWidget->SetHelpText(HelpText); connect(m_Controls->dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); connect(m_Controls->differenceButton, SIGNAL(clicked()), this, SLOT(OnDifferenceButtonClicked())); connect(m_Controls->intersectionButton, SIGNAL(clicked()), this, SLOT(OnIntersectionButtonClicked())); connect(m_Controls->unionButton, SIGNAL(clicked()), this, SLOT(OnUnionButtonClicked())); } QmitkBooleanOperationsWidget::~QmitkBooleanOperationsWidget() { } void QmitkBooleanOperationsWidget::OnSelectionChanged(unsigned int, const mitk::DataNode*) { auto dataSelectionWidget = m_Controls->dataSelectionWidget; auto nodeA = dataSelectionWidget->GetSelection(0); auto nodeB = dataSelectionWidget->GetSelection(1); if (nodeA.IsNotNull() && nodeB.IsNotNull() && nodeA != nodeB) { dataSelectionWidget->SetHelpText(""); this->EnableButtons(); } else { dataSelectionWidget->SetHelpText(HelpText); this->EnableButtons(false); } } void QmitkBooleanOperationsWidget::EnableButtons(bool enable) { m_Controls->differenceButton->setEnabled(enable); m_Controls->intersectionButton->setEnabled(enable); m_Controls->unionButton->setEnabled(enable); } void QmitkBooleanOperationsWidget::OnDifferenceButtonClicked() { this->DoBooleanOperation(mitk::BooleanOperation::Difference); } void QmitkBooleanOperationsWidget::OnIntersectionButtonClicked() { this->DoBooleanOperation(mitk::BooleanOperation::Intersection); } void QmitkBooleanOperationsWidget::OnUnionButtonClicked() { this->DoBooleanOperation(mitk::BooleanOperation::Union); } void QmitkBooleanOperationsWidget::DoBooleanOperation(mitk::BooleanOperation::Type type) { - auto timeNavigationController = this->GetTimeNavigationController(); + const auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController(); assert(timeNavigationController != nullptr); mitk::Image::Pointer segmentationA = dynamic_cast(m_Controls->dataSelectionWidget->GetSelection(0)->GetData()); mitk::Image::Pointer segmentationB = dynamic_cast(m_Controls->dataSelectionWidget->GetSelection(1)->GetData()); mitk::Image::Pointer result; try { mitk::BooleanOperation booleanOperation(type, segmentationA, segmentationB, timeNavigationController->GetSelectedTimePoint()); result = booleanOperation.GetResult(); assert(result.IsNotNull()); auto dataSelectionWidget = m_Controls->dataSelectionWidget; AddToDataStorage( dataSelectionWidget->GetDataStorage(), result, GetPrefix(type) + dataSelectionWidget->GetSelection(1)->GetName(), dataSelectionWidget->GetSelection(0)); } catch (const mitk::Exception& exception) { MITK_ERROR << "Boolean operation failed: " << exception.GetDescription(); QMessageBox::information(nullptr, "Boolean operation failed", exception.GetDescription()); } } diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.h index 29b0e89e87..5d09e3eec6 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.h +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkBooleanOperationsWidget.h @@ -1,55 +1,54 @@ /*============================================================================ 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 QmitkBooleanOperationsWidget_h #define QmitkBooleanOperationsWidget_h #include #include -#include + +#include namespace Ui { class QmitkBooleanOperationsWidgetControls; } namespace mitk { class DataNode; class DataStorage; } -class MITKSEGMENTATIONUI_EXPORT QmitkBooleanOperationsWidget : public QmitkSegmentationUtilityWidget +class MITKSEGMENTATIONUI_EXPORT QmitkBooleanOperationsWidget : public QWidget { Q_OBJECT public: - explicit QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent = nullptr); + explicit QmitkBooleanOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr); ~QmitkBooleanOperationsWidget() override; private slots: void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); void OnDifferenceButtonClicked(); void OnIntersectionButtonClicked(); void OnUnionButtonClicked(); private: void EnableButtons(bool enable = true); void DoBooleanOperation(mitk::BooleanOperation::Type type); Ui::QmitkBooleanOperationsWidgetControls* m_Controls; }; #endif diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp index 883633b384..604206f78e 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp @@ -1,259 +1,258 @@ /*============================================================================ 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 "QmitkContourModelToImageWidget.h" #include #include #include #include #include #include -#include +#include +#include #include #include #include #include static const char* const HelpText = "Select a image and a contour(set)"; class QmitkContourModelToImageWidgetPrivate { public: QmitkContourModelToImageWidgetPrivate(); ~QmitkContourModelToImageWidgetPrivate(); /** @brief Check if selections is valid. */ void SelectionControl( unsigned int index, const mitk::DataNode* selection); /** @brief Enable buttons if data selction is valid. */ void EnableButtons(bool enable = true); /** @brief Does the actual contour filling */ mitk::LabelSetImage::Pointer FillContourModelSetIntoImage(mitk::Image *image, mitk::ContourModelSet *contourSet, mitk::TimePointType timePoint); Ui::QmitkContourModelToImageWidgetControls m_Controls; QFutureWatcher m_Watcher; }; QmitkContourModelToImageWidgetPrivate::QmitkContourModelToImageWidgetPrivate() { } QmitkContourModelToImageWidgetPrivate::~QmitkContourModelToImageWidgetPrivate() { } void QmitkContourModelToImageWidgetPrivate::EnableButtons(bool enable) { m_Controls.btnProcess->setEnabled(enable); } void QmitkContourModelToImageWidgetPrivate::SelectionControl(unsigned int index, const mitk::DataNode* /*selection*/) { QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index); dataSelectionWidget->SetHelpText(""); this->EnableButtons(); } mitk::LabelSetImage::Pointer QmitkContourModelToImageWidgetPrivate::FillContourModelSetIntoImage(mitk::Image* image, mitk::ContourModelSet* contourSet, mitk::TimePointType timePoint) { // Use mitk::ContourModelSetToImageFilter to fill the ContourModelSet into the image mitk::ContourModelSetToImageFilter::Pointer contourFiller = mitk::ContourModelSetToImageFilter::New(); auto timeStep = image->GetTimeGeometry()->TimePointToTimeStep(timePoint); contourFiller->SetTimeStep(timeStep); contourFiller->SetImage(image); contourFiller->SetInput(contourSet); contourFiller->MakeOutputBinaryOn(); 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."; } if (nullptr == contourFiller->GetOutput()) { MITK_ERROR<<"Could not write the selected contours into the image!"; } auto result = mitk::LabelSetImage::New(); result->InitializeByLabeledImage(contourFiller->GetOutput()); return result; } void QmitkContourModelToImageWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection) { Q_D(QmitkContourModelToImageWidget); QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget; mitk::DataNode::Pointer node0 = dataSelectionWidget->GetSelection(0); mitk::DataNode::Pointer node1 = dataSelectionWidget->GetSelection(1); if (node0.IsNull() || node1.IsNull() ) { d->EnableButtons(false); dataSelectionWidget->SetHelpText(HelpText); } else { d->SelectionControl(index, selection); } } void QmitkContourModelToImageWidget::OnProcessingFinished() { // Called when processing finished // Adding the result to the data storage Q_D(QmitkContourModelToImageWidget); // Adding the result to the data storage auto result = d->m_Watcher.result(); if (result.IsNotNull()) { QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget; mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0); mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1); mitk::DataNode::Pointer filled = mitk::DataNode::New(); std::stringstream stream; stream << imageNode->GetName(); stream << "_"; stream << contourNode->GetName(); filled->SetName(stream.str()); filled->SetData(result); auto dataStorage = dataSelectionWidget->GetDataStorage(); if (dataStorage.IsNull()) { std::string exception = "Cannot add result to the data storage. Data storage invalid."; MITK_ERROR << "Error filling contours into an image: " << exception; QMessageBox::information(nullptr, "Error filling contours into an image", QString::fromStdString(exception)); } dataStorage->Add(filled, imageNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else { MITK_ERROR<<"Error filling contours into an image!"; } d->EnableButtons(); } void QmitkContourModelToImageWidget::OnProcessPressed() { Q_D(QmitkContourModelToImageWidget); QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget; mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0); mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1); // Check if data nodes are valid if(imageNode.IsNull() || contourNode.IsNull() ) { MITK_ERROR << "Selection does not contain valid data"; QMessageBox::information( this, "Contour To Image", "Selection does not contain valid data, please select a binary image and a contour(set)", QMessageBox::Ok ); d->m_Controls.btnProcess->setEnabled(false); return; } mitk::Image::Pointer image = static_cast(imageNode->GetData()); // Check if the image is valid if (image.IsNull()) { MITK_ERROR<<"Error writing contours into image! Invalid image data selected!"; return; } - const auto timePoint = this->GetTimeNavigationController()->GetSelectedTimePoint(); + const mitk::TimePointType timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint)) { MITK_ERROR << "Error writing contours into image! Currently selected time point is not supported by selected image data."; return; } // Check if the selected contours are valid mitk::ContourModelSet::Pointer contourSet; mitk::ContourModel::Pointer contour = dynamic_cast(contourNode->GetData()); if (contour.IsNotNull()) { contourSet = mitk::ContourModelSet::New(); contourSet->AddContourModel(contour); } else { contourSet = static_cast(contourNode->GetData()); if (contourSet.IsNull()) { MITK_ERROR<<"Error writing contours into binary image! Invalid contour data selected!"; return; } } //Disable Buttons during calculation and initialize Progressbar d->EnableButtons(false); // Start the computation in a background thread QFuture< mitk::LabelSetImage::Pointer > future = QtConcurrent::run(d, &QmitkContourModelToImageWidgetPrivate::FillContourModelSetIntoImage, image, contourSet, timePoint); d->m_Watcher.setFuture(future); } -QmitkContourModelToImageWidget::QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent) - : QmitkSegmentationUtilityWidget(timeNavigationController, parent), - d_ptr(new QmitkContourModelToImageWidgetPrivate()) +QmitkContourModelToImageWidget::QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent) + : QWidget(parent) + , d_ptr(new QmitkContourModelToImageWidgetPrivate()) { Q_D(QmitkContourModelToImageWidget); // Set up UI d->m_Controls.setupUi(this); d->m_Controls.dataSelectionWidget->SetDataStorage(dataStorage); d->m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImageAndSegmentationPredicate); d->m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ContourModelPredicate); d->m_Controls.dataSelectionWidget->SetHelpText(HelpText); d->EnableButtons(false); // Create connections connect (d->m_Controls.btnProcess, SIGNAL(pressed()), this, SLOT(OnProcessPressed())); connect(d->m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); connect(&d->m_Watcher, SIGNAL(finished()), this, SLOT(OnProcessingFinished())); if( d->m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull() && d->m_Controls.dataSelectionWidget->GetSelection(1).IsNotNull() ) { OnSelectionChanged(0, d->m_Controls.dataSelectionWidget->GetSelection(0)); } } QmitkContourModelToImageWidget::~QmitkContourModelToImageWidget() { } diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h index 562d254434..797def3584 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h @@ -1,76 +1,72 @@ /*============================================================================ 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 QmitkContourModelToImageWidget_h #define QmitkContourModelToImageWidget_h #include -#include - #include +#include class QmitkContourModelToImageWidgetPrivate; namespace mitk { class DataNode; class DataStorage; class Image; class ContourModelSet; class ContourModel; class Geometry3D; class PlaneGeometry; } /*! \brief QmitkContourModelToImageWidget Tool masks an image with a binary image or a surface. The Method requires an image and a binary image mask or a surface. The input image and the binary image mask must be of the same size. Masking with a surface creates first a binary image of the surface and then use this for the masking of the input image. */ -class MITKSEGMENTATIONUI_EXPORT QmitkContourModelToImageWidget : public QmitkSegmentationUtilityWidget +class MITKSEGMENTATIONUI_EXPORT QmitkContourModelToImageWidget : public QWidget { Q_OBJECT public: /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */ - explicit QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent = nullptr); - + explicit QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr); /** @brief Defaul destructor. */ ~QmitkContourModelToImageWidget() override; private slots: /** @brief This slot is called if the selection in the workbench is changed. */ void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); /** @brief This slot is called if user activates the button to mask an image. */ void OnProcessPressed(); /** @brief This slot is called after processing is finished */ void OnProcessingFinished(); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QmitkContourModelToImageWidget) Q_DISABLE_COPY(QmitkContourModelToImageWidget) }; #endif diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.cpp index 0e542d4d04..884c5a79cd 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.cpp +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.cpp @@ -1,393 +1,389 @@ /*============================================================================ 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 "QmitkImageMaskingWidget.h" #include -#include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include namespace { bool IsSurface(const mitk::DataNode* dataNode) { if (nullptr != dataNode) { if (nullptr != dynamic_cast(dataNode->GetData())) return true; } return false; } } static const char* const HelpText = "Select an image and a segmentation or surface"; -QmitkImageMaskingWidget::QmitkImageMaskingWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent) - : QmitkSegmentationUtilityWidget(timeNavigationController, parent) +QmitkImageMaskingWidget::QmitkImageMaskingWidget(mitk::DataStorage* dataStorage, QWidget* parent) + : QWidget(parent) { m_Controls = new Ui::QmitkImageMaskingWidgetControls; m_Controls->setupUi(this); m_Controls->dataSelectionWidget->SetDataStorage(dataStorage); m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImagePredicate); m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SegmentationOrSurfacePredicate); m_Controls->dataSelectionWidget->SetHelpText(HelpText); // T28795: Disable 2-d reference images since they do not work yet (segmentations are at least 3-d images with a single slice) m_Controls->dataSelectionWidget->SetPredicate(0, mitk::NodePredicateAnd::New( mitk::NodePredicateNot::New(mitk::NodePredicateDimension::New(2)), m_Controls->dataSelectionWidget->GetPredicate(0))); this->EnableButtons(false); connect(m_Controls->btnMaskImage, SIGNAL(clicked()), this, SLOT(OnMaskImagePressed())); connect(m_Controls->rbnCustom, SIGNAL(toggled(bool)), this, SLOT(OnCustomValueButtonToggled(bool))); connect(m_Controls->dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); if( m_Controls->dataSelectionWidget->GetSelection(0).IsNotNull() && m_Controls->dataSelectionWidget->GetSelection(1).IsNotNull() ) { this->OnSelectionChanged(0, m_Controls->dataSelectionWidget->GetSelection(0)); } } QmitkImageMaskingWidget::~QmitkImageMaskingWidget() { } void QmitkImageMaskingWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode *selection) { auto *dataSelectionWidget = m_Controls->dataSelectionWidget; auto node0 = dataSelectionWidget->GetSelection(0); if (index == 0) { dataSelectionWidget->SetPredicate(1, QmitkDataSelectionWidget::SegmentationOrSurfacePredicate); if (node0.IsNotNull()) { dataSelectionWidget->SetPredicate(1, mitk::NodePredicateAnd::New( mitk::NodePredicateGeometry::New(node0->GetData()->GetGeometry()), dataSelectionWidget->GetPredicate(1))); } } auto node1 = dataSelectionWidget->GetSelection(1); if (node0.IsNull() || node1.IsNull()) { dataSelectionWidget->SetHelpText(HelpText); this->EnableButtons(false); } else { this->SelectionControl(index, selection); } } void QmitkImageMaskingWidget::SelectionControl(unsigned int index, const mitk::DataNode* selection) { QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index); //if Image-Masking is enabled, check if image-dimension of reference and binary image is identical if( !IsSurface(dataSelectionWidget->GetSelection(1)) ) { if( dataSelectionWidget->GetSelection(0) == dataSelectionWidget->GetSelection(1) ) { dataSelectionWidget->SetHelpText("Select two different images above"); this->EnableButtons(false); return; } else if( node.IsNotNull() && selection ) { mitk::Image::Pointer referenceImage = dynamic_cast ( dataSelectionWidget->GetSelection(0)->GetData() ); mitk::Image::Pointer maskImage = dynamic_cast ( dataSelectionWidget->GetSelection(1)->GetData() ); if (maskImage.IsNull()) { dataSelectionWidget->SetHelpText("Different image sizes cannot be masked"); this->EnableButtons(false); return; } } else { dataSelectionWidget->SetHelpText(HelpText); return; } } dataSelectionWidget->SetHelpText(""); this->EnableButtons(); } void QmitkImageMaskingWidget::EnableButtons(bool enable) { m_Controls->grpBackgroundValue->setEnabled(enable); m_Controls->btnMaskImage->setEnabled(enable); } template void GetRange(const itk::Image*, double& bottom, double& top) { bottom = std::numeric_limits::lowest(); top = std::numeric_limits::max(); } void QmitkImageMaskingWidget::OnCustomValueButtonToggled(bool checked) { m_Controls->txtCustom->setEnabled(checked); } void QmitkImageMaskingWidget::OnMaskImagePressed() { //Disable Buttons during calculation and initialize Progressbar this->EnableButtons(false); mitk::ProgressBar::GetInstance()->AddStepsToDo(4); mitk::ProgressBar::GetInstance()->Progress(); QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; //create result image, get mask node and reference image mitk::Image::Pointer resultImage(nullptr); mitk::DataNode::Pointer maskingNode = dataSelectionWidget->GetSelection(1); mitk::Image::Pointer referenceImage = static_cast(dataSelectionWidget->GetSelection(0)->GetData()); if(referenceImage.IsNull() || maskingNode.IsNull() ) { MITK_ERROR << "Selection does not contain an image"; QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain an image", QMessageBox::Ok ); m_Controls->btnMaskImage->setEnabled(true); return; } //Do Image-Masking if (!IsSurface(maskingNode)) { mitk::ProgressBar::GetInstance()->Progress(); mitk::Image::Pointer maskImage = dynamic_cast ( maskingNode->GetData() ); if(maskImage.IsNull() ) { MITK_ERROR << "Selection does not contain a segmentation"; QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a segmentation", QMessageBox::Ok ); this->EnableButtons(); return; } resultImage = this->MaskImage(referenceImage, maskImage); } //Do Surface-Masking else { mitk::ProgressBar::GetInstance()->Progress(); //1. convert surface to image mitk::Surface::Pointer surface = dynamic_cast ( maskingNode->GetData() ); //TODO Get 3D Surface of current time step if(surface.IsNull()) { MITK_ERROR << "Selection does not contain a surface"; QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a surface", QMessageBox::Ok ); this->EnableButtons(); return; } mitk::Image::Pointer maskImage = this->ConvertSurfaceToImage( referenceImage, surface ); //2. mask reference image with mask image if(maskImage.IsNotNull() && referenceImage->GetLargestPossibleRegion().GetSize() == maskImage->GetLargestPossibleRegion().GetSize() ) { resultImage = this->MaskImage( referenceImage, maskImage ); } } mitk::ProgressBar::GetInstance()->Progress(); if( resultImage.IsNull() ) { MITK_ERROR << "Masking failed"; QMessageBox::information( this, "Image and Surface Masking", "Masking failed. For more information please see logging window.", QMessageBox::Ok ); this->EnableButtons(); mitk::ProgressBar::GetInstance()->Progress(4); return; } //Add result to data storage this->AddToDataStorage( dataSelectionWidget->GetDataStorage(), resultImage, dataSelectionWidget->GetSelection(0)->GetName() + "_" + dataSelectionWidget->GetSelection(1)->GetName(), dataSelectionWidget->GetSelection(0)); this->EnableButtons(); mitk::ProgressBar::GetInstance()->Progress(); } mitk::Image::Pointer QmitkImageMaskingWidget::MaskImage(mitk::Image::Pointer referenceImage, mitk::Image::Pointer maskImage ) { mitk::ScalarType backgroundValue = 0.0; if (m_Controls->rbnMinimum->isChecked()) { backgroundValue = referenceImage->GetStatistics()->GetScalarValueMin(); } else if (m_Controls->rbnCustom->isChecked()) { auto warningTitle = QStringLiteral("Invalid custom pixel value"); bool ok = false; auto originalBackgroundValue = m_Controls->txtCustom->text().toDouble(&ok); if (!ok) { // Input is not even a number QMessageBox::warning(nullptr, warningTitle, "Please enter a valid number as custom pixel value."); return nullptr; } else { // Clamp to the numerical limits of the pixel/component type double bottom, top; if (referenceImage->GetDimension() == 4) { AccessFixedDimensionByItk_n(referenceImage, GetRange, 4, (bottom, top)); } else { AccessByItk_n(referenceImage, GetRange, (bottom, top)); } backgroundValue = std::max(bottom, std::min(originalBackgroundValue, top)); // Get rid of decimals for integral numbers auto type = referenceImage->GetPixelType().GetComponentType(); if (type != itk::IOComponentEnum::FLOAT && type != itk::IOComponentEnum::DOUBLE) backgroundValue = std::round(backgroundValue); } // Ask the user for permission before correcting their input if (std::abs(originalBackgroundValue - backgroundValue) > 1e-4) { auto warningText = QString( "

The custom pixel value %1 lies not within the range of valid pixel values for the selected image.

" "

Apply the closest valid pixel value %2 instead?

").arg(originalBackgroundValue).arg(backgroundValue); auto ret = QMessageBox::warning( nullptr, warningTitle, warningText, QMessageBox::StandardButton::Apply | QMessageBox::StandardButton::Cancel, QMessageBox::StandardButton::Apply); if (QMessageBox::StandardButton::Apply != ret) return nullptr; m_Controls->txtCustom->setText(QString("%1").arg(backgroundValue)); } } auto maskFilter = mitk::MaskImageFilter::New(); maskFilter->SetInput(referenceImage); maskFilter->SetMask(maskImage); maskFilter->OverrideOutsideValueOn(); maskFilter->SetOutsideValue(backgroundValue); try { maskFilter->Update(); } catch(const itk::ExceptionObject& e) { MITK_ERROR << e.GetDescription(); return nullptr; } return maskFilter->GetOutput(); } mitk::Image::Pointer QmitkImageMaskingWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface ) { mitk::ProgressBar::GetInstance()->AddStepsToDo(2); mitk::ProgressBar::GetInstance()->Progress(); mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New(); surfaceToImageFilter->MakeOutputBinaryOn(); surfaceToImageFilter->SetInput(surface); surfaceToImageFilter->SetImage(image); try { surfaceToImageFilter->Update(); } catch(itk::ExceptionObject& excpt) { MITK_ERROR << excpt.GetDescription(); return nullptr; } mitk::ProgressBar::GetInstance()->Progress(); mitk::Image::Pointer resultImage = mitk::Image::New(); resultImage = surfaceToImageFilter->GetOutput(); return resultImage; } void QmitkImageMaskingWidget::AddToDataStorage(mitk::DataStorage::Pointer dataStorage, mitk::Image::Pointer segmentation, const std::string& name, mitk::DataNode::Pointer parent ) { if (dataStorage.IsNull()) { std::string exception = "Cannot add result to the data storage. Data storage invalid."; MITK_ERROR << "Masking failed: " << exception; QMessageBox::information(nullptr, "Masking failed", QString::fromStdString(exception)); } auto dataNode = mitk::DataNode::New(); dataNode->SetName(name); dataNode->SetData(segmentation); if (parent.IsNotNull()) { mitk::LevelWindow levelWindow; parent->GetLevelWindow(levelWindow); dataNode->SetLevelWindow(levelWindow); } dataStorage->Add(dataNode, parent); } diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h index b8be1847bf..5769a75990 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkImageMaskingWidget.h @@ -1,87 +1,85 @@ /*============================================================================ 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 QmitkImageMaskingWidget_h #define QmitkImageMaskingWidget_h #include #include #include -#include + +#include namespace Ui { class QmitkImageMaskingWidgetControls; } namespace mitk { - class DataStorage; class Image; } /*! \brief QmitkImageMaskingWidget Tool masks an image with a binary image or a surface. The Method requires an image and a binary image mask or a surface. The input image and the binary image mask must be of the same size. Masking with a surface creates first a binary image of the surface and then use this for the masking of the input image. */ -class MITKSEGMENTATIONUI_EXPORT QmitkImageMaskingWidget : public QmitkSegmentationUtilityWidget +class MITKSEGMENTATIONUI_EXPORT QmitkImageMaskingWidget : public QWidget { Q_OBJECT public: /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */ - explicit QmitkImageMaskingWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent = nullptr); + explicit QmitkImageMaskingWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr); /** @brief Defaul destructor. */ ~QmitkImageMaskingWidget() override; private slots: /** @brief This slot is called if the selection in the workbench is changed. */ void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); /** @brief This slot is called if user activates the button to mask an image. */ void OnMaskImagePressed(); /** @brief This slot is called if the user toggles the "Custom" radio button. */ void OnCustomValueButtonToggled(bool checked); private: /** @brief Check if selections is valid. */ void SelectionControl( unsigned int index, const mitk::DataNode* selection); /** @brief Enable buttons if data selction is valid. */ void EnableButtons(bool enable = true); /** @brief Mask an image with a given binary mask. Note that the input image and the mask image must be of the same size. */ itk::SmartPointer MaskImage(itk::SmartPointer referenceImage, itk::SmartPointer maskImage ); /** @brief Convert a surface into an binary image. */ itk::SmartPointer ConvertSurfaceToImage( itk::SmartPointer image, mitk::Surface::Pointer surface ); /** @brief Adds a new data object to the DataStorage.*/ void AddToDataStorage(mitk::DataStorage::Pointer dataStorage, itk::SmartPointer segmentation, const std::string& name, mitk::DataNode::Pointer parent = nullptr); Ui::QmitkImageMaskingWidgetControls* m_Controls; }; #endif diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp index b02a5ea938..ef4c3bc979 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp @@ -1,258 +1,254 @@ /*============================================================================ 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 "QmitkMorphologicalOperationsWidget.h" #include #include -#include - #include static const char* const HelpText = "Select a segmentation above"; -QmitkMorphologicalOperationsWidget::QmitkMorphologicalOperationsWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent) - : QmitkSegmentationUtilityWidget(timeNavigationController, parent) +QmitkMorphologicalOperationsWidget::QmitkMorphologicalOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent) + : QWidget(parent) { m_Controls = new Ui::QmitkMorphologicalOperationsWidgetControls; m_Controls->setupUi(this); m_Controls->dataSelectionWidget->SetDataStorage(dataStorage); m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SegmentationPredicate); m_Controls->dataSelectionWidget->SetHelpText(HelpText); connect(m_Controls->btnClosing, SIGNAL(clicked()), this, SLOT(OnClosingButtonClicked())); connect(m_Controls->btnOpening, SIGNAL(clicked()), this, SLOT(OnOpeningButtonClicked())); connect(m_Controls->btnDilatation, SIGNAL(clicked()), this, SLOT(OnDilatationButtonClicked())); connect(m_Controls->btnErosion, SIGNAL(clicked()), this, SLOT(OnErosionButtonClicked())); connect(m_Controls->btnFillHoles, SIGNAL(clicked()), this, SLOT(OnFillHolesButtonClicked())); connect(m_Controls->radioButtonMorphoCross, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked())); connect(m_Controls->radioButtonMorphoBall, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked())); connect(m_Controls->dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); if (m_Controls->dataSelectionWidget->GetSelection(0).IsNotNull()) this->OnSelectionChanged(0, m_Controls->dataSelectionWidget->GetSelection(0)); } QmitkMorphologicalOperationsWidget::~QmitkMorphologicalOperationsWidget() { } void QmitkMorphologicalOperationsWidget::OnSelectionChanged(unsigned int, const mitk::DataNode*) { QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0); if (node.IsNotNull()) { m_Controls->dataSelectionWidget->SetHelpText(""); this->EnableButtons(true); } else { m_Controls->dataSelectionWidget->SetHelpText(HelpText); this->EnableButtons(false); } } void QmitkMorphologicalOperationsWidget::EnableButtons(bool enable) { m_Controls->btnClosing->setEnabled(enable); m_Controls->btnDilatation->setEnabled(enable); m_Controls->btnErosion->setEnabled(enable); m_Controls->btnFillHoles->setEnabled(enable); m_Controls->btnOpening->setEnabled(enable); } void QmitkMorphologicalOperationsWidget::OnRadioButtonsClicked() { bool enable = m_Controls->radioButtonMorphoBall->isChecked(); m_Controls->sliderMorphFactor->setEnabled(enable); m_Controls->spinBoxMorphFactor->setEnabled(enable); } void QmitkMorphologicalOperationsWidget::OnClosingButtonClicked() { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); mitk::MorphologicalOperations::StructuralElementType structuralElement = CreateStructerElement_UI(); try { int factor = m_Controls->spinBoxMorphFactor->isEnabled() ? m_Controls->spinBoxMorphFactor->value() : 1; mitk::MorphologicalOperations::Closing(image, factor, structuralElement); } catch (const itk::ExceptionObject& exception) { MITK_WARN << "Exception caught: " << exception.GetDescription(); QApplication::restoreOverrideCursor(); return; } node->SetData(image); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QApplication::restoreOverrideCursor(); } void QmitkMorphologicalOperationsWidget::OnOpeningButtonClicked() { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); mitk::MorphologicalOperations::StructuralElementType structuralElement = CreateStructerElement_UI(); try { int factor = m_Controls->spinBoxMorphFactor->isEnabled() ? m_Controls->spinBoxMorphFactor->value() : 1; mitk::MorphologicalOperations::Opening(image, factor, structuralElement); } catch (const itk::ExceptionObject& exception) { MITK_WARN << "Exception caught: " << exception.GetDescription(); QApplication::restoreOverrideCursor(); return; } node->SetData(image); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QApplication::restoreOverrideCursor(); } void QmitkMorphologicalOperationsWidget::OnDilatationButtonClicked() { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); mitk::MorphologicalOperations::StructuralElementType structuralElement = this->CreateStructerElement_UI(); try { int factor = m_Controls->spinBoxMorphFactor->isEnabled() ? m_Controls->spinBoxMorphFactor->value() : 1; mitk::MorphologicalOperations::Dilate(image, factor, structuralElement); } catch (const itk::ExceptionObject& exception) { MITK_WARN << "Exception caught: " << exception.GetDescription(); QApplication::restoreOverrideCursor(); return; } node->SetData(image); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QApplication::restoreOverrideCursor(); } void QmitkMorphologicalOperationsWidget::OnErosionButtonClicked() { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); mitk::MorphologicalOperations::StructuralElementType structuralElement = CreateStructerElement_UI(); try { int factor = m_Controls->spinBoxMorphFactor->isEnabled() ? m_Controls->spinBoxMorphFactor->value() : 1; mitk::MorphologicalOperations::Erode(image, factor, structuralElement); } catch (const itk::ExceptionObject& exception) { MITK_WARN << "Exception caught: " << exception.GetDescription(); QApplication::restoreOverrideCursor(); return; } node->SetData(image); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QApplication::restoreOverrideCursor(); } void QmitkMorphologicalOperationsWidget::OnFillHolesButtonClicked() { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); try { mitk::MorphologicalOperations::FillHoles(image); } catch (const itk::ExceptionObject& exception) { MITK_WARN << "Exception caught: " << exception.GetDescription(); QApplication::restoreOverrideCursor(); return; } node->SetData(image); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); QApplication::restoreOverrideCursor(); } mitk::MorphologicalOperations::StructuralElementType QmitkMorphologicalOperationsWidget::CreateStructerElement_UI() { bool ball = m_Controls->radioButtonMorphoBall->isChecked(); int accum_flag = 0; if(ball){ if(m_Controls->planeSelectionComboBox->currentIndex() == 0) accum_flag = mitk::MorphologicalOperations::Ball; // 3D Operation if(m_Controls->planeSelectionComboBox->currentIndex() == 1) accum_flag = mitk::MorphologicalOperations::Ball_Axial; // 2D Operation - Axial plane if(m_Controls->planeSelectionComboBox->currentIndex() == 2) accum_flag = mitk::MorphologicalOperations::Ball_Sagittal; // 2D Operation - Sagittal plane if(m_Controls->planeSelectionComboBox->currentIndex() == 3) accum_flag = mitk::MorphologicalOperations::Ball_Coronal; // 2D Operation - Coronal plane }else{ if(m_Controls->planeSelectionComboBox->currentIndex() == 0) accum_flag = mitk::MorphologicalOperations::Cross; if(m_Controls->planeSelectionComboBox->currentIndex() == 1) accum_flag = mitk::MorphologicalOperations::Cross_Axial; if(m_Controls->planeSelectionComboBox->currentIndex() == 2) accum_flag = mitk::MorphologicalOperations::Cross_Sagittal; if(m_Controls->planeSelectionComboBox->currentIndex() == 3) accum_flag = mitk::MorphologicalOperations::Cross_Coronal; } return (mitk::MorphologicalOperations::StructuralElementType)accum_flag; } diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.h index 3d19b84668..5e3862e85e 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.h +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkMorphologicalOperationsWidget.h @@ -1,61 +1,61 @@ /*============================================================================ 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 QmitkMorphologicalOperationsWidget_h #define QmitkMorphologicalOperationsWidget_h #include #include -#include +#include + +#include namespace Ui { class QmitkMorphologicalOperationsWidgetControls; } namespace mitk { class DataNode; class DataStorage; } /** \brief GUI class for morphological segmentation tools. */ -class MITKSEGMENTATIONUI_EXPORT QmitkMorphologicalOperationsWidget : public QmitkSegmentationUtilityWidget +class MITKSEGMENTATIONUI_EXPORT QmitkMorphologicalOperationsWidget : public QWidget { Q_OBJECT public: - explicit QmitkMorphologicalOperationsWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent = nullptr); + explicit QmitkMorphologicalOperationsWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr); ~QmitkMorphologicalOperationsWidget() override; public slots: void OnClosingButtonClicked(); void OnOpeningButtonClicked(); void OnDilatationButtonClicked(); void OnErosionButtonClicked(); void OnFillHolesButtonClicked(); void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); void OnRadioButtonsClicked(); protected: void EnableButtons(bool enable); private: Ui::QmitkMorphologicalOperationsWidgetControls* m_Controls; mitk::MorphologicalOperations::StructuralElementType CreateStructerElement_UI(); }; #endif diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp deleted file mode 100644 index 2389dda82b..0000000000 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/*============================================================================ - -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 "QmitkSegmentationUtilityWidget.h" - -QmitkSegmentationUtilityWidget::QmitkSegmentationUtilityWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent) - : QWidget(parent) -{ - this->SetTimeNavigationController(timeNavigationController); -} - -QmitkSegmentationUtilityWidget::~QmitkSegmentationUtilityWidget() -{ -} - -mitk::SliceNavigationController* QmitkSegmentationUtilityWidget::GetTimeNavigationController() const -{ - return m_TimeNavigationController; -} - -void QmitkSegmentationUtilityWidget::SetTimeNavigationController(mitk::SliceNavigationController* timeNavigationController) -{ - m_TimeNavigationController = timeNavigationController; - this->setEnabled(timeNavigationController != nullptr); -} diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.h deleted file mode 100644 index d0328f9804..0000000000 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSegmentationUtilityWidget.h +++ /dev/null @@ -1,53 +0,0 @@ -/*============================================================================ - -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 QmitkSegmentationUtilityWidget_h -#define QmitkSegmentationUtilityWidget_h - -#include - -#include - -namespace mitk -{ - class SliceNavigationController; -} - -/** \brief Base class for segmentation utility widgets that need access to the time navigation controller. - * - * Call GetTimeNavigationController() in your derived class to gain access to the time navigation controller. - * The time navigation controller is not not available at all times and hence this method can return nullptr. - */ -class MITKSEGMENTATIONUI_EXPORT QmitkSegmentationUtilityWidget : public QWidget -{ - Q_OBJECT - -public: - explicit QmitkSegmentationUtilityWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = nullptr); - ~QmitkSegmentationUtilityWidget() override; - - /** \brief Usually called only from QmitkSegmentationUtilitiesView::RenderWindowPartActivated() and QmitkSegmentationUtilitiesView::RenderWindowPartDeactivated(). - */ - void SetTimeNavigationController(mitk::SliceNavigationController* timeNavigationController); - -protected: - /** \brief Call this method to access the time navigation controller. - * - * \return Pointer to the time navigation controller or nullptr, if it is not available. - */ - mitk::SliceNavigationController* GetTimeNavigationController() const; - -private: - mitk::SliceNavigationController* m_TimeNavigationController; -}; - -#endif diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp index 2e0edecc2f..7e6ad451b1 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp @@ -1,170 +1,168 @@ /*============================================================================ 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 "QmitkSurfaceToImageWidget.h" #include #include #include #include #include #include #include #include #include #include #include static const char* const HelpText = "Select an image and a surface above"; -QmitkSurfaceToImageWidget::QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent) - : QmitkSegmentationUtilityWidget(timeNavigationController, parent) +QmitkSurfaceToImageWidget::QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent) + : QWidget(parent) { m_Controls = new Ui::QmitkSurfaceToImageWidgetControls; m_Controls->setupUi(this); m_Controls->dataSelectionWidget->SetDataStorage(dataStorage); m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImageAndSegmentationPredicate); m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SurfacePredicate); m_Controls->dataSelectionWidget->SetHelpText(HelpText); this->EnableButtons(false); connect (m_Controls->btnSurface2Image, SIGNAL(pressed()), this, SLOT(OnSurface2ImagePressed())); connect(m_Controls->dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); if( m_Controls->dataSelectionWidget->GetSelection(0).IsNotNull() && m_Controls->dataSelectionWidget->GetSelection(1).IsNotNull() ) { this->OnSelectionChanged(0, m_Controls->dataSelectionWidget->GetSelection(0)); } } QmitkSurfaceToImageWidget::~QmitkSurfaceToImageWidget() { } void QmitkSurfaceToImageWidget::EnableButtons(bool enable) { m_Controls->btnSurface2Image->setEnabled(enable); } void QmitkSurfaceToImageWidget::OnSelectionChanged(unsigned int, const mitk::DataNode*) { QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0); mitk::DataNode::Pointer surfaceNode = dataSelectionWidget->GetSelection(1); if (imageNode.IsNull() || surfaceNode.IsNull() ) { dataSelectionWidget->SetHelpText(HelpText); this->EnableButtons(false); } else { mitk::Image::Pointer image = dynamic_cast( dataSelectionWidget->GetSelection(0)->GetData() ); mitk::Surface::Pointer surface = dynamic_cast( dataSelectionWidget->GetSelection(1)->GetData() ); if( image->GetTimeSteps() != surface->GetTimeSteps() ) { dataSelectionWidget->SetHelpText("Image and surface are of different size"); this->EnableButtons(false); } else { dataSelectionWidget->SetHelpText(""); this->EnableButtons(); } } } void QmitkSurfaceToImageWidget::OnSurface2ImagePressed() { this->EnableButtons(false); QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget; mitk::Image::Pointer image = dynamic_cast( dataSelectionWidget->GetSelection(0)->GetData() ); mitk::Surface::Pointer surface = dynamic_cast( dataSelectionWidget->GetSelection(1)->GetData() ); if( image.IsNull() || surface.IsNull()) { MITK_ERROR << "Selection does not contain an image and/or a surface"; QMessageBox::information( this, "Surface To Image", "Selection does not contain an image and/or a surface", QMessageBox::Ok ); this->EnableButtons(); return; } mitk::Image::Pointer resultImage(nullptr); resultImage = this->ConvertSurfaceToImage( image, surface ); if( resultImage.IsNull() ) { MITK_ERROR << "Convert Surface to binary image failed"; QMessageBox::information( this, "Surface To Image", "Convert Surface to binary image failed", QMessageBox::Ok ); this->EnableButtons(); return; } //create name for result node std::string nameOfResultImage = dataSelectionWidget->GetSelection(0)->GetName(); nameOfResultImage.append("_"); nameOfResultImage.append(dataSelectionWidget->GetSelection(1)->GetName()); //create data node and add to data storage mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); resultNode->SetData( resultImage ); resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) ); // resultNode->SetProperty("binary", mitk::BoolProperty::New(true) ); auto dataStorage = dataSelectionWidget->GetDataStorage(); if (dataStorage.IsNull()) { std::string exception = "Cannot add result to the data storage. Data storage invalid."; MITK_ERROR << "Error converting surface to binary image: " << exception; QMessageBox::information(nullptr, "Error converting surface to binary image", QString::fromStdString(exception)); } dataStorage->Add(resultNode, dataSelectionWidget->GetSelection(0)); this->EnableButtons(); } mitk::LabelSetImage::Pointer QmitkSurfaceToImageWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface ) { mitk::ProgressBar::GetInstance()->AddStepsToDo(2); mitk::ProgressBar::GetInstance()->Progress(); mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New(); surfaceToImageFilter->MakeOutputBinaryOn(); surfaceToImageFilter->SetInput(surface); surfaceToImageFilter->SetImage(image); try { surfaceToImageFilter->Update(); } catch(itk::ExceptionObject& excpt) { MITK_ERROR << excpt.GetDescription(); return nullptr; } mitk::ProgressBar::GetInstance()->Progress(); mitk::Image::Pointer resultImage = surfaceToImageFilter->GetOutput(); mitk::LabelSetImage::Pointer multilabelImage = mitk::LabelSetImage::New(); multilabelImage->InitializeByLabeledImage(resultImage); return multilabelImage; } diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h index 55e2178163..b218cf76c9 100644 --- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h +++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h @@ -1,77 +1,75 @@ /*============================================================================ 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 QmitkSurfaceToImageWidget_h #define QmitkSurfaceToImageWidget_h #include -#include - #include "itkSmartPointer.h" +#include + namespace Ui { class QmitkSurfaceToImageWidgetControls; } namespace mitk { class DataNode; class DataStorage; class Surface; class Image; class LabelSetImage; } /*! \brief QmitkSurfaceToImageWidget The Tool converts a surface to a binary image. The Method requires a surface and an image, which header information defines the output image. The resulting binary image has the same dimension, size, and Geometry3D as the input image. */ -class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceToImageWidget : public QmitkSegmentationUtilityWidget +class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceToImageWidget : public QWidget { Q_OBJECT public: /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */ - explicit QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage, - mitk::SliceNavigationController* timeNavigationController, - QWidget* parent = nullptr); + explicit QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr); /** @brief Defaul destructor. */ ~QmitkSurfaceToImageWidget() override; private slots: /** @brief This slot is called if the selection in the workbench is changed. */ void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); /** @brief This slot is called if user activates the button to convert a surface into a binary image. */ void OnSurface2ImagePressed(); private: /** @brief Enable buttons if data selction is valid. */ void EnableButtons(bool enable = true); /** @brief Convert a surface into an binary image. */ itk::SmartPointer ConvertSurfaceToImage( itk::SmartPointer image, itk::SmartPointer surface ); Ui::QmitkSurfaceToImageWidgetControls* m_Controls; }; #endif diff --git a/Modules/SegmentationUI/files.cmake b/Modules/SegmentationUI/files.cmake index 31888eed64..fff1c66311 100644 --- a/Modules/SegmentationUI/files.cmake +++ b/Modules/SegmentationUI/files.cmake @@ -1,125 +1,123 @@ 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 SegmentationUtilities/QmitkBooleanOperationsWidget.cpp SegmentationUtilities/QmitkContourModelToImageWidget.cpp SegmentationUtilities/QmitkImageMaskingWidget.cpp SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp SegmentationUtilities/QmitkSurfaceToImageWidget.cpp - SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp SegmentationUtilities/QmitkDataSelectionWidget.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 SegmentationUtilities/QmitkBooleanOperationsWidget.h SegmentationUtilities/QmitkContourModelToImageWidget.h SegmentationUtilities/QmitkImageMaskingWidget.h SegmentationUtilities/QmitkMorphologicalOperationsWidget.h SegmentationUtilities/QmitkSurfaceToImageWidget.h - SegmentationUtilities/QmitkSegmentationUtilityWidget.h SegmentationUtilities/QmitkDataSelectionWidget.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 SegmentationUtilities/QmitkBooleanOperationsWidgetControls.ui SegmentationUtilities/QmitkContourModelToImageWidgetControls.ui SegmentationUtilities/QmitkImageMaskingWidgetControls.ui SegmentationUtilities/QmitkMorphologicalOperationsWidgetControls.ui SegmentationUtilities/QmitkSurfaceToImageWidgetControls.ui SegmentationUtilities/QmitkDataSelectionWidgetControls.ui ) set(QRC_FILES resources/SegmentationUI.qrc ) diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp index 330e893f69..4a96a422a7 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp @@ -1,86 +1,68 @@ /*============================================================================ 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 "QmitkSegmentationUtilitiesView.h" #include #include #include #include #include QmitkSegmentationUtilitiesView::QmitkSegmentationUtilitiesView() : m_BooleanOperationsWidget(nullptr), m_ContourModelToImageWidget(nullptr), m_ImageMaskingWidget(nullptr), m_MorphologicalOperationsWidget(nullptr), m_SurfaceToImageWidget(nullptr) { } QmitkSegmentationUtilitiesView::~QmitkSegmentationUtilitiesView() { } void QmitkSegmentationUtilitiesView::CreateQtPartControl(QWidget* parent) { m_Controls.setupUi(parent); - mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart(); - - mitk::SliceNavigationController* timeNavigationController = renderWindowPart != nullptr - ? renderWindowPart->GetTimeNavigationController() - : nullptr; - auto dataStorage = this->GetDataStorage(); - m_BooleanOperationsWidget = new QmitkBooleanOperationsWidget(dataStorage, timeNavigationController, parent); - m_ContourModelToImageWidget = new QmitkContourModelToImageWidget(dataStorage, timeNavigationController, parent); - m_ImageMaskingWidget = new QmitkImageMaskingWidget(dataStorage, timeNavigationController, parent); - m_MorphologicalOperationsWidget = new QmitkMorphologicalOperationsWidget(dataStorage, timeNavigationController, parent); - m_SurfaceToImageWidget = new QmitkSurfaceToImageWidget(dataStorage, timeNavigationController, parent); + m_BooleanOperationsWidget = new QmitkBooleanOperationsWidget(dataStorage, parent); + m_ContourModelToImageWidget = new QmitkContourModelToImageWidget(dataStorage, parent); + m_ImageMaskingWidget = new QmitkImageMaskingWidget(dataStorage, parent); + m_MorphologicalOperationsWidget = new QmitkMorphologicalOperationsWidget(dataStorage, parent); + m_SurfaceToImageWidget = new QmitkSurfaceToImageWidget(dataStorage, parent); this->AddUtilityWidget(m_BooleanOperationsWidget, QIcon(":/SegmentationUtilities/BooleanOperations_48x48.png"), "Boolean Operations"); this->AddUtilityWidget(m_ContourModelToImageWidget, QIcon(":/SegmentationUtilities/ContourModelSetToImage_48x48.png"), "Contour to Image"); this->AddUtilityWidget(m_ImageMaskingWidget, QIcon(":/SegmentationUtilities/ImageMasking_48x48.png"), "Image Masking"); this->AddUtilityWidget(m_MorphologicalOperationsWidget, QIcon(":/SegmentationUtilities/MorphologicalOperations_48x48.png"), "Morphological Operations"); this->AddUtilityWidget(m_SurfaceToImageWidget, QIcon(":/SegmentationUtilities/SurfaceToImage_48x48.png"), "Surface to Image"); } void QmitkSegmentationUtilitiesView::AddUtilityWidget(QWidget* widget, const QIcon& icon, const QString& text) { m_Controls.toolBox->addItem(widget, icon, text); } void QmitkSegmentationUtilitiesView::SetFocus() { m_Controls.toolBox->setFocus(); } -void QmitkSegmentationUtilitiesView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) +void QmitkSegmentationUtilitiesView::RenderWindowPartActivated(mitk::IRenderWindowPart*) { - mitk::SliceNavigationController* timeNavigationController = renderWindowPart->GetTimeNavigationController(); - - m_BooleanOperationsWidget->SetTimeNavigationController(timeNavigationController); - m_ContourModelToImageWidget->SetTimeNavigationController(timeNavigationController); - m_ImageMaskingWidget->SetTimeNavigationController(timeNavigationController); - m_MorphologicalOperationsWidget->SetTimeNavigationController(timeNavigationController); - m_SurfaceToImageWidget->SetTimeNavigationController(timeNavigationController); } void QmitkSegmentationUtilitiesView::RenderWindowPartDeactivated(mitk::IRenderWindowPart*) { - m_BooleanOperationsWidget->SetTimeNavigationController(nullptr); - m_ContourModelToImageWidget->SetTimeNavigationController(nullptr); - m_ImageMaskingWidget->SetTimeNavigationController(nullptr); - m_MorphologicalOperationsWidget->SetTimeNavigationController(nullptr); - m_SurfaceToImageWidget->SetTimeNavigationController(nullptr); }