diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/files.cmake b/Modules/Bundles/org.mitk.gui.qt.segmentation/files.cmake index 7d4c80c548..aa73a6dc4d 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/files.cmake +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/files.cmake @@ -1,52 +1,57 @@ SET(SRC_CPP_FILES QmitkSegmentationPreferencePage.cpp ) SET(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkSegmentationView.cpp QmitkSegmentationPostProcessing.cpp QmitkThresholdAction.cpp QmitkCreatePolygonModelAction.cpp QmitkStatisticsAction.cpp QmitkAutocropAction.cpp + QmitkBooleanOperationsView.cpp QmitkDeformableClippingPlaneView.cpp ) SET(UI_FILES src/internal/QmitkSegmentationControls.ui + src/internal/QmitkBooleanOperationsView.ui src/internal/QmitkDeformableClippingPlaneViewControls.ui ) SET(MOC_H_FILES src/QmitkSegmentationPreferencePage.h src/internal/mitkPluginActivator.h src/internal/QmitkSegmentationView.h src/internal/QmitkSegmentationPostProcessing.h src/internal/QmitkThresholdAction.h src/internal/QmitkCreatePolygonModelAction.h src/internal/QmitkStatisticsAction.h src/internal/QmitkAutocropAction.h + src/internal/QmitkBooleanOperationsView.h src/internal/QmitkDeformableClippingPlaneView.h ) SET(CACHED_RESOURCE_FILES resources/segmentation.png + resources/boolean.png resources/deformablePlane.png plugin.xml ) SET(QRC_FILES resources/segmentation.qrc + resources/boolean.qrc ) SET(CPP_FILES) foreach(file ${SRC_CPP_FILES}) SET(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) SET(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/plugin.xml b/Modules/Bundles/org.mitk.gui.qt.segmentation/plugin.xml index c39189e193..2be45b9c15 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/plugin.xml +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/plugin.xml @@ -1,42 +1,41 @@ - - - - + + name="Clipping Plane" + class="QmitkDeformableClippingPlaneView" + icon="resources/deformablePlane.png" /> diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/boolean.png b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/boolean.png new file mode 100644 index 0000000000..6eeb2cdf8b Binary files /dev/null and b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/boolean.png differ diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/boolean.qrc b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/boolean.qrc new file mode 100644 index 0000000000..6094c0644f --- /dev/null +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/boolean.qrc @@ -0,0 +1,7 @@ + + + btnDifference.png + btnIntersection.png + btnUnion.png + + diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnDifference.png b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnDifference.png new file mode 100644 index 0000000000..918548c943 Binary files /dev/null and b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnDifference.png differ diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnIntersection.png b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnIntersection.png new file mode 100644 index 0000000000..93eb7af027 Binary files /dev/null and b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnIntersection.png differ diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnUnion.png b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnUnion.png new file mode 100644 index 0000000000..6ab4e6d79c Binary files /dev/null and b/Modules/Bundles/org.mitk.gui.qt.segmentation/resources/btnUnion.png differ diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.cpp new file mode 100644 index 0000000000..9c4cceeb1f --- /dev/null +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.cpp @@ -0,0 +1,244 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "QmitkBooleanOperationsView.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QmitkBooleanOperationsView::QmitkBooleanOperationsView() + : m_Parent(NULL) +{ +} + +QmitkBooleanOperationsView::~QmitkBooleanOperationsView() +{ +} + +void QmitkBooleanOperationsView::CreateQtPartControl(QWidget *parent) +{ + mitk::DataStorage::Pointer dataStorage = GetDefaultDataStorage(); + + mitk::NodePredicateAnd::Pointer segmentationPredicate = mitk::NodePredicateAnd::New( + mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)), + mitk::NodePredicateNot::New( + mitk::NodePredicateProperty::New("helper object"))); + + m_Parent = parent; + + m_Controls.setupUi(parent); + + m_Controls.cmbSegmentationImage1->SetDataStorage(dataStorage); + m_Controls.cmbSegmentationImage1->SetPredicate(segmentationPredicate); + + m_Controls.cmbSegmentationImage2->SetPredicate(segmentationPredicate); + m_Controls.cmbSegmentationImage2->SetDataStorage(dataStorage); + + connect(m_Controls.cmbSegmentationImage1, SIGNAL(OnSelectionChanged(const mitk::DataNode *)), this, SLOT(OnSegmentationImage1Changed(const mitk::DataNode *))); + connect(m_Controls.cmbSegmentationImage2, SIGNAL(OnSelectionChanged(const mitk::DataNode *)), this, SLOT(OnSegmentationImage2Changed(const mitk::DataNode *))); + connect(m_Controls.btnDifference, SIGNAL(clicked()), this, SLOT(OnDifferenceButtonClicked())); + connect(m_Controls.btnUnion, SIGNAL(clicked()), this, SLOT(OnUnionButtonClicked())); + connect(m_Controls.btnIntersection, SIGNAL(clicked()), this, SLOT(OnIntersectionButtonClicked())); +} + +bool QmitkBooleanOperationsView::CheckSegmentationImages() +{ + mitk::Image::Pointer image1 = dynamic_cast(m_Controls.cmbSegmentationImage1->GetSelectedNode()->GetData()); + mitk::Image::Pointer image2 = dynamic_cast(m_Controls.cmbSegmentationImage2->GetSelectedNode()->GetData()); + + if (image1.IsNull() || image2.IsNull()) + { + MITK_ERROR << "At least one input segmentation image is invalid!"; + return false; + } + + if (image1->GetDimension() != image2->GetDimension()) + { + MITK_ERROR << "Dimensions of input segmentation images are different!"; + return false; + } + + if (image1->GetDimension() == 4) + { + unsigned int time = GetActiveStdMultiWidget()->GetTimeNavigationController()->GetTime()->GetPos(); + + if (time >= image1->GetDimension(3) || time >= image2->GetDimension(3)) + { + MITK_ERROR << "At least one input segmentation image has no data for current time slice!"; + return false; + } + } + + return true; +} + +mitk::Image::Pointer QmitkBooleanOperationsView::To3D(const mitk::Image::Pointer &image) +{ + if (image->GetDimension() == 4) + { + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + + imageTimeSelector->SetInput(image); + imageTimeSelector->SetTimeNr(static_cast(GetActiveStdMultiWidget()->GetTimeNavigationController()->GetTime()->GetPos())); + + imageTimeSelector->UpdateLargestPossibleRegion(); + + return imageTimeSelector->GetOutput(); + } + else + { + return image; + } +} + +void QmitkBooleanOperationsView::AddToDataStorage(const mitk::Image::Pointer &image, const std::string &prefix) const +{ + mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); + + dataNode->SetBoolProperty("binary", true); + dataNode->SetName(prefix + m_Controls.cmbSegmentationImage2->GetSelectedNode()->GetName()); + dataNode->SetData(image); + + GetDefaultDataStorage()->Add(dataNode, m_Controls.cmbSegmentationImage1->GetSelectedNode()); +} + +void QmitkBooleanOperationsView::EnableButtons(bool enable) +{ + m_Controls.lblInputImagesWarning->setVisible(!enable); + m_Controls.btnDifference->setEnabled(enable); + m_Controls.btnUnion->setEnabled(enable); + m_Controls.btnIntersection->setEnabled(enable); +} + +void QmitkBooleanOperationsView::DisableButtons() +{ + EnableButtons(false); +} + +void QmitkBooleanOperationsView::OnSegmentationImage1Changed(const mitk::DataNode *dataNode) +{ + if (dataNode != m_Controls.cmbSegmentationImage2->GetSelectedNode()) + EnableButtons(); + else + DisableButtons(); +} + +void QmitkBooleanOperationsView::OnSegmentationImage2Changed(const mitk::DataNode *dataNode) +{ + if (dataNode != m_Controls.cmbSegmentationImage1->GetSelectedNode()) + EnableButtons(); + else + DisableButtons(); +} + +void QmitkBooleanOperationsView::OnDifferenceButtonClicked() +{ + if (!CheckSegmentationImages()) + return; + + mitk::Image::Pointer image1 = To3D(dynamic_cast(m_Controls.cmbSegmentationImage1->GetSelectedNode()->GetData())); + mitk::Image::Pointer image2 = To3D(dynamic_cast(m_Controls.cmbSegmentationImage2->GetSelectedNode()->GetData())); + + typedef itk::Image ImageType; + + ImageType::Pointer itkImage1 = ImageType::New(); + ImageType::Pointer itkImage2 = ImageType::New(); + + mitk::CastToItkImage(image1, itkImage1); + mitk::CastToItkImage(image2, itkImage2); + + itk::NotImageFilter::Pointer notFilter = itk::NotImageFilter::New(); + notFilter->SetInput(itkImage2); + + itk::AndImageFilter::Pointer andFilter = itk::AndImageFilter::New(); + andFilter->SetInput1(itkImage1); + andFilter->SetInput2(notFilter->GetOutput()); + andFilter->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer image3 = mitk::Image::New(); + mitk::CastToMitkImage(andFilter->GetOutput(), image3); + + image3->DisconnectPipeline(); + + AddToDataStorage(image3, "Difference_"); +} + +void QmitkBooleanOperationsView::OnUnionButtonClicked() +{ + if (!CheckSegmentationImages()) + return; + + mitk::Image::Pointer image1 = To3D(dynamic_cast(m_Controls.cmbSegmentationImage1->GetSelectedNode()->GetData())); + mitk::Image::Pointer image2 = To3D(dynamic_cast(m_Controls.cmbSegmentationImage2->GetSelectedNode()->GetData())); + + typedef itk::Image ImageType; + + ImageType::Pointer itkImage1 = ImageType::New(); + ImageType::Pointer itkImage2 = ImageType::New(); + + mitk::CastToItkImage(image1, itkImage1); + mitk::CastToItkImage(image2, itkImage2); + + itk::OrImageFilter::Pointer orFilter = itk::OrImageFilter::New(); + orFilter->SetInput1(itkImage1); + orFilter->SetInput2(itkImage2); + orFilter->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer image3 = mitk::Image::New(); + mitk::CastToMitkImage(orFilter->GetOutput(), image3); + + image3->DisconnectPipeline(); + + AddToDataStorage(image3, "Union_"); +} + +void QmitkBooleanOperationsView::OnIntersectionButtonClicked() +{ + if (!CheckSegmentationImages()) + return; + + mitk::Image::Pointer image1 = To3D(dynamic_cast(m_Controls.cmbSegmentationImage1->GetSelectedNode()->GetData())); + mitk::Image::Pointer image2 = To3D(dynamic_cast(m_Controls.cmbSegmentationImage2->GetSelectedNode()->GetData())); + + typedef itk::Image ImageType; + + ImageType::Pointer itkImage1 = ImageType::New(); + ImageType::Pointer itkImage2 = ImageType::New(); + + mitk::CastToItkImage(image1, itkImage1); + mitk::CastToItkImage(image2, itkImage2); + + itk::AndImageFilter::Pointer andFilter = itk::AndImageFilter::New(); + andFilter->SetInput1(itkImage1); + andFilter->SetInput2(itkImage2); + andFilter->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer image3 = mitk::Image::New(); + mitk::CastToMitkImage(andFilter->GetOutput(), image3); + + image3->DisconnectPipeline(); + + AddToDataStorage(image3, "Intersection_"); +} diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.h b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.h new file mode 100644 index 0000000000..ebf43cde57 --- /dev/null +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.h @@ -0,0 +1,54 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef QMITKBOOLEANOPERATIONSVIEW_H +#define QMITKBOOLEANOPERATIONSVIEW_H + +#include +#include + +class QmitkBooleanOperationsView : public QmitkFunctionality +{ + Q_OBJECT + +public: + QmitkBooleanOperationsView(); + ~QmitkBooleanOperationsView(); + +protected: + void CreateQtPartControl(QWidget *parent); + +private slots: + void OnSegmentationImage1Changed(const mitk::DataNode *dataNode); + void OnSegmentationImage2Changed(const mitk::DataNode *dataNode); + void OnDifferenceButtonClicked(); + void OnUnionButtonClicked(); + void OnIntersectionButtonClicked(); + +private: + bool CheckSegmentationImages(); + mitk::Image::Pointer To3D(const mitk::Image::Pointer &image); + void AddToDataStorage(const mitk::Image::Pointer &image, const std::string &prefix) const; + void EnableButtons(bool enable = true); + void DisableButtons(); + + QWidget *m_Parent; + Ui::QmitkBooleanOperationsView m_Controls; +}; + +#endif diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.ui b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.ui new file mode 100644 index 0000000000..2702257ae3 --- /dev/null +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/QmitkBooleanOperationsView.ui @@ -0,0 +1,276 @@ + + + QmitkBooleanOperationsView + + + + 0 + 0 + 295 + 374 + + + + + + + Segmentation Images + + + + + + true + + + + 0 + 0 + + + + QComboBox::AdjustToMinimumContentsLength + + + + + + + true + + + + 0 + 0 + + + + QComboBox::AdjustToMinimumContentsLength + + + + + + + + + + + + + + + 200 + 0 + 0 + + + + + + + 200 + 0 + 0 + + + + + + + 200 + 0 + 0 + + + + + + + + + 200 + 0 + 0 + + + + + + + 200 + 0 + 0 + + + + + + + 200 + 0 + 0 + + + + + + + + + 84 + 82 + 78 + + + + + + + 84 + 82 + 78 + + + + + + + 84 + 82 + 78 + + + + + + + + + 50 + false + + + + Please select two different segmentation images above. + + + + + + + + + false + + + + 0 + 0 + + + + + 71 + 0 + + + + Difference + + + + :/boolean/btnDifference.png:/boolean/btnDifference.png + + + Qt::ToolButtonTextUnderIcon + + + + + + + false + + + + 0 + 0 + + + + + 71 + 0 + + + + Union + + + + :/boolean/btnUnion.png:/boolean/btnUnion.png + + + Qt::ToolButtonTextUnderIcon + + + + + + + false + + + + 0 + 0 + + + + + 71 + 0 + + + + Intersection + + + + :/boolean/btnIntersection.png:/boolean/btnIntersection.png + + + Qt::ToolButtonTextUnderIcon + + + + + + + + + Qt::Vertical + + + + 20 + 271 + + + + + + + + + QmitkDataStorageComboBox + QComboBox +
QmitkDataStorageComboBox.h
+
+
+ + + + +
diff --git a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp index 9613ce7ab7..7f05e95115 100644 --- a/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp +++ b/Modules/Bundles/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp @@ -1,28 +1,30 @@ #include "mitkPluginActivator.h" #include "QmitkSegmentationView.h" +#include "QmitkBooleanOperationsView.h" #include "QmitkThresholdAction.h" #include "QmitkCreatePolygonModelAction.h" #include "QmitkStatisticsAction.h" #include "QmitkAutocropAction.h" #include "QmitkSegmentationPreferencePage.h" #include "QmitkDeformableClippingPlaneView.h" using namespace mitk; void PluginActivator::start(ctkPluginContext *context) { - BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationView, context); - BERRY_REGISTER_EXTENSION_CLASS(QmitkThresholdAction, context); - BERRY_REGISTER_EXTENSION_CLASS(QmitkCreatePolygonModelAction, context); - BERRY_REGISTER_EXTENSION_CLASS(QmitkStatisticsAction, context); - BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropAction, context); - BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationPreferencePage, context); + BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkBooleanOperationsView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkThresholdAction, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkCreatePolygonModelAction, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkStatisticsAction, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropAction, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationPreferencePage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDeformableClippingPlaneView, context) } void PluginActivator::stop(ctkPluginContext *) { } Q_EXPORT_PLUGIN2(org_mitk_gui_qt_segmentation, mitk::PluginActivator)