diff --git a/Plugins/org.mitk.gui.qt.segmentation/files.cmake b/Plugins/org.mitk.gui.qt.segmentation/files.cmake
index 69bc5eadc3..ae0e49a418 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/files.cmake
+++ b/Plugins/org.mitk.gui.qt.segmentation/files.cmake
@@ -1,79 +1,81 @@
set(SRC_CPP_FILES
QmitkSegmentationPreferencePage.cpp
)
set(INTERNAL_CPP_FILES
mitkPluginActivator.cpp
QmitkSegmentationView.cpp
QmitkThresholdAction.cpp
QmitkCreatePolygonModelAction.cpp
#QmitkStatisticsAction.cpp
QmitkAutocropAction.cpp
+ QmitkAutocropLabelSetImageAction.cpp
QmitkDeformableClippingPlaneView.cpp
Common/QmitkDataSelectionWidget.cpp
SegmentationUtilities/QmitkSegmentationUtilitiesView.cpp
SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp
SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.cpp
SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp
SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.cpp
SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp
SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp
)
set(UI_FILES
src/internal/QmitkSegmentationControls.ui
src/internal/QmitkDeformableClippingPlaneViewControls.ui
src/internal/Common/QmitkDataSelectionWidgetControls.ui
src/internal/SegmentationUtilities/QmitkSegmentationUtilitiesViewControls.ui
src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidgetControls.ui
src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui
src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidgetControls.ui
src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidgetControls.ui
src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidgetControls.ui
)
set(MOC_H_FILES
src/QmitkSegmentationPreferencePage.h
src/internal/mitkPluginActivator.h
src/internal/QmitkSegmentationView.h
src/internal/QmitkThresholdAction.h
src/internal/QmitkCreatePolygonModelAction.h
#src/internal/QmitkStatisticsAction.h
src/internal/QmitkAutocropAction.h
+ src/internal/QmitkAutocropLabelSetImageAction.h
src/internal/QmitkDeformableClippingPlaneView.h
src/internal/Common/QmitkDataSelectionWidget.h
src/internal/SegmentationUtilities/QmitkSegmentationUtilitiesView.h
src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.h
src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.h
src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h
src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.h
src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.h
src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h
)
set(CACHED_RESOURCE_FILES
resources/segmentation.svg
resources/deformablePlane.png
resources/clipping_plane_translate_48x48.png
resources/clipping_plane_rotate48x48.png
resources/clipping_plane_deform48x48.png
resources/segmentation_utilities.svg
plugin.xml
)
set(QRC_FILES
resources/segmentation.qrc
resources/SegmentationUtilities.qrc
resources/BooleanOperationsWidget.qrc
resources/MorphologicalOperationsWidget.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/Plugins/org.mitk.gui.qt.segmentation/plugin.xml b/Plugins/org.mitk.gui.qt.segmentation/plugin.xml
index 56282d66a3..24f382cdeb 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/plugin.xml
+++ b/Plugins/org.mitk.gui.qt.segmentation/plugin.xml
@@ -1,94 +1,94 @@
Allows the segmentation of images using different tools.
Allow the clipping of a volume using a deformable plane.
Edit segmentations using standard operations.
-
+
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp
new file mode 100644
index 0000000000..9789f6d240
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp
@@ -0,0 +1,289 @@
+/*============================================================================
+
+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 "QmitkAutocropLabelSetImageAction.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+QmitkAutocropLabelSetImageAction::QmitkAutocropLabelSetImageAction()
+{
+}
+
+QmitkAutocropLabelSetImageAction::~QmitkAutocropLabelSetImageAction()
+{
+}
+
+void QmitkAutocropLabelSetImageAction::Run(const QList& selectedNodes)
+{
+ using PixelType = mitk::LabelSetImage::PixelType;
+ using PixelReaderType = mitk::ImagePixelReadAccessor;
+
+ for (const auto& dataNode : selectedNodes)
+ {
+ if (nullptr == dataNode->GetData())
+ continue;
+
+ auto* labelSetImage = dynamic_cast(dataNode->GetData());
+
+ if (nullptr == labelSetImage)
+ continue;
+
+ // Backup currently active layer as we need to restore it later
+ auto activeLayer = labelSetImage->GetActiveLayer();
+
+ const auto background = labelSetImage->GetExteriorLabel()->GetValue();
+ const auto numLayers = labelSetImage->GetNumberOfLayers();
+ const auto numTimeSteps = labelSetImage->GetTimeSteps();
+
+ // We need a time selector to handle 3d+t images. It is not used for 3d images, though.
+ auto timeSelector = mitk::ImageTimeSelector::New();
+ timeSelector->SetInput(labelSetImage);
+
+ // Iterate over all layers, time steps, and dimensions to determine the overall minimum
+ // and maximum indices of labeled pixels
+
+ const itk::Index<3> dim = {
+ labelSetImage->GetDimension(0),
+ labelSetImage->GetDimension(1),
+ labelSetImage->GetDimension(2)
+ };
+
+ itk::Index<3> maxIndex = { 0, 0, 0 };
+ itk::Index<3> minIndex = dim;
+ itk::Index<3> index;
+
+ bool labelSetImageIsEmpty = true;
+
+ for (std::remove_const_t layer = 0; layer < numLayers; ++layer)
+ {
+ labelSetImage->SetActiveLayer(layer);
+
+ for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep)
+ {
+ const mitk::Image* image = nullptr;
+
+ if (numTimeSteps > 1)
+ {
+ timeSelector->SetTimeNr(timeStep);
+ timeSelector->Update();
+ image = timeSelector->GetOutput();
+ }
+ else
+ {
+ image = labelSetImage;
+ }
+
+ std::unique_ptr pixelReader;
+
+ try
+ {
+ pixelReader = std::make_unique(image);
+ }
+ catch (const mitk::Exception&)
+ {
+ MITK_ERROR << "Autocrop was aborted: Image read access to \"" << dataNode->GetName() << "\" was denied.";
+ return;
+ }
+
+ bool imageIsEmpty = true;
+
+ for (index[2] = 0; index[2] < dim[2]; ++index[2])
+ {
+ for (index[1] = 0; index[1] < dim[1]; ++index[1])
+ {
+ for (index[0] = 0; index[0] < dim[0]; ++index[0])
+ {
+ if (background != pixelReader->GetPixelByIndex(index))
+ {
+ imageIsEmpty = false;
+ minIndex = {
+ std::min(minIndex[0], index[0]),
+ std::min(minIndex[1], index[1]),
+ std::min(minIndex[2], index[2])
+ };
+ break;
+ }
+ }
+ }
+ }
+
+ if (imageIsEmpty)
+ continue;
+
+ maxIndex = {
+ std::max(maxIndex[0], minIndex[0]),
+ std::max(maxIndex[1], minIndex[1]),
+ std::max(maxIndex[2], minIndex[2])
+ };
+
+ for (index[2] = dim[2] - 1; index[2] >= 0; --index[2])
+ {
+ for (index[1] = dim[1] - 1; index[1] >= 0; --index[1])
+ {
+ for (index[0] = dim[0] - 1; index[0] >= 0; --index[0])
+ {
+ if (background != pixelReader->GetPixelByIndex(index))
+ {
+ maxIndex = {
+ std::max(maxIndex[0], index[0]),
+ std::max(maxIndex[1], index[1]),
+ std::max(maxIndex[2], index[2])
+ };
+ break;
+ }
+ }
+ }
+ }
+
+ if (!imageIsEmpty)
+ labelSetImageIsEmpty = false;
+ }
+ }
+
+ if (labelSetImageIsEmpty)
+ {
+ MITK_WARN << "Autocrop was skipped: Image \"" << dataNode->GetName() << "\" is empty.";
+ return;
+ }
+
+ // We are ready to construct a cropped LabelSetImage. Fasten your seat belts, please!
+
+ const itk::Index<3> croppedDim = {
+ 1 + maxIndex[0] - minIndex[0],
+ 1 + maxIndex[1] - minIndex[1],
+ 1 + maxIndex[2] - minIndex[2]
+ };
+
+ const auto numPixels = croppedDim[0] * croppedDim[1] * croppedDim[2];
+
+ mitk::BaseGeometry::BoundsArrayType croppedBounds;
+ croppedBounds[0] = 0;
+ croppedBounds[1] = croppedDim[0];
+ croppedBounds[2] = 0;
+ croppedBounds[3] = croppedDim[1];
+ croppedBounds[4] = 0;
+ croppedBounds[5] = croppedDim[2];
+
+ // Clone and adapt the original TimeGeometry to the cropped region
+
+ auto croppedTimeGeometry = labelSetImage->GetTimeGeometry()->Clone();
+
+ for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep)
+ {
+ auto geometry = croppedTimeGeometry->GetGeometryForTimeStep(timeStep);
+
+ mitk::Point3D croppedOrigin;
+ geometry->IndexToWorld(minIndex, croppedOrigin);
+ geometry->SetOrigin(croppedOrigin);
+
+ geometry->SetBounds(croppedBounds);
+ }
+
+ auto croppedLabelSetImage = mitk::LabelSetImage::New();
+ croppedLabelSetImage->Initialize(mitk::MakeScalarPixelType(), *croppedTimeGeometry);
+
+ // Create cropped image volumes for all time steps in all layers
+
+ for (std::remove_const_t layer = 0; layer < numLayers; ++layer)
+ {
+ labelSetImage->SetActiveLayer(layer);
+ croppedLabelSetImage->AddLayer();
+
+ for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep)
+ {
+ auto* croppedVolume = new PixelType[numPixels];
+
+ const mitk::Image* image = nullptr;
+
+ if (numTimeSteps > 1)
+ {
+ timeSelector->SetTimeNr(timeStep);
+ timeSelector->Update();
+ image = timeSelector->GetOutput();
+ }
+ else
+ {
+ image = labelSetImage;
+ }
+
+ std::unique_ptr pixelReader;
+
+ try
+ {
+ pixelReader = std::make_unique(image);
+ }
+ catch (const mitk::Exception&)
+ {
+ MITK_ERROR << "Autocrop was aborted: Image read access to \"" << dataNode->GetName() << "\" was denied.";
+ return;
+ }
+
+ itk::Index<3> croppedIndex;
+
+ for (croppedIndex[2] = 0; croppedIndex[2] < croppedDim[2]; ++croppedIndex[2])
+ {
+ for (croppedIndex[1] = 0; croppedIndex[1] < croppedDim[1]; ++croppedIndex[1])
+ {
+ // The inner loop may be replaced by a single memcpy, also using an ImageReadAccessor
+ // instead of an ImagePixelReadAccessor. I wasn't able to correctly calculate the
+ // source address, though. You like challenges? - Go ahead! :-)
+ for (croppedIndex[0] = 0; croppedIndex[0] < croppedDim[0]; ++croppedIndex[0])
+ {
+ index[0] = croppedIndex[0] + minIndex[0];
+ index[1] = croppedIndex[1] + minIndex[1];
+ index[2] = croppedIndex[2] + minIndex[2];
+ const auto& pixel = pixelReader->GetPixelByIndex(index);
+
+ croppedVolume[croppedIndex[2] * croppedDim[1] * croppedDim[0] + croppedIndex[1] * croppedDim[0] + croppedIndex[0]] = pixel;
+ }
+ }
+ }
+
+ croppedLabelSetImage->SetVolume(croppedVolume, timeStep);
+
+ // Make sure the labels still have their original properties like names and colors
+ croppedLabelSetImage->AddLabelSetToLayer(layer, labelSetImage->GetLabelSet(layer));
+ }
+ }
+
+ // Restore the originally active layer
+ croppedLabelSetImage->SetActiveLayer(activeLayer);
+
+ // Override the original LabelSetImage with the cropped LabelSetImage
+ dataNode->SetData(croppedLabelSetImage);
+
+ // If we cropped a single LabelSetImage, reinit the views to give a visible feedback to the user
+ if (1 == selectedNodes.size())
+ mitk::RenderingManager::GetInstance()->InitializeViews(croppedTimeGeometry, mitk::RenderingManager::REQUEST_UPDATE_ALL, true);
+ }
+}
+
+void QmitkAutocropLabelSetImageAction::SetSmoothed(bool)
+{
+}
+
+void QmitkAutocropLabelSetImageAction::SetDecimated(bool)
+{
+}
+
+void QmitkAutocropLabelSetImageAction::SetDataStorage(mitk::DataStorage*)
+{
+}
+
+void QmitkAutocropLabelSetImageAction::SetFunctionality(berry::QtViewPart*)
+{
+}
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.h
new file mode 100644
index 0000000000..e882b2903a
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.h
@@ -0,0 +1,35 @@
+/*============================================================================
+
+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 QmitkAutocropLabelSetImageAction_h
+#define QmitkAutocropLabelSetImageAction_h
+
+#include
+#include
+
+class MITK_QT_SEGMENTATION QmitkAutocropLabelSetImageAction : public QObject, public mitk::IContextMenuAction
+{
+ Q_OBJECT
+ Q_INTERFACES(mitk::IContextMenuAction)
+
+public:
+ QmitkAutocropLabelSetImageAction();
+ ~QmitkAutocropLabelSetImageAction() override;
+
+ void Run(const QList& selectedNodes) override;
+ void SetDataStorage(mitk::DataStorage* dataStorage) override;
+ void SetSmoothed(bool smoothed) override;
+ void SetDecimated(bool decimated) override;
+ void SetFunctionality(berry::QtViewPart* view) override;
+};
+
+#endif
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp
index c21a7055b0..173eff2449 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp
@@ -1,63 +1,65 @@
/*============================================================================
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 "mitkPluginActivator.h"
#include "QmitkSegmentationView.h"
#include "QmitkThresholdAction.h"
#include "QmitkCreatePolygonModelAction.h"
#include "QmitkAutocropAction.h"
+#include "QmitkAutocropLabelSetImageAction.h"
#include "QmitkSegmentationPreferencePage.h"
#include "QmitkDeformableClippingPlaneView.h"
#include "SegmentationUtilities/QmitkSegmentationUtilitiesView.h"
using namespace mitk;
ctkPluginContext* PluginActivator::m_context = nullptr;
PluginActivator* PluginActivator::m_Instance = nullptr;
PluginActivator::PluginActivator()
{
m_Instance = this;
}
PluginActivator::~PluginActivator()
{
m_Instance = nullptr;
}
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(QmitkAutocropAction, context)
+ BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropLabelSetImageAction, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationPreferencePage, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkDeformableClippingPlaneView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationUtilitiesView, context)
this->m_context = context;
}
void PluginActivator::stop(ctkPluginContext *)
{
this->m_context = nullptr;
}
PluginActivator* PluginActivator::getDefault()
{
return m_Instance;
}
ctkPluginContext*PluginActivator::getContext()
{
return m_context;
}