diff --git a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui index bc3644aca2..2b91deefe8 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui +++ b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui @@ -1,227 +1,227 @@ QmitkAdaptiveRegionGrowingToolGUIControls 0 0 264 - 170 + 171 0 0 0 0 QmitkAdaptiveRegionGrowingWidget Move to adjust the segmentation 0 0 0 Shift+Click to place seedpoint 0 Define thresholds: true 0 6 0 0 Qt::Horizontal 40 20 false 0 0 Press to start the segmentation of the tubular structure. Run Segmentation Alt+R false 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Enable/disable GPU volume rendering for the segmentation preview.</span></p></body></html> Qt::LeftToRight 3D preview false Qt::Horizontal 40 20 Adapt Region Growing: true 0 6 0 0 false Press to confirm the segmentation and calculate 3D representation. - &Confirm segmentation + &Confirm Segmentation Alt+C ctkRangeWidget QWidget
ctkRangeWidget.h
1
ctkSliderWidget QWidget
ctkSliderWidget.h
1
diff --git a/Modules/SegmentationUI/Qmitk/QmitkFastMarchingTool3DGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkFastMarchingTool3DGUI.cpp index a93f2d7737..34babb6669 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkFastMarchingTool3DGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkFastMarchingTool3DGUI.cpp @@ -1,357 +1,357 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkFastMarchingTool3DGUI.h" #include "QmitkConfirmSegmentationDialog.h" #include #include #include #include #include #include #include #include #include "mitkStepper.h" #include "mitkBaseRenderer.h" MITK_TOOL_GUI_MACRO(SegmentationUI_EXPORT, QmitkFastMarchingTool3DGUI, "") QmitkFastMarchingTool3DGUI::QmitkFastMarchingTool3DGUI() :QmitkToolGUI(), m_TimeIsConnected(false) { this->setContentsMargins( 0, 0, 0, 0 ); // create the visible widgets QVBoxLayout *widgetLayout = new QVBoxLayout(this); widgetLayout->setContentsMargins(0, 0, 0, 0); QFont fntHelp; fntHelp.setBold(true); QLabel *lblHelp = new QLabel(this); lblHelp->setText("Press shift-click to add seeds repeatedly."); lblHelp->setFont(fntHelp); widgetLayout->addWidget(lblHelp); // Sigma controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Sigma: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addItem(hlayout); } m_slSigma = new ctkSliderWidget(this); m_slSigma->setMinimum(0.1); m_slSigma->setMaximum(5.0); m_slSigma->setPageStep(0.1); m_slSigma->setSingleStep(0.01); m_slSigma->setValue(1.0); m_slSigma->setDecimals(2); m_slSigma->setTracking(false); m_slSigma->setToolTip("The \"sigma\" parameter in the Gradient Magnitude filter."); connect( m_slSigma, SIGNAL(valueChanged(double)), this, SLOT(OnSigmaChanged(double))); widgetLayout->addWidget( m_slSigma ); // Alpha controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Alpha: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addItem(hlayout); } m_slAlpha = new ctkSliderWidget(this); m_slAlpha->setMinimum(-10); m_slAlpha->setMaximum(0); m_slAlpha->setPageStep(0.1); m_slAlpha->setSingleStep(0.01); m_slAlpha->setValue(-2.5); m_slAlpha->setDecimals(2); m_slAlpha->setTracking(false); m_slAlpha->setToolTip("The \"alpha\" parameter in the Sigmoid mapping filter."); connect( m_slAlpha, SIGNAL(valueChanged(double)), this, SLOT(OnAlphaChanged(double))); widgetLayout->addWidget( m_slAlpha ); // Beta controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Beta: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addLayout(hlayout); } m_slBeta = new ctkSliderWidget(this); m_slBeta->setMinimum(0); m_slBeta->setMaximum(100); m_slBeta->setPageStep(0.1); m_slBeta->setSingleStep(0.01); m_slBeta->setValue(3.5); m_slBeta->setDecimals(2); m_slBeta->setTracking(false); m_slBeta->setToolTip("The \"beta\" parameter in the Sigmoid mapping filter."); connect( m_slBeta, SIGNAL(valueChanged(double)), this, SLOT(OnBetaChanged(double))); widgetLayout->addWidget( m_slBeta ); // stopping value controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Stopping value: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addLayout(hlayout); } m_slStoppingValue = new ctkSliderWidget(this); m_slStoppingValue->setMinimum(0); m_slStoppingValue->setMaximum(10000); m_slStoppingValue->setPageStep(10); m_slStoppingValue->setSingleStep(1); m_slStoppingValue->setValue(2000); m_slStoppingValue->setDecimals(0); m_slStoppingValue->setTracking(false); m_slStoppingValue->setToolTip("The \"stopping value\" parameter in the fast marching 3D algorithm"); connect( m_slStoppingValue, SIGNAL(valueChanged(double)), this, SLOT(OnStoppingValueChanged(double))); widgetLayout->addWidget( m_slStoppingValue ); // threshold controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Threshold: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addLayout(hlayout); } m_slwThreshold = new ctkRangeWidget(this); m_slwThreshold->setMinimum(-100); m_slwThreshold->setMaximum(5000); m_slwThreshold->setMinimumValue(-100); m_slwThreshold->setMaximumValue(2000); m_slwThreshold->setDecimals(0); m_slwThreshold->setTracking(false); m_slwThreshold->setToolTip("The lower and upper thresholds for the final thresholding"); connect( m_slwThreshold, SIGNAL(valuesChanged(double, double)), this, SLOT(OnThresholdChanged(double, double))); widgetLayout->addWidget( m_slwThreshold ); m_btClearSeeds = new QPushButton("Clear"); m_btClearSeeds->setToolTip("Clear current result and start over again"); widgetLayout->addWidget(m_btClearSeeds); connect( m_btClearSeeds, SIGNAL(clicked()), this, SLOT(OnClearSeeds()) ); - m_btConfirm = new QPushButton("Accept"); + m_btConfirm = new QPushButton("Confirm Segmentation"); m_btConfirm->setToolTip("Incorporate current result in your working session."); m_btConfirm->setEnabled(false); widgetLayout->addWidget(m_btConfirm); connect( m_btConfirm, SIGNAL(clicked()), this, SLOT(OnConfirmSegmentation()) ); connect( this, SIGNAL(NewToolAssociated(mitk::Tool*)), this, SLOT(OnNewToolAssociated(mitk::Tool*)) ); this->setEnabled(false); } QmitkFastMarchingTool3DGUI::~QmitkFastMarchingTool3DGUI() { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->CurrentlyBusy -= mitk::MessageDelegate1( this, &QmitkFastMarchingTool3DGUI::BusyStateChanged ); m_FastMarchingTool->RemoveReadyListener(mitk::MessageDelegate(this, &QmitkFastMarchingTool3DGUI::OnFastMarchingToolReady) ); } } void QmitkFastMarchingTool3DGUI::OnNewToolAssociated(mitk::Tool* tool) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->CurrentlyBusy -= mitk::MessageDelegate1( this, &QmitkFastMarchingTool3DGUI::BusyStateChanged ); m_FastMarchingTool->RemoveReadyListener(mitk::MessageDelegate(this, &QmitkFastMarchingTool3DGUI::OnFastMarchingToolReady) ); } m_FastMarchingTool = dynamic_cast( tool ); if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->CurrentlyBusy += mitk::MessageDelegate1( this, &QmitkFastMarchingTool3DGUI::BusyStateChanged ); m_FastMarchingTool->AddReadyListener(mitk::MessageDelegate(this, &QmitkFastMarchingTool3DGUI::OnFastMarchingToolReady) ); //listen to timestep change events mitk::BaseRenderer::Pointer renderer; renderer = mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") ); if (renderer.IsNotNull() && !m_TimeIsConnected) { new QmitkStepperAdapter(this, renderer->GetSliceNavigationController()->GetTime(), "stepper"); // connect(m_TimeStepper, SIGNAL(Refetch()), this, SLOT(Refetch())); m_TimeIsConnected = true; } } } void QmitkFastMarchingTool3DGUI::Update() { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetLowerThreshold( this->m_slwThreshold->minimumValue()); m_FastMarchingTool->SetUpperThreshold( this->m_slwThreshold->maximumValue()); m_FastMarchingTool->SetStoppingValue( this->m_slStoppingValue->value()); m_FastMarchingTool->SetSigma( this->m_slSigma->value()); m_FastMarchingTool->SetAlpha( this->m_slAlpha->value()); m_FastMarchingTool->SetBeta( this->m_slBeta->value()); m_FastMarchingTool->Update(); } } void QmitkFastMarchingTool3DGUI::OnThresholdChanged(double lower, double upper) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetLowerThreshold( lower ); m_FastMarchingTool->SetUpperThreshold( upper ); this->Update(); } } void QmitkFastMarchingTool3DGUI::OnBetaChanged(double value) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetBeta( value ); this->Update(); } } void QmitkFastMarchingTool3DGUI::OnSigmaChanged(double value) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetSigma( value ); this->Update(); } } void QmitkFastMarchingTool3DGUI::OnAlphaChanged(double value) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetAlpha( value ); this->Update(); } } void QmitkFastMarchingTool3DGUI::OnStoppingValueChanged(double value) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetStoppingValue( value ); this->Update(); } } void QmitkFastMarchingTool3DGUI::OnConfirmSegmentation() { QmitkConfirmSegmentationDialog dialog; QString segName = QString::fromStdString(m_FastMarchingTool->GetCurrentSegmentationName()); dialog.SetSegmentationName(segName); int result = dialog.exec(); switch(result) { case QmitkConfirmSegmentationDialog::CREATE_NEW_SEGMENTATION: m_FastMarchingTool->SetOverwriteExistingSegmentation(false); break; case QmitkConfirmSegmentationDialog::OVERWRITE_SEGMENTATION: m_FastMarchingTool->SetOverwriteExistingSegmentation(true); break; case QmitkConfirmSegmentationDialog::CANCEL_SEGMENTATION: return; } if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->ConfirmSegmentation(); m_btConfirm->setEnabled(false); } } void QmitkFastMarchingTool3DGUI::SetStepper(mitk::Stepper *stepper) { this->m_TimeStepper = stepper; } void QmitkFastMarchingTool3DGUI::Refetch() { //event from image navigator recieved - timestep has changed m_FastMarchingTool->SetCurrentTimeStep(m_TimeStepper->GetPos()); } void QmitkFastMarchingTool3DGUI::OnClearSeeds() { //event from image navigator recieved - timestep has changed m_FastMarchingTool->ClearSeeds(); m_btConfirm->setEnabled(false); this->Update(); } void QmitkFastMarchingTool3DGUI::BusyStateChanged(bool value) { if (value) QApplication::setOverrideCursor( QCursor(Qt::BusyCursor) ); else QApplication::restoreOverrideCursor(); } void QmitkFastMarchingTool3DGUI::OnFastMarchingToolReady() { this->setEnabled(true); this->m_btConfirm->setEnabled(true); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkFastMarchingToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkFastMarchingToolGUI.cpp index b82ca4e761..41daa39969 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkFastMarchingToolGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkFastMarchingToolGUI.cpp @@ -1,337 +1,337 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkFastMarchingToolGUI.h" #include "QmitkNewSegmentationDialog.h" #include #include #include #include #include #include #include #include #include "mitkStepper.h" #include "mitkBaseRenderer.h" MITK_TOOL_GUI_MACRO(SegmentationUI_EXPORT, QmitkFastMarchingToolGUI, "") QmitkFastMarchingToolGUI::QmitkFastMarchingToolGUI() :QmitkToolGUI(), m_TimeIsConnected(false) { this->setContentsMargins( 0, 0, 0, 0 ); // create the visible widgets QVBoxLayout *widgetLayout = new QVBoxLayout(this); widgetLayout->setContentsMargins(0, 0, 0, 0); QFont fntHelp; fntHelp.setBold(true); QLabel *lblHelp = new QLabel(this); lblHelp->setText("Press shift-click to add seeds repeatedly."); lblHelp->setFont(fntHelp); widgetLayout->addWidget(lblHelp); // Sigma controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Sigma: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addItem(hlayout); } m_slSigma = new ctkSliderWidget(this); m_slSigma->setMinimum(0.1); m_slSigma->setMaximum(5.0); m_slSigma->setPageStep(0.1); m_slSigma->setSingleStep(0.01); m_slSigma->setValue(1.0); m_slSigma->setDecimals(2); m_slSigma->setTracking(false); m_slSigma->setToolTip("The \"sigma\" parameter in the Gradient Magnitude filter."); connect( m_slSigma, SIGNAL(valueChanged(double)), this, SLOT(OnSigmaChanged(double))); widgetLayout->addWidget( m_slSigma ); // Alpha controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Alpha: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addItem(hlayout); } m_slAlpha = new ctkSliderWidget(this); m_slAlpha->setMinimum(-10); m_slAlpha->setMaximum(0); m_slAlpha->setPageStep(0.1); m_slAlpha->setSingleStep(0.01); m_slAlpha->setValue(-2.5); m_slAlpha->setDecimals(2); m_slAlpha->setTracking(false); m_slAlpha->setToolTip("The \"alpha\" parameter in the Sigmoid mapping filter."); connect( m_slAlpha, SIGNAL(valueChanged(double)), this, SLOT(OnAlphaChanged(double))); widgetLayout->addWidget( m_slAlpha ); // Beta controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Beta: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addLayout(hlayout); } m_slBeta = new ctkSliderWidget(this); m_slBeta->setMinimum(0); m_slBeta->setMaximum(100); m_slBeta->setPageStep(0.1); m_slBeta->setSingleStep(0.01); m_slBeta->setValue(3.5); m_slBeta->setDecimals(2); m_slBeta->setTracking(false); m_slBeta->setToolTip("The \"beta\" parameter in the Sigmoid mapping filter."); connect( m_slBeta, SIGNAL(valueChanged(double)), this, SLOT(OnBetaChanged(double))); widgetLayout->addWidget( m_slBeta ); // stopping value controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Stopping value: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addLayout(hlayout); } m_slStoppingValue = new ctkSliderWidget(this); m_slStoppingValue->setMinimum(0); m_slStoppingValue->setMaximum(10000); m_slStoppingValue->setPageStep(10); m_slStoppingValue->setSingleStep(1); m_slStoppingValue->setValue(2000); m_slStoppingValue->setDecimals(0); m_slStoppingValue->setTracking(false); m_slStoppingValue->setToolTip("The \"stopping value\" parameter in the fast marching 3D algorithm"); connect( m_slStoppingValue, SIGNAL(valueChanged(double)), this, SLOT(OnStoppingValueChanged(double))); widgetLayout->addWidget( m_slStoppingValue ); // threshold controls { QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->setSpacing(2); QLabel *lbl = new QLabel(this); lbl->setText("Threshold: "); hlayout->addWidget(lbl); QSpacerItem* sp2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); hlayout->addItem(sp2); widgetLayout->addLayout(hlayout); } m_slwThreshold = new ctkRangeWidget(this); m_slwThreshold->setMinimum(-100); m_slwThreshold->setMaximum(5000); m_slwThreshold->setMinimumValue(-100); m_slwThreshold->setMaximumValue(2000); m_slwThreshold->setDecimals(0); m_slwThreshold->setTracking(false); m_slwThreshold->setToolTip("The lower and upper thresholds for the final thresholding"); connect( m_slwThreshold, SIGNAL(valuesChanged(double, double)), this, SLOT(OnThresholdChanged(double, double))); widgetLayout->addWidget( m_slwThreshold ); m_btClearSeeds = new QPushButton("Clear"); m_btClearSeeds->setToolTip("Clear current result and start over again"); widgetLayout->addWidget(m_btClearSeeds); connect( m_btClearSeeds, SIGNAL(clicked()), this, SLOT(OnClearSeeds()) ); - m_btConfirm = new QPushButton("Accept"); + m_btConfirm = new QPushButton("Confirm Segmentation"); m_btConfirm->setToolTip("Incorporate current result in your working session."); m_btConfirm->setEnabled(false); widgetLayout->addWidget(m_btConfirm); connect( m_btConfirm, SIGNAL(clicked()), this, SLOT(OnConfirmSegmentation()) ); connect( this, SIGNAL(NewToolAssociated(mitk::Tool*)), this, SLOT(OnNewToolAssociated(mitk::Tool*)) ); this->setEnabled(false); } QmitkFastMarchingToolGUI::~QmitkFastMarchingToolGUI() { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->CurrentlyBusy -= mitk::MessageDelegate1( this, &QmitkFastMarchingToolGUI::BusyStateChanged ); m_FastMarchingTool->RemoveReadyListener(mitk::MessageDelegate(this, &QmitkFastMarchingToolGUI::OnFastMarchingToolReady) ); } } void QmitkFastMarchingToolGUI::OnNewToolAssociated(mitk::Tool* tool) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->CurrentlyBusy -= mitk::MessageDelegate1( this, &QmitkFastMarchingToolGUI::BusyStateChanged ); m_FastMarchingTool->RemoveReadyListener(mitk::MessageDelegate(this, &QmitkFastMarchingToolGUI::OnFastMarchingToolReady) ); } m_FastMarchingTool = dynamic_cast( tool ); if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->CurrentlyBusy += mitk::MessageDelegate1( this, &QmitkFastMarchingToolGUI::BusyStateChanged ); m_FastMarchingTool->AddReadyListener(mitk::MessageDelegate(this, &QmitkFastMarchingToolGUI::OnFastMarchingToolReady) ); //listen to timestep change events mitk::BaseRenderer::Pointer renderer; renderer = mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") ); if (renderer.IsNotNull() && !m_TimeIsConnected) { new QmitkStepperAdapter(this, renderer->GetSliceNavigationController()->GetTime(), "stepper"); // connect(m_TimeStepper, SIGNAL(Refetch()), this, SLOT(Refetch())); m_TimeIsConnected = true; } } } void QmitkFastMarchingToolGUI::Update() { m_FastMarchingTool->SetLowerThreshold( this->m_slwThreshold->minimumValue()); m_FastMarchingTool->SetUpperThreshold( this->m_slwThreshold->maximumValue()); m_FastMarchingTool->SetStoppingValue( this->m_slStoppingValue->value()); m_FastMarchingTool->SetSigma( this->m_slSigma->value()); m_FastMarchingTool->SetAlpha( this->m_slAlpha->value()); m_FastMarchingTool->SetBeta( this->m_slBeta->value()); m_FastMarchingTool->Update(); } void QmitkFastMarchingToolGUI::OnThresholdChanged(double lower, double upper) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetLowerThreshold( lower ); m_FastMarchingTool->SetUpperThreshold( upper ); this->Update(); } } void QmitkFastMarchingToolGUI::OnBetaChanged(double value) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetBeta( value ); this->Update(); } } void QmitkFastMarchingToolGUI::OnSigmaChanged(double value) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetSigma( value ); this->Update(); } } void QmitkFastMarchingToolGUI::OnAlphaChanged(double value) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetAlpha( value ); this->Update(); } } void QmitkFastMarchingToolGUI::OnStoppingValueChanged(double value) { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->SetStoppingValue( value ); this->Update(); } } void QmitkFastMarchingToolGUI::OnConfirmSegmentation() { if (m_FastMarchingTool.IsNotNull()) { m_FastMarchingTool->ConfirmSegmentation(); m_btConfirm->setEnabled(false); } } void QmitkFastMarchingToolGUI::SetStepper(mitk::Stepper *stepper) { this->m_TimeStepper = stepper; } void QmitkFastMarchingToolGUI::Refetch() { //event from image navigator recieved - timestep has changed m_FastMarchingTool->SetCurrentTimeStep(m_TimeStepper->GetPos()); } void QmitkFastMarchingToolGUI::OnClearSeeds() { //event from image navigator recieved - timestep has changed m_FastMarchingTool->ClearSeeds(); m_btConfirm->setEnabled(false); this->Update(); } void QmitkFastMarchingToolGUI::BusyStateChanged(bool value) { if (value) QApplication::setOverrideCursor( QCursor(Qt::BusyCursor) ); else QApplication::restoreOverrideCursor(); } void QmitkFastMarchingToolGUI::OnFastMarchingToolReady() { this->setEnabled(true); this->m_btConfirm->setEnabled(true); } diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp index d5232c2503..d96ade3cf7 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp @@ -1,1060 +1,1060 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkSlicesInterpolator.h" #include "QmitkStdMultiWidget.h" #include "QmitkSelectableGLWidget.h" #include "mitkToolManager.h" #include "mitkDataNodeFactory.h" #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkProgressBar.h" #include "mitkGlobalInteraction.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkInteractionConst.h" #include "mitkApplyDiffImageOperation.h" #include "mitkDiffImageApplier.h" #include "mitkSegTool2D.h" #include "mitkCoreObjectFactory.h" #include "mitkSurfaceToImageFilter.h" #include "mitkSliceNavigationController.h" #include #include #include #include #include #include #include #include #include #include //#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) const std::map QmitkSlicesInterpolator::createActionToSliceDimension() { std::map actionToSliceDimension; foreach(mitk::SliceNavigationController* slicer, m_ControllerToDeleteObserverTag.keys()) { actionToSliceDimension[new QAction(QString::fromStdString(slicer->GetRenderer()->GetName()),0)] = slicer; } return actionToSliceDimension; } QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget* parent, const char* /*name*/) :QWidget(parent), // ACTION_TO_SLICEDIMENSION( createActionToSliceDimension() ), m_Interpolator( mitk::SegmentationInterpolationController::New() ), m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()), m_ToolManager(NULL), m_Initialized(false), m_LastSNC(0), m_LastSliceIndex(0), m_2DInterpolationEnabled(false), m_3DInterpolationEnabled(false) { m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this); QVBoxLayout* vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode); m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode); m_CmbInterpolation->addItem("Disabled"); m_CmbInterpolation->addItem("2-Dimensional"); m_CmbInterpolation->addItem("3-Dimensional"); vboxLayout->addWidget(m_CmbInterpolation); - m_BtnApply2D = new QPushButton("Apply", m_GroupBoxEnableExclusiveInterpolationMode); + m_BtnApply2D = new QPushButton("Confirm Interpolation", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApply2D); - m_BtnApplyForAllSlices2D = new QPushButton("Apply for all slices", m_GroupBoxEnableExclusiveInterpolationMode); + m_BtnApplyForAllSlices2D = new QPushButton("Confirm For All Slices", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApplyForAllSlices2D); - m_BtnApply3D = new QPushButton("Apply", m_GroupBoxEnableExclusiveInterpolationMode); + m_BtnApply3D = new QPushButton("Confirm Interpolation", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_BtnApply3D); m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode); vboxLayout->addWidget(m_ChkShowPositionNodes); this->HideAllInterpolationControls(); connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int))); connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked())); connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked())); connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked())); connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool))); connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool))); QHBoxLayout* layout = new QHBoxLayout(this); layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode); this->setLayout(layout); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged ); InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver( itk::ModifiedEvent(), command ); itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged ); SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver( itk::ModifiedEvent(), command2 ); // feedback node and its visualization properties m_FeedbackNode = mitk::DataNode::New(); mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties( m_FeedbackNode ); m_FeedbackNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); m_FeedbackNode->SetProperty( "outline binary", mitk::BoolProperty::New(true) ); m_FeedbackNode->SetProperty( "color", mitk::ColorProperty::New(255.0, 255.0, 0.0) ); m_FeedbackNode->SetProperty( "texture interpolation", mitk::BoolProperty::New(false) ); m_FeedbackNode->SetProperty( "layer", mitk::IntProperty::New( 20 ) ); m_FeedbackNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); m_FeedbackNode->SetProperty( "name", mitk::StringProperty::New("Interpolation feedback") ); m_FeedbackNode->SetProperty( "opacity", mitk::FloatProperty::New(0.8) ); m_FeedbackNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_InterpolatedSurfaceNode = mitk::DataNode::New(); m_InterpolatedSurfaceNode->SetProperty( "color", mitk::ColorProperty::New(255.0,255.0,0.0) ); m_InterpolatedSurfaceNode->SetProperty( "name", mitk::StringProperty::New("Surface Interpolation feedback") ); 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->SetProperty( "color", mitk::ColorProperty::New(0.0, 0.0, 0.0) ); m_3DContourNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty( "name", mitk::StringProperty::New("Drawn Contours") ); m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f)); m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); 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"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); QWidget::setContentsMargins(0, 0, 0, 0); if ( QWidget::layout() != NULL ) { QWidget::layout()->setContentsMargins(0, 0, 0, 0); } //For running 3D Interpolation in background // create a QFuture and a QFutureWatcher 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())); } void QmitkSlicesInterpolator::SetDataStorage( mitk::DataStorage::Pointer storage ) { m_DataStorage = storage; m_SurfaceInterpolator->SetDataStorage(storage); } mitk::DataStorage* QmitkSlicesInterpolator::GetDataStorage() { if ( m_DataStorage.IsNotNull() ) { return m_DataStorage; } else { return NULL; } } void QmitkSlicesInterpolator::Initialize(mitk::ToolManager* toolManager, const QList &controllers) { Q_ASSERT(!controllers.empty()); if (m_Initialized) { // remove old observers Uninitialize(); } m_ToolManager = toolManager; if (m_ToolManager) { // set enabled only if a segmentation is selected mitk::DataNode* node = m_ToolManager->GetWorkingData(0); QWidget::setEnabled( node != NULL ); // react whenever the set of selected segmentation changes m_ToolManager->WorkingDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified ); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified ); // 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_TimeStep.insert(slicer, slicer->GetTime()->GetPos()); itk::MemberCommand::Pointer deleteCommand = itk::MemberCommand::New(); deleteCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted); m_ControllerToDeleteObserverTag.insert(slicer, slicer->AddObserver(itk::DeleteEvent(), deleteCommand)); itk::MemberCommand::Pointer timeChangedCommand = itk::MemberCommand::New(); timeChangedCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnTimeChanged); m_ControllerToTimeObserverTag.insert(slicer, slicer->AddObserver(mitk::SliceNavigationController::TimeSlicedGeometryEvent(NULL,0), timeChangedCommand)); itk::MemberCommand::Pointer sliceChangedCommand = itk::MemberCommand::New(); sliceChangedCommand->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSliceChanged); m_ControllerToSliceObserverTag.insert(slicer, slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(NULL,0), sliceChangedCommand)); } ACTION_TO_SLICEDIMENSION = createActionToSliceDimension(); } m_Initialized = true; } void QmitkSlicesInterpolator::Uninitialize() { if (m_ToolManager.IsNotNull()) { m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate(this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified); } 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)); } ACTION_TO_SLICEDIMENSION.clear(); m_ToolManager = NULL; m_Initialized = false; } QmitkSlicesInterpolator::~QmitkSlicesInterpolator() { if (m_Initialized) { // remove old observers Uninitialize(); } 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_Interpolator->RemoveObserver( InterpolationInfoChangedObserverTag ); m_SurfaceInterpolator->RemoveObserver( SurfaceInterpolationInfoChangedObserverTag ); delete m_Timer; } /** External enableization... */ void QmitkSlicesInterpolator::setEnabled( bool enable ) { QWidget::setEnabled(enable); //Set the gui elements of the different interpolation modi enabled if (enable) { if (m_2DInterpolationEnabled) { this->Show2DInterpolationControls(true); m_Interpolator->Activate2DInterpolation(true); } else if (m_3DInterpolationEnabled) { this->Show3DInterpolationControls(true); this->Show3DInterpolationResult(true); } } //Set all gui elements of the interpolation disabled else { this->HideAllInterpolationControls(); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status) { OnInterpolationActivated(status); m_Interpolator->Activate2DInterpolation(status); } void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status) { On3DInterpolationActivated(status); } void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status) { if (status) { OnInterpolationActivated(!status); On3DInterpolationActivated(!status); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::HideAllInterpolationControls() { this->Show2DInterpolationControls(false); this->Show3DInterpolationControls(false); } void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show) { m_BtnApply2D->setVisible(show); m_BtnApplyForAllSlices2D->setVisible(show); } void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show) { m_BtnApply3D->setVisible(show); m_ChkShowPositionNodes->setVisible(show); } void QmitkSlicesInterpolator::OnInterpolationMethodChanged(int index) { switch(index) { case 0: // Disabled m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation"); this->HideAllInterpolationControls(); this->OnInterpolationActivated(false); this->On3DInterpolationActivated(false); this->Show3DInterpolationResult(false); break; case 1: // 2D m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)"); this->HideAllInterpolationControls(); this->Show2DInterpolationControls(true); this->OnInterpolationActivated(true); this->On3DInterpolationActivated(false); m_Interpolator->Activate2DInterpolation(true); break; case 2: // 3D m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)"); this->HideAllInterpolationControls(); this->Show3DInterpolationControls(true); this->OnInterpolationActivated(false); this->On3DInterpolationActivated(true); break; default: MITK_ERROR << "Unknown interpolation method!"; m_CmbInterpolation->setCurrentIndex(0); break; } } void QmitkSlicesInterpolator::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)); } } void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified() { if (m_ToolManager->GetWorkingData(0) != 0) { m_Segmentation = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); } //Updating the current selected segmentation for the 3D interpolation SetCurrentContourListID(); if (m_2DInterpolationEnabled) { OnInterpolationActivated( true ); // re-initialize if needed } } void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified() { if (m_2DInterpolationEnabled) { OnInterpolationActivated( true ); // re-initialize if needed } if (m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::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_TimeStep[slicer]/* = event.GetPos()*/; //TODO Macht das hier wirklich Sinn???? if (m_LastSNC == slicer) { slicer->SendSlice();//will trigger a new interpolation } } void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e) { //Check whether we really have a GeometrySliceEvent if (!dynamic_cast(&e)) return; mitk::SliceNavigationController* slicer = dynamic_cast(sender); if (TranslateAndInterpolateChangedSlice(e, slicer)) { slicer->GetRenderer()->RequestUpdate(); } } bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e, mitk::SliceNavigationController* slicer) { if (!m_2DInterpolationEnabled) return false; try { const mitk::SliceNavigationController::GeometrySliceEvent& event = dynamic_cast(e); mitk::TimeSlicedGeometry* tsg = event.GetTimeSlicedGeometry(); if (tsg && m_TimeStep.contains(slicer)) { mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(tsg->GetGeometry3D(m_TimeStep[slicer])); if (slicedGeometry) { m_LastSNC = slicer; mitk::PlaneGeometry* plane = dynamic_cast(slicedGeometry->GetGeometry2D( event.GetPos() )); if (plane) Interpolate( plane, m_TimeStep[slicer], slicer ); return true; } } } catch(std::bad_cast) { return false; // so what } return false; } void QmitkSlicesInterpolator::Interpolate( mitk::PlaneGeometry* plane, unsigned int timeStep, mitk::SliceNavigationController* slicer ) { if (m_ToolManager) { mitk::DataNode* node = m_ToolManager->GetWorkingData(0); if (node) { m_Segmentation = dynamic_cast(node->GetData()); if (m_Segmentation) { int clickedSliceDimension(-1); int clickedSliceIndex(-1); // calculate real slice position, i.e. slice of the image and not slice of the TimeSlicedGeometry mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex ); mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( clickedSliceDimension, clickedSliceIndex, plane, timeStep ); m_FeedbackNode->SetData( interpolation ); m_LastSNC = slicer; m_LastSliceIndex = clickedSliceIndex; } } } } void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished() { mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult(); mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if(interpolatedSurface.IsNotNull() && workingNode && workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) { m_BtnApply3D->setEnabled(true); m_InterpolatedSurfaceNode->SetData(interpolatedSurface); m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface()); this->Show3DInterpolationResult(true); if( !m_DataStorage->Exists(m_InterpolatedSurfaceNode) && !m_DataStorage->Exists(m_3DContourNode)) { m_DataStorage->Add(m_3DContourNode); m_DataStorage->Add(m_InterpolatedSurfaceNode); } } else if (interpolatedSurface.IsNull()) { m_BtnApply3D->setEnabled(false); if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { this->Show3DInterpolationResult(false); } } foreach (mitk::SliceNavigationController* slicer, m_ControllerToTimeObserverTag.keys()) { slicer->GetRenderer()->RequestUpdate(); } } void QmitkSlicesInterpolator::OnAcceptInterpolationClicked() { if (m_Segmentation && m_FeedbackNode->GetData()) { //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); //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 slice as input mitk::Image::Pointer slice = dynamic_cast(m_FeedbackNode->GetData()); reslice->SetInputSlice(slice->GetSliceData()->GetVtkImageData(slice)); //set overwrite mode to true to write back to the image volume reslice->SetOverwriteMode(true); reslice->Modified(); mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice); extractor->SetInput( m_Segmentation ); unsigned int timestep = m_LastSNC->GetTime()->GetPos(); extractor->SetTimeStep( timestep ); extractor->SetWorldGeometry( m_LastSNC->GetCurrentPlaneGeometry() ); extractor->SetVtkOutputRequest(true); extractor->SetResliceTransformByGeometry( m_Segmentation->GetTimeSlicedGeometry()->GetGeometry3D( timestep ) ); extractor->Modified(); extractor->Update(); //the image was modified within the pipeline, but not marked so m_Segmentation->Modified(); m_Segmentation->GetVtkImageData()->Modified(); m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::AcceptAllInterpolations(mitk::SliceNavigationController* slicer) { /* * What exactly is done here: * 1. We create an empty diff image for the current segmentation * 2. All interpolated slices are written into the diff image * 3. Then the diffimage is applied to the original segmentation */ if (m_Segmentation) { //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); mitk::Image::Pointer image3D = m_Segmentation; unsigned int timeStep( slicer->GetTime()->GetPos() ); if (m_Segmentation->GetDimension() == 4) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput( m_Segmentation ); timeSelector->SetTimeNr( timeStep ); timeSelector->Update(); image3D = timeSelector->GetOutput(); } // create a empty diff image for the undo operation mitk::Image::Pointer diffImage = mitk::Image::New(); diffImage->Initialize( image3D ); // Set all pixels to zero mitk::PixelType pixelType( mitk::MakeScalarPixelType() ); memset( diffImage->GetData(), 0, (pixelType.GetBpe() >> 3) * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2) ); // 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(); int sliceDimension(-1); int sliceIndex(-1); mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, reslicePlane, sliceDimension, sliceIndex ); unsigned int zslices = m_Segmentation->GetDimension( sliceDimension ); mitk::ProgressBar::GetInstance()->AddStepsToDo(zslices); mitk::Point3D origin = reslicePlane->GetOrigin(); unsigned int totalChangedSlices(0); for (unsigned int sliceIndex = 0; sliceIndex < zslices; ++sliceIndex) { // Transforming the current origin of the reslice plane // so that it matches the one of the next slice m_Segmentation->GetSlicedGeometry()->WorldToIndex(origin, origin); origin[sliceDimension] = sliceIndex; m_Segmentation->GetSlicedGeometry()->IndexToWorld(origin, origin); reslicePlane->SetOrigin(origin); //Set the slice as 'input' mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( sliceDimension, sliceIndex, reslicePlane, timeStep ); if (interpolation.IsNotNull()) // we don't check if interpolation is necessary/sensible - but m_Interpolator does { //Setting up the reslicing pipeline which allows us to write the interpolation results back into //the image volume vtkSmartPointer reslice = vtkSmartPointer::New(); //set overwrite mode to true to write back to the image volume reslice->SetInputSlice(interpolation->GetSliceData()->GetVtkImageData(interpolation)); reslice->SetOverwriteMode(true); reslice->Modified(); mitk::ExtractSliceFilter::Pointer diffslicewriter = mitk::ExtractSliceFilter::New(reslice); diffslicewriter->SetInput( diffImage ); diffslicewriter->SetTimeStep( timeStep ); diffslicewriter->SetWorldGeometry(reslicePlane); diffslicewriter->SetVtkOutputRequest(true); diffslicewriter->SetResliceTransformByGeometry( diffImage->GetTimeSlicedGeometry()->GetGeometry3D( timeStep ) ); diffslicewriter->Modified(); diffslicewriter->Update(); ++totalChangedSlices; } mitk::ProgressBar::GetInstance()->Progress(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (totalChangedSlices > 0) { // store undo stack items if ( true ) { // create do/undo operations mitk::ApplyDiffImageOperation* doOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep ); mitk::ApplyDiffImageOperation* undoOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep ); undoOp->SetFactor( -1.0 ); std::stringstream comment; - comment << "Accept all interpolations (" << totalChangedSlices << ")"; + comment << "Confirm all interpolations (" << totalChangedSlices << ")"; mitk::OperationEvent* undoStackItem = new mitk::OperationEvent( mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment.str() ); mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem ); // acutally apply the changes here to the original image mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation( doOp ); } } m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController* slicer) { //this redirect is for calling from outside if (slicer == NULL) OnAcceptAllInterpolationsClicked(); else AcceptAllInterpolations( slicer ); } void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked() { QMenu orientationPopup(this); std::map::const_iterator it; for(it = ACTION_TO_SLICEDIMENSION.begin(); it != ACTION_TO_SLICEDIMENSION.end(); it++) orientationPopup.addAction(it->first); connect( &orientationPopup, SIGNAL(triggered(QAction*)), this, SLOT(OnAcceptAllPopupActivated(QAction*)) ); orientationPopup.exec( QCursor::pos() ); } void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked() { if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData()) { mitk::SurfaceToImageFilter::Pointer s2iFilter = mitk::SurfaceToImageFilter::New(); s2iFilter->MakeOutputBinaryOn(); s2iFilter->SetInput(dynamic_cast(m_InterpolatedSurfaceNode->GetData())); // check if ToolManager holds valid ReferenceData if (m_ToolManager->GetReferenceData(0) == NULL || m_ToolManager->GetWorkingData(0) == NULL) { return; } s2iFilter->SetImage(dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData())); s2iFilter->Update(); mitk::DataNode* segmentationNode = m_ToolManager->GetWorkingData(0); segmentationNode->SetData(s2iFilter->GetOutput()); m_CmbInterpolation->setCurrentIndex(0); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction* action) { try { std::map::const_iterator iter = ACTION_TO_SLICEDIMENSION.find( action ); if (iter != ACTION_TO_SLICEDIMENSION.end()) { mitk::SliceNavigationController* slicer = iter->second; AcceptAllInterpolations( slicer ); } } catch(...) { /* Showing message box with possible memory error */ QMessageBox errorInfo; errorInfo.setWindowTitle("Interpolation Process"); errorInfo.setIcon(QMessageBox::Critical); errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!"); errorInfo.exec(); //additional error message on std::cerr std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl; } } void QmitkSlicesInterpolator::OnInterpolationActivated(bool on) { m_2DInterpolationEnabled = on; try { if ( m_DataStorage.IsNotNull() ) { if (on && !m_DataStorage->Exists(m_FeedbackNode)) { m_DataStorage->Add( m_FeedbackNode ); } } } catch(...) { // don't care (double add/remove) } if (m_ToolManager) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0); QWidget::setEnabled( workingNode != NULL ); m_BtnApply2D->setEnabled( on ); m_FeedbackNode->SetVisibility( on ); if (!on) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } if (workingNode) { mitk::Image* segmentation = dynamic_cast(workingNode->GetData()); if (segmentation) { m_Interpolator->SetSegmentationVolume( segmentation ); if (referenceNode) { mitk::Image* referenceImage = dynamic_cast(referenceNode->GetData()); m_Interpolator->SetReferenceVolume( referenceImage ); // may be NULL } } } } UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::Run3DInterpolation() { m_SurfaceInterpolator->Interpolate(); } void QmitkSlicesInterpolator::StartUpdateInterpolationTimer() { m_Timer->start(500); } void QmitkSlicesInterpolator::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.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::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.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on) { m_3DInterpolationEnabled = on; try { if ( m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); if ((workingNode->IsSelected() && workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) && !isInterpolationResult && m_3DInterpolationEnabled) { int ret = QMessageBox::Yes; if (m_SurfaceInterpolator->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, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } else { m_CmbInterpolation->setCurrentIndex(0); } } else if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnApply3D->setEnabled(m_3DInterpolationEnabled); } } else { QWidget::setEnabled( false ); m_ChkShowPositionNodes->setEnabled(m_3DInterpolationEnabled); } } if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnApply3D->setEnabled(m_3DInterpolationEnabled); } } catch(...) { MITK_ERROR<<"Error with 3D surface interpolation!"; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::EnableInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated OnInterpolationActivated(on); } void QmitkSlicesInterpolator::Enable3DInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated On3DInterpolationActivated(on); } void QmitkSlicesInterpolator::UpdateVisibleSuggestion() { if (m_2DInterpolationEnabled && 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::TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast( renderer->GetWorldGeometry() ); if (timeSlicedGeometry) { mitk::SliceNavigationController::GeometrySliceEvent event( const_cast(timeSlicedGeometry), renderer->GetSlice() ); TranslateAndInterpolateChangedSlice(event, m_LastSNC); } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject& /*e*/) { // something (e.g. undo) changed the interpolation info, we should refresh our display UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject& /*e*/) { if(m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } void QmitkSlicesInterpolator:: SetCurrentContourListID() { // New ContourList = hide current interpolation Show3DInterpolationResult(false); if ( m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC ) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); bool isVisible (workingNode->IsVisible(m_LastSNC->GetRenderer())); if (isVisible && !isInterpolationResult) { QWidget::setEnabled( true ); //TODO Aufruf hier pruefen! mitk::Vector3D spacing = workingNode->GetData()->GetGeometry( m_LastSNC->GetTime()->GetPos() )->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_SurfaceInterpolator->SetSegmentationImage(dynamic_cast(workingNode->GetData())); m_SurfaceInterpolator->SetMaxSpacing(maxSpacing); m_SurfaceInterpolator->SetMinSpacing(minSpacing); m_SurfaceInterpolator->SetDistanceImageVolume(50000); m_SurfaceInterpolator->SetCurrentSegmentationInterpolationList(dynamic_cast(workingNode->GetData())); if (m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } } else { QWidget::setEnabled(false); } } } void QmitkSlicesInterpolator::Show3DInterpolationResult(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.widget4"))); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::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); } } diff --git a/Modules/SegmentationUI/Qmitk/QmitkWatershedToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkWatershedToolGUI.cpp index b060891efe..c6f6082cab 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkWatershedToolGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkWatershedToolGUI.cpp @@ -1,156 +1,156 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkWatershedToolGUI.h" #include "QmitkNewSegmentationDialog.h" #include "mitkProgressBar.h" #include #include #include #include #include #include MITK_TOOL_GUI_MACRO(SegmentationUI_EXPORT, QmitkWatershedToolGUI, "") QmitkWatershedToolGUI::QmitkWatershedToolGUI() :QmitkToolGUI(), m_SliderThreshold(NULL), m_SliderLevel(NULL) { // create the visible widgets QGridLayout* layout = new QGridLayout( this ); this->setContentsMargins( 0, 0, 0, 0 ); QLabel* label = new QLabel( "Threshold ", this ); QFont f = label->font(); f.setBold(false); label->setFont( f ); layout->addWidget(label,0,0); QLabel* label2 = new QLabel( "Level ", this ); f = label2->font(); f.setBold(false); label2->setFont( f ); layout->addWidget(label2,2,0); m_ThresholdLabel = new QLabel( " 0.04", this ); f = m_ThresholdLabel->font(); f.setBold(false); m_ThresholdLabel->setFont( f ); layout->addWidget(m_ThresholdLabel,0,1); m_SliderThreshold = new QSlider( Qt::Horizontal, this ); m_SliderThreshold->setMinimum(0); m_SliderThreshold->setMaximum(100); m_SliderThreshold->setPageStep(1); m_SliderThreshold->setValue(4); connect( m_SliderThreshold, SIGNAL(valueChanged(int)), this, SLOT(OnSliderValueThresholdChanged(int))); layout->addWidget( m_SliderThreshold, 1, 0, 1, 2 ); m_LevelLabel = new QLabel( " 0.35", this ); f = m_LevelLabel->font(); f.setBold(false); m_LevelLabel->setFont( f ); layout->addWidget(m_LevelLabel,2,1); m_SliderLevel = new QSlider( Qt::Horizontal, this ); m_SliderLevel->setMinimum(0); m_SliderLevel->setMaximum(100); m_SliderLevel->setPageStep(1); m_SliderLevel->setValue(35); connect( m_SliderLevel, SIGNAL(valueChanged(int)), this, SLOT(OnSliderValueLevelChanged(int))); layout->addWidget( m_SliderLevel, 3, 0, 1, 2 ); - QPushButton* okButton = new QPushButton("Create Segmentation", this); + QPushButton* okButton = new QPushButton("Run Segmentation", this); connect( okButton, SIGNAL(clicked()), this, SLOT(OnCreateSegmentation())); okButton->setFont( f ); layout->addWidget( okButton, 4, 0, 1, 2 ); m_InformationLabel = new QLabel("", this); f = m_InformationLabel->font(); f.setBold(false); m_InformationLabel->setFont( f ); layout->addWidget( m_InformationLabel, 5,0,1,2); connect( this, SIGNAL(NewToolAssociated(mitk::Tool*)), this, SLOT(OnNewToolAssociated(mitk::Tool*)) ); } QmitkWatershedToolGUI::~QmitkWatershedToolGUI() { if (m_WatershedTool.IsNotNull()) { //m_WatershedTool->SizeChanged -= mitk::MessageDelegate1( this, &QmitkWatershedToolGUI::OnSizeChanged ); } } void QmitkWatershedToolGUI::OnNewToolAssociated(mitk::Tool* tool) { if (m_WatershedTool.IsNotNull()) { //m_WatershedTool->SizeChanged -= mitk::MessageDelegate1( this, &QmitkWatershedToolGUI::OnSizeChanged ); } m_WatershedTool = dynamic_cast( tool ); OnSliderValueLevelChanged(35); OnSliderValueThresholdChanged(4); if (m_WatershedTool.IsNotNull()) { // m_WatershedTool->SizeChanged += mitk::MessageDelegate1( this, &QmitkWatershedToolGUI::OnSizeChanged ); } } void QmitkWatershedToolGUI::OnSliderValueThresholdChanged(int value) { if (m_WatershedTool.IsNotNull()) { double realValue = value / 100.; m_WatershedTool->SetThreshold( realValue ); m_ThresholdLabel->setText(QString::number(realValue)); } } void QmitkWatershedToolGUI::OnSliderValueLevelChanged(int value) { if (m_WatershedTool.IsNotNull()) { double realValue = value / 100.; m_WatershedTool->SetLevel( realValue ); m_LevelLabel->setText(QString::number(realValue)); } } void QmitkWatershedToolGUI::OnCreateSegmentation() { QApplication::setOverrideCursor(Qt::BusyCursor); m_InformationLabel->setText(QString("Please wait some time for computation...")); m_InformationLabel->repaint(); QApplication::processEvents(); m_WatershedTool->DoIt(); m_InformationLabel->setText(QString("")); QApplication::setOverrideCursor(Qt::ArrowCursor); for(int i=0; i<60; ++i) { mitk::ProgressBar::GetInstance()->Progress(); } }