diff --git a/Modules/Segmentation/Interactions/mitkSegmentationInteractor.cpp b/Modules/Segmentation/Interactions/mitkSegmentationInteractor.cpp index f14f92c7a4..5cbc3921b9 100644 --- a/Modules/Segmentation/Interactions/mitkSegmentationInteractor.cpp +++ b/Modules/Segmentation/Interactions/mitkSegmentationInteractor.cpp @@ -1,65 +1,64 @@ /*============================================================================ 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 "mitkSegmentationInteractor.h" #include "mitkInteractionPositionEvent.h" #include "mitkLabelSetImage.h" #include "mitkToolManager.h" #include "mitkToolManagerProvider.h" #include #include void mitk::SegmentationInteractor::ConnectActionsAndFunctions() { Superclass::ConnectActionsAndFunctions(); // CONNECT_FUNCTION("change_active_label", ChangeActiveLabel); } bool mitk::SegmentationInteractor::ChangeActiveLabel(StateMachineAction *, InteractionEvent *interactionEvent) { BaseRenderer::Pointer sender = interactionEvent->GetSender(); auto positionEvent = static_cast(interactionEvent); - auto toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager( - mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + auto toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); assert(toolManager); DataNode *workingNode(toolManager->GetWorkingData(0)); if (workingNode && positionEvent) { //TODO T28561 //Code uses a deprecated method. deactivated whole code until the refactorization is done. throw "TODO T28561. Was forgot to refactor in context of T28524. The new MultiLabelSegmentation class will have a dedicated function for querying the label of world position."; //auto *workingImage = dynamic_cast(workingNode->GetData()); //assert(workingImage); //const auto timestep = positionEvent->GetSender()->GetTimeStep(workingImage); //int pixelValue = static_cast(workingImage->GetPixelValueByWorldCoordinate(positionEvent->GetPositionInWorld(), timestep)); //workingImage->GetActiveLabelSet()->SetActiveLabel(pixelValue); // can be the background // // Call Events // // workingImage->ActiveLabelEvent.Send(pixelValue); // // MLI TODO // // toolManager->WorkingDataModified.Send(); //TODO END Refactor with T28524 } RenderingManager::GetInstance()->RequestUpdateAll(); return true; } diff --git a/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.cpp b/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.cpp index 5d72312905..2eca2226cd 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.cpp @@ -1,115 +1,115 @@ /*============================================================================ 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 "QmitkMaskStampWidget.h" #include #include #include #include QmitkMaskStampWidget::QmitkMaskStampWidget(QWidget *parent, const char * /*name*/) : QWidget(parent), m_ToolManager(nullptr), m_DataStorage(nullptr) { m_Controls.setupUi(this); m_Controls.m_InformationWidget->hide(); - m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); m_ToolManager->ActivateTool(-1); mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer isMask = mitk::NodePredicateAnd::New(isBinary, isImage); mitk::NodePredicateAnd::Pointer maskPredicate = mitk::NodePredicateAnd::New(); maskPredicate->AddPredicate(isMask); maskPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); m_Controls.m_cbMaskNodeSelector->SetPredicate(maskPredicate); connect(m_Controls.m_pbStamp, SIGNAL(clicked()), this, SLOT(OnStamp())); connect(m_Controls.m_cbShowInformation, SIGNAL(toggled(bool)), this, SLOT(OnShowInformation(bool))); m_Controls.m_InformationWidget->hide(); } QmitkMaskStampWidget::~QmitkMaskStampWidget() { } void QmitkMaskStampWidget::SetDataStorage(mitk::DataStorage *storage) { m_DataStorage = storage; m_Controls.m_cbMaskNodeSelector->SetDataStorage(m_DataStorage); } void QmitkMaskStampWidget::OnStamp() { mitk::DataNode *maskNode = m_Controls.m_cbMaskNodeSelector->GetSelectedNode(); if (!maskNode) { QMessageBox::information(this, "Mask Stamp", "Please load and select a mask before starting some action."); return; } mitk::Image *mask = dynamic_cast(maskNode->GetData()); if (!mask) { QMessageBox::information(this, "Mask Stamp", "Please load and select a mask before starting some action."); return; } mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); if (!workingNode) { QMessageBox::information(this, "Mask Stamp", "Please load and select a segmentation before starting some action."); return; } mitk::LabelSetImage *workingImage = dynamic_cast(workingNode->GetData()); if (!workingImage) { QMessageBox::information(this, "Mask Stamp", "Please load and select a segmentation before starting some action."); return; } QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); try { workingImage->MaskStamp(mask, m_Controls.m_chkOverwrite->isChecked()); } catch (mitk::Exception &e) { QApplication::restoreOverrideCursor(); MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information(this, "Mask Stamp", "Could not stamp the selected mask.\n See error log for details.\n"); return; } QApplication::restoreOverrideCursor(); maskNode->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkMaskStampWidget::OnShowInformation(bool on) { if (on) m_Controls.m_InformationWidget->show(); else m_Controls.m_InformationWidget->hide(); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.h b/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.h index e75f8c8adf..456a6f1cc4 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.h +++ b/Modules/SegmentationUI/Qmitk/QmitkMaskStampWidget.h @@ -1,61 +1,59 @@ /*============================================================================ 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 QmitkMaskStampWidget_h_Included #define QmitkMaskStampWidget_h_Included #include "MitkSegmentationUIExports.h" #include "mitkDataNode.h" #include #include "ui_QmitkMaskStampWidgetGUIControls.h" namespace mitk { class ToolManager; } /** \brief GUI for mask stamp functionality - This class uses the mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION context. - \ingroup ToolManagerEtAl \ingroup Widgets */ class MITKSEGMENTATIONUI_EXPORT QmitkMaskStampWidget : public QWidget { Q_OBJECT public: QmitkMaskStampWidget(QWidget *parent = nullptr, const char *name = nullptr); ~QmitkMaskStampWidget() override; void SetDataStorage(mitk::DataStorage *storage); protected slots: void OnShowInformation(bool); void OnStamp(); private: mitk::ToolManager *m_ToolManager; mitk::DataStorage *m_DataStorage; Ui::QmitkMaskStampWidgetGUIControls m_Controls; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.cpp b/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.cpp index d731966d1f..7533b4382e 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.cpp @@ -1,710 +1,710 @@ /*============================================================================ 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 "QmitkSliceBasedInterpolatorWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "QmitkStdMultiWidget.h" #include #include #include #include #include QmitkSliceBasedInterpolatorWidget::QmitkSliceBasedInterpolatorWidget(QWidget *parent, const char * /*name*/) : QWidget(parent), m_SliceInterpolatorController(mitk::SliceBasedInterpolationController::New()), m_ToolManager(nullptr), m_Activated(false), m_DataStorage(nullptr), m_LastSNC(nullptr), m_LastSliceIndex(0) { m_Controls.setupUi(this); - m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); m_ToolManager->WorkingDataChanged += mitk::MessageDelegate( this, &QmitkSliceBasedInterpolatorWidget::OnToolManagerWorkingDataModified); connect(m_Controls.m_btStart, SIGNAL(toggled(bool)), this, SLOT(OnToggleWidgetActivation(bool))); connect(m_Controls.m_btApplyForCurrentSlice, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked())); connect(m_Controls.m_btApplyForAllSlices, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked())); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSliceBasedInterpolatorWidget::OnSliceInterpolationInfoChanged); m_InterpolationInfoChangedObserverTag = m_SliceInterpolatorController->AddObserver(itk::ModifiedEvent(), command); // feedback node and its visualization properties m_PreviewNode = mitk::DataNode::New(); m_PreviewNode->SetName("3D tool preview"); m_PreviewNode->SetProperty("texture interpolation", mitk::BoolProperty::New(false)); m_PreviewNode->SetProperty("layer", mitk::IntProperty::New(100)); m_PreviewNode->SetProperty("binary", mitk::BoolProperty::New(true)); m_PreviewNode->SetProperty("outline binary", mitk::BoolProperty::New(true)); m_PreviewNode->SetProperty("outline binary shadow", mitk::BoolProperty::New(true)); m_PreviewNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_PreviewNode->SetOpacity(1.0); m_PreviewNode->SetColor(0.0, 1.0, 0.0); m_Controls.m_btApplyForCurrentSlice->setEnabled(false); m_Controls.m_btApplyForAllSlices->setEnabled(false); this->setEnabled(false); } QmitkSliceBasedInterpolatorWidget::~QmitkSliceBasedInterpolatorWidget() { m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate( this, &QmitkSliceBasedInterpolatorWidget::OnToolManagerWorkingDataModified); foreach (mitk::SliceNavigationController *slicer, m_ControllerToSliceObserverTag.keys()) { slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer)); slicer->RemoveObserver(m_ControllerToTimeObserverTag.take(slicer)); slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer)); } m_ActionToSliceDimensionMap.clear(); // remove observer m_SliceInterpolatorController->RemoveObserver(m_InterpolationInfoChangedObserverTag); } const QmitkSliceBasedInterpolatorWidget::ActionToSliceDimensionMapType QmitkSliceBasedInterpolatorWidget::CreateActionToSliceDimension() { ActionToSliceDimensionMapType actionToSliceDimension; foreach (mitk::SliceNavigationController *slicer, m_ControllerToDeleteObserverTag.keys()) { std::string name = slicer->GetRenderer()->GetName(); if (name == "stdmulti.widget0") name = "Axial (red window)"; else if (name == "stdmulti.widget1") name = "Sagittal (green window)"; else if (name == "stdmulti.widget2") name = "Coronal (blue window)"; actionToSliceDimension[new QAction(QString::fromStdString(name), nullptr)] = slicer; } return actionToSliceDimension; } void QmitkSliceBasedInterpolatorWidget::SetDataStorage(mitk::DataStorage &storage) { m_DataStorage = &storage; } void QmitkSliceBasedInterpolatorWidget::SetSliceNavigationControllers( const QList &controllers) { Q_ASSERT(!controllers.empty()); // connect to the slice navigation controller. after each change, call the interpolator foreach (mitk::SliceNavigationController *slicer, controllers) { // Has to be initialized m_LastSNC = slicer; m_TimePoints.insert(slicer, slicer->GetSelectedTimePoint()); itk::MemberCommand::Pointer deleteCommand = itk::MemberCommand::New(); deleteCommand->SetCallbackFunction(this, &QmitkSliceBasedInterpolatorWidget::OnSliceNavigationControllerDeleted); m_ControllerToDeleteObserverTag.insert(slicer, slicer->AddObserver(itk::DeleteEvent(), deleteCommand)); itk::MemberCommand::Pointer timeChangedCommand = itk::MemberCommand::New(); timeChangedCommand->SetCallbackFunction(this, &QmitkSliceBasedInterpolatorWidget::OnTimeChanged); m_ControllerToTimeObserverTag.insert( slicer, slicer->AddObserver(mitk::SliceNavigationController::TimeGeometryEvent(nullptr, 0), timeChangedCommand)); itk::MemberCommand::Pointer sliceChangedCommand = itk::MemberCommand::New(); sliceChangedCommand->SetCallbackFunction(this, &QmitkSliceBasedInterpolatorWidget::OnSliceChanged); m_ControllerToSliceObserverTag.insert( slicer, slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), sliceChangedCommand)); } m_ActionToSliceDimensionMap = this->CreateActionToSliceDimension(); } void QmitkSliceBasedInterpolatorWidget::OnToolManagerWorkingDataModified() { mitk::DataNode *workingNode = this->m_ToolManager->GetWorkingData(0); if (!workingNode) { this->setEnabled(false); return; } mitk::LabelSetImage *workingImage = dynamic_cast(workingNode->GetData()); // TODO adapt tool manager so that this check is done there, e.g. convenience function // Q_ASSERT(workingImage); if (!workingImage) { this->setEnabled(false); return; } if (workingImage->GetDimension() > 4 || workingImage->GetDimension() < 3) { this->setEnabled(false); return; } m_WorkingImage = workingImage; this->setEnabled(true); } void QmitkSliceBasedInterpolatorWidget::OnTimeChanged(itk::Object *sender, const itk::EventObject &e) { // Check if we really have a GeometryTimeEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController *slicer = dynamic_cast(sender); Q_ASSERT(slicer); m_TimePoints[slicer] = slicer->GetSelectedTimePoint(); // TODO Macht das hier wirklich Sinn???? if (m_LastSNC == slicer) { slicer->SendSlice(); // will trigger a new interpolation } } void QmitkSliceBasedInterpolatorWidget::OnSliceChanged(itk::Object *sender, const itk::EventObject &e) { if (m_Activated && m_WorkingImage.IsNotNull()) { // Check whether we really have a GeometrySliceEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController *slicer = dynamic_cast(sender); if (slicer) { this->TranslateAndInterpolateChangedSlice(e, slicer); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // slicer->GetRenderer()->RequestUpdate(); } } } void QmitkSliceBasedInterpolatorWidget::TranslateAndInterpolateChangedSlice(const itk::EventObject &e, mitk::SliceNavigationController *slicer) { if (m_Activated && m_WorkingImage.IsNotNull()) { const mitk::SliceNavigationController::GeometrySliceEvent &geometrySliceEvent = dynamic_cast(e); mitk::TimeGeometry *timeGeometry = geometrySliceEvent.GetTimeGeometry(); if (timeGeometry && m_TimePoints.contains(slicer) && timeGeometry->IsValidTimePoint(m_TimePoints[slicer])) { mitk::SlicedGeometry3D *slicedGeometry = dynamic_cast(timeGeometry->GetGeometryForTimePoint(m_TimePoints[slicer]).GetPointer()); if (slicedGeometry) { mitk::PlaneGeometry *plane = slicedGeometry->GetPlaneGeometry(geometrySliceEvent.GetPos()); if (plane) { m_LastSNC = slicer; this->Interpolate(plane, m_TimePoints[slicer], slicer); } } } } } void QmitkSliceBasedInterpolatorWidget::Interpolate(mitk::PlaneGeometry *plane, mitk::TimePointType timePoint, mitk::SliceNavigationController *slicer) { int clickedSliceDimension(-1); int clickedSliceIndex(-1); if (!m_WorkingImage->GetTimeGeometry()->IsValidTimePoint(timePoint)) { MITK_WARN << "Cannot interpolate WorkingImage. Passed time point is not within the time bounds of WorkingImage. Time point: " << timePoint; return; } const auto timeStep = m_WorkingImage->GetTimeGeometry()->TimePointToTimeStep(timePoint); // calculate real slice position, i.e. slice of the image // see if timestep is needed here mitk::SegTool2D::DetermineAffectedImageSlice(m_WorkingImage, plane, clickedSliceDimension, clickedSliceIndex); mitk::Image::Pointer interpolation = m_SliceInterpolatorController->Interpolate(clickedSliceDimension, clickedSliceIndex, plane, timeStep); m_PreviewNode->SetData(interpolation); const mitk::Color &color = m_WorkingImage->GetActiveLabel()->GetColor(); m_PreviewNode->SetColor(color); m_LastSNC = slicer; m_LastSliceIndex = clickedSliceIndex; } mitk::Image::Pointer QmitkSliceBasedInterpolatorWidget::GetWorkingSlice(const mitk::PlaneGeometry *planeGeometry) { const auto timePoint = m_LastSNC->GetSelectedTimePoint(); if (!m_WorkingImage->GetTimeGeometry()->IsValidTimePoint(timePoint)) { MITK_WARN << "Cannot get slice of WorkingImage. Time point selected by SliceNavigationController is not within the time bounds of WorkingImage. Time point: " << timePoint; return nullptr; } // Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk // reslicer vtkSmartPointer reslice = vtkSmartPointer::New(); // set to false to extract a slice reslice->SetOverwriteMode(false); reslice->Modified(); // use ExtractSliceFilter with our specific vtkImageReslice for overwriting and extracting mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice); extractor->SetInput(m_WorkingImage); const auto timeStep = m_WorkingImage->GetTimeGeometry()->TimePointToTimeStep(timePoint); extractor->SetTimeStep(timeStep); extractor->SetWorldGeometry(planeGeometry); extractor->SetVtkOutputRequest(false); extractor->SetResliceTransformByGeometry(m_WorkingImage->GetTimeGeometry()->GetGeometryForTimeStep(timeStep)); extractor->Modified(); try { extractor->Update(); } catch (itk::ExceptionObject &excep) { MITK_ERROR << "Exception caught: " << excep.GetDescription(); return nullptr; } mitk::Image::Pointer slice = extractor->GetOutput(); // specify the undo operation with the non edited slice // MLI TODO added code starts here mitk::SlicedGeometry3D *sliceGeometry = dynamic_cast(slice->GetGeometry()); // m_undoOperation = new mitk::DiffSliceOperation(m_WorkingImage, extractor->GetVtkOutput(), slice->GetGeometry(), // timeStep, const_cast(planeGeometry)); // added code ends here m_undoOperation = new mitk::DiffSliceOperation( m_WorkingImage, extractor->GetOutput(), sliceGeometry, timeStep, const_cast(planeGeometry)); slice->DisconnectPipeline(); return slice; } void QmitkSliceBasedInterpolatorWidget::OnToggleWidgetActivation(bool enabled) { Q_ASSERT(m_ToolManager); mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); if (!workingNode) return; m_Controls.m_btApplyForCurrentSlice->setEnabled(enabled); m_Controls.m_btApplyForAllSlices->setEnabled(enabled); if (enabled) m_Controls.m_btStart->setText("Stop"); else m_Controls.m_btStart->setText("Start"); unsigned int numberOfExistingTools = m_ToolManager->GetTools().size(); for (unsigned int i = 0; i < numberOfExistingTools; i++) { // mitk::SegTool2D* tool = dynamic_cast(m_ToolManager->GetToolById(i)); // MLI TODO // if (tool) tool->SetEnable2DInterpolation( enabled ); } if (enabled) { if (!m_DataStorage->Exists(m_PreviewNode)) { m_DataStorage->Add(m_PreviewNode); } m_SliceInterpolatorController->SetWorkingImage(m_WorkingImage); this->UpdateVisibleSuggestion(); } else { if (m_DataStorage->Exists(m_PreviewNode)) { m_DataStorage->Remove(m_PreviewNode); } mitk::UndoController::GetCurrentUndoModel()->Clear(); } m_Activated = enabled; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } template void QmitkSliceBasedInterpolatorWidget::WritePreviewOnWorkingImage(itk::Image *targetSlice, const mitk::Image *sourceSlice, int overwritevalue) { typedef itk::Image ImageType; typename ImageType::Pointer sourceSliceITK; mitk::CastToItkImage(sourceSlice, sourceSliceITK); // now the original slice and the ipSegmentation-painted slice are in the same format, and we can just copy all pixels // that are non-zero typedef itk::ImageRegionIterator OutputIteratorType; typedef itk::ImageRegionConstIterator InputIteratorType; InputIteratorType inputIterator(sourceSliceITK, sourceSliceITK->GetLargestPossibleRegion()); OutputIteratorType outputIterator(targetSlice, targetSlice->GetLargestPossibleRegion()); outputIterator.GoToBegin(); inputIterator.GoToBegin(); int activePixelValue = m_WorkingImage->GetActiveLabel()->GetValue(); if (activePixelValue == 0) // if exterior is the active label { while (!outputIterator.IsAtEnd()) { if (inputIterator.Get() != 0) { outputIterator.Set(overwritevalue); } ++outputIterator; ++inputIterator; } } else if (overwritevalue != 0) // if we are not erasing { while (!outputIterator.IsAtEnd()) { int targetValue = static_cast(outputIterator.Get()); if (inputIterator.Get() != 0) { if (!m_WorkingImage->GetLabel(targetValue)->GetLocked()) outputIterator.Set(overwritevalue); } ++outputIterator; ++inputIterator; } } else // if we are erasing { while (!outputIterator.IsAtEnd()) { const int targetValue = outputIterator.Get(); if (inputIterator.Get() != 0) { if (targetValue == activePixelValue) outputIterator.Set(overwritevalue); } ++outputIterator; ++inputIterator; } } } void QmitkSliceBasedInterpolatorWidget::OnAcceptInterpolationClicked() { if (m_WorkingImage.IsNotNull() && m_PreviewNode->GetData()) { const mitk::PlaneGeometry *planeGeometry = m_LastSNC->GetCurrentPlaneGeometry(); if (!planeGeometry) return; mitk::Image::Pointer sliceImage = this->GetWorkingSlice(planeGeometry); if (sliceImage.IsNull()) return; mitk::Image::Pointer previewSlice = dynamic_cast(m_PreviewNode->GetData()); AccessFixedDimensionByItk_2( sliceImage, WritePreviewOnWorkingImage, 2, previewSlice, m_WorkingImage->GetActiveLabel()->GetValue()); // Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk // reslicer vtkSmartPointer overwrite = vtkSmartPointer::New(); overwrite->SetInputSlice(sliceImage->GetVtkImageData()); // set overwrite mode to true to write back to the image volume overwrite->SetOverwriteMode(true); overwrite->Modified(); const auto timePoint = m_LastSNC->GetSelectedTimePoint(); if (!m_WorkingImage->GetTimeGeometry()->IsValidTimePoint(timePoint)) { MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the time bounds of WorkingImage. Time point: " << timePoint; return; } mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(overwrite); extractor->SetInput(m_WorkingImage); const auto timeStep = m_WorkingImage->GetTimeGeometry()->TimePointToTimeStep(timePoint); extractor->SetTimeStep(timeStep); extractor->SetWorldGeometry(planeGeometry); extractor->SetVtkOutputRequest(false); extractor->SetResliceTransformByGeometry(m_WorkingImage->GetTimeGeometry()->GetGeometryForTimeStep(timeStep)); extractor->Modified(); try { extractor->Update(); } catch (itk::ExceptionObject &excep) { MITK_ERROR << "Exception caught: " << excep.GetDescription(); return; } // the image was modified within the pipeline, but not marked so m_WorkingImage->Modified(); int clickedSliceDimension(-1); int clickedSliceIndex(-1); mitk::SegTool2D::DetermineAffectedImageSlice( m_WorkingImage, planeGeometry, clickedSliceDimension, clickedSliceIndex); m_SliceInterpolatorController->SetChangedSlice(sliceImage, clickedSliceDimension, clickedSliceIndex, timeStep); // specify the undo operation with the edited slice // MLI TODO added code starts here mitk::SlicedGeometry3D *sliceGeometry = dynamic_cast(sliceImage->GetGeometry()); // m_undoOperation = new mitk::DiffSliceOperation(m_WorkingImage, extractor->GetVtkOutput(), slice->GetGeometry(), // timeStep, const_cast(planeGeometry)); // added code ends here m_doOperation = new mitk::DiffSliceOperation(m_WorkingImage, extractor->GetOutput(), sliceGeometry, timeStep, const_cast(planeGeometry)); // create an operation event for the undo stack mitk::OperationEvent *undoStackItem = new mitk::OperationEvent( mitk::DiffSliceOperationApplier::GetInstance(), m_doOperation, m_undoOperation, "Slice Interpolation"); // add it to the undo controller mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent(undoStackItem); // clear the pointers as the operation are stored in the undo controller and also deleted from there m_undoOperation = nullptr; m_doOperation = nullptr; m_PreviewNode->SetData(nullptr); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSliceBasedInterpolatorWidget::AcceptAllInterpolations(mitk::SliceNavigationController *slicer) { // Since we need to shift the plane it must be clone so that the original plane isn't altered mitk::PlaneGeometry::Pointer reslicePlane = slicer->GetCurrentPlaneGeometry()->Clone(); const auto timePoint = slicer->GetSelectedTimePoint(); if (!m_WorkingImage->GetTimeGeometry()->IsValidTimePoint(timePoint)) { MITK_WARN << "Cannot accept all interpolations. Time point selected by SliceNavigationController is not within the time bounds of WorkingImage. Time point: " << timePoint; return; } const auto timeStep = m_WorkingImage->GetTimeGeometry()->TimePointToTimeStep(timePoint); int sliceDimension(-1); int sliceIndex(-1); mitk::SegTool2D::DetermineAffectedImageSlice(m_WorkingImage, reslicePlane, sliceDimension, sliceIndex); unsigned int zslices = m_WorkingImage->GetDimension(sliceDimension); mitk::ProgressBar::GetInstance()->Reset(); mitk::ProgressBar::GetInstance()->AddStepsToDo(zslices); mitk::Point3D origin = reslicePlane->GetOrigin(); for (unsigned int idx = 0; idx < zslices; ++idx) { // Transforming the current origin of the reslice plane // so that it matches the one of the next slice m_WorkingImage->GetSlicedGeometry()->WorldToIndex(origin, origin); origin[sliceDimension] = idx; m_WorkingImage->GetSlicedGeometry()->IndexToWorld(origin, origin); reslicePlane->SetOrigin(origin); mitk::Image::Pointer interpolation = m_SliceInterpolatorController->Interpolate(sliceDimension, idx, reslicePlane, timeStep); if (interpolation.IsNotNull()) { m_PreviewNode->SetData(interpolation); mitk::Image::Pointer sliceImage = this->GetWorkingSlice(reslicePlane); if (sliceImage.IsNull()) return; AccessFixedDimensionByItk_2( sliceImage, WritePreviewOnWorkingImage, 2, interpolation, m_WorkingImage->GetActiveLabel()->GetValue()); // Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk // reslicer vtkSmartPointer overwrite = vtkSmartPointer::New(); overwrite->SetInputSlice(sliceImage->GetVtkImageData()); // set overwrite mode to true to write back to the image volume overwrite->SetOverwriteMode(true); overwrite->Modified(); mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(overwrite); extractor->SetInput(m_WorkingImage); extractor->SetTimeStep(timeStep); extractor->SetWorldGeometry(reslicePlane); extractor->SetVtkOutputRequest(true); extractor->SetResliceTransformByGeometry(m_WorkingImage->GetTimeGeometry()->GetGeometryForTimeStep(timeStep)); extractor->Modified(); try { extractor->Update(); } catch (itk::ExceptionObject &excep) { MITK_ERROR << "Exception caught: " << excep.GetDescription(); return; } m_WorkingImage->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); } mitk::ProgressBar::GetInstance()->Progress(); } m_SliceInterpolatorController->SetWorkingImage(m_WorkingImage); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSliceBasedInterpolatorWidget::OnAcceptAllInterpolationsClicked() { QMenu orientationPopup(this); std::map::const_iterator it; for (it = m_ActionToSliceDimensionMap.begin(); it != m_ActionToSliceDimensionMap.end(); it++) orientationPopup.addAction(it->first); connect(&orientationPopup, SIGNAL(triggered(QAction *)), this, SLOT(OnAcceptAllPopupActivated(QAction *))); orientationPopup.exec(QCursor::pos()); } void QmitkSliceBasedInterpolatorWidget::OnAcceptAllPopupActivated(QAction *action) { ActionToSliceDimensionMapType::const_iterator iter = m_ActionToSliceDimensionMap.find(action); if (iter != m_ActionToSliceDimensionMap.end()) { mitk::SliceNavigationController *slicer = iter->second; this->AcceptAllInterpolations(slicer); } } void QmitkSliceBasedInterpolatorWidget::UpdateVisibleSuggestion() { if (m_Activated && m_LastSNC) { // determine which one is the current view, try to do an initial interpolation mitk::BaseRenderer *renderer = m_LastSNC->GetRenderer(); if (renderer && renderer->GetMapperID() == mitk::BaseRenderer::Standard2D) { const mitk::TimeGeometry *timeGeometry = dynamic_cast(renderer->GetWorldTimeGeometry()); if (timeGeometry) { mitk::SliceNavigationController::GeometrySliceEvent event(const_cast(timeGeometry), renderer->GetSlice()); this->TranslateAndInterpolateChangedSlice(event, m_LastSNC); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } } void QmitkSliceBasedInterpolatorWidget::OnSliceInterpolationInfoChanged(const itk::EventObject & /*e*/) { // something (e.g. undo) changed the interpolation info, we should refresh our display this->UpdateVisibleSuggestion(); } void QmitkSliceBasedInterpolatorWidget::OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject & /*e*/) { // Don't know how to avoid const_cast here?! mitk::SliceNavigationController *slicer = dynamic_cast(const_cast(sender)); if (slicer) { m_ControllerToTimeObserverTag.remove(slicer); m_ControllerToSliceObserverTag.remove(slicer); m_ControllerToDeleteObserverTag.remove(slicer); } } void QmitkSliceBasedInterpolatorWidget::WaitCursorOn() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); } void QmitkSliceBasedInterpolatorWidget::WaitCursorOff() { this->RestoreOverrideCursor(); } void QmitkSliceBasedInterpolatorWidget::RestoreOverrideCursor() { QApplication::restoreOverrideCursor(); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.h b/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.h index b447a67e11..86c6cdab0a 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.h +++ b/Modules/SegmentationUI/Qmitk/QmitkSliceBasedInterpolatorWidget.h @@ -1,197 +1,195 @@ /*============================================================================ 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 QmitkSliceBasedInterpolatorWidget_h_Included #define QmitkSliceBasedInterpolatorWidget_h_Included #include "MitkSegmentationUIExports.h" #include "mitkDataStorage.h" #include "mitkSliceBasedInterpolationController.h" #include #include #include "ui_QmitkSliceBasedInterpolatorWidgetGUIControls.h" namespace mitk { class PlaneGeometry; class SliceNavigationController; class LabelSetImage; class ToolManager; class DiffSliceOperation; } /** \brief GUI for slices interpolation. \ingroup ToolManagerEtAl \ingroup Widgets \sa QmitkInteractiveSegmentation \sa mitk::SegmentationInterpolation While mitk::SegmentationInterpolation does the bookkeeping of interpolation (keeping track of which slices contain how much segmentation) and the algorithmic work, QmitkSliceBasedInterpolatorWidget is responsible to watch the GUI, to notice, which slice is currently visible. It triggers generation of interpolation suggestions and also triggers acception of suggestions. - This class uses the mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION context. - \todo show/hide feedback on demand Last contributor: $Author: maleike $ */ class MITKSEGMENTATIONUI_EXPORT QmitkSliceBasedInterpolatorWidget : public QWidget { Q_OBJECT public: QmitkSliceBasedInterpolatorWidget(QWidget *parent = nullptr, const char *name = nullptr); ~QmitkSliceBasedInterpolatorWidget() override; void SetDataStorage(mitk::DataStorage &storage); /** Sets the slice navigation controllers for getting slice changed events from the views. */ void SetSliceNavigationControllers(const QList &controllers); void OnToolManagerWorkingDataModified(); void OnTimeChanged(itk::Object *sender, const itk::EventObject &); void OnSliceChanged(itk::Object *sender, const itk::EventObject &); void OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject &); /** Just public because it is called by itk::Commands. You should not need to call this. */ void OnSliceInterpolationInfoChanged(const itk::EventObject &); Ui::QmitkSliceBasedInterpolatorWidgetGUIControls m_Controls; signals: void signalSliceBasedInterpolationEnabled(bool); public slots: /** \brief Reaction to "Start/Stop" button click */ void OnToggleWidgetActivation(bool); protected slots: /** \brief Reaction to "Accept Current Slice" button click. */ void OnAcceptInterpolationClicked(); /* \brief Reaction to "Accept All Slices" button click. Opens popup to ask about which orientation should be interpolated */ void OnAcceptAllInterpolationsClicked(); /* \brief Called from popup menu of OnAcceptAllInterpolationsClicked() Will trigger interpolation for all slices in given orientation */ void OnAcceptAllPopupActivated(QAction *action); protected: typedef std::map ActionToSliceDimensionMapType; const ActionToSliceDimensionMapType CreateActionToSliceDimension(); ActionToSliceDimensionMapType m_ActionToSliceDimensionMap; void AcceptAllInterpolations(mitk::SliceNavigationController *slicer); void WaitCursorOn(); void WaitCursorOff(); void RestoreOverrideCursor(); /** Gets the working slice based on the given plane geometry and last saved interaction \param planeGeometry a plane geometry */ mitk::Image::Pointer GetWorkingSlice(const mitk::PlaneGeometry *planeGeometry); /** Retrieves the currently selected PlaneGeometry from a SlicedGeometry3D that is generated by a SliceNavigationController and calls Interpolate to further process this PlaneGeometry into an interpolation. \param e is a actually a mitk::SliceNavigationController::GeometrySliceEvent, sent by a SliceNavigationController \param slicer the SliceNavigationController */ void TranslateAndInterpolateChangedSlice(const itk::EventObject &e, mitk::SliceNavigationController *slicer); /** Given a PlaneGeometry, this method figures out which slice of the first working image (of the associated ToolManager) should be interpolated. The actual work is then done by our SegmentationInterpolation object. */ void Interpolate(mitk::PlaneGeometry *plane, mitk::TimePointType timePoint, mitk::SliceNavigationController *slicer); /** Called internally to update the interpolation suggestion. Finds out about the focused render window and requests an interpolation. */ void UpdateVisibleSuggestion(); private: mitk::SliceBasedInterpolationController::Pointer m_SliceInterpolatorController; mitk::ToolManager *m_ToolManager; bool m_Activated; template void WritePreviewOnWorkingImage(itk::Image *target, const mitk::Image *source, int overwritevalue); QHash m_ControllerToTimeObserverTag; QHash m_ControllerToSliceObserverTag; QHash m_ControllerToDeleteObserverTag; unsigned int m_InterpolationInfoChangedObserverTag; mitk::DiffSliceOperation *m_doOperation; mitk::DiffSliceOperation *m_undoOperation; mitk::DataNode::Pointer m_PreviewNode; mitk::Image::Pointer m_PreviewImage; mitk::LabelSetImage::Pointer m_WorkingImage; QHash m_TimePoints; mitk::DataStorage::Pointer m_DataStorage; mitk::SliceNavigationController *m_LastSNC; unsigned int m_LastSliceIndex; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.cpp b/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.cpp index cba76244e0..8449344205 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.cpp @@ -1,355 +1,355 @@ /*============================================================================ 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 "QmitkSurfaceBasedInterpolatorWidget.h" #include "mitkColorProperty.h" #include "mitkInteractionConst.h" #include "mitkOperationEvent.h" #include "mitkProgressBar.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkSegTool2D.h" #include "mitkSliceNavigationController.h" #include "mitkSurfaceToImageFilter.h" #include "mitkUndoController.h" #include "mitkVtkRepresentationProperty.h" #include #include "QmitkStdMultiWidget.h" #include #include #include QmitkSurfaceBasedInterpolatorWidget::QmitkSurfaceBasedInterpolatorWidget(QWidget *parent, const char * /*name*/) : QWidget(parent), m_SurfaceBasedInterpolatorController(mitk::SurfaceBasedInterpolationController::GetInstance()), m_ToolManager(nullptr), m_Activated(false), m_DataStorage(nullptr) { m_Controls.setupUi(this); - m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); m_ToolManager->WorkingDataChanged += mitk::MessageDelegate( this, &QmitkSurfaceBasedInterpolatorWidget::OnToolManagerWorkingDataModified); connect(m_Controls.m_btStart, SIGNAL(toggled(bool)), this, SLOT(OnToggleWidgetActivation(bool))); connect(m_Controls.m_btAccept, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked())); connect(m_Controls.m_cbShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool))); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSurfaceBasedInterpolatorWidget::OnSurfaceInterpolationInfoChanged); m_SurfaceInterpolationInfoChangedObserverTag = m_SurfaceBasedInterpolatorController->AddObserver(itk::ModifiedEvent(), command); m_InterpolatedSurfaceNode = mitk::DataNode::New(); m_InterpolatedSurfaceNode->SetName("Surface Interpolation feedback"); m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0)); m_InterpolatedSurfaceNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); m_InterpolatedSurfaceNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_InterpolatedSurfaceNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode = mitk::DataNode::New(); m_3DContourNode->SetName("Drawn Contours"); m_3DContourNode->SetProperty("color", mitk::ColorProperty::New(0.0, 0.0, 0.0)); m_3DContourNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f)); m_3DContourNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_3DContourNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget0"))); m_3DContourNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); m_3DContourNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); m_3DContourNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer())); m_Timer = new QTimer(this); connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor())); m_Controls.m_btAccept->setEnabled(false); m_Controls.m_cbShowPositionNodes->setEnabled(false); this->setEnabled(false); } void QmitkSurfaceBasedInterpolatorWidget::SetDataStorage(mitk::DataStorage &storage) { m_DataStorage = &storage; } QmitkSurfaceBasedInterpolatorWidget::~QmitkSurfaceBasedInterpolatorWidget() { m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate( this, &QmitkSurfaceBasedInterpolatorWidget::OnToolManagerWorkingDataModified); if (m_DataStorage->Exists(m_3DContourNode)) m_DataStorage->Remove(m_3DContourNode); if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) m_DataStorage->Remove(m_InterpolatedSurfaceNode); // remove observer m_SurfaceBasedInterpolatorController->RemoveObserver(m_SurfaceInterpolationInfoChangedObserverTag); delete m_Timer; } void QmitkSurfaceBasedInterpolatorWidget::ShowInterpolationResult(bool status) { if (m_InterpolatedSurfaceNode.IsNotNull()) m_InterpolatedSurfaceNode->SetVisibility(status); if (m_3DContourNode.IsNotNull()) m_3DContourNode->SetVisibility( status, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSurfaceBasedInterpolatorWidget::OnSurfaceInterpolationFinished() { mitk::Surface::Pointer interpolatedSurface = m_SurfaceBasedInterpolatorController->GetInterpolationResult(); if (interpolatedSurface.IsNotNull()) { m_InterpolatedSurfaceNode->SetData(interpolatedSurface); m_3DContourNode->SetData(m_SurfaceBasedInterpolatorController->GetContoursAsSurface()); this->ShowInterpolationResult(true); } else { m_InterpolatedSurfaceNode->SetData(nullptr); m_3DContourNode->SetData(nullptr); this->ShowInterpolationResult(false); } } void QmitkSurfaceBasedInterpolatorWidget::OnShowMarkers(bool state) { mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true))); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state)); } mitk::SegTool2D::Pointer manualSegmentationTool; unsigned int numberOfExistingTools = m_ToolManager->GetTools().size(); for (unsigned int i = 0; i < numberOfExistingTools; i++) { manualSegmentationTool = dynamic_cast(m_ToolManager->GetToolById(i)); if (manualSegmentationTool) { manualSegmentationTool->SetShowMarkerNodes(state); } } } void QmitkSurfaceBasedInterpolatorWidget::StartUpdateInterpolationTimer() { m_Timer->start(500); } void QmitkSurfaceBasedInterpolatorWidget::StopUpdateInterpolationTimer() { m_Timer->stop(); m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0)); mitk::RenderingManager::GetInstance()->RequestUpdate( mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetRenderWindow()); } void QmitkSurfaceBasedInterpolatorWidget::ChangeSurfaceColor() { float currentColor[3]; m_InterpolatedSurfaceNode->GetColor(currentColor); float yellow[3] = {255.0, 255.0, 0.0}; if (currentColor[2] == yellow[2]) { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 255.0)); } else { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(yellow)); } m_InterpolatedSurfaceNode->Update(); mitk::RenderingManager::GetInstance()->RequestUpdate( mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))->GetRenderWindow()); } void QmitkSurfaceBasedInterpolatorWidget::OnToolManagerWorkingDataModified() { mitk::DataNode *workingNode = this->m_ToolManager->GetWorkingData(0); if (!workingNode) { this->setEnabled(false); return; } mitk::LabelSetImage *workingImage = dynamic_cast(workingNode->GetData()); // TODO adapt tool manager so that this check is done there, e.g. convenience function // Q_ASSERT(workingImage); if (!workingImage) { this->setEnabled(false); return; } if (workingImage->GetDimension() > 4 || workingImage->GetDimension() < 3) { this->setEnabled(false); return; } m_WorkingImage = workingImage; this->setEnabled(true); } void QmitkSurfaceBasedInterpolatorWidget::OnRunInterpolation() { m_SurfaceBasedInterpolatorController->Interpolate(); } void QmitkSurfaceBasedInterpolatorWidget::OnToggleWidgetActivation(bool enabled) { Q_ASSERT(m_ToolManager); mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); if (!workingNode) return; m_Controls.m_btAccept->setEnabled(enabled); m_Controls.m_cbShowPositionNodes->setEnabled(enabled); if (enabled) m_Controls.m_btStart->setText("Stop"); else m_Controls.m_btStart->setText("Start"); for (unsigned int i = 0; i < m_ToolManager->GetTools().size(); i++) { mitk::SegTool2D *tool = dynamic_cast(m_ToolManager->GetToolById(i)); if (tool) tool->SetEnable3DInterpolation(enabled); } if (enabled) { if (!m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { m_DataStorage->Add(m_InterpolatedSurfaceNode); } if (!m_DataStorage->Exists(m_3DContourNode)) { m_DataStorage->Add(m_3DContourNode); } mitk::Vector3D spacing = m_WorkingImage->GetGeometry(0)->GetSpacing(); double minSpacing(100); double maxSpacing(0); for (int i = 0; i < 3; i++) { if (spacing[i] < minSpacing) { minSpacing = spacing[i]; } else if (spacing[i] > maxSpacing) { maxSpacing = spacing[i]; } } m_SurfaceBasedInterpolatorController->SetWorkingImage(m_WorkingImage); m_SurfaceBasedInterpolatorController->SetActiveLabel(m_WorkingImage->GetActiveLabel()->GetValue()); m_SurfaceBasedInterpolatorController->SetMaxSpacing(maxSpacing); m_SurfaceBasedInterpolatorController->SetMinSpacing(minSpacing); m_SurfaceBasedInterpolatorController->SetDistanceImageVolume(50000); int ret = QMessageBox::Yes; if (m_SurfaceBasedInterpolatorController->EstimatePortionOfNeededMemory() > 0.5) { QMessageBox msgBox; msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!"); msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?"); msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); ret = msgBox.exec(); } if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); if (ret == QMessageBox::Yes) { m_Future = QtConcurrent::run(this, &QmitkSurfaceBasedInterpolatorWidget::OnRunInterpolation); m_Watcher.setFuture(m_Future); } } else { if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { m_DataStorage->Remove(m_InterpolatedSurfaceNode); } if (m_DataStorage->Exists(m_3DContourNode)) { m_DataStorage->Remove(m_3DContourNode); } mitk::UndoController::GetCurrentUndoModel()->Clear(); } m_Activated = enabled; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSurfaceBasedInterpolatorWidget::OnAcceptInterpolationClicked() { if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData()) { // m_WorkingImage->SurfaceStamp(dynamic_cast(m_InterpolatedSurfaceNode->GetData()), false); this->ShowInterpolationResult(false); } } void QmitkSurfaceBasedInterpolatorWidget::OnSurfaceInterpolationInfoChanged(const itk::EventObject & /*e*/) { if (m_Activated) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSurfaceBasedInterpolatorWidget::OnRunInterpolation); m_Watcher.setFuture(m_Future); } } diff --git a/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.h b/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.h index fb16e7f7b0..a4582310dc 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.h +++ b/Modules/SegmentationUI/Qmitk/QmitkSurfaceBasedInterpolatorWidget.h @@ -1,121 +1,119 @@ /*============================================================================ 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 QmitkSurfaceBasedInterpolatorWidgetWidget_h_Included #define QmitkSurfaceBasedInterpolatorWidgetWidget_h_Included #include "MitkSegmentationUIExports.h" #include "mitkDataNode.h" #include "mitkDataStorage.h" #include "mitkLabelSetImage.h" #include "mitkSurfaceBasedInterpolationController.h" #include #include // For running 3D interpolation in background #include #include #include #include #include "ui_QmitkSurfaceBasedInterpolatorWidgetGUIControls.h" namespace mitk { class ToolManager; } /** \brief GUI for surface-based interpolation. \ingroup ToolManagerEtAl \ingroup Widgets \sa QmitkInteractiveSegmentation \sa mitk::SurfaceBasedInterpolationController QmitkSurfaceBasedInterpolatorWidgetController is responsible to watch the GUI, to notice, which slice is currently visible. It triggers generation of interpolation suggestions and also triggers acception of suggestions. - - This class uses the mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION context. */ class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceBasedInterpolatorWidget : public QWidget { Q_OBJECT public: QmitkSurfaceBasedInterpolatorWidget(QWidget *parent = nullptr, const char *name = nullptr); ~QmitkSurfaceBasedInterpolatorWidget() override; void SetDataStorage(mitk::DataStorage &storage); void OnToolManagerWorkingDataModified(); /** Just public because it is called by itk::Commands. You should not need to call this. */ void OnSurfaceInterpolationInfoChanged(const itk::EventObject &); /** * @brief Set the visibility of the interpolation */ void ShowInterpolationResult(bool); Ui::QmitkSurfaceBasedInterpolatorWidgetGUIControls m_Controls; public slots: /** \brief Reaction to "Start/Stop" button click */ void OnToggleWidgetActivation(bool); protected slots: void OnAcceptInterpolationClicked(); void OnSurfaceInterpolationFinished(); void OnRunInterpolation(); void OnShowMarkers(bool); void StartUpdateInterpolationTimer(); void StopUpdateInterpolationTimer(); void ChangeSurfaceColor(); private: mitk::SurfaceBasedInterpolationController::Pointer m_SurfaceBasedInterpolatorController; mitk::ToolManager *m_ToolManager; bool m_Activated; unsigned int m_SurfaceInterpolationInfoChangedObserverTag; mitk::DataNode::Pointer m_InterpolatedSurfaceNode; mitk::DataNode::Pointer m_3DContourNode; mitk::DataStorage::Pointer m_DataStorage; mitk::LabelSetImage::Pointer m_WorkingImage; QFuture m_Future; QFutureWatcher m_Watcher; QTimer *m_Timer; }; #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.cpp b/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.cpp index ad9a9a0f92..544ffbc76b 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.cpp @@ -1,117 +1,117 @@ /*============================================================================ 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 "QmitkSurfaceStampWidget.h" #include #include #include #include #include QmitkSurfaceStampWidget::QmitkSurfaceStampWidget(QWidget *parent, const char * /*name*/) : QWidget(parent), m_ToolManager(nullptr), m_DataStorage(nullptr) { m_Controls.setupUi(this); m_Controls.m_InformationWidget->hide(); - m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); m_ToolManager->ActivateTool(-1); mitk::NodePredicateAnd::Pointer m_SurfacePredicate = mitk::NodePredicateAnd::New(); m_SurfacePredicate->AddPredicate(mitk::NodePredicateDataType::New("Surface")); m_SurfacePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); m_Controls.m_cbSurfaceNodeSelector->SetPredicate(m_SurfacePredicate); connect(m_Controls.m_pbStamp, SIGNAL(clicked()), this, SLOT(OnStamp())); connect(m_Controls.m_cbShowInformation, SIGNAL(toggled(bool)), this, SLOT(OnShowInformation(bool))); m_Controls.m_InformationWidget->hide(); } QmitkSurfaceStampWidget::~QmitkSurfaceStampWidget() { } void QmitkSurfaceStampWidget::SetDataStorage(mitk::DataStorage *storage) { m_DataStorage = storage; m_Controls.m_cbSurfaceNodeSelector->SetDataStorage(m_DataStorage); } void QmitkSurfaceStampWidget::OnStamp() { mitk::DataNode *surfaceNode = m_Controls.m_cbSurfaceNodeSelector->GetSelectedNode(); if (!surfaceNode) { QMessageBox::information(this, "Surface Stamp", "Please load and select a surface before starting some action."); return; } - m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); assert(m_ToolManager); m_ToolManager->ActivateTool(-1); mitk::Surface *surface = dynamic_cast(surfaceNode->GetData()); if (!surface) { QMessageBox::information(this, "Surface Stamp", "Please load and select a surface before starting some action."); return; } mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); if (!workingNode) { QMessageBox::information( this, "Surface Stamp", "Please load and select a segmentation before starting some action."); return; } mitk::LabelSetImage *workingImage = dynamic_cast(workingNode->GetData()); if (!workingImage) { QMessageBox::information( this, "Surface Stamp", "Please load and select a segmentation before starting some action."); return; } QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); try { // workingImage->SurfaceStamp( surface, m_Controls.m_chkOverwrite->isChecked() ); } catch (mitk::Exception &e) { QApplication::restoreOverrideCursor(); MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information( this, "Surface Stamp", "Could not stamp the selected surface.\n See error log for details.\n"); return; } QApplication::restoreOverrideCursor(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSurfaceStampWidget::OnShowInformation(bool on) { if (on) m_Controls.m_InformationWidget->show(); else m_Controls.m_InformationWidget->hide(); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.h b/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.h index 852eced247..6320838ba2 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.h +++ b/Modules/SegmentationUI/Qmitk/QmitkSurfaceStampWidget.h @@ -1,60 +1,58 @@ /*============================================================================ 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 QmitkSurfaceStampWidget_h_Included #define QmitkSurfaceStampWidget_h_Included #include "MitkSegmentationUIExports.h" #include #include "ui_QmitkSurfaceStampWidgetGUIControls.h" namespace mitk { class ToolManager; } /** \brief GUI for surface-based interpolation. - This class uses the mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION context. - \ingroup ToolManagerEtAl \ingroup Widgets */ class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceStampWidget : public QWidget { Q_OBJECT public: QmitkSurfaceStampWidget(QWidget *parent = nullptr, const char *name = nullptr); ~QmitkSurfaceStampWidget() override; void SetDataStorage(mitk::DataStorage *storage); protected slots: void OnShowInformation(bool); void OnStamp(); private: mitk::ToolManager *m_ToolManager; mitk::DataStorage *m_DataStorage; Ui::QmitkSurfaceStampWidgetGUIControls m_Controls; }; #endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.cpp index 0a23d04b1a..9485543eb2 100644 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.cpp +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.cpp @@ -1,97 +1,97 @@ /*============================================================================ 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 "QmitkConvertMaskToLabelAction.h" #include "mitkRenderingManager.h" #include "mitkLabelSetImage.h" #include "mitkToolManagerProvider.h" //needed for qApp #include QmitkConvertMaskToLabelAction::QmitkConvertMaskToLabelAction() { } QmitkConvertMaskToLabelAction::~QmitkConvertMaskToLabelAction() { } void QmitkConvertMaskToLabelAction::Run( const QList &selectedNodes ) { - mitk::ToolManager::Pointer toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + mitk::ToolManager::Pointer toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); mitk::DataNode* workingNode = toolManager->GetWorkingData(0); if (!workingNode) { MITK_INFO << "There is no available segmentation. Please load or create one before using this tool."; return; } mitk::LabelSetImage* workingImage = dynamic_cast( workingNode->GetData() ); assert(workingImage); foreach ( mitk::DataNode::Pointer maskNode, selectedNodes ) { if (maskNode) { mitk::Image* mask = dynamic_cast(maskNode->GetData() ); if (!mask) continue; std::string name = maskNode->GetName(); mitk::Color color; mitk::ColorProperty::Pointer colorProp; maskNode->GetProperty(colorProp,"color"); if (colorProp.IsNull()) continue; color = colorProp->GetValue(); workingImage->GetLabelSet()->AddLabel(name,color); //workingImage->AddLabelEvent.Send(); try { workingImage->MaskStamp( mask, false ); } catch ( mitk::Exception& e ) { MITK_ERROR << "Exception caught: " << e.GetDescription(); return; } maskNode->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else { MITK_INFO << " a nullptr node was selected"; } } } void QmitkConvertMaskToLabelAction::SetSmoothed(bool /*smoothed*/) { //not needed } void QmitkConvertMaskToLabelAction::SetDecimated(bool /*decimated*/) { //not needed } void QmitkConvertMaskToLabelAction::SetDataStorage(mitk::DataStorage* /*dataStorage*/) { //not needed } void QmitkConvertMaskToLabelAction::SetFunctionality(berry::QtViewPart* /*functionality*/) { //not needed } diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.cpp index e9f5716fa4..b4311d7105 100644 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.cpp +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.cpp @@ -1,102 +1,102 @@ /*============================================================================ 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 "QmitkConvertSurfaceToLabelAction.h" #include "mitkRenderingManager.h" #include "mitkLabelSetImage.h" #include "mitkToolManagerProvider.h" #include //needed for qApp #include #include QmitkConvertSurfaceToLabelAction::QmitkConvertSurfaceToLabelAction() { } QmitkConvertSurfaceToLabelAction::~QmitkConvertSurfaceToLabelAction() { } void QmitkConvertSurfaceToLabelAction::Run( const QList &selectedNodes ) { - mitk::ToolManager::Pointer toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); + mitk::ToolManager::Pointer toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); mitk::DataNode* workingNode = toolManager->GetWorkingData(0); if (!workingNode) { MITK_INFO << "There is no available segmentation. Please load or create one before using this tool."; return; } mitk::LabelSetImage* workingImage = dynamic_cast( workingNode->GetData() ); assert(workingImage); foreach ( mitk::DataNode::Pointer surfaceNode, selectedNodes ) { if (surfaceNode) { mitk::Surface* surface = dynamic_cast(surfaceNode->GetData() ); if (!surface) continue; std::string name = surfaceNode->GetName(); mitk::Color color; mitk::ColorProperty::Pointer colorProp; surfaceNode->GetProperty(colorProp,"color"); if (colorProp.IsNull()) continue; color = colorProp->GetValue(); workingImage->GetLabelSet()->AddLabel(name,color); //workingImage->AddLabelEvent.Send(); try { QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); // workingImage->SurfaceStamp( surface, false ); QApplication::restoreOverrideCursor(); } catch ( mitk::Exception& e ) { QApplication::restoreOverrideCursor(); MITK_ERROR << "Exception caught: " << e.GetDescription(); return; } surfaceNode->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else { MITK_INFO << " a nullptr node was selected"; } } } void QmitkConvertSurfaceToLabelAction::SetSmoothed(bool /*smoothed*/) { //not needed } void QmitkConvertSurfaceToLabelAction::SetDecimated(bool /*decimated*/) { //not needed } void QmitkConvertSurfaceToLabelAction::SetDataStorage(mitk::DataStorage* /*dataStorage*/) { //not needed } void QmitkConvertSurfaceToLabelAction::SetFunctionality(berry::QtViewPart* /*functionality*/) { //not needed } diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp index ebf2baba70..185b773c1c 100644 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp @@ -1,245 +1,245 @@ /*============================================================================ 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 #include #include static const char* const HelpText = "Select a mask above"; QmitkMorphologicalOperationsWidget::QmitkMorphologicalOperationsWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent) : QmitkSegmentationUtilityWidget(timeNavigationController, parent) { m_Controls.setupUi(this); m_Controls.m_DataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::MaskPredicate); m_Controls.m_DataSelectionWidget->SetHelpText(HelpText); mitk::DataStorage::Pointer ds = m_Controls.m_DataSelectionWidget->GetDataStorage(); m_Controls.m_LabelSetWidget->SetDataStorage(ds); m_Controls.m_LabelSetWidget->setEnabled(true); - m_Controls.m_ToolSelectionBox->SetToolManager(*mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION)); + m_Controls.m_ToolSelectionBox->SetToolManager(*mitk::ToolManagerProvider::GetInstance()->GetToolManager()); m_Controls.m_ToolSelectionBox->SetGenerateAccelerators(true); m_Controls.m_ToolSelectionBox->SetToolGUIArea( m_Controls.m_ToolGUIContainer ); m_Controls.m_ToolSelectionBox->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible ); m_Controls.m_ToolSelectionBox->SetDisplayedToolGroups("Median Dilate Erode Open Close 'Fill Holes' 'Keep N Largest' 'Split' 'Region Selector'"); 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.m_DataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); if (m_Controls.m_DataSelectionWidget->GetSelection(0).IsNotNull()) this->OnSelectionChanged(0, m_Controls.m_DataSelectionWidget->GetSelection(0)); } QmitkMorphologicalOperationsWidget::~QmitkMorphologicalOperationsWidget() { } void QmitkMorphologicalOperationsWidget::OnSelectionChanged(unsigned int, const mitk::DataNode*) { QmitkDataSelectionWidget* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); if (node.IsNotNull()) { m_Controls.m_DataSelectionWidget->SetHelpText(""); this->EnableButtons(true); } else { m_Controls.m_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* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); bool ball = m_Controls.radioButtonMorphoBall->isChecked(); mitk::MorphologicalOperations::StructuralElementType structuralElement = ball ? mitk::MorphologicalOperations::Ball : mitk::MorphologicalOperations::Cross; try { mitk::MorphologicalOperations::Closing(image, m_Controls.spinBoxMorphFactor->value(), 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* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); bool ball = m_Controls.radioButtonMorphoBall->isChecked(); mitk::MorphologicalOperations::StructuralElementType structuralElement = ball ? mitk::MorphologicalOperations::Ball : mitk::MorphologicalOperations::Cross; try { mitk::MorphologicalOperations::Opening(image, m_Controls.spinBoxMorphFactor->value(), 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* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); bool ball = m_Controls.radioButtonMorphoBall->isChecked(); mitk::MorphologicalOperations::StructuralElementType structuralElement = ball ? mitk::MorphologicalOperations::Ball : mitk::MorphologicalOperations::Cross; try { mitk::MorphologicalOperations::Dilate(image, m_Controls.spinBoxMorphFactor->value(), 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* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); mitk::Image::Pointer image = static_cast(node->GetData()); bool ball = m_Controls.radioButtonMorphoBall->isChecked(); mitk::MorphologicalOperations::StructuralElementType structuralElement = ball ? mitk::MorphologicalOperations::Ball : mitk::MorphologicalOperations::Cross; try { mitk::MorphologicalOperations::Erode(image, m_Controls.spinBoxMorphFactor->value(), 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* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; mitk::DataNode::Pointer node = m_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(); }