diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox
index 0d9b10b310..623bfb4c2b 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox
+++ b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox
@@ -1,80 +1,80 @@
/**
\page org_mitk_views_segmentationutilities The Segmentation Utilities View
\imageMacro{segmentation_utilities-dox.svg,"Icon of the Segmentation Utilities View",5.00}
\imageMacro{QmitkSegmentationUtilities_Overview.png,"The Segmentation Utilities View",16.00}
\tableofcontents
\section org_mitk_views_segmentationUtilitiesManualOverview Overview
The Segmentation Utilities View allows to postprocess existing segmentations. Currently five different operations exist:
- \ref org_mitk_views_segmentationUtilitiesBooleanOperations
- \ref org_mitk_views_segmentationUtilitiesContourToImage
- \ref org_mitk_views_segmentationUtilitiesImageMasking
- \ref org_mitk_views_segmentationUtilitiesMorphologicalOperations
- \ref org_mitk_views_segmentationUtilitiesSurfaceToImage
\section org_mitk_views_segmentationUtilitiesDataSelection Data Selection
All postprocessing operations provide one or more selection widgets, which allow to select the data for the operation.
\section org_mitk_views_segmentationUtilitiesBooleanOperations Boolean operations
Boolean operations allows to perform the following fundamental operations on two segmentations:
- Difference: Subtracts the second segmentation from the first segmentation.
- Intersection: Extracts the overlapping areas of the two selected segmentations.
- Union: Combines the two existing segmentations.
The selected segmentations must have the same geometry (size, spacing, ...) in order for the operations to work correctly.
The result will be stored in a new data node as a child node of the first selected segmentation.
\imageMacro{QmitkSegmentationUtilities_BooleanOperations.png,"Boolean operations",6.00}
\section org_mitk_views_segmentationUtilitiesContourToImage Contour to image
Contour to image allows to create a segmentation out of a given contour-model.
The operation requires a contour model set and a reference image.
The created segmentation image will have the same geometrical properties like the reference image (dimension, size and Geometry3D).
\imageMacro{QmitkSegmentationUtilities_ContourToImage.png,"Contour to image",6.00}
\section org_mitk_views_segmentationUtilitiesImageMasking Image masking
Image masking allows to mask an image with either an existing segmentation or a surface.
-The operation requires an image and a binary image mask or a surface.
+The operation requires an image and a segmentation or a surface.
The result will be an image containing only the pixels that are covered by the respective mask.
\imageMacro{QmitkSegmentationUtilities_ImageMasking.png,"Image masking",6.00}
\section org_mitk_views_segmentationUtilitiesMorphologicalOperations Morphological operations
Morphological operations are applied to a single segmentation image. Based on a given structuring element the underlying segmentation will be modfied.
The plugin provides a ball and a cross as structuring elements. The follow operations are available:
- Dilation: Each labeled pixel within the segmentation will be dilated based on the selected structuring element.
- Erosion: Each labeled pixel within the segmentation will be eroded based on the selected structuring element.
- Opening: A dilation followed by an erosion, used for smoothing edges or eliminating small objects.
- Closing: An erosion followed by an dilation, used for filling small holes.
- Fill Holes: Fills bigger holes within a segmentation.
\imageMacro{QmitkSegmentationUtilities_MorphologicalOperations.png,"Morphological operations",6.00}
\section org_mitk_views_segmentationUtilitiesSurfaceToImage Surface to image
Surface to image allows to create a segmentation out of a given surface.
The operation requires a surface and a reference image.
The created segmentation image will have the same geometrical properties like the reference image (dimension, size and Geometry3D).
\imageMacro{QmitkSegmentationUtilities_SurfaceToImage.png,"Surface to image",6.00}
**/
diff --git a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities_ImageMasking.png b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities_ImageMasking.png
index ae33391505..5664184a23 100644
Binary files a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities_ImageMasking.png and b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities_ImageMasking.png differ
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp
index 033d760819..d1cfce7c08 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp
@@ -1,298 +1,284 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#include "QmitkImageMaskingWidget.h"
#include "mitkImage.h"
#include "../../Common/QmitkDataSelectionWidget.h"
#include
#include
#include
#include
#include
#include
#include
#include
-static const char* const HelpText = "Select a regular image and a binary image";
+namespace
+{
+ bool IsSurface(const mitk::DataNode* dataNode)
+ {
+ if (nullptr != dataNode)
+ {
+ if (nullptr != dynamic_cast(dataNode->GetData()))
+ return true;
+ }
+
+ return false;
+ }
+}
+
+static const char* const HelpText = "Select an image and a segmentation or surface";
QmitkImageMaskingWidget::QmitkImageMaskingWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent)
: QmitkSegmentationUtilityWidget(timeNavigationController, parent)
{
m_Controls.setupUi(this);
m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImagePredicate);
- m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SegmentationPredicate);
+ m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SegmentationOrSurfacePredicate);
m_Controls.dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
- connect (m_Controls.rbMaskImage, SIGNAL(toggled(bool)), this, SLOT(OnImageMaskingToggled(bool)));
- connect (m_Controls.rbMaskSurface, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceMaskingToggled(bool)));
connect (m_Controls.btnMaskImage, SIGNAL(clicked()), this, SLOT(OnMaskImagePressed()));
connect(m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)),
this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
if( m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull() &&
m_Controls.dataSelectionWidget->GetSelection(1).IsNotNull() )
{
this->OnSelectionChanged(0, m_Controls.dataSelectionWidget->GetSelection(0));
}
}
QmitkImageMaskingWidget::~QmitkImageMaskingWidget()
{
}
void QmitkImageMaskingWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection)
{
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer node0 = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer node1 = dataSelectionWidget->GetSelection(1);
if (node0.IsNull() || node1.IsNull() )
{
- if( m_Controls.rbMaskImage->isChecked() )
- {
- dataSelectionWidget->SetHelpText(HelpText);
- }
- else
- {
- dataSelectionWidget->SetHelpText("Select a regular image and a surface");
- }
+ dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
}
else
{
this->SelectionControl(index, selection);
}
}
void QmitkImageMaskingWidget::SelectionControl(unsigned int index, const mitk::DataNode* selection)
{
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index);
//if Image-Masking is enabled, check if image-dimension of reference and binary image is identical
- if( m_Controls.rbMaskImage->isChecked() )
+ if( !IsSurface(dataSelectionWidget->GetSelection(1)) )
{
if( dataSelectionWidget->GetSelection(0) == dataSelectionWidget->GetSelection(1) )
{
dataSelectionWidget->SetHelpText("Select two different images above");
this->EnableButtons(false);
return;
}
else if( node.IsNotNull() && selection )
{
mitk::Image::Pointer referenceImage = dynamic_cast ( dataSelectionWidget->GetSelection(0)->GetData() );
mitk::Image::Pointer maskImage = dynamic_cast ( dataSelectionWidget->GetSelection(1)->GetData() );
if( maskImage.IsNull() || referenceImage->GetLargestPossibleRegion().GetSize() != maskImage->GetLargestPossibleRegion().GetSize() )
{
dataSelectionWidget->SetHelpText("Different image sizes cannot be masked");
this->EnableButtons(false);
return;
}
}
else
{
dataSelectionWidget->SetHelpText(HelpText);
return;
}
}
dataSelectionWidget->SetHelpText("");
this->EnableButtons();
}
void QmitkImageMaskingWidget::EnableButtons(bool enable)
{
m_Controls.btnMaskImage->setEnabled(enable);
}
-void QmitkImageMaskingWidget::OnImageMaskingToggled(bool status)
-{
- if (status)
- {
- m_Controls.dataSelectionWidget->SetHelpText("Select a regular image and a binary image");
- m_Controls.dataSelectionWidget->SetPredicate(1, QmitkDataSelectionWidget::SegmentationPredicate);
- }
-}
-
-void QmitkImageMaskingWidget::OnSurfaceMaskingToggled(bool status)
-{
- if (status)
- {
- m_Controls.dataSelectionWidget->SetHelpText("Select a regular image and a surface");
- m_Controls.dataSelectionWidget->SetPredicate(1, QmitkDataSelectionWidget::SurfacePredicate);
- }
-}
-
-
void QmitkImageMaskingWidget::OnMaskImagePressed()
{
//Disable Buttons during calculation and initialize Progressbar
this->EnableButtons(false);
mitk::ProgressBar::GetInstance()->AddStepsToDo(4);
mitk::ProgressBar::GetInstance()->Progress();
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
//create result image, get mask node and reference image
mitk::Image::Pointer resultImage(nullptr);
mitk::DataNode::Pointer maskingNode = dataSelectionWidget->GetSelection(1);
mitk::Image::Pointer referenceImage = static_cast(dataSelectionWidget->GetSelection(0)->GetData());
if(referenceImage.IsNull() || maskingNode.IsNull() )
{
MITK_ERROR << "Selection does not contain an image";
QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain an image", QMessageBox::Ok );
m_Controls.btnMaskImage->setEnabled(true);
return;
}
//Do Image-Masking
- if (m_Controls.rbMaskImage->isChecked())
+ if (!IsSurface(maskingNode))
{
mitk::ProgressBar::GetInstance()->Progress();
mitk::Image::Pointer maskImage = dynamic_cast ( maskingNode->GetData() );
if(maskImage.IsNull() )
{
- MITK_ERROR << "Selection does not contain a binary image";
- QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a binary image", QMessageBox::Ok );
+ MITK_ERROR << "Selection does not contain a segmentation";
+ QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a segmentation", QMessageBox::Ok );
this->EnableButtons();
return;
}
if( referenceImage->GetLargestPossibleRegion().GetSize() == maskImage->GetLargestPossibleRegion().GetSize() )
{
resultImage = this->MaskImage( referenceImage, maskImage );
}
}
//Do Surface-Masking
else
{
mitk::ProgressBar::GetInstance()->Progress();
//1. convert surface to image
mitk::Surface::Pointer surface = dynamic_cast ( maskingNode->GetData() );
//TODO Get 3D Surface of current time step
if(surface.IsNull())
{
MITK_ERROR << "Selection does not contain a surface";
QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a surface", QMessageBox::Ok );
this->EnableButtons();
return;
}
mitk::Image::Pointer maskImage = this->ConvertSurfaceToImage( referenceImage, surface );
//2. mask reference image with mask image
if(maskImage.IsNotNull() &&
referenceImage->GetLargestPossibleRegion().GetSize() == maskImage->GetLargestPossibleRegion().GetSize() )
{
resultImage = this->MaskImage( referenceImage, maskImage );
}
}
mitk::ProgressBar::GetInstance()->Progress();
if( resultImage.IsNull() )
{
MITK_ERROR << "Masking failed";
QMessageBox::information( this, "Image and Surface Masking", "Masking failed. For more information please see logging window.", QMessageBox::Ok );
this->EnableButtons();
mitk::ProgressBar::GetInstance()->Progress(4);
return;
}
//Add result to data storage
this->AddToDataStorage(
dataSelectionWidget->GetDataStorage(),
resultImage,
dataSelectionWidget->GetSelection(0)->GetName() + "_" + dataSelectionWidget->GetSelection(1)->GetName(),
dataSelectionWidget->GetSelection(0));
this->EnableButtons();
mitk::ProgressBar::GetInstance()->Progress();
}
mitk::Image::Pointer QmitkImageMaskingWidget::MaskImage(mitk::Image::Pointer referenceImage, mitk::Image::Pointer maskImage )
{
mitk::Image::Pointer resultImage(nullptr);
mitk::MaskImageFilter::Pointer maskFilter = mitk::MaskImageFilter::New();
maskFilter->SetInput( referenceImage );
maskFilter->SetMask( maskImage );
maskFilter->OverrideOutsideValueOn();
maskFilter->SetOutsideValue( referenceImage->GetStatistics()->GetScalarValueMin() );
try
{
maskFilter->Update();
}
catch(itk::ExceptionObject& excpt)
{
MITK_ERROR << excpt.GetDescription();
return nullptr;
}
resultImage = maskFilter->GetOutput();
return resultImage;
}
mitk::Image::Pointer QmitkImageMaskingWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface )
{
mitk::ProgressBar::GetInstance()->AddStepsToDo(2);
mitk::ProgressBar::GetInstance()->Progress();
mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
surfaceToImageFilter->MakeOutputBinaryOn();
surfaceToImageFilter->SetInput(surface);
surfaceToImageFilter->SetImage(image);
try
{
surfaceToImageFilter->Update();
}
catch(itk::ExceptionObject& excpt)
{
MITK_ERROR << excpt.GetDescription();
return nullptr;
}
mitk::ProgressBar::GetInstance()->Progress();
mitk::Image::Pointer resultImage = mitk::Image::New();
resultImage = surfaceToImageFilter->GetOutput();
return resultImage;
}
void QmitkImageMaskingWidget::AddToDataStorage(mitk::DataStorage::Pointer dataStorage, mitk::Image::Pointer segmentation, const std::string& name, mitk::DataNode::Pointer parent )
{
mitk::DataNode::Pointer dataNode = mitk::DataNode::New();
dataNode->SetName(name);
dataNode->SetData(segmentation);
dataStorage->Add(dataNode, parent);
}
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h
index 374d9bc5c2..37a5711983 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h
@@ -1,80 +1,74 @@
/*============================================================================
The Medical Imaging Interaction Toolkit (MITK)
Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.
Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.
============================================================================*/
#ifndef QmitkImageMaskingWidget_h
#define QmitkImageMaskingWidget_h
#include "../QmitkSegmentationUtilityWidget.h"
#include
#include
namespace mitk {
class Image;
}
/*!
\brief QmitkImageMaskingWidget
Tool masks an image with a binary image or a surface. The Method requires
an image and a binary image mask or a surface. The input image and the binary
image mask must be of the same size. Masking with a surface creates first a
binary image of the surface and then use this for the masking of the input image.
*/
class QmitkImageMaskingWidget : public QmitkSegmentationUtilityWidget
{
Q_OBJECT
public:
/** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
explicit QmitkImageMaskingWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = nullptr);
/** @brief Defaul destructor. */
~QmitkImageMaskingWidget() override;
private slots:
/** @brief This slot is called if the selection in the workbench is changed. */
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
- /** @brief This slot is called if user activates the radio button for masking an image with a binary image mask. */
- void OnImageMaskingToggled(bool);
-
- /** @brief This slot is called if user activates the radio button for masking an image with a surface. */
- void OnSurfaceMaskingToggled(bool);
-
/** @brief This slot is called if user activates the button to mask an image. */
void OnMaskImagePressed();
private:
/** @brief Check if selections is valid. */
void SelectionControl( unsigned int index, const mitk::DataNode* selection);
/** @brief Enable buttons if data selction is valid. */
void EnableButtons(bool enable = true);
/** @brief Mask an image with a given binary mask. Note that the input image and the mask image must be of the same size. */
itk::SmartPointer MaskImage(itk::SmartPointer referenceImage, itk::SmartPointer maskImage );
/** @brief Convert a surface into an binary image. */
itk::SmartPointer ConvertSurfaceToImage( itk::SmartPointer image, mitk::Surface::Pointer surface );
/** @brief Adds a new data object to the DataStorage.*/
void AddToDataStorage(mitk::DataStorage::Pointer dataStorage, itk::SmartPointer segmentation,
const std::string& name, mitk::DataNode::Pointer parent = nullptr);
Ui::QmitkImageMaskingWidgetControls m_Controls;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui
index 1882ccdfbf..7ff3b3184c 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui
@@ -1,82 +1,56 @@
QmitkImageMaskingWidgetControls
0
0
147
155
-
0
0
- -
-
-
- Masking Mode
-
-
-
-
-
-
- Image Masking
-
-
- true
-
-
-
- -
-
-
- Surface Masking
-
-
-
-
-
-
-
Mask
-
Qt::Vertical
20
40
QmitkDataSelectionWidget
QWidget
internal/Common/QmitkDataSelectionWidget.h
1