diff --git a/Modules/AlgorithmsExt/include/mitkPadImageFilter.h b/Modules/AlgorithmsExt/include/mitkPadImageFilter.h
index cd0d63d72f..d83b134489 100644
--- a/Modules/AlgorithmsExt/include/mitkPadImageFilter.h
+++ b/Modules/AlgorithmsExt/include/mitkPadImageFilter.h
@@ -1,68 +1,71 @@
 /*============================================================================
 
 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 mitkPadImageFilter_h
 #define mitkPadImageFilter_h
 
 #include "MitkAlgorithmsExtExports.h"
 #include "mitkCommon.h"
 #include "mitkImageTimeSelector.h"
 #include "mitkImageToImageFilter.h"
 
 #include "itkImage.h"
 
 namespace mitk
 {
   /**
    * \brief PadImageFilter class pads the first input image to the size of the second input image.
    * Two Images have to be set.
    * The first image is the image to pad. The second image defines the pad size.
    * It is also possible to use an included binary filter.
    *
    * \ingroup Process
    */
   class MITKALGORITHMSEXT_EXPORT PadImageFilter : public ImageToImageFilter
   {
   public:
     mitkClassMacro(PadImageFilter, ImageToImageFilter);
 
     itkFactorylessNewMacro(Self);
 
     itkCloneMacro(Self);
 
       /** \brief Sets the intensity of the pixel to pad */
       itkSetMacro(PadConstant, int);
 
     /** \brief sets the binary filter ON or OFF */
     itkSetMacro(BinaryFilter, bool);
 
     /** \brief Sets the lower threshold of the included binary filter */
     itkSetMacro(LowerThreshold, int);
 
     /** \brief Sets the upper threshold of the included binary filter */
     itkSetMacro(UpperThreshold, int);
 
   protected:
     PadImageFilter();
 
     ~PadImageFilter() override;
 
     void GenerateData() override;
 
   private:
+    template <typename SourceImageType>
+    void GenerateDataInternal(SourceImageType* sourceItkImage, mitk::Image::Pointer outputImage);
+
     bool m_BinaryFilter;
     int m_PadConstant, m_LowerThreshold, m_UpperThreshold;
   };
 
 } // namespace mitk
 
 #endif
diff --git a/Modules/AlgorithmsExt/src/mitkPadImageFilter.cpp b/Modules/AlgorithmsExt/src/mitkPadImageFilter.cpp
index 332f79e0b3..1da308c532 100644
--- a/Modules/AlgorithmsExt/src/mitkPadImageFilter.cpp
+++ b/Modules/AlgorithmsExt/src/mitkPadImageFilter.cpp
@@ -1,101 +1,105 @@
 /*============================================================================
 
 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 "mitkPadImageFilter.h"
 #include "mitkImageCast.h"
-
+#include <mitkImageAccessByItk.h>
 #include "itkBinaryThresholdImageFilter.h"
 #include "itkConstantPadImageFilter.h"
 
 mitk::PadImageFilter::PadImageFilter()
 {
   this->SetNumberOfIndexedInputs(2);
   this->SetNumberOfRequiredInputs(2);
   m_BinaryFilter = false;
 
   m_PadConstant = -32766;
   m_LowerThreshold = -32766;
   m_UpperThreshold = -32765;
 }
 
 mitk::PadImageFilter::~PadImageFilter()
 {
 }
 
-void mitk::PadImageFilter::GenerateData()
+
+template <typename SourceImageType>
+void mitk::PadImageFilter::GenerateDataInternal(SourceImageType* sourceItkImage, mitk::Image::Pointer outputImage)
 {
-  mitk::Image::ConstPointer image = this->GetInput(0);
+  mitk::Image::ConstPointer sourceImage = this->GetInput(0);
   mitk::Image::ConstPointer referenceImage = this->GetInput(1);
 
-  typedef itk::Image<short, 3> ImageType;
-  ImageType::Pointer itkImage = ImageType::New();
-  mitk::CastToItkImage(image, itkImage);
-
-  mitk::BaseGeometry *imageGeometry = image->GetGeometry();
+  mitk::BaseGeometry* imageGeometry = sourceImage->GetGeometry();
   mitk::Point3D origin = imageGeometry->GetOrigin();
   mitk::Vector3D spacing = imageGeometry->GetSpacing();
 
-  mitk::BaseGeometry *referenceImageGeometry = referenceImage->GetGeometry();
+  mitk::BaseGeometry* referenceImageGeometry = referenceImage->GetGeometry();
   mitk::Point3D referenceOrigin = referenceImageGeometry->GetOrigin();
 
   double outputOrigin[3];
   itk::SizeValueType padLowerBound[3];
   itk::SizeValueType padUpperBound[3];
 
   int i;
   for (i = 0; i < 3; ++i)
   {
     outputOrigin[i] = referenceOrigin[i];
 
     padLowerBound[i] = static_cast<unsigned long>((origin[i] - referenceOrigin[i]) / spacing[i] + 0.5);
 
-    padUpperBound[i] = referenceImage->GetDimension(i) - image->GetDimension(i) - padLowerBound[i];
+    padUpperBound[i] = referenceImage->GetDimension(i) - sourceImage->GetDimension(i) - padLowerBound[i];
   }
 
   // The origin of the input image is passed through the filter and used as
   // output origin as well. Hence, it needs to be overwritten accordingly.
-  itkImage->SetOrigin(outputOrigin);
+  sourceItkImage->SetOrigin(outputOrigin);
 
-  typedef itk::ConstantPadImageFilter<ImageType, ImageType> PadFilterType;
-  PadFilterType::Pointer padFilter = PadFilterType::New();
-  padFilter->SetInput(itkImage);
+  typedef itk::ConstantPadImageFilter<SourceImageType, SourceImageType> PadFilterType;
+  typename PadFilterType::Pointer padFilter = PadFilterType::New();
+  padFilter->SetInput(sourceItkImage);
   padFilter->SetConstant(m_PadConstant);
   padFilter->SetPadLowerBound(padLowerBound);
   padFilter->SetPadUpperBound(padUpperBound);
 
-  mitk::Image::Pointer outputImage = this->GetOutput();
-
   // If the Binary flag is set, use an additional binary threshold filter after
   // padding.
   if (m_BinaryFilter)
   {
     typedef itk::Image<unsigned char, 3> BinaryImageType;
-    typedef itk::BinaryThresholdImageFilter<ImageType, BinaryImageType> BinaryFilterType;
-    BinaryFilterType::Pointer binaryFilter = BinaryFilterType::New();
+    typedef itk::BinaryThresholdImageFilter<SourceImageType, BinaryImageType> BinaryFilterType;
+    typename BinaryFilterType::Pointer binaryFilter = BinaryFilterType::New();
 
     binaryFilter->SetInput(padFilter->GetOutput());
     binaryFilter->SetLowerThreshold(m_LowerThreshold);
     binaryFilter->SetUpperThreshold(m_UpperThreshold);
     binaryFilter->SetInsideValue(1);
     binaryFilter->SetOutsideValue(0);
     binaryFilter->Update();
 
     mitk::CastToMitkImage(binaryFilter->GetOutput(), outputImage);
   }
   else
   {
     padFilter->Update();
     mitk::CastToMitkImage(padFilter->GetOutput(), outputImage);
   }
+}
+
+void mitk::PadImageFilter::GenerateData()
+{
+  mitk::Image::Pointer image = this->GetInput(0);
+  mitk::Image::Pointer outputImage = this->GetOutput();
+
+  AccessFixedDimensionByItk_1(image, GenerateDataInternal, 3, outputImage);
 
   outputImage->SetRequestedRegionToLargestPossibleRegion();
 }
diff --git a/Modules/Core/include/mitkWeakPointer.h b/Modules/Core/include/mitkWeakPointer.h
index a001e5742e..4ee116aa28 100644
--- a/Modules/Core/include/mitkWeakPointer.h
+++ b/Modules/Core/include/mitkWeakPointer.h
@@ -1,419 +1,419 @@
 /*============================================================================
 
 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 mitkWeakPointer_h
 #define mitkWeakPointer_h
 
 #include <itkCommand.h>
 #include <functional>
 
 namespace mitk
 {
   template <class T>
   class WeakPointer final
   {
   public:
     using DeleteEventCallbackType = std::function<void ()>;
 
     WeakPointer() noexcept
       : m_RawPointer(nullptr)
     {
     }
 
     WeakPointer(T *rawPointer)
       : m_RawPointer(rawPointer)
     {
       this->AddDeleteEventObserver();
     }
 
     WeakPointer(const WeakPointer &other)
       : m_RawPointer(other.m_RawPointer)
     {
       this->AddDeleteEventObserver();
     }
 
     WeakPointer(WeakPointer &&other)
       : m_RawPointer(other.m_RawPointer)
     {
       other.RemoveDeleteEventObserver();
       other.m_RawPointer = nullptr;
       this->AddDeleteEventObserver();
     }
 
     ~WeakPointer() noexcept
     {
       try
       {
         this->RemoveDeleteEventObserver();
       }
       catch (...)
       {
         // Swallow. Otherwise, the application would terminate if another
         // exception is already propagating.
       }
     }
 
     // Prefer classic implementation to copy-and-swap idiom. Swapping is
     // non-trivial for this class as the observed object is keeping references
     // to its observers.
     WeakPointer & operator =(const WeakPointer &other)
     {
       if (this != &other)
       {
         this->RemoveDeleteEventObserver();
         m_RawPointer = other.m_RawPointer;
         this->AddDeleteEventObserver();
       }
 
       return *this;
     }
 
     WeakPointer & operator =(WeakPointer &&other)
     {
       // No check for self-assignment as it is allowed to assume that the
       // parameter is a unique reference to this argument.
 
       this->RemoveDeleteEventObserver();
       m_RawPointer = other.m_RawPointer;
       other.m_RawPointer = nullptr;
       this->AddDeleteEventObserver();
 
       return *this;
     }
 
     WeakPointer & operator =(std::nullptr_t)
     {
       this->RemoveDeleteEventObserver();
       m_RawPointer = nullptr;
 
       return *this;
     }
 
     WeakPointer & operator =(T *other)
     {
       if (m_RawPointer != other)
       {
         this->RemoveDeleteEventObserver();
         m_RawPointer = other;
         this->AddDeleteEventObserver();
       }
 
       return *this;
     }
 
     explicit operator bool() const noexcept
     {
       return nullptr != m_RawPointer;
     }
 
     bool IsExpired() const noexcept
     {
       return !*this;
     }
 
     itk::SmartPointer<T> Lock() const
     {
       return m_RawPointer;
     }
 
     void SetDeleteEventCallback(const DeleteEventCallbackType &callback)
     {
       m_DeleteEventCallback = callback;
     }
 
   private:
     void AddDeleteEventObserver()
     {
       if (nullptr != m_RawPointer)
       {
         auto command = itk::SimpleMemberCommand<WeakPointer>::New();
         command->SetCallbackFunction(this, &WeakPointer::OnDeleteEvent);
 
-        using TWithoutConst = typename std::remove_const<T>::type;
+        using TWithoutConst = typename std::remove_const_t<T>;
         //cast the pointer to non const before adding the observer. This is done to ensure that
         //weak pointer also supports const pointers.
         auto nonConstPointer = const_cast<TWithoutConst*>(m_RawPointer);
         m_ObserverTag = nonConstPointer->AddObserver(itk::DeleteEvent(), command);
       }
     }
 
     void RemoveDeleteEventObserver()
     {
       if (nullptr != m_RawPointer)
       {
-        using TWithoutConst = typename std::remove_const<T>::type;
+        using TWithoutConst = typename std::remove_const_t<T>;
         //cast the pointer to non const before removing the observer. This is done to ensure that
         //weak pointer also supports const pointers.
         auto nonConstPointer = const_cast<TWithoutConst*>(m_RawPointer);
         nonConstPointer->RemoveObserver(m_ObserverTag);
       }
     }
 
     void OnDeleteEvent() noexcept
     {
       // Don't remove any observers from the observed object as it is about to
       // die and can't handle this operation anymore.
 
       m_RawPointer = nullptr;
 
       if (m_DeleteEventCallback)
         m_DeleteEventCallback();
     }
 
     // The following comparison operators need access to class internals.
     // All remaining comparison operators are implemented as non-member
     // non-friend functions that use logical combinations of these non-member
     // friend functions.
 
     friend bool operator ==(const WeakPointer &left, const WeakPointer &right) noexcept
     {
       return left.m_RawPointer == right.m_RawPointer;
     }
 
     // Also covers comparisons to T::Pointer and T::ConstPointer as
     // itk::SmartPointer can be implicitly converted to a raw pointer.
     friend bool operator ==(const WeakPointer &left, const T *right) noexcept
     {
       return left.m_RawPointer == right;
     }
 
     friend bool operator <(const WeakPointer &left, const WeakPointer &right) noexcept
     {
       // The specialization of std::less for any pointer type yields a total
       // order, even if the built-in operator < doesn't.
       return std::less<T*>()(left.m_RawPointer, right.m_RawPointer);
     }
 
     friend bool operator <(const WeakPointer &left, std::nullptr_t right) noexcept
     {
       return std::less<T*>()(left.m_RawPointer, right);
     }
 
     friend bool operator <(std::nullptr_t left, const WeakPointer &right) noexcept
     {
       return std::less<T*>()(left, right.m_RawPointer);
     }
 
     friend bool operator <(const WeakPointer &left, const T *right) noexcept
     {
       return std::less<T*>()(left.m_RawPointer, right);
     }
 
     friend bool operator <(const T *left, const WeakPointer &right) noexcept
     {
       return std::less<T*>()(left, right.m_RawPointer);
     }
 
     T *m_RawPointer;
 
     // m_ObserverTag is completely managed by the two methods
     // AddDeleteEventObserver() and RemoveDeleteEventObserver(). There
     // isn't any need to initialize or use it at all outside of these methods.
     unsigned long m_ObserverTag;
 
     DeleteEventCallbackType m_DeleteEventCallback;
   };
 }
 
 template <class T>
 bool operator !=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(left == right);
 }
 
 template <class T>
 bool operator <=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(right < left);
 }
 
 template <class T>
 bool operator >(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
 {
   return right < left;
 }
 
 template <class T>
 bool operator >=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(left < right);
 }
 
 template <class T>
 bool operator ==(const mitk::WeakPointer<T> &left, std::nullptr_t) noexcept
 {
   return !left;
 }
 
 template <class T>
 bool operator !=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
 {
   return !(left == right);
 }
 
 template <class T>
 bool operator ==(std::nullptr_t, const mitk::WeakPointer<T> &right) noexcept
 {
   return !right;
 }
 
 template <class T>
 bool operator !=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(left == right);
 }
 
 template <class T>
 bool operator <=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
 {
   return !(right < left);
 }
 
 template <class T>
 bool operator >(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
 {
   return right < left;
 }
 
 template <class T>
 bool operator >=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
 {
   return !(left < right);
 }
 
 template <class T>
 bool operator <=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(right < left);
 }
 
 template <class T>
 bool operator >(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
 {
   return right < left;
 }
 
 template <class T>
 bool operator >=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(left < right);
 }
 
 template <class T>
 bool operator !=(const mitk::WeakPointer<T> &left, const T *right) noexcept
 {
   return !(left == right);
 }
 
 template <class T>
 bool operator <=(const mitk::WeakPointer<T> &left, const T *right) noexcept
 {
   return !(right < left);
 }
 
 template <class T>
 bool operator >(const mitk::WeakPointer<T> &left, const T *right) noexcept
 {
   return right < left;
 }
 
 template <class T>
 bool operator >=(const mitk::WeakPointer<T> &left, const T *right) noexcept
 {
   return !(left < right);
 }
 
 template <class T>
 bool operator ==(const T *left, const mitk::WeakPointer<T> &right) noexcept
 {
   return right == left;
 }
 
 template <class T>
 bool operator !=(const T *left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(right == left);
 }
 
 template <class T>
 bool operator <=(const T *left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(right < left);
 }
 
 template <class T>
 bool operator >(const T *left, const mitk::WeakPointer<T> &right) noexcept
 {
   return right < left;
 }
 
 template <class T>
 bool operator >=(const T *left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(left < right);
 }
 
 template <class T>
 bool operator !=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
 {
   return !(left == right);
 }
 
 template <class T>
 bool operator <=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
 {
   return !(right < left);
 }
 
 template <class T>
 bool operator >(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
 {
   return right < left;
 }
 
 template <class T>
 bool operator >=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
 {
   return !(left < right);
 }
 
 template <class T>
 bool operator ==(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
 {
   return right == left;
 }
 
 template <class T>
 bool operator !=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(right == left);
 }
 
 template <class T>
 bool operator <=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(right < left);
 }
 
 template <class T>
 bool operator >(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
 {
   return right < left;
 }
 
 template <class T>
 bool operator >=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
 {
   return !(left < right);
 }
 
 #endif
diff --git a/Modules/Multilabel/Testing/mitkLabelSetImageTest.cpp b/Modules/Multilabel/Testing/mitkLabelSetImageTest.cpp
index 32fc677470..e71358bd70 100644
--- a/Modules/Multilabel/Testing/mitkLabelSetImageTest.cpp
+++ b/Modules/Multilabel/Testing/mitkLabelSetImageTest.cpp
@@ -1,663 +1,664 @@
 /*============================================================================
 
 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 <mitkIOUtil.h>
 #include <mitkImageStatisticsHolder.h>
 #include <mitkLabelSetImage.h>
+#include <mitkLabelSetImageConverter.h>
 #include <mitkTestFixture.h>
 #include <mitkTestingMacros.h>
 
 #include <mitkAutoCropImageFilter.h>
 
 namespace CppUnit
 {
   namespace StringHelper
   {
     template<> inline std::string toString(const mitk::LabelSetImage::LabelValueVectorType& lvs)
     {
       std::ostringstream stream;
       stream << "[";
       for (mitk::LabelSetImage::LabelValueVectorType::const_iterator iter = lvs.begin(); iter!=lvs.end(); ++iter)
       {
         stream << *iter;
         if (iter + 1 != lvs.end()) stream << ", ";
 
       }
       stream << "]";
       return stream.str();
     }
 
     template<> inline std::string toString(const std::vector<std::string>& strings)
     {
       std::ostringstream stream;
       stream << "[";
       for (std::vector<std::string>::const_iterator iter = strings.begin(); iter != strings.end(); ++iter)
       {
         stream << *iter;
         if (iter + 1 != strings.end()) stream << ", ";
 
       }
       stream << "]";
       return stream.str();
     }
 
   }
 }
 
 class mitkLabelSetImageTestSuite : public mitk::TestFixture
 {
   CPPUNIT_TEST_SUITE(mitkLabelSetImageTestSuite);
   MITK_TEST(TestInitialize);
   MITK_TEST(TestClone);
   MITK_TEST(TestAddLayer);
   MITK_TEST(TestGetActiveLabelSet);
   MITK_TEST(TestGetActiveLabel);
   MITK_TEST(TestInitializeByLabeledImage);
   MITK_TEST(TestGetLabel);
   MITK_TEST(TestGetLabelValues);
   MITK_TEST(TestGetLabelClassNames);
   MITK_TEST(TestSetUnlabeledLabelLock);
   MITK_TEST(TestGetTotalNumberOfLabels);
   MITK_TEST(TestGetNumberOfLabels);
   MITK_TEST(TestExistsLabel);
   MITK_TEST(TestExistsGroup);
   MITK_TEST(TestSetActiveLayer);
   MITK_TEST(TestRemoveLayer);
   MITK_TEST(TestRemoveLabels);
   MITK_TEST(TestEraseLabels);
   MITK_TEST(TestMergeLabels);
   MITK_TEST(TestCreateLabelMask);
   CPPUNIT_TEST_SUITE_END();
 
 private:
   mitk::LabelSetImage::Pointer m_LabelSetImage;
   int m_LabelAddedEventCount;
   int m_LabelModifiedEventCount;
   int m_LabelRemovedEventCount;
   int m_LabelsChangedEventCount;
   int m_GroupAddedEventCount;
   int m_GroupModifiedEventCount;
   int m_GroupRemovedEventCount;
 
 public:
   void setUp() override
   {
     // Create a new labelset image
     m_LabelSetImage = mitk::LabelSetImage::New();
     mitk::Image::Pointer regularImage = mitk::Image::New();
     unsigned int dimensions[3] = { 96, 128, 52 };
     regularImage->Initialize(mitk::MakeScalarPixelType<char>(), 3, dimensions);
     m_LabelSetImage->Initialize(regularImage);
 
     this->ResetEvents();
     m_LabelSetImage->AddObserver(mitk::LabelAddedEvent(), [this](const itk::EventObject&) { ++(this->m_LabelAddedEventCount); });
     m_LabelSetImage->AddObserver(mitk::LabelModifiedEvent(), [this](const itk::EventObject&) { ++(this->m_LabelModifiedEventCount); });
     m_LabelSetImage->AddObserver(mitk::LabelRemovedEvent(), [this](const itk::EventObject&) { ++(this->m_LabelRemovedEventCount); });
     m_LabelSetImage->AddObserver(mitk::LabelsChangedEvent(), [this](const itk::EventObject&) { ++(this->m_LabelsChangedEventCount); });
     m_LabelSetImage->AddObserver(mitk::GroupAddedEvent(), [this](const itk::EventObject&) { ++(this->m_GroupAddedEventCount); });
     m_LabelSetImage->AddObserver(mitk::GroupModifiedEvent(), [this](const itk::EventObject&) { ++(this->m_GroupModifiedEventCount); });
     m_LabelSetImage->AddObserver(mitk::GroupRemovedEvent(), [this](const itk::EventObject&) { ++(this->m_GroupRemovedEventCount); });
   }
 
   void tearDown() override
   {
     // Delete LabelSetImage
     m_LabelSetImage = nullptr;
   }
 
   void ResetEvents()
   {
     m_LabelAddedEventCount = 0;
     m_LabelModifiedEventCount = 0;
     m_LabelRemovedEventCount = 0;
     m_LabelsChangedEventCount = 0;
     m_GroupAddedEventCount = 0;
     m_GroupModifiedEventCount = 0;
     m_GroupRemovedEventCount = 0;
   }
 
   bool CheckEvents(int lAdd, int lMod, int lRem, int lsC, int gAdd, int gMod, int gRem)
   {
     return m_GroupAddedEventCount == gAdd && m_GroupModifiedEventCount == gMod && m_GroupRemovedEventCount == gRem
       && m_LabelAddedEventCount == lAdd && m_LabelModifiedEventCount == lMod && m_LabelRemovedEventCount == lRem
       && m_LabelsChangedEventCount == lsC;
   }
 
   void InitializeTestSegmentation()
   {
     mitk::Label::Pointer label1 = mitk::Label::New(1, "Label1");
     mitk::Label::Pointer label2 = mitk::Label::New(20, "Label2");
     mitk::Label::Pointer label22 = mitk::Label::New(22, "Label2");
     mitk::Label::Pointer label3 = mitk::Label::New(30, "Label3");
 
     m_LabelSetImage->AddLabel(label1, 0);
     m_LabelSetImage->AddLayer({ label2, label22, label3 });
     m_LabelSetImage->AddLayer();
     this->ResetEvents();
   }
 
   void TestInitialize()
   {
     // LabelSet image should always has the pixel type mitk::Label::PixelType
     CPPUNIT_ASSERT_MESSAGE("LabelSetImage has wrong pixel type",
                            m_LabelSetImage->GetPixelType() == mitk::MakeScalarPixelType<mitk::Label::PixelType>());
 
     mitk::Image::Pointer regularImage = mitk::Image::New();
     unsigned int dimensions[3] = { 96, 128, 52 };
     regularImage->Initialize(mitk::MakeScalarPixelType<char>(), 3, dimensions);
 
     mitk::BaseGeometry::Pointer regularImageGeo = regularImage->GetGeometry();
     mitk::BaseGeometry::Pointer labelImageGeo = m_LabelSetImage->GetGeometry();
     MITK_ASSERT_EQUAL(labelImageGeo, regularImageGeo, "LabelSetImage has wrong geometry");
 
     // By default one layer should be added
     CPPUNIT_ASSERT_MESSAGE("Image was not correctly initialized - number of layers is not one",
                            m_LabelSetImage->GetNumberOfLayers() == 1);
     CPPUNIT_ASSERT_MESSAGE("Image was not correctly initialized - active layer has wrong ID",
                            m_LabelSetImage->GetActiveLayer() == 0);
 
     CPPUNIT_ASSERT_MESSAGE("Image was not correctly initialized - no active label should be selected",
                            m_LabelSetImage->GetActiveLabel() == nullptr);
   }
 
   void TestClone()
   {
     mitk::Label::Pointer label1 = mitk::Label::New();
     label1->SetName("Label1");
     label1->SetValue(1);
 
     mitk::Label::Pointer label2 = mitk::Label::New();
     label2->SetName("Label2");
     label2->SetValue(200);
 
     mitk::Label::Pointer label3 = mitk::Label::New();
     label2->SetName("Label3");
     label2->SetValue(300);
 
     m_LabelSetImage->AddLabel(label1, 0);
     m_LabelSetImage->AddLayer({ label2, label3 });
 
     auto clone = m_LabelSetImage->Clone();
     MITK_ASSERT_EQUAL(m_LabelSetImage, clone, "LabelSetImage clone is not equal.");
   }
 
   void TestAddLayer()
   {
     CPPUNIT_ASSERT_MESSAGE("Number of layers is not zero", m_LabelSetImage->GetNumberOfLayers() == 1);
 
     m_LabelSetImage->AddLayer();
     CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - number of layers is not one",
                            m_LabelSetImage->GetNumberOfLayers() == 2);
     CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active layer has wrong ID",
                            m_LabelSetImage->GetActiveLayer() == 0);
 
     CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - no active label should be selected",
                            m_LabelSetImage->GetActiveLabel() == nullptr);
 
     CPPUNIT_ASSERT_MESSAGE("Event count incorrect", CheckEvents(0,0,0,0,1,0,0));
 
     mitk::Label::Pointer label1 = mitk::Label::New();
     label1->SetName("Label1");
     label1->SetValue(1);
 
     mitk::Label::Pointer label2 = mitk::Label::New();
     label2->SetName("Label2");
     label2->SetValue(200);
 
 
     const auto layerID = m_LabelSetImage->AddLayer({ label1, label2 });
     m_LabelSetImage->SetActiveLabel(200);
     CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - number of layers is not two",
                            m_LabelSetImage->GetNumberOfLayers() == 3);
     CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active layer has wrong ID",
                            m_LabelSetImage->GetActiveLayer() == layerID);
     CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active label is wrong",
                            m_LabelSetImage->GetActiveLabel()->GetValue() == 200);
 
     CPPUNIT_ASSERT_MESSAGE("Event count incorrect", CheckEvents(0, 0, 0, 0, 2, 0, 0));
   }
 
   void TestGetActiveLabelSet()
   {
     mitk::Label::Pointer label1 = mitk::Label::New();
     label1->SetName("Label1");
     label1->SetValue(1);
 
     mitk::Label::Pointer label2 = mitk::Label::New();
     label2->SetName("Label2");
     label2->SetValue(200);
 
     mitk::LabelSetImage::ConstLabelVectorType refLayer = { label1, label2 };
     unsigned int layerID = m_LabelSetImage->AddLayer(refLayer);
     m_LabelSetImage->SetActiveLabel(200);
 
     auto activeLayer = m_LabelSetImage->GetConstLabelsByValue(m_LabelSetImage->GetLabelValuesByGroup(m_LabelSetImage->GetActiveLayer()));
 
     CPPUNIT_ASSERT_MESSAGE("Wrong layer ID was returned", layerID == 1);
     CPPUNIT_ASSERT_MESSAGE("Wrong layer ID was returned", layerID == m_LabelSetImage->GetActiveLayer());
 
     CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned", mitk::Equal(refLayer, activeLayer, 0.00001, true));
   }
 
   void TestGetActiveLabel()
   {
     mitk::Label::Pointer label1 = mitk::Label::New();
     label1->SetName("Label1");
     mitk::Label::PixelType value1 = 1;
     label1->SetValue(value1);
 
     mitk::Label::Pointer label2 = mitk::Label::New();
     label2->SetName("Label2");
     mitk::Label::PixelType value2 = 200;
     label2->SetValue(value2);
 
     m_LabelSetImage->AddLabel(label1,0);
     m_LabelSetImage->AddLabel(label2,0);
     m_LabelSetImage->SetActiveLabel(1);
     CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active label is wrong",
                            m_LabelSetImage->GetActiveLabel()->GetValue() == value1);
     m_LabelSetImage->SetActiveLabel(value2);
     CPPUNIT_ASSERT_MESSAGE("Layer was not added correctly to image - active label is wrong",
                            m_LabelSetImage->GetActiveLabel()->GetValue() == value2);
 
     CPPUNIT_ASSERT_MESSAGE("Active Label was not correctly retreived with const getter",
       const_cast<const mitk::LabelSetImage*>(m_LabelSetImage.GetPointer())->GetActiveLabel()->GetValue() == value2);
 
   }
 
   void TestInitializeByLabeledImage()
   {
     mitk::Image::Pointer image =
       mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Multilabel/LabelSetTestInitializeImage.nrrd"));
     m_LabelSetImage->InitializeByLabeledImage(image);
     CPPUNIT_ASSERT_MESSAGE("Image - number of labels is not 5", m_LabelSetImage->GetNumberOfLabels(0) == 5);
   }
 
   void TestGetLabel()
   {
     mitk::Label::Pointer label1 = mitk::Label::New(1, "Label1");
     mitk::Label::Pointer label2 = mitk::Label::New(20,"Label2");
 
     m_LabelSetImage->AddLabel(label1,0);
     m_LabelSetImage->AddLayer();
     m_LabelSetImage->AddLabel(label2,1);
     this->ResetEvents();
 
     CPPUNIT_ASSERT_MESSAGE("Wrong label retrieved for active layer",
                            mitk::Equal(*m_LabelSetImage->GetLabel(1), *label1, 0.0001, true));
     CPPUNIT_ASSERT_MESSAGE("Wrong label retrieved for layer 1",
                            mitk::Equal(*m_LabelSetImage->GetLabel(20), *label2, 0.0001, true));
 
     // Try to get a non existing label
     mitk::Label *unkownLabel = m_LabelSetImage->GetLabel(1000);
     CPPUNIT_ASSERT_MESSAGE("Non existing label should be nullptr", unkownLabel == nullptr);
     CPPUNIT_ASSERT_MESSAGE("Event count incorrect", CheckEvents(0, 0, 0, 0, 0, 0, 0));
   }
 
   void TestGetLabelValues()
   {
     InitializeTestSegmentation();
 
     auto labels = m_LabelSetImage->GetLabelValuesByGroup(0);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for group 0",
       mitk::LabelSetImage::LabelValueVectorType({ 1 }), labels);
 
     labels = m_LabelSetImage->GetLabelValuesByGroup(1);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for group 1",
       mitk::LabelSetImage::LabelValueVectorType({ 20, 22, 30 }), labels);
 
     labels = m_LabelSetImage->GetLabelValuesByGroup(2);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for group 2",
       mitk::LabelSetImage::LabelValueVectorType(), labels);
 
     CPPUNIT_ASSERT_THROW(m_LabelSetImage->GetLabelValuesByGroup(3), mitk::Exception);
 
     labels = m_LabelSetImage->GetLabelValuesByName(0, "Label1");
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for \"Label2\" in group 0",
       mitk::LabelSetImage::LabelValueVectorType({ 1 }), labels);
 
     labels = m_LabelSetImage->GetLabelValuesByName(1, "Label2");
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for \"Label2\" in group 1",
       mitk::LabelSetImage::LabelValueVectorType({ 20, 22 }), labels);
 
     labels = m_LabelSetImage->GetLabelValuesByName(1, "Label3");
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for \"Label3\" in group 1",
       mitk::LabelSetImage::LabelValueVectorType({ 30 }), labels);
 
     labels = m_LabelSetImage->GetLabelValuesByName(2, "Label1");
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for group 2",
       mitk::LabelSetImage::LabelValueVectorType(), labels);
 
     labels = m_LabelSetImage->GetLabelValuesByName(0, "unkown");
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for unkown name",
       mitk::LabelSetImage::LabelValueVectorType(), labels);
 
     CPPUNIT_ASSERT_THROW(m_LabelSetImage->GetLabelValuesByName(3,"invalid"), mitk::Exception);
 
     labels = m_LabelSetImage->GetAllLabelValues();
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong label values retrieved for unkown name",
       mitk::LabelSetImage::LabelValueVectorType({1,20,22,30}), labels);
 
     CPPUNIT_ASSERT_MESSAGE("Event count incorrect", CheckEvents(0, 0, 0, 0, 0, 0, 0));
   }
 
 
   void TestGetLabelClassNames()
   {
     InitializeTestSegmentation();
 
     auto names = m_LabelSetImage->GetLabelClassNames();
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong names retrieved",
       std::vector<std::string>({ "Label1", "Label2", "Label3"}), names);
     names = m_LabelSetImage->GetLabelClassNamesByGroup(0);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong names retrieved for group 0",
       std::vector<std::string>({ "Label1"}), names);
     names = m_LabelSetImage->GetLabelClassNamesByGroup(1);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong names retrieved for group 1",
       std::vector<std::string>({"Label2", "Label3" }), names);
     names = m_LabelSetImage->GetLabelClassNamesByGroup(2);
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong names retrieved for group 2",
       std::vector<std::string>(), names);
 
     CPPUNIT_ASSERT_THROW(m_LabelSetImage->GetLabelValuesByGroup(3), mitk::Exception);
 
     CPPUNIT_ASSERT_MESSAGE("Event count incorrect", CheckEvents(0, 0, 0, 0, 0, 0, 0));
   }
 
   void TestSetUnlabeledLabelLock()
   {
     auto locked = m_LabelSetImage->GetUnlabeledLabelLock();
     CPPUNIT_ASSERT_MESSAGE("Wrong UnlabeledLabelLock default state",
       locked == false);
 
     m_LabelSetImage->SetUnlabeledLabelLock(true);
     locked = m_LabelSetImage->GetUnlabeledLabelLock();
     CPPUNIT_ASSERT_MESSAGE("Wrong UnlabeledLabelLock state",
       locked == true);
   }
 
   void TestGetTotalNumberOfLabels()
   {
     this->InitializeTestSegmentation();
     CPPUNIT_ASSERT_MESSAGE(
       "Wrong total number of labels",
       m_LabelSetImage->GetTotalNumberOfLabels() == 4);
     CPPUNIT_ASSERT_MESSAGE("Event count incorrect", CheckEvents(0, 0, 0, 0, 0, 0, 0));
   }
 
   void TestGetNumberOfLabels()
   {
     this->InitializeTestSegmentation();
     CPPUNIT_ASSERT_MESSAGE(
       "Wrong number of labels in group 0",
       m_LabelSetImage->GetNumberOfLabels(0) == 1);
     CPPUNIT_ASSERT_MESSAGE(
       "Wrong number of labels in group 1",
       m_LabelSetImage->GetNumberOfLabels(1) == 3);
     CPPUNIT_ASSERT_MESSAGE(
       "Wrong number of labels in group 2",
       m_LabelSetImage->GetNumberOfLabels(2) == 0);
 
     CPPUNIT_ASSERT_THROW(m_LabelSetImage->GetNumberOfLabels(3), mitk::Exception);
 
     CPPUNIT_ASSERT_MESSAGE("Event count incorrect", CheckEvents(0, 0, 0, 0, 0, 0, 0));
   }
 
   void TestExistsLabel()
   {
     mitk::Label::Pointer label = mitk::Label::New();
     label->SetName("Label2");
     mitk::Label::PixelType value = 200;
     label->SetValue(value);
 
     m_LabelSetImage->AddLayer();
     m_LabelSetImage->AddLabel(label,1);
     m_LabelSetImage->SetActiveLayer(0);
     CPPUNIT_ASSERT_MESSAGE("Existing label was not found", m_LabelSetImage->ExistLabel(value) == true);
 
     CPPUNIT_ASSERT_MESSAGE("Non existing label was found", m_LabelSetImage->ExistLabel(10000) == false);
   }
 
   void TestExistsGroup()
   {
     mitk::Label::Pointer label1 = mitk::Label::New();
     label1->SetName("Label1");
     label1->SetValue(1);
 
     mitk::Label::Pointer label2 = mitk::Label::New();
     label2->SetName("Label2");
     label2->SetValue(200);
 
     m_LabelSetImage->AddLayer({label1, label2});
 
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(0) == true);
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(1) == true);
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(20) == false);
   }
 
   void TestSetActiveLayer()
   {
     // Cache active layer
     auto refActiveLayer = m_LabelSetImage->GetConstLabelsByValue(m_LabelSetImage->GetLabelValuesByGroup(m_LabelSetImage->GetActiveLayer()));
 
     // Add new layer
     mitk::Label::Pointer label1 = mitk::Label::New();
     label1->SetName("Label1");
     label1->SetValue(1);
 
     mitk::Label::Pointer label2 = mitk::Label::New();
     label2->SetName("Label2");
     label2->SetValue(200);
 
     mitk::LabelSetImage::ConstLabelVectorType newlayer = { label1, label2 };
     unsigned int layerID = m_LabelSetImage->AddLayer(newlayer);
 
     // Set initial layer as active layer
     m_LabelSetImage->SetActiveLayer(0);
     auto activeLayer = m_LabelSetImage->GetConstLabelsByValue(m_LabelSetImage->GetLabelValuesByGroup(m_LabelSetImage->GetActiveLayer()));
     CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned",
                            mitk::Equal(refActiveLayer, activeLayer, 0.00001, true));
 
     // Set previously added layer as active layer
     m_LabelSetImage->SetActiveLayer(layerID);
     activeLayer = m_LabelSetImage->GetConstLabelsByValue(m_LabelSetImage->GetLabelValuesByGroup(m_LabelSetImage->GetActiveLayer()));
     CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned",
                            mitk::Equal(newlayer, activeLayer, 0.00001, true));
 
     // Set a non existing layer as active layer - nothing should change
     m_LabelSetImage->SetActiveLayer(10000);
     CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned",
                            mitk::Equal(newlayer, activeLayer, 0.00001, true));
   }
 
   void TestRemoveLayer()
   {
     // Cache active layer
     auto refActiveLayer = m_LabelSetImage->GetConstLabelsByValue(m_LabelSetImage->GetLabelValuesByGroup(m_LabelSetImage->GetActiveLayer()));
 
     // Add new layers
     m_LabelSetImage->AddLayer();
 
     mitk::Label::Pointer label1 = mitk::Label::New();
     label1->SetName("Label1");
     label1->SetValue(1);
 
     mitk::Label::Pointer label2 = mitk::Label::New();
     label2->SetName("Label2");
     label2->SetValue(200);
 
     mitk::LabelSetImage::ConstLabelVectorType newlayer = { label1, label2 };
     unsigned int layerID = m_LabelSetImage->AddLayer(newlayer);
     m_LabelSetImage->SetActiveLayer(layerID);
 
     auto activeLayer = m_LabelSetImage->GetConstLabelsByValue(m_LabelSetImage->GetLabelValuesByGroup(m_LabelSetImage->GetActiveLayer()));
     CPPUNIT_ASSERT_MESSAGE("Wrong active labelset returned",
                            mitk::Equal(newlayer, activeLayer, 0.00001, true));
 
     m_LabelSetImage->RemoveGroup(1);
     CPPUNIT_ASSERT_MESSAGE("Wrong number of layers, after a layer was removed",
                            m_LabelSetImage->GetNumberOfLayers() == 2);
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(2) == false);
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(1) == true);
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(0) == true);
 
     m_LabelSetImage->RemoveGroup(1);
     activeLayer = m_LabelSetImage->GetConstLabelsByValue(m_LabelSetImage->GetLabelValuesByGroup(m_LabelSetImage->GetActiveLayer()));
     CPPUNIT_ASSERT_MESSAGE("Wrong number of layers, after a layer was removed",
                            m_LabelSetImage->GetNumberOfLayers() == 1);
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(1) == false);
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(0) == true);
     CPPUNIT_ASSERT_MESSAGE("Wrong active layer",
                            mitk::Equal(refActiveLayer, activeLayer, 0.00001, true));
 
     m_LabelSetImage->RemoveGroup(0);
     CPPUNIT_ASSERT_MESSAGE("Wrong number of layers, after a layer was removed",
                            m_LabelSetImage->GetNumberOfLayers() == 0);
     CPPUNIT_ASSERT_MESSAGE("Check for existing layer failed", m_LabelSetImage->ExistGroup(0) == false);
     CPPUNIT_ASSERT_THROW_MESSAGE("GetActiveLayers does not fail although all layer have been removed",
                            m_LabelSetImage->GetActiveLayer(), mitk::Exception);
   }
 
   void TestRemoveLabels()
   {
     mitk::Image::Pointer image =
       mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Multilabel/LabelSetTestInitializeImage.nrrd"));
 
     m_LabelSetImage = nullptr;
     m_LabelSetImage = mitk::LabelSetImage::New();
     m_LabelSetImage->InitializeByLabeledImage(image);
 
     CPPUNIT_ASSERT_MESSAGE("Image - number of labels is not 6", m_LabelSetImage->GetNumberOfLabels(0) == 5);
     // 2ndMin because of unlabeled pixels = 0
     CPPUNIT_ASSERT_MESSAGE("Wrong MIN value", m_LabelSetImage->GetStatistics()->GetScalarValue2ndMin() == 1);
     CPPUNIT_ASSERT_MESSAGE("Wrong MAX value", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 7);
 
     CPPUNIT_ASSERT_MESSAGE("Label with ID 3 does not exist after initialization",
                            m_LabelSetImage->ExistLabel(3) == true);
 
     m_LabelSetImage->RemoveLabel(1);
     std::vector<mitk::Label::PixelType> labelsToBeRemoved;
     labelsToBeRemoved.push_back(3);
     labelsToBeRemoved.push_back(7);
     m_LabelSetImage->RemoveLabels(labelsToBeRemoved);
 
     CPPUNIT_ASSERT_MESSAGE("Wrong number of labels after some have been removed",
                            m_LabelSetImage->GetNumberOfLabels(0) == 2);
     // Values within the image are 0, 1, 3, 5, 6, 7 - New Min / Max value should be 5 / 6
     // 2ndMin because of unlabeled pixels = 0
     CPPUNIT_ASSERT_MESSAGE("Labels with value 1 and 3 were not removed from the image",
                            m_LabelSetImage->GetStatistics()->GetScalarValue2ndMin() == 5);
     CPPUNIT_ASSERT_MESSAGE("Label with value 7 was not removed from the image",
                            m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 6);
   }
 
   void TestEraseLabels()
   {
     mitk::Image::Pointer image =
       mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Multilabel/LabelSetTestInitializeImage.nrrd"));
 
     m_LabelSetImage = nullptr;
     m_LabelSetImage = mitk::LabelSetImage::New();
     m_LabelSetImage->InitializeByLabeledImage(image);
 
     CPPUNIT_ASSERT_MESSAGE("Image - number of labels is not 6", m_LabelSetImage->GetNumberOfLabels(0) == 5);
     // 2ndMin because of unlabeled pixels = 0
     CPPUNIT_ASSERT_MESSAGE("Wrong MIN value", m_LabelSetImage->GetStatistics()->GetScalarValue2ndMin() == 1);
     CPPUNIT_ASSERT_MESSAGE("Wrong MAX value", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 7);
 
     CPPUNIT_ASSERT_MESSAGE("Label with ID 3 does not exist after initialization",
       m_LabelSetImage->ExistLabel(3) == true);
 
     m_LabelSetImage->EraseLabel(1);
     std::vector<mitk::Label::PixelType> labelsToBeErased;
     labelsToBeErased.push_back(3);
     labelsToBeErased.push_back(7);
     m_LabelSetImage->EraseLabels(labelsToBeErased);
 
     CPPUNIT_ASSERT_MESSAGE("Wrong number of labels since none have been removed",
       m_LabelSetImage->GetNumberOfLabels(0) == 5);
     // Values within the image are 0, 1, 3, 5, 6, 7 - New Min / Max value should be 5 / 6
     // 2ndMin because of unlabeled pixels = 0
     CPPUNIT_ASSERT_MESSAGE("Labels with value 1 and 3 were not erased from the image",
       m_LabelSetImage->GetStatistics()->GetScalarValue2ndMin() == 5);
     CPPUNIT_ASSERT_MESSAGE("Label with value 7 was not erased from the image",
       m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 6);
   }
 
   void TestMergeLabels()
   {
     mitk::Image::Pointer image =
       mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Multilabel/LabelSetTestInitializeImage.nrrd"));
 
     m_LabelSetImage = nullptr;
     m_LabelSetImage = mitk::LabelSetImage::New();
     m_LabelSetImage->InitializeByLabeledImage(image);
 
     CPPUNIT_ASSERT_MESSAGE("Image - number of labels is not 6", m_LabelSetImage->GetNumberOfLabels(0) == 5);
     // 2ndMin because of unlabeled pixels = 0
     CPPUNIT_ASSERT_MESSAGE("Wrong MIN value", m_LabelSetImage->GetStatistics()->GetScalarValue2ndMin() == 1);
     CPPUNIT_ASSERT_MESSAGE("Wrong MAX value", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 7);
 
     CPPUNIT_ASSERT_MESSAGE("Label with ID 6 does not exist after initialization",
       m_LabelSetImage->ExistLabel(6) == true);
 
     // Merge label 7 with label 6. Result should be that label 7 is not present anymore.
     m_LabelSetImage->MergeLabel(6, 7);
     CPPUNIT_ASSERT_MESSAGE("Label with value 7 was not removed from the image", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 6);
 
     // Count all pixels with value 6 = 507
     // Count all pixels with value 7 = 823
     // Check if merged label has 507 + 823 = 1330 pixels
     CPPUNIT_ASSERT_MESSAGE("Labels were not correctly merged", m_LabelSetImage->GetStatistics()->GetCountOfMaxValuedVoxels() == 1330);
 
     CPPUNIT_ASSERT_MESSAGE("Label with ID 3 does not exist after initialization",
       m_LabelSetImage->ExistLabel(3) == true);
     CPPUNIT_ASSERT_MESSAGE("Label with ID 5 does not exist after initialization",
       m_LabelSetImage->ExistLabel(5) == true);
 
     // Merge labels 5 and 6 with 3. Result should be that labels 5 and 6 are not present anymore.
     std::vector<mitk::Label::PixelType> vectorOfSourcePixelValues{ 5, 6 };
     m_LabelSetImage->MergeLabels(3, vectorOfSourcePixelValues);
     // Values within the image are 0, 1, 3, 5, 6, 7 - New Max value should be 3
     CPPUNIT_ASSERT_MESSAGE("Labels with value 5 and 6 were not removed from the image", m_LabelSetImage->GetStatistics()->GetScalarValueMax() == 3);
 
     // Count all pixels with value 3 = 1893
     // Count all pixels with value 5 = 2143
     // Count all pixels with value 6 = 1330
     // Check if merged label has 1893 + 2143 + 1330 = 5366 pixels
     CPPUNIT_ASSERT_MESSAGE("Labels were not correctly merged", m_LabelSetImage->GetStatistics()->GetCountOfMaxValuedVoxels() == 5366);
   }
 
   void TestCreateLabelMask()
   {
     mitk::Image::Pointer image =
       mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("Multilabel/LabelSetTestInitializeImage.nrrd"));
 
     m_LabelSetImage = nullptr;
     m_LabelSetImage = mitk::LabelSetImage::New();
     m_LabelSetImage->InitializeByLabeledImage(image);
 
-    auto labelMask = m_LabelSetImage->CreateLabelMask(6);
+    auto labelMask = mitk::CreateLabelMask(m_LabelSetImage,6);
 
     mitk::AutoCropImageFilter::Pointer cropFilter = mitk::AutoCropImageFilter::New();
     cropFilter->SetInput(labelMask);
     cropFilter->SetBackgroundValue(0);
     cropFilter->SetMarginFactor(1.15);
     cropFilter->Update();
     auto maskImage = cropFilter->GetOutput();
 
     // Count all pixels with value 6 = 507
     CPPUNIT_ASSERT_MESSAGE("Label mask not correctly created", maskImage->GetStatistics()->GetCountOfMaxValuedVoxels() == 507);
   }
 };
 
 MITK_TEST_SUITE_REGISTRATION(mitkLabelSetImage)
diff --git a/Modules/Multilabel/files.cmake b/Modules/Multilabel/files.cmake
index 950a2a736f..3253bf602b 100644
--- a/Modules/Multilabel/files.cmake
+++ b/Modules/Multilabel/files.cmake
@@ -1,21 +1,22 @@
 set(CPP_FILES
   mitkLabel.cpp
   mitkLabelSetImage.cpp
   mitkLabelSetImageConverter.cpp
   mitkLabelSetImageSource.cpp
   mitkLabelSetImageHelper.cpp
   mitkLabelSetImageSurfaceStampFilter.cpp
   mitkLabelSetImageToSurfaceFilter.cpp
   mitkLabelSetImageToSurfaceThreadedFilter.cpp
   mitkLabelSetImageVtkMapper2D.cpp
   mitkMultilabelObjectFactory.cpp
   mitkMultiLabelIOHelper.cpp
   mitkMultiLabelEvents.cpp
+  mitkMultiLabelPredicateHelper.cpp
   mitkDICOMSegmentationPropertyHelper.cpp
   mitkDICOMSegmentationConstants.cpp
   mitkSegmentationTaskList.cpp
 )
 
 set(RESOURCE_FILES
 
 )
diff --git a/Modules/Multilabel/mitkLabel.cpp b/Modules/Multilabel/mitkLabel.cpp
index e71e6c3b7a..5499525fae 100644
--- a/Modules/Multilabel/mitkLabel.cpp
+++ b/Modules/Multilabel/mitkLabel.cpp
@@ -1,309 +1,309 @@
 /*============================================================================
 
 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 "mitkLabel.h"
 
 #include "itkProcessObject.h"
 #include <itkCommand.h>
 #include <mitkProperties.h>
 #include <mitkDICOMSegmentationPropertyHelper.h>
 #include <mitkStringProperty.h>
 
 const mitk::Label::PixelType mitk::Label::MAX_LABEL_VALUE = std::numeric_limits<mitk::Label::PixelType>::max();
 
 mitk::Label::Label() : PropertyList()
 {
   if (GetProperty("locked") == nullptr)
     SetLocked(true);
   if (GetProperty("visible") == nullptr)
     SetVisible(true);
   if (GetProperty("opacity") == nullptr)
     SetOpacity(0.6);
   if (GetProperty("center.coordinates") == nullptr)
   {
     mitk::Point3D pnt;
     pnt.SetElement(0, 0);
     pnt.SetElement(1, 0);
     pnt.SetElement(2, 0);
     SetCenterOfMassCoordinates(pnt);
   }
   if (GetProperty("center.index") == nullptr)
   {
     mitk::Point3D pnt;
     pnt.SetElement(0, 0);
     pnt.SetElement(1, 0);
     pnt.SetElement(2, 0);
     SetCenterOfMassIndex(pnt);
   }
   if (GetProperty("color") == nullptr)
   {
     mitk::Color col;
     col.Set(0, 0, 0);
     SetColor(col);
   }
   if (GetProperty("name") == nullptr)
     SetName("noName!");
   if (GetProperty("value") == nullptr)
     SetValue(0);
   if (GetProperty("layer") == nullptr)
     SetLayer(0);
 
   DICOMSegmentationPropertyHelper::SetDICOMSegmentProperties(this);
 }
 
 mitk::Label::Label(PixelType value, const std::string& name) : Label()
 {
   this->SetValue(value);
   this->SetName(name);
 }
 
 mitk::Label::Label(const Label &other) : PropertyList(other)
-// copyconstructer of property List handles the coping action
+// copy constructor of property List handles the coping action
 {
   auto *map = this->GetMap();
   auto it = map->begin();
   auto end = map->end();
 
   for (; it != end; ++it)
   {
     itk::SimpleMemberCommand<Label>::Pointer command = itk::SimpleMemberCommand<Label>::New();
     command->SetCallbackFunction(this, &Label::Modified);
     it->second->AddObserver(itk::ModifiedEvent(), command);
   }
 }
 
 mitk::Label::~Label()
 {
 }
 
 void mitk::Label::SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName, bool fallBackOnDefaultContext)
 {
   itk::SimpleMemberCommand<Label>::Pointer command = itk::SimpleMemberCommand<Label>::New();
   command->SetCallbackFunction(this, &Label::Modified);
   property->AddObserver(itk::ModifiedEvent(), command);
 
   Superclass::SetProperty(propertyKey, property, contextName, fallBackOnDefaultContext);
 }
 
 void mitk::Label::SetLocked(bool locked)
 {
   mitk::BoolProperty *property = dynamic_cast<mitk::BoolProperty *>(GetProperty("locked"));
   if (property != nullptr)
     // Update Property
     property->SetValue(locked);
   else
     // Create new Property
     SetBoolProperty("locked", locked);
 }
 
 bool mitk::Label::GetLocked() const
 {
   bool locked;
   GetBoolProperty("locked", locked);
   return locked;
 }
 
 void mitk::Label::SetVisible(bool visible)
 {
   mitk::BoolProperty *property = dynamic_cast<mitk::BoolProperty *>(GetProperty("visible"));
   if (property != nullptr)
     // Update Property
     property->SetValue(visible);
   else
     // Create new Property
     SetBoolProperty("visible", visible);
 }
 
 bool mitk::Label::GetVisible() const
 {
   bool visible;
   GetBoolProperty("visible", visible);
   return visible;
 }
 
 void mitk::Label::SetOpacity(float opacity)
 {
   mitk::FloatProperty *property = dynamic_cast<mitk::FloatProperty *>(GetProperty("opacity"));
   if (property != nullptr)
     // Update Property
     property->SetValue(opacity);
   else
     // Create new Property
     SetFloatProperty("opacity", opacity);
 }
 
 float mitk::Label::GetOpacity() const
 {
   float opacity;
   GetFloatProperty("opacity", opacity);
   return opacity;
 }
 
 void mitk::Label::SetName(const std::string &name)
 {
   SetStringProperty("name", name.c_str());
 }
 
 std::string mitk::Label::GetName() const
 {
   std::string name;
   GetStringProperty("name", name);
   return name;
 }
 
 std::string mitk::Label::GetTrackingID() const
 {
   return std::to_string(this->GetValue());
 }
 
 void mitk::Label::SetValue(PixelType pixelValue)
 {
   mitk::UShortProperty *property = dynamic_cast<mitk::UShortProperty *>(GetProperty("value"));
   if (property != nullptr)
     // Update Property
     property->SetValue(pixelValue);
   else
     // Create new Property
     SetProperty("value", mitk::UShortProperty::New(pixelValue));
 }
 
 mitk::Label::PixelType mitk::Label::GetValue() const
 {
   PixelType pixelValue;
   mitk::UShortProperty *property = dynamic_cast<UShortProperty *>(GetProperty("value"));
   assert(property);
   pixelValue = property->GetValue();
   return pixelValue;
 }
 
 void mitk::Label::SetLayer(unsigned int layer)
 {
   mitk::UIntProperty *property = dynamic_cast<mitk::UIntProperty *>(GetProperty("layer"));
   if (property != nullptr)
     // Update Property
     property->SetValue(layer);
   else
     // Create new Property
     SetProperty("layer", mitk::UIntProperty::New(layer));
 }
 
 unsigned int mitk::Label::GetLayer() const
 {
   unsigned int layer;
   mitk::UIntProperty *prop = dynamic_cast<mitk::UIntProperty *>(GetProperty("layer"));
   layer = prop->GetValue();
   return layer;
 }
 
 const mitk::Color &mitk::Label::GetColor() const
 {
   mitk::ColorProperty *colorProp = dynamic_cast<mitk::ColorProperty *>(GetProperty("color"));
   return colorProp->GetColor();
 }
 
 void mitk::Label::SetColor(const mitk::Color &_color)
 {
   mitk::ColorProperty *colorProp = dynamic_cast<mitk::ColorProperty *>(GetProperty("color"));
   if (colorProp != nullptr)
     // Update Property
     colorProp->SetColor(_color);
   else
     // Create new Property
     SetProperty("color", mitk::ColorProperty::New(_color));
 }
 
 void mitk::Label::SetCenterOfMassIndex(const mitk::Point3D &center)
 {
   mitk::Point3dProperty *property = dynamic_cast<mitk::Point3dProperty *>(GetProperty("center.index"));
   if (property != nullptr)
     // Update Property
     property->SetValue(center);
   else
     // Create new Property
     SetProperty("center.index", mitk::Point3dProperty::New(center));
 }
 
 mitk::Point3D mitk::Label::GetCenterOfMassIndex() const
 {
   mitk::Point3dProperty *property = dynamic_cast<mitk::Point3dProperty *>(GetProperty("center.index"));
   return property->GetValue();
 }
 
 void mitk::Label::SetCenterOfMassCoordinates(const mitk::Point3D &center)
 {
   mitk::Point3dProperty *property = dynamic_cast<mitk::Point3dProperty *>(GetProperty("center.coordinates"));
   if (property != nullptr)
     // Update Property
     property->SetValue(center);
   else
     // Create new Property
     SetProperty("center.coordinates", mitk::Point3dProperty::New(center));
 }
 
 mitk::Point3D mitk::Label::GetCenterOfMassCoordinates() const
 {
   mitk::Point3dProperty *property = dynamic_cast<mitk::Point3dProperty *>(GetProperty("center.coordinates"));
   return property->GetValue();
 }
 
 itk::LightObject::Pointer mitk::Label::InternalClone() const
 {
   itk::LightObject::Pointer result(new Self(*this));
   result->UnRegister();
   return result;
 }
 
 void mitk::Label::PrintSelf(std::ostream & /*os*/, itk::Indent /*indent*/) const
 {
   // todo
 }
 
 bool mitk::Equal(const mitk::Label &leftHandSide, const mitk::Label &rightHandSide, ScalarType /*eps*/, bool verbose)
 {
   MITK_INFO(verbose) << "--- Label Equal ---";
 
   bool returnValue = true;
   // have to be replaced until a PropertyList Equal was implemented :
   // returnValue = mitk::Equal((const mitk::PropertyList &)leftHandSide,(const mitk::PropertyList
   // &)rightHandSide,eps,verbose);
 
   const mitk::PropertyList::PropertyMap *lhsmap = leftHandSide.GetMap();
   const mitk::PropertyList::PropertyMap *rhsmap = rightHandSide.GetMap();
 
   returnValue = lhsmap->size() == rhsmap->size();
 
   if (!returnValue)
   {
     MITK_INFO(verbose) << "Labels in label container are not equal.";
     return returnValue;
   }
 
   auto lhsmapIt = lhsmap->begin();
   auto lhsmapItEnd = lhsmap->end();
 
   for (; lhsmapIt != lhsmapItEnd; ++lhsmapIt)
   {
     if (rhsmap->find(lhsmapIt->first) == rhsmap->end())
     {
       returnValue = false;
       break;
     }
   }
 
   if (!returnValue)
   {
     MITK_INFO(verbose) << "Labels in label container are not equal.";
     return returnValue;
   }
 
   return returnValue;
 }
diff --git a/Modules/Multilabel/mitkLabelSetImage.cpp b/Modules/Multilabel/mitkLabelSetImage.cpp
index 62a34446f4..4bdd077127 100644
--- a/Modules/Multilabel/mitkLabelSetImage.cpp
+++ b/Modules/Multilabel/mitkLabelSetImage.cpp
@@ -1,1651 +1,1700 @@
 /*============================================================================
 
 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 "mitkLabelSetImage.h"
 
 #include <mitkImageAccessByItk.h>
 #include <mitkImageCast.h>
 #include <mitkImagePixelWriteAccessor.h>
 #include <mitkPadImageFilter.h>
 #include <mitkDICOMSegmentationPropertyHelper.h>
 #include <mitkDICOMQIPropertyHelper.h>
+#include <mitkNodePredicateGeometry.h>
 
 #include <itkLabelGeometryImageFilter.h>
 #include <itkCommand.h>
 #include <itkBinaryFunctorImageFilter.h>
 
 
 namespace mitk
 {
   template <typename ImageType>
   void ClearBufferProcessing(ImageType* itkImage)
   {
     itkImage->FillBuffer(0);
   }
 
   void ClearImageBuffer(mitk::Image* image)
   {
     if (image->GetDimension() == 4)
     { //remark: this extra branch was added, because LabelSetImage instances can be
       //dynamic (4D), but AccessByItk by support only supports 2D and 3D.
       //The option to change the CMake default dimensions for AccessByItk was
       //dropped (for details see discussion in T28756)
       AccessFixedDimensionByItk(image, ClearBufferProcessing, 4);
     }
     else
     {
       AccessByItk(image, ClearBufferProcessing);
     }
   }
 }
 
 const mitk::LabelSetImage::LabelValueType mitk::LabelSetImage::UNLABELED_VALUE = 0;
 
 mitk::LabelSetImage::LabelSetImage()
   : mitk::Image(), m_ActiveLabelValue(0), m_UnlabeledLabelLock(false), m_ActiveLayer(0), m_activeLayerInvalid(false)
 {
   m_LookupTable = mitk::LookupTable::New();
   m_LookupTable->SetType(mitk::LookupTable::MULTILABEL);
 
   // Add some DICOM Tags as properties to segmentation image
   DICOMSegmentationPropertyHelper::DeriveDICOMSegmentationProperties(this);
 }
 
 mitk::LabelSetImage::LabelSetImage(const mitk::LabelSetImage &other)
   : Image(other),
     m_ActiveLabelValue(other.m_ActiveLabelValue),
     m_LookupTable(other.m_LookupTable->Clone()),
     m_UnlabeledLabelLock(other.m_UnlabeledLabelLock),
     m_ActiveLayer(other.GetActiveLayer()),
     m_activeLayerInvalid(false)
 {
   GroupIndexType i = 0;
   for (auto groupImage : other.m_LayerContainer)
   {
     this->AddLayer(groupImage->Clone(), other.GetConstLabelsByValue(other.GetLabelValuesByGroup(i)));
     i++;
   }
   m_Groups = other.m_Groups;
 
   // Add some DICOM Tags as properties to segmentation image
   DICOMSegmentationPropertyHelper::DeriveDICOMSegmentationProperties(this);
 }
 
 void mitk::LabelSetImage::Initialize(const mitk::Image *other)
 {
   mitk::PixelType pixelType(mitk::MakeScalarPixelType<LabelSetImage::PixelType>());
   if (other->GetDimension() == 2)
   {
     const unsigned int dimensions[] = {other->GetDimension(0), other->GetDimension(1), 1};
     Superclass::Initialize(pixelType, 3, dimensions);
   }
   else
   {
     Superclass::Initialize(pixelType, other->GetDimension(), other->GetDimensions());
   }
 
   auto originalGeometry = other->GetTimeGeometry()->Clone();
   this->SetTimeGeometry(originalGeometry);
 
   // initialize image memory to zero
   ClearImageBuffer(this);
 
   // Transfer some general DICOM properties from the source image to derived image (e.g. Patient information,...)
   DICOMQIPropertyHelper::DeriveDICOMSourceProperties(other, this);
 
   // Add a inital LabelSet ans corresponding image data to the stack
   if (this->GetNumberOfLayers() == 0)
   {
     AddLayer();
   }
 }
 
 mitk::LabelSetImage::~LabelSetImage()
 {
   for (auto [value, label] : m_LabelMap)
   {
     this->ReleaseLabel(label);
   }
   m_LabelMap.clear();
 }
 
 unsigned int mitk::LabelSetImage::GetActiveLayer() const
 {
   if (m_LayerContainer.size() == 0) mitkThrow() << "Cannot return active layer index. No layer is available.";
 
   return m_ActiveLayer;
 }
 
 unsigned int mitk::LabelSetImage::GetNumberOfLayers() const
 {
   return m_LayerContainer.size();
 }
 
 void mitk::LabelSetImage::RemoveGroup(GroupIndexType indexToDelete)
 {
   if (!this->ExistGroup(indexToDelete)) mitkThrow() << "Cannot remove group. Group does not exist. Invalid group index: "<<indexToDelete;
 
   const auto activeIndex = GetActiveLayer();
 
   auto newActiveIndex = activeIndex;
   auto newActiveIndexBeforeDeletion = activeIndex;
   //determine new active group index (after the group will be removed);
   if (indexToDelete < activeIndex)
   { //lower the index because position in m_LayerContainer etc has changed
     newActiveIndex = activeIndex-1;
   }
   else if (indexToDelete == activeIndex)
   {
     if (this->GetNumberOfLayers() == 1)
     { //last layer is about to be deleted
       newActiveIndex = 0;
     }
     else
     {
       //we have to add/subtract one more because we have not removed the layer yet, thus the group count is to 1 high.
       newActiveIndex = indexToDelete+1 < GetNumberOfLayers() ? indexToDelete : GetNumberOfLayers() - 2;
       newActiveIndexBeforeDeletion = indexToDelete + 1 < GetNumberOfLayers() ? indexToDelete+1 : indexToDelete -1;
     }
   }
 
   if (activeIndex == indexToDelete)
   {
     // we are deleting the active layer, it should not be copied back into the vector
     m_activeLayerInvalid = true;
     //copy the image content of the upcoming new active layer; 
     SetActiveLayer(newActiveIndexBeforeDeletion);
   }
 
   auto relevantLabels = m_GroupToLabelMap[indexToDelete];
 
   {
     std::lock_guard<std::shared_mutex> guard(m_LabelNGroupMapsMutex);
     // remove labels of group
     for (auto labelValue : relevantLabels)
     {
       auto label = m_LabelMap[labelValue];
       this->ReleaseLabel(label);
       m_LabelToGroupMap.erase(labelValue);
       m_LabelMap.erase(labelValue);
       this->InvokeEvent(LabelRemovedEvent(labelValue));
     }
     // remove the group entries in the maps and the image.
     m_Groups.erase(m_Groups.begin() + indexToDelete);
     m_GroupToLabelMap.erase(m_GroupToLabelMap.begin() + indexToDelete);
     m_LayerContainer.erase(m_LayerContainer.begin() + indexToDelete);
   }
 
   //update old indexes in m_GroupToLabelMap to new layer indexes
   for (auto& element : m_LabelToGroupMap)
   {
     if (element.second > indexToDelete) element.second = element.second -1;
   }
 
   //correct active layer index
   m_ActiveLayer = newActiveIndex;
 
   this->InvokeEvent(LabelsChangedEvent(relevantLabels));
   this->InvokeEvent(GroupRemovedEvent(indexToDelete));
   this->Modified();
 }
 
 mitk::LabelSetImage::LabelValueVectorType mitk::LabelSetImage::ExtractLabelValuesFromLabelVector(const LabelVectorType& labels)
 {
   LabelValueVectorType result;
 
   for (auto label : labels)
   {
     result.emplace_back(label->GetValue());
   }
   return result;
 }
 
 mitk::LabelSetImage::LabelValueVectorType mitk::LabelSetImage::ExtractLabelValuesFromLabelVector(const ConstLabelVectorType& labels)
 {
   LabelValueVectorType result;
 
   for (auto label : labels)
   {
     result.emplace_back(label->GetValue());
   }
   return result;
 }
 
 mitk::LabelSetImage::ConstLabelVectorType mitk::LabelSetImage::ConvertLabelVectorConst(const LabelVectorType& labels)
 {
   ConstLabelVectorType result(labels.begin(), labels.end());
   return result;
 };
 
 const mitk::LabelSetImage::LabelValueVectorType mitk::LabelSetImage::GetAllLabelValues() const
 {
   LabelValueVectorType result;
 
   for (auto [value, label] : m_LabelMap)
   {
     result.emplace_back(value);
   }
   return result;
 }
 
 mitk::LabelSetImage::LabelValueVectorType mitk::LabelSetImage::GetUsedLabelValues() const
 {
   LabelValueVectorType result = { UNLABELED_VALUE };
 
   for (auto [value, label] : m_LabelMap)
   {
     result.emplace_back(value);
   }
 
   return result;
 }
 
 mitk::LabelSetImage::GroupIndexType mitk::LabelSetImage::AddLayer(ConstLabelVector labels)
 {
   mitk::Image::Pointer newImage = mitk::Image::New();
   newImage->Initialize(this->GetPixelType(),
                        this->GetDimension(),
                        this->GetDimensions(),
                        this->GetImageDescriptor()->GetNumberOfChannels());
   newImage->SetTimeGeometry(this->GetTimeGeometry()->Clone());
 
   ClearImageBuffer(newImage);
 
   return this->AddLayer(newImage, labels);
 }
 
-mitk::LabelSetImage::GroupIndexType mitk::LabelSetImage::AddLayer(mitk::Image::Pointer layerImage, ConstLabelVector labels)
+mitk::LabelSetImage::GroupIndexType mitk::LabelSetImage::AddLayer(mitk::Image* layerImage, ConstLabelVector labels)
 {
   GroupIndexType newGroupID = m_Groups.size();
 
+  if (nullptr == layerImage)
+    mitkThrow() << "Cannot add group. Passed group image is nullptr.";
+
+  bool equalGeometries = Equal(
+    *(this->GetTimeGeometry()),
+    *(layerImage->GetTimeGeometry()),
+    NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION,
+    NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION,
+    false);
+
+  if (!equalGeometries)
+    mitkThrow() << "Cannot add group. Passed group image has not the same geometry like segmentation.";
+
+  if (layerImage->GetPixelType() != MakePixelType<LabelValueType, LabelValueType, 1>())
+    mitkThrow() << "Cannot add group. Passed group image has incorrect pixel type. Only LabelValueType is supported. Invalid pixel type: "<< layerImage->GetPixelType().GetTypeAsString();
+
   // push a new working image for the new layer
   m_LayerContainer.push_back(layerImage);
 
   m_Groups.push_back("");
   m_GroupToLabelMap.push_back({});
 
   for (auto label : labels)
   {
     if (m_LabelMap.end() != m_LabelMap.find(label->GetValue()))
     {
       mitkThrow() << "Cannot add layer. Labels that should be added with layer use at least one label value that is already in use. Conflicted label value: " << label->GetValue();
     }
 
     auto labelClone = label->Clone();
 
     DICOMSegmentationPropertyHelper::SetDICOMSegmentProperties(labelClone);
     this->AddLabelToMap(labelClone->GetValue(), labelClone, newGroupID);
     this->RegisterLabel(labelClone);
   }
 
   this->Modified();
   this->InvokeEvent(GroupAddedEvent(newGroupID));
 
   return newGroupID;
 }
 
 void mitk::LabelSetImage::ReplaceGroupLabels(const GroupIndexType groupID, const ConstLabelVectorType& labelSet)
 {
   if (m_LayerContainer.size() <= groupID)
   {
     mitkThrow() << "Trying to replace labels of non-existing group. Invalid group id: "<<groupID;
   }
 
   //remove old group labels
   LabelValueVectorType oldLabels;
   {
     std::lock_guard<std::shared_mutex> guard(m_LabelNGroupMapsMutex);
     oldLabels = this->m_GroupToLabelMap[groupID];
     for (auto labelID : oldLabels)
     {
       this->RemoveLabelFromMap(labelID);
       this->InvokeEvent(LabelRemovedEvent(labelID));
 
     }
   }
   this->InvokeEvent(LabelsChangedEvent(oldLabels));
   this->InvokeEvent(GroupModifiedEvent(groupID));
 
   //add new labels to group
   for (auto label : labelSet)
   {
     this->AddLabel(label->Clone(), groupID, true, false);
   }
 }
 
 void mitk::LabelSetImage::ReplaceGroupLabels(const GroupIndexType groupID, const LabelVectorType& labelSet)
 {
   return ReplaceGroupLabels(groupID, ConvertLabelVectorConst(labelSet));
 }
 
 mitk::Image* mitk::LabelSetImage::GetGroupImage(GroupIndexType groupID)
 {
   if (!this->ExistGroup(groupID)) mitkThrow() << "Error, cannot return group image. Group ID is invalid. Invalid ID: " << groupID;
 
   return groupID == this->GetActiveLayer() ? this : m_LayerContainer[groupID];
 }
 
+
 const mitk::Image* mitk::LabelSetImage::GetGroupImage(GroupIndexType groupID) const
 {
   if (!this->ExistGroup(groupID)) mitkThrow() << "Error, cannot return group image. Group ID is invalid. Invalid ID: " << groupID;
 
-  return groupID == this->GetActiveLayer() ? this : m_LayerContainer[groupID].GetPointer();
+  return groupID == this->GetActiveLayer() ? this : m_LayerContainer.at(groupID).GetPointer();
+}
+
+const mitk::Image* mitk::LabelSetImage::GetGroupImageWorkaround(GroupIndexType groupID) const
+{
+  if (!this->ExistGroup(groupID))
+    mitkThrow() << "Error, cannot return group image. Group ID is invalid. Invalid ID: " << groupID;
+
+  if (groupID == this->GetActiveLayer() && this->GetMTime()> m_LayerContainer[groupID]->GetMTime())
+  { //we have to transfer the content first into the group image
+    if (4 == this->GetDimension())
+    {
+      AccessFixedDimensionByItk_n(this, ImageToLayerContainerProcessing, 4, (groupID));
+    }
+    else
+    {
+      AccessByItk_1(this, ImageToLayerContainerProcessing, groupID);
+    }
+  }
+
+  return m_LayerContainer[groupID].GetPointer();
 }
 
 void mitk::LabelSetImage::SetActiveLayer(unsigned int layer)
 {
   try
   {
     if (4 == this->GetDimension())
     {
       if ((layer != GetActiveLayer() || m_activeLayerInvalid) && (layer < this->GetNumberOfLayers()))
       {
         BeforeChangeLayerEvent.Send();
 
         if (m_activeLayerInvalid)
         {
           // We should not write the invalid layer back to the vector
           m_activeLayerInvalid = false;
         }
         else
         {
           AccessFixedDimensionByItk_n(this, ImageToLayerContainerProcessing, 4, (GetActiveLayer()));
         }
         m_ActiveLayer = layer;
         AccessFixedDimensionByItk_n(this, LayerContainerToImageProcessing, 4, (GetActiveLayer()));
 
         AfterChangeLayerEvent.Send();
       }
     }
     else
     {
       if ((layer != GetActiveLayer() || m_activeLayerInvalid) && (layer < this->GetNumberOfLayers()))
       {
         BeforeChangeLayerEvent.Send();
 
         if (m_activeLayerInvalid)
         {
           // We should not write the invalid layer back to the vector
           m_activeLayerInvalid = false;
         }
         else
         {
           AccessByItk_1(this, ImageToLayerContainerProcessing, GetActiveLayer());
         }
         m_ActiveLayer = layer;
         AccessByItk_1(this, LayerContainerToImageProcessing, GetActiveLayer());
 
         AfterChangeLayerEvent.Send();
       }
     }
   }
   catch (itk::ExceptionObject &e)
   {
     mitkThrow() << e.GetDescription();
   }
   this->Modified();
 }
 
 void mitk::LabelSetImage::SetActiveLabel(LabelValueType label)
 {
   m_ActiveLabelValue = label;
 
   if (label != UNLABELED_VALUE)
   {
     auto groupID = this->GetGroupIndexOfLabel(label);
     if (groupID!=this->GetActiveLayer()) this->SetActiveLayer(groupID);
   }
   Modified();
 }
 
 void mitk::LabelSetImage::ClearBuffer()
 {
   try
   {
     ClearImageBuffer(this);
     this->Modified();
   }
   catch (itk::ExceptionObject &e)
   {
     mitkThrow() << e.GetDescription();
   }
 }
 
 void mitk::LabelSetImage::MergeLabel(PixelType pixelValue, PixelType sourcePixelValue)
 {
   try
   {
     AccessByItk_2(this, MergeLabelProcessing, pixelValue, sourcePixelValue);
   }
   catch (itk::ExceptionObject &e)
   {
     mitkThrow() << e.GetDescription();
   }
   this->SetActiveLabel(pixelValue);
   this->InvokeEvent(LabelModifiedEvent(sourcePixelValue));
   this->InvokeEvent(LabelModifiedEvent(pixelValue));
   this->InvokeEvent(LabelsChangedEvent({ sourcePixelValue, pixelValue }));
   Modified();
 }
 
 void mitk::LabelSetImage::MergeLabels(PixelType pixelValue, const std::vector<PixelType>& vectorOfSourcePixelValues)
 {
   try
   {
     for (unsigned int idx = 0; idx < vectorOfSourcePixelValues.size(); idx++)
     {
       AccessByItk_2(this, MergeLabelProcessing, pixelValue, vectorOfSourcePixelValues[idx]);
       this->InvokeEvent(LabelModifiedEvent(vectorOfSourcePixelValues[idx]));
     }
   }
   catch (itk::ExceptionObject &e)
   {
     mitkThrow() << e.GetDescription();
   }
   this->SetActiveLabel(pixelValue);
   this->InvokeEvent(LabelModifiedEvent(pixelValue));
   auto modifiedValues = vectorOfSourcePixelValues;
   modifiedValues.push_back(pixelValue);
   this->InvokeEvent(LabelsChangedEvent(modifiedValues));
 
   Modified();
 }
 
 void mitk::LabelSetImage::RemoveLabel(LabelValueType pixelValue)
 {
   GroupIndexType groupID = 0;
   {
     std::lock_guard<std::shared_mutex> guard(m_LabelNGroupMapsMutex);
     if (m_LabelMap.find(pixelValue) == m_LabelMap.end()) return;
 
     groupID = this->GetGroupIndexOfLabel(pixelValue);
 
     //first erase the pixel content (also triggers a LabelModified event)
     this->EraseLabel(pixelValue);
     this->RemoveLabelFromMap(pixelValue);
 
 
     if (m_ActiveLabelValue == pixelValue)
     {
       this->SetActiveLabel(0);
     }
   }
 
   this->InvokeEvent(LabelRemovedEvent(pixelValue));
   this->InvokeEvent(LabelsChangedEvent({ pixelValue }));
   this->InvokeEvent(GroupModifiedEvent(groupID));
 }
 
 void mitk::LabelSetImage::RemoveLabelFromMap(LabelValueType pixelValue)
 {
   if (m_LabelMap.find(pixelValue) == m_LabelMap.end()) mitkThrow()<<"Invalid state of instance. RemoveLabelFromMap was called for unknown label id. invalid label id: "<<pixelValue;
 
   auto groupID = this->GetGroupIndexOfLabel(pixelValue);
 
   this->ReleaseLabel(m_LabelMap[pixelValue]);
   //now remove the label entry itself
   m_LabelMap.erase(pixelValue);
   m_LabelToGroupMap.erase(pixelValue);
   auto labelsInGroup = m_GroupToLabelMap[groupID];
   labelsInGroup.erase(std::remove(labelsInGroup.begin(), labelsInGroup.end(), pixelValue), labelsInGroup.end());
   m_GroupToLabelMap[groupID] = labelsInGroup;
 }
 
 void mitk::LabelSetImage::RemoveLabels(const LabelValueVectorType& vectorOfLabelPixelValues)
 {
   for (const auto labelValue : vectorOfLabelPixelValues)
   {
     this->RemoveLabel(labelValue);
   }
   this->InvokeEvent(LabelsChangedEvent(vectorOfLabelPixelValues));
 }
 
 void mitk::LabelSetImage::EraseLabel(LabelValueType pixelValue)
 {
   try
   {
     auto groupID = this->GetGroupIndexOfLabel(pixelValue);
 
     mitk::Image* groupImage = this->GetGroupImage(groupID);
 
     if (4 == this->GetDimension())
     {
       AccessFixedDimensionByItk_1(groupImage, EraseLabelProcessing, 4, pixelValue);
     }
     else
     {
       AccessByItk_1(groupImage, EraseLabelProcessing, pixelValue);
     }
   }
   catch (const itk::ExceptionObject& e)
   {
     mitkThrow() << e.GetDescription();
   }
 
   this->InvokeEvent(LabelModifiedEvent(pixelValue));
   this->InvokeEvent(LabelsChangedEvent({ pixelValue }));
   Modified();
 }
 
 void mitk::LabelSetImage::EraseLabels(const LabelValueVectorType& labelValues)
 {
   for (auto labelValue : labelValues)
   {
     this->EraseLabel(labelValue);
   }
 }
 
 mitk::LabelSetImage::LabelValueType mitk::LabelSetImage::GetUnusedLabelValue() const
 {
   auto usedValues = this->GetUsedLabelValues();
   return usedValues.back() + 1;
 }
 
 mitk::Label* mitk::LabelSetImage::AddLabel(mitk::Label* label, GroupIndexType groupID, bool addAsClone, bool correctLabelValue)
 {
   mitk::Label::Pointer newLabel = label;
 
   {
     std::lock_guard<std::shared_mutex> guard(m_LabelNGroupMapsMutex);
 
     unsigned int max_size = mitk::Label::MAX_LABEL_VALUE + 1;
     if (m_LayerContainer.size() >= max_size)
       return nullptr;
 
     if (addAsClone) newLabel = label->Clone();
 
     auto pixelValue = newLabel->GetValue();
     auto usedValues = this->GetUsedLabelValues();
     auto finding = std::find(usedValues.begin(), usedValues.end(), pixelValue);
 
     if (!usedValues.empty() && usedValues.end() != finding)
     {
       if (correctLabelValue)
       {
         pixelValue = this->GetUnusedLabelValue();
         newLabel->SetValue(pixelValue);
       }
       else
       {
         mitkThrow() << "Cannot add label due to conflicting label value that already exists in the MultiLabelSegmentation. Conflicting label value: " << pixelValue;
       }
     }
 
     // add DICOM information of the label
     DICOMSegmentationPropertyHelper::SetDICOMSegmentProperties(newLabel);
 
     this->AddLabelToMap(pixelValue, newLabel, groupID);
     this->RegisterLabel(newLabel);
   }
 
   this->InvokeEvent(LabelAddedEvent(newLabel->GetValue()));
   m_ActiveLabelValue = newLabel->GetValue();
   this->Modified();
 
   return newLabel;
 }
 
 mitk::Label* mitk::LabelSetImage::AddLabel(const std::string& name, const mitk::Color& color, GroupIndexType groupID)
 {
   mitk::Label::Pointer newLabel = mitk::Label::New();
   newLabel->SetName(name);
   newLabel->SetColor(color);
   return AddLabel(newLabel,groupID,false);
 }
 
 void mitk::LabelSetImage::RenameLabel(LabelValueType pixelValue, const std::string& name, const mitk::Color& color)
 {
   std::shared_lock<std::shared_mutex> guard(m_LabelNGroupMapsMutex);
 
   mitk::Label* label = GetLabel(pixelValue);
   if (nullptr == label) mitkThrow() << "Cannot rename label.Unknown label value provided. Unknown label value:" << pixelValue;
 
   label->SetName(name);
   label->SetColor(color);
 
   this->UpdateLookupTable(pixelValue);
   // change DICOM information of the label
   DICOMSegmentationPropertyHelper::SetDICOMSegmentProperties(label);
 }
 
 mitk::Label *mitk::LabelSetImage::GetActiveLabel()
 {
   if (m_ActiveLabelValue == UNLABELED_VALUE) return nullptr;
 
   auto finding = m_LabelMap.find(m_ActiveLabelValue);
   return finding == m_LabelMap.end() ? nullptr : finding->second;
 }
 
 const mitk::Label* mitk::LabelSetImage::GetActiveLabel() const
 {
   if (m_ActiveLabelValue == UNLABELED_VALUE) return nullptr;
 
   auto finding = m_LabelMap.find(m_ActiveLabelValue);
   return finding == m_LabelMap.end() ? nullptr : finding->second;
 }
 
 void mitk::LabelSetImage::UpdateCenterOfMass(PixelType pixelValue)
 {
   if (4 == this->GetDimension())
   {
     AccessFixedDimensionByItk_1(this->GetGroupImage(this->GetGroupIndexOfLabel(pixelValue)), CalculateCenterOfMassProcessing, 4, pixelValue);
   }
   else
   {
     AccessByItk_1(this->GetGroupImage(this->GetGroupIndexOfLabel(pixelValue)), CalculateCenterOfMassProcessing, pixelValue);
   }
 }
 
 void mitk::LabelSetImage::SetLookupTable(mitk::LookupTable* lut)
 {
   m_LookupTable = lut;
   this->Modified();
 }
 
 void mitk::LabelSetImage::UpdateLookupTable(PixelType pixelValue)
 {
   const mitk::Color& color = this->GetLabel(pixelValue)->GetColor();
 
   double rgba[4];
   m_LookupTable->GetTableValue(static_cast<int>(pixelValue), rgba);
   rgba[0] = color.GetRed();
   rgba[1] = color.GetGreen();
   rgba[2] = color.GetBlue();
   if (GetLabel(pixelValue)->GetVisible())
     rgba[3] = GetLabel(pixelValue)->GetOpacity();
   else
     rgba[3] = 0.0;
   m_LookupTable->SetTableValue(static_cast<int>(pixelValue), rgba);
 }
 
 unsigned int mitk::LabelSetImage::GetNumberOfLabels(unsigned int layer) const
 {
   if (layer >= m_Groups.size()) mitkThrow() << "Cannot get number of labels in group. Group is unknown. Invalid index:" << layer;
   return m_GroupToLabelMap[layer].size();
 }
 
 unsigned int mitk::LabelSetImage::GetTotalNumberOfLabels() const
 {
   return m_LabelMap.size();
 }
 
 void mitk::LabelSetImage::MaskStamp(mitk::Image *mask, bool forceOverwrite)
 {
   try
   {
     mitk::PadImageFilter::Pointer padImageFilter = mitk::PadImageFilter::New();
     padImageFilter->SetInput(0, mask);
     padImageFilter->SetInput(1, this);
     padImageFilter->SetPadConstant(0);
     padImageFilter->SetBinaryFilter(false);
     padImageFilter->SetLowerThreshold(0);
     padImageFilter->SetUpperThreshold(1);
 
     padImageFilter->Update();
 
     mitk::Image::Pointer paddedMask = padImageFilter->GetOutput();
 
     if (paddedMask.IsNull())
       return;
 
     AccessByItk_2(this, MaskStampProcessing, paddedMask, forceOverwrite);
   }
   catch (...)
   {
     mitkThrow() << "Could not stamp the provided mask on the selected label.";
   }
 }
 
-mitk::Image::Pointer mitk::LabelSetImage::CreateLabelMask(PixelType index)
-{
-  if (!this->ExistLabel(index)) mitkThrow() << "Error, cannot return label mask. Label ID is invalid. Invalid ID: " << index;
-
-  auto mask = mitk::Image::New();
-
-  // mask->Initialize(this) does not work here if this label set image has a single slice,
-  // since the mask would be automatically flattened to a 2-d image, whereas we expect the
-  // original dimension of this label set image. Hence, initialize the mask more explicitly:
-  mask->Initialize(this->GetPixelType(), this->GetDimension(), this->GetDimensions());
-  mask->SetTimeGeometry(this->GetTimeGeometry()->Clone());
-
-  ClearImageBuffer(mask);
-
-  const auto groupID = this->GetGroupIndexOfLabel(index);
-
-  auto destinationLabel = this->GetLabel(index)->Clone();
-  destinationLabel->SetValue(1);
-
-  TransferLabelContent(this->GetGroupImage(groupID), mask.GetPointer(),
-    {destinationLabel},
-    LabelSetImage::UNLABELED_VALUE, LabelSetImage::UNLABELED_VALUE, false,
-    { { index, destinationLabel->GetValue()}}, MultiLabelSegmentation::MergeStyle::Replace, MultiLabelSegmentation::OverwriteStyle::IgnoreLocks);
-
-  return mask;
-}
-
 void mitk::LabelSetImage::InitializeByLabeledImage(mitk::Image::Pointer image)
 {
   if (image.IsNull() || image->IsEmpty() || !image->IsInitialized())
     mitkThrow() << "Invalid labeled image.";
 
   try
   {
     this->Initialize(image);
 
     unsigned int byteSize = sizeof(LabelSetImage::PixelType);
     for (unsigned int dim = 0; dim < image->GetDimension(); ++dim)
     {
       byteSize *= image->GetDimension(dim);
     }
 
     mitk::ImageWriteAccessor *accessor = new mitk::ImageWriteAccessor(static_cast<mitk::Image *>(this));
     memset(accessor->GetData(), 0, byteSize);
     delete accessor;
 
     auto geometry = image->GetTimeGeometry()->Clone();
     this->SetTimeGeometry(geometry);
 
     if (image->GetDimension() == 3)
     {
       AccessTwoImagesFixedDimensionByItk(this, image, InitializeByLabeledImageProcessing, 3);
     }
     else if (image->GetDimension() == 4)
     {
       AccessTwoImagesFixedDimensionByItk(this, image, InitializeByLabeledImageProcessing, 4);
     }
     else
     {
       mitkThrow() << image->GetDimension() << "-dimensional label set images not yet supported";
     }
   }
   catch (Exception& e)
   {
     mitkReThrow(e) << "Could not initialize by provided labeled image.";
   }
   catch (...)
   {
     mitkThrow() << "Could not initialize by provided labeled image due to unknown error.";
   }
   this->Modified();
 }
 
 template <typename LabelSetImageType, typename ImageType>
 void mitk::LabelSetImage::InitializeByLabeledImageProcessing(LabelSetImageType *labelSetImage, ImageType *image)
 {
   typedef itk::ImageRegionConstIteratorWithIndex<ImageType> SourceIteratorType;
   typedef itk::ImageRegionIterator<LabelSetImageType> TargetIteratorType;
 
   TargetIteratorType targetIter(labelSetImage, labelSetImage->GetRequestedRegion());
   targetIter.GoToBegin();
 
   SourceIteratorType sourceIter(image, image->GetRequestedRegion());
   sourceIter.GoToBegin();
 
   while (!sourceIter.IsAtEnd())
   {
     const auto originalSourceValue = sourceIter.Get();
     const auto sourceValue = static_cast<PixelType>(originalSourceValue);
 
     if (originalSourceValue > mitk::Label::MAX_LABEL_VALUE)
     {
       mitkThrow() << "Cannot initialize MultiLabelSegmentation by image. Image contains a pixel value that exceeds the label value range. Invalid pixel value:" << originalSourceValue;
     }
 
     targetIter.Set(sourceValue);
 
     if (LabelSetImage::UNLABELED_VALUE!=sourceValue && !this->ExistLabel(sourceValue))
     {
       if (this->GetTotalNumberOfLabels() >= mitk::Label::MAX_LABEL_VALUE)
       {
         mitkThrow() << "Cannot initialize MultiLabelSegmentation by image. Image contains to many labels.";
       }
 
       std::stringstream name;
       name << "object-" << sourceValue;
 
       double rgba[4];
       this->GetLookupTable()->GetTableValue(sourceValue, rgba);
 
       mitk::Color color;
       color.SetRed(rgba[0]);
       color.SetGreen(rgba[1]);
       color.SetBlue(rgba[2]);
 
       auto label = mitk::Label::New();
       label->SetName(name.str().c_str());
       label->SetColor(color);
       label->SetOpacity(rgba[3]);
       label->SetValue(sourceValue);
 
       this->AddLabel(label,0,false);
     }
 
     ++sourceIter;
     ++targetIter;
   }
 }
 
 template <typename ImageType>
 void mitk::LabelSetImage::MaskStampProcessing(ImageType *itkImage, mitk::Image *mask, bool forceOverwrite)
 {
   typename ImageType::Pointer itkMask;
   mitk::CastToItkImage(mask, itkMask);
 
   typedef itk::ImageRegionConstIterator<ImageType> SourceIteratorType;
   typedef itk::ImageRegionIterator<ImageType> TargetIteratorType;
 
   SourceIteratorType sourceIter(itkMask, itkMask->GetLargestPossibleRegion());
   sourceIter.GoToBegin();
 
   TargetIteratorType targetIter(itkImage, itkImage->GetLargestPossibleRegion());
   targetIter.GoToBegin();
 
   const auto activeLabel = this->GetActiveLabel()->GetValue();
 
   while (!sourceIter.IsAtEnd())
   {
     PixelType sourceValue = sourceIter.Get();
     PixelType targetValue = targetIter.Get();
 
     if ((sourceValue != UNLABELED_VALUE) &&
         (forceOverwrite || !this->IsLabelLocked(targetValue))) // skip unlabeled pixels and locked labels
     {
       targetIter.Set(activeLabel);
     }
     ++sourceIter;
     ++targetIter;
   }
 
   this->Modified();
 }
 
 template <typename ImageType>
 void mitk::LabelSetImage::CalculateCenterOfMassProcessing(ImageType *itkImage, LabelValueType pixelValue)
 {
   if (ImageType::GetImageDimension() != 3)
   {
     return;
   }
 
   auto labelGeometryFilter = itk::LabelGeometryImageFilter<ImageType>::New();
   labelGeometryFilter->SetInput(itkImage);
   labelGeometryFilter->Update();
   auto centroid = labelGeometryFilter->GetCentroid(pixelValue);
 
   mitk::Point3D pos;
   pos[0] = centroid[0];
   pos[1] = centroid[1];
   pos[2] = centroid[2];
 
   this->GetLabel(pixelValue)->SetCenterOfMassIndex(pos);
   this->GetSlicedGeometry()->IndexToWorld(pos, pos);
   this->GetLabel(pixelValue)->SetCenterOfMassCoordinates(pos);
 }
 
 template <typename TPixel, unsigned int VImageDimension>
 void mitk::LabelSetImage::LayerContainerToImageProcessing(itk::Image<TPixel, VImageDimension> *target,
                                                           unsigned int layer)
 {
   typedef itk::Image<TPixel, VImageDimension> ImageType;
   typename ImageType::Pointer itkSource;
   // mitk::CastToItkImage(m_LayerContainer[layer], itkSource);
   itkSource = ImageToItkImage<TPixel, VImageDimension>(m_LayerContainer[layer]);
   typedef itk::ImageRegionConstIterator<ImageType> SourceIteratorType;
   typedef itk::ImageRegionIterator<ImageType> TargetIteratorType;
 
   SourceIteratorType sourceIter(itkSource, itkSource->GetLargestPossibleRegion());
   sourceIter.GoToBegin();
 
   TargetIteratorType targetIter(target, target->GetLargestPossibleRegion());
   targetIter.GoToBegin();
 
   while (!sourceIter.IsAtEnd())
   {
     targetIter.Set(sourceIter.Get());
     ++sourceIter;
     ++targetIter;
   }
 }
 
 template <typename TPixel, unsigned int VImageDimension>
-void mitk::LabelSetImage::ImageToLayerContainerProcessing(itk::Image<TPixel, VImageDimension> *source,
+void mitk::LabelSetImage::ImageToLayerContainerProcessing(const itk::Image<TPixel, VImageDimension> *source,
                                                           unsigned int layer) const
 {
   typedef itk::Image<TPixel, VImageDimension> ImageType;
   typename ImageType::Pointer itkTarget;
   // mitk::CastToItkImage(m_LayerContainer[layer], itkTarget);
   itkTarget = ImageToItkImage<TPixel, VImageDimension>(m_LayerContainer[layer]);
 
   typedef itk::ImageRegionConstIterator<ImageType> SourceIteratorType;
   typedef itk::ImageRegionIterator<ImageType> TargetIteratorType;
 
   SourceIteratorType sourceIter(source, source->GetLargestPossibleRegion());
   sourceIter.GoToBegin();
 
   TargetIteratorType targetIter(itkTarget, itkTarget->GetLargestPossibleRegion());
   targetIter.GoToBegin();
 
   while (!sourceIter.IsAtEnd())
   {
     targetIter.Set(sourceIter.Get());
     ++sourceIter;
     ++targetIter;
   }
+
+  m_LayerContainer[layer]->Modified();
 }
 
 template <typename ImageType>
 void mitk::LabelSetImage::EraseLabelProcessing(ImageType *itkImage, PixelType pixelValue)
 {
   typedef itk::ImageRegionIterator<ImageType> IteratorType;
 
   IteratorType iter(itkImage, itkImage->GetLargestPossibleRegion());
   iter.GoToBegin();
 
   while (!iter.IsAtEnd())
   {
     PixelType value = iter.Get();
 
     if (value == pixelValue)
     {
       iter.Set(0);
     }
     ++iter;
   }
 }
 
 template <typename ImageType>
 void mitk::LabelSetImage::MergeLabelProcessing(ImageType *itkImage, PixelType pixelValue, PixelType index)
 {
   typedef itk::ImageRegionIterator<ImageType> IteratorType;
 
   IteratorType iter(itkImage, itkImage->GetLargestPossibleRegion());
   iter.GoToBegin();
 
   while (!iter.IsAtEnd())
   {
     if (iter.Get() == index)
     {
       iter.Set(pixelValue);
     }
     ++iter;
   }
 }
 
 void mitk::LabelSetImage::AddLabelToMap(LabelValueType labelValue, mitk::Label* label, GroupIndexType groupID)
 {
   if (m_LabelMap.find(labelValue)!=m_LabelMap.end())
     mitkThrow() << "Segmentation is in an invalid state: Label value collision. A label was added with a LabelValue already in use. LabelValue: " << labelValue;
 
   if (!this->ExistGroup(groupID))
     mitkThrow() << "Cannot add label. Defined group is unknown. Invalid group index: " << groupID;
 
   m_LabelMap[labelValue] = label;
   m_LabelToGroupMap[labelValue] = groupID;
   auto groupFinding = std::find(m_GroupToLabelMap[groupID].begin(), m_GroupToLabelMap[groupID].end(), labelValue);
   if (groupFinding == m_GroupToLabelMap[groupID].end())
   {
     m_GroupToLabelMap[groupID].push_back(labelValue);
   }
 }
 
 void mitk::LabelSetImage::RegisterLabel(mitk::Label* label)
 {
   if (nullptr == label) mitkThrow() << "Invalid call of RegisterLabel with a nullptr.";
 
   UpdateLookupTable(label->GetValue());
 
   auto command = itk::MemberCommand<LabelSetImage>::New();
   command->SetCallbackFunction(this, &LabelSetImage::OnLabelModified);
   m_LabelModEventGuardMap.emplace(label->GetValue(), ITKEventObserverGuard(label, itk::ModifiedEvent(), command));
 }
 
 void mitk::LabelSetImage::ReleaseLabel(Label* label)
 {
   if (nullptr == label) mitkThrow() << "Invalid call of ReleaseLabel with a nullptr.";
   m_LabelModEventGuardMap.erase(label->GetValue());
 }
 
 void mitk::LabelSetImage::ApplyToLabels(const LabelValueVectorType& values, std::function<void(Label*)>&& lambda)
 {
   auto labels = this->GetLabelsByValue(values);
   std::for_each(labels.begin(), labels.end(), lambda);
   this->InvokeEvent(LabelsChangedEvent(values));
 }
 
 void mitk::LabelSetImage::VisitLabels(const LabelValueVectorType& values, std::function<void(const Label*)>&& lambda) const
 {
   auto labels = this->GetConstLabelsByValue(values);
   std::for_each(labels.begin(), labels.end(), lambda);
 }
 
 
 void mitk::LabelSetImage::OnLabelModified(const Object* sender, const itk::EventObject&)
 {
   auto label = dynamic_cast<const Label*>(sender);
   if (nullptr == label)
     mitkThrow() << "LabelSet is in wrong state. LabelModified event is not send by a label instance.";
 
   Superclass::Modified();
   this->InvokeEvent(LabelModifiedEvent(label->GetValue()));
 }
 
 bool mitk::LabelSetImage::ExistLabel(LabelValueType value) const
 {
   auto finding = m_LabelMap.find(value);
   return m_LabelMap.end() != finding;
 }
 
 bool mitk::LabelSetImage::ExistLabel(LabelValueType value, GroupIndexType groupIndex) const
 {
   auto finding = m_LabelToGroupMap.find(value);
   if (m_LabelToGroupMap.end() != finding)
   {
     return finding->second == groupIndex;
   }
   return false;
 }
 
 bool mitk::LabelSetImage::ExistGroup(GroupIndexType index) const
 {
   return index < m_LayerContainer.size();
 }
 
 mitk::LabelSetImage::GroupIndexType mitk::LabelSetImage::GetGroupIndexOfLabel(LabelValueType value) const
 {
   auto finding = m_LabelToGroupMap.find(value);
   if (m_LabelToGroupMap.end() == finding)
   {
     mitkThrow()<< "Cannot deduce group index. Passed label value does not exist. Value: "<< value;
   }
   return finding->second;
 }
 
 
 const mitk::Label* mitk::LabelSetImage::GetLabel(LabelValueType value) const
 {
   auto finding = m_LabelMap.find(value);
   if (m_LabelMap.end() != finding)
   {
     return finding->second;
   }
   return nullptr;
 };
 
 mitk::Label* mitk::LabelSetImage::GetLabel(LabelValueType value)
 {
   auto finding = m_LabelMap.find(value);
   if (m_LabelMap.end() != finding)
   {
     return finding->second;
   }
   return nullptr;
 };
 
 bool mitk::LabelSetImage::IsLabelLocked(LabelValueType value) const
 {
   if (value == UNLABELED_VALUE)
   {
     return m_UnlabeledLabelLock;
   }
 
   const auto label = this->GetLabel(value);
   return label->GetLocked();
 }
 
 const mitk::LabelSetImage::ConstLabelVectorType mitk::LabelSetImage::GetLabels() const
 {
   ConstLabelVectorType result;
   for (auto [value, label] : m_LabelMap)
   {
     result.emplace_back(label);
   }
   return result;
 }
 
 const mitk::LabelSetImage::LabelVectorType mitk::LabelSetImage::GetLabels()
 {
   LabelVectorType result;
   for (auto [value, label] : m_LabelMap)
   {
     result.emplace_back(label);
   }
   return result;
 }
 
 const mitk::LabelSetImage::LabelVectorType mitk::LabelSetImage::GetLabelsByValue(const LabelValueVectorType& labelValues, bool ignoreMissing)
 {
   LabelVectorType result;
   for (const auto& labelValue : labelValues)
   {
     auto* label = this->GetLabel(labelValue);
 
     if (label != nullptr)
     {
       result.emplace_back(label);
     }
     else if (!ignoreMissing) mitkThrow() << "Error cannot get labels by Value. At least one passed value is unknown. Unknown value: " << labelValue;
   }
   return result;
 }
 
 const mitk::LabelSetImage::ConstLabelVectorType mitk::LabelSetImage::GetConstLabelsByValue(const LabelValueVectorType& labelValues, bool ignoreMissing) const
 {
   ConstLabelVectorType result;
   for (const auto& labelValue : labelValues)
   {
     const auto* label = this->GetLabel(labelValue);
 
     if (label != nullptr)
     {
       result.emplace_back(label);
     }
     else if (!ignoreMissing) mitkThrow() << "Error cannot get labels by Value. At least one passed value is unknown. Unknown value: " << labelValue;
   }
   return result;
 }
 
 const mitk::LabelSetImage::LabelValueVectorType mitk::LabelSetImage::GetLabelValuesByGroup(GroupIndexType index) const
 {
   if (!this->ExistGroup(index))
     mitkThrow() << "Cannot get labels of an invalid group. Invalid group index: " << index;
 
   return m_GroupToLabelMap[index];
 }
 
 const mitk::LabelSetImage::LabelValueVectorType mitk::LabelSetImage::GetLabelValuesByName(GroupIndexType index, const std::string_view name) const
 {
   LabelValueVectorType result;
 
   auto searchName = [&result, name](const Label* l) { if(l->GetName() == name) result.push_back(l->GetValue()); };
 
   this->VisitLabels(this->GetLabelValuesByGroup(index), searchName);
 
   return result;
 }
 
 std::vector<std::string> mitk::LabelSetImage::GetLabelClassNames() const
 {
   std::set<std::string> names;
   auto searchName = [&names](const Label* l) { names.emplace(l->GetName()); };
   this->VisitLabels(this->GetAllLabelValues(), searchName);
 
   return std::vector<std::string>(names.begin(), names.end());
 }
 
 std::vector<std::string> mitk::LabelSetImage::GetLabelClassNamesByGroup(GroupIndexType index) const
 {
   std::set<std::string> names;
   auto searchName = [&names](const Label* l) { names.emplace(l->GetName()); };
   this->VisitLabels(this->GetLabelValuesByGroup(index), searchName);
 
   return std::vector<std::string>(names.begin(), names.end());
 }
 
 void mitk::LabelSetImage::SetAllLabelsVisible(bool visible)
 {
-  auto setVisibility = [visible](Label* l) { l->SetVisible(visible); };
+  auto setVisibility = [this, visible](Label* l)
+    {
+      l->SetVisible(visible);
+      this->UpdateLookupTable(l->GetValue());
+    };
 
   this->ApplyToLabels(this->GetAllLabelValues(), setVisibility);
 }
 
 void mitk::LabelSetImage::SetAllLabelsVisibleByGroup(GroupIndexType group, bool visible)
 {
-  auto setVisibility = [visible](Label* l) { l->SetVisible(visible); };
+  auto setVisibility = [this, visible](Label* l)
+    {
+      l->SetVisible(visible);
+      this->UpdateLookupTable(l->GetValue());
+    };
 
   this->ApplyToLabels(this->GetLabelValuesByGroup(group), setVisibility);
 }
 
 void mitk::LabelSetImage::SetAllLabelsVisibleByName(GroupIndexType group, const std::string_view name, bool visible)
 {
-  auto setVisibility = [visible](Label* l) { l->SetVisible(visible); };
+  auto setVisibility = [this, visible](Label* l)
+    {
+      l->SetVisible(visible);
+      this->UpdateLookupTable(l->GetValue());
+    };
 
   this->ApplyToLabels(this->GetLabelValuesByName(group, name), setVisibility);
 }
 
 void mitk::LabelSetImage::SetAllLabelsLocked(bool locked)
 {
   auto setLock = [locked](Label* l) { l->SetLocked(locked); };
 
   this->ApplyToLabels(this->GetAllLabelValues(), setLock);
 }
 
 void mitk::LabelSetImage::SetAllLabelsLockedByGroup(GroupIndexType group, bool locked)
 {
   auto setLock = [locked](Label* l) { l->SetLocked(locked); };
 
   this->ApplyToLabels(this->GetLabelValuesByGroup(group), setLock);
 }
 
 void mitk::LabelSetImage::SetAllLabelsLockedByName(GroupIndexType group, const std::string_view name, bool locked)
 {
   auto setLock = [locked](Label* l) { l->SetLocked(locked); };
 
   this->ApplyToLabels(this->GetLabelValuesByName(group, name), setLock);
 }
 
 bool mitk::Equal(const mitk::LabelSetImage &leftHandSide,
                  const mitk::LabelSetImage &rightHandSide,
                  ScalarType eps,
                  bool verbose)
 {
   bool returnValue = true;
 
   /* LabelSetImage members */
 
   MITK_INFO(verbose) << "--- LabelSetImage Equal ---";
 
   // m_LookupTable;
   const mitk::LookupTable* lhsLUT = leftHandSide.GetLookupTable();
   const mitk::LookupTable* rhsLUT = rightHandSide.GetLookupTable();
 
   returnValue = *lhsLUT == *rhsLUT;
   if (!returnValue)
   {
     MITK_INFO(verbose) << "Lookup tables not equal.";
     return returnValue;
     ;
   }
 
   // number layers
   returnValue = leftHandSide.GetNumberOfLayers() == rightHandSide.GetNumberOfLayers();
   if (!returnValue)
   {
     MITK_INFO(verbose) << "Number of layers not equal.";
     return false;
   }
 
   // total number labels
   returnValue = leftHandSide.GetTotalNumberOfLabels() == rightHandSide.GetTotalNumberOfLabels();
   if (!returnValue)
   {
     MITK_INFO(verbose) << "Total number of labels not equal.";
     return false;
   }
 
   // active layer
   returnValue = leftHandSide.GetActiveLayer() == rightHandSide.GetActiveLayer();
   if (!returnValue)
   {
     MITK_INFO(verbose) << "Active layer not equal.";
     return false;
   }
 
   if (4 == leftHandSide.GetDimension())
   {
     MITK_INFO(verbose) << "Can not compare image data for 4D images - skipping check.";
   }
   else
   {
     // working image data
     returnValue = mitk::Equal((const mitk::Image &)leftHandSide, (const mitk::Image &)rightHandSide, eps, verbose);
     if (!returnValue)
     {
       MITK_INFO(verbose) << "Working image data not equal.";
       return false;
     }
   }
 
   if (leftHandSide.GetTotalNumberOfLabels() != rightHandSide.GetTotalNumberOfLabels())
   {
     MITK_INFO(verbose) << "Number of labels are not equal.";
     return false;
   }
 
   for (unsigned int layerIndex = 0; layerIndex < leftHandSide.GetNumberOfLayers(); layerIndex++)
   {
     if (4 == leftHandSide.GetDimension())
     {
       MITK_INFO(verbose) << "Can not compare image data for 4D images - skipping check.";
     }
     else
     {
       // layer image data
       returnValue =
         mitk::Equal(*leftHandSide.GetGroupImage(layerIndex), *rightHandSide.GetGroupImage(layerIndex), eps, verbose);
       if (!returnValue)
       {
         MITK_INFO(verbose) << "Layer image data not equal.";
         return false;
       }
     }
 
     // label data
     auto leftLabelsInGroup = leftHandSide.GetLabelValuesByGroup(layerIndex);
     auto rightLabelsInGroup = rightHandSide.GetLabelValuesByGroup(layerIndex);
 
     if (leftLabelsInGroup.size()!=rightLabelsInGroup.size())
     {
       MITK_INFO(verbose) << "Number of layer labels is not equal. Invalid layer:" <<layerIndex;
       return false;
     }
 
     for (ConstLabelVector::size_type index = 0; index < leftLabelsInGroup.size(); ++index)
     {
       if (!mitk::Equal(*(leftHandSide.GetLabel(leftLabelsInGroup[index])), *(rightHandSide.GetLabel(rightLabelsInGroup[index])),eps,verbose))
       {
         MITK_INFO(verbose) << "At least one label in layer is not equal. Invalid layer:" << layerIndex;
         return false;
       }
     }
   }
 
   return returnValue;
 }
 
 bool mitk::Equal(const mitk::LabelSetImage::ConstLabelVectorType& leftHandSide,
   const mitk::LabelSetImage::ConstLabelVectorType& rightHandSide, ScalarType eps, bool verbose)
 {
   bool returnValue = true;
 
   // container size;
   returnValue = leftHandSide.size() == rightHandSide.size();
   if (!returnValue)
   {
     MITK_INFO(verbose) << "Number of labels not equal.";
     return returnValue;
     ;
   }
 
   // m_LabelContainer;
   auto lhsit = leftHandSide.begin();
   auto rhsit = rightHandSide.begin();
   for (; lhsit != leftHandSide.end(); ++lhsit, ++rhsit)
   {
     returnValue = mitk::Equal(**rhsit, **lhsit,eps,verbose);
     if (!returnValue)
     {
       MITK_INFO(verbose) << "Label in label container not equal.";
       return returnValue;
       ;
     }
   }
 
   return returnValue;
 }
 
 /**Helper function to convert a vector of labels into a label map
  * @pre every label in the vector has a unique value.*/
 using ConstLabelMapType = std::map<mitk::LabelSetImage::LabelValueType, mitk::Label::ConstPointer>;
 ConstLabelMapType ConvertLabelVectorToMap(const mitk::ConstLabelVector& labelV)
 {
   ConstLabelMapType result;
   for (auto label : labelV)
   {
     const auto value = label->GetValue();
     auto finding = result.find(value);
     if (finding != result.end()) mitkThrow() << "Operation failed. Cannot convert label vector into label map, because at least one label value is not unique. Violating label value: " << value;
     result.insert(std::make_pair(value, label));
   }
 
   return result;
 }
 
 
 /** Functor class that implements the label transfer and is used in conjunction with the itk::BinaryFunctorImageFilter.
 * For details regarding the usage of the filter and the functor patterns, please see info of itk::BinaryFunctorImageFilter.
 */
 template <class TDestinationPixel, class TSourcePixel, class TOutputpixel>
 class LabelTransferFunctor
 {
 
 public:
   LabelTransferFunctor() {};
 
   LabelTransferFunctor(const ConstLabelMapType& destinationLabels, mitk::Label::PixelType sourceBackground,
     mitk::Label::PixelType destinationBackground, bool destinationBackgroundLocked,
     mitk::Label::PixelType sourceLabel, mitk::Label::PixelType newDestinationLabel, mitk::MultiLabelSegmentation::MergeStyle mergeStyle,
     mitk::MultiLabelSegmentation::OverwriteStyle overwriteStyle) :
     m_DestinationLabels(destinationLabels), m_SourceBackground(sourceBackground),
     m_DestinationBackground(destinationBackground), m_DestinationBackgroundLocked(destinationBackgroundLocked),
     m_SourceLabel(sourceLabel), m_NewDestinationLabel(newDestinationLabel), m_MergeStyle(mergeStyle), m_OverwriteStyle(overwriteStyle)
   {
   };
 
   ~LabelTransferFunctor() {};
 
   bool operator!=(const LabelTransferFunctor& other)const
   {
     return !(*this == other);
   }
   bool operator==(const LabelTransferFunctor& other) const
   {
     return this->m_SourceBackground == other.m_SourceBackground &&
       this->m_DestinationBackground == other.m_DestinationBackground &&
       this->m_DestinationBackgroundLocked == other.m_DestinationBackgroundLocked &&
       this->m_SourceLabel == other.m_SourceLabel &&
       this->m_NewDestinationLabel == other.m_NewDestinationLabel &&
       this->m_MergeStyle == other.m_MergeStyle &&
       this->m_OverwriteStyle == other.m_OverwriteStyle &&
       this->m_DestinationLabels == other.m_DestinationLabels;
   }
 
   LabelTransferFunctor& operator=(const LabelTransferFunctor& other)
   {
     this->m_DestinationLabels = other.m_DestinationLabels;
     this->m_SourceBackground = other.m_SourceBackground;
     this->m_DestinationBackground = other.m_DestinationBackground;
     this->m_DestinationBackgroundLocked = other.m_DestinationBackgroundLocked;
     this->m_SourceLabel = other.m_SourceLabel;
     this->m_NewDestinationLabel = other.m_NewDestinationLabel;
     this->m_MergeStyle = other.m_MergeStyle;
     this->m_OverwriteStyle = other.m_OverwriteStyle;
 
     return *this;
   }
 
   inline TOutputpixel operator()(const TDestinationPixel& existingDestinationValue, const TSourcePixel& existingSourceValue)
   {
     if (existingSourceValue == this->m_SourceLabel)
     {
       if (mitk::MultiLabelSegmentation::OverwriteStyle::IgnoreLocks == this->m_OverwriteStyle)
       {
         return this->m_NewDestinationLabel;
       }
       else
       {
         if (existingDestinationValue == m_DestinationBackground)
         {
           if (!m_DestinationBackgroundLocked)
           {
             return this->m_NewDestinationLabel;
           }
         }
         else
         {
           auto labelFinding = this->m_DestinationLabels.find(existingDestinationValue);
           if (labelFinding==this->m_DestinationLabels.end() || !labelFinding->second->GetLocked())
           {
             return this->m_NewDestinationLabel;
           }
         }
       }
     }
     else if (mitk::MultiLabelSegmentation::MergeStyle::Replace == this->m_MergeStyle
       && existingSourceValue == this->m_SourceBackground
       && existingDestinationValue == this->m_NewDestinationLabel
       && (mitk::MultiLabelSegmentation::OverwriteStyle::IgnoreLocks == this->m_OverwriteStyle
           || !this->m_DestinationBackgroundLocked))
     {
       return this->m_DestinationBackground;
     }
 
     return existingDestinationValue;
   }
 
 private:
   ConstLabelMapType m_DestinationLabels;
   mitk::Label::PixelType m_SourceBackground = 0;
   mitk::Label::PixelType m_DestinationBackground = 0;
   bool m_DestinationBackgroundLocked = false;
   mitk::Label::PixelType m_SourceLabel = 1;
   mitk::Label::PixelType m_NewDestinationLabel = 1;
   mitk::MultiLabelSegmentation::MergeStyle m_MergeStyle = mitk::MultiLabelSegmentation::MergeStyle::Replace;
   mitk::MultiLabelSegmentation::OverwriteStyle m_OverwriteStyle = mitk::MultiLabelSegmentation::OverwriteStyle::RegardLocks;
 };
 
 /**Helper function used by TransferLabelContentAtTimeStep to allow the templating over different image dimensions in conjunction of AccessFixedPixelTypeByItk_n.*/
 template<unsigned int VImageDimension>
 void TransferLabelContentAtTimeStepHelper(const itk::Image<mitk::Label::PixelType, VImageDimension>* itkSourceImage, mitk::Image* destinationImage,
   const mitk::ConstLabelVector& destinationLabels, mitk::Label::PixelType sourceBackground, mitk::Label::PixelType destinationBackground,
   bool destinationBackgroundLocked, mitk::Label::PixelType sourceLabel, mitk::Label::PixelType newDestinationLabel, mitk::MultiLabelSegmentation::MergeStyle mergeStyle, mitk::MultiLabelSegmentation::OverwriteStyle overwriteStyle)
 {
   typedef itk::Image<mitk::Label::PixelType, VImageDimension> ContentImageType;
   typename ContentImageType::Pointer itkDestinationImage;
   mitk::CastToItkImage(destinationImage, itkDestinationImage);
 
   auto sourceRegion = itkSourceImage->GetLargestPossibleRegion();
   auto relevantRegion = itkDestinationImage->GetLargestPossibleRegion();
   bool overlapping = relevantRegion.Crop(sourceRegion);
 
   if (!overlapping)
   {
     mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; sourceImage and destinationImage seem to have no overlapping image region.";
   }
 
   typedef LabelTransferFunctor <mitk::Label::PixelType, mitk::Label::PixelType, mitk::Label::PixelType> LabelTransferFunctorType;
   typedef itk::BinaryFunctorImageFilter<ContentImageType, ContentImageType, ContentImageType, LabelTransferFunctorType> FilterType;
 
   LabelTransferFunctorType transferFunctor(ConvertLabelVectorToMap(destinationLabels), sourceBackground, destinationBackground,
     destinationBackgroundLocked, sourceLabel, newDestinationLabel, mergeStyle, overwriteStyle);
 
   auto transferFilter = FilterType::New();
 
   transferFilter->SetFunctor(transferFunctor);
   transferFilter->InPlaceOn();
   transferFilter->SetInput1(itkDestinationImage);
   transferFilter->SetInput2(itkSourceImage);
   transferFilter->GetOutput()->SetRequestedRegion(relevantRegion);
 
   transferFilter->Update();
 }
 
 void mitk::TransferLabelContentAtTimeStep(
   const Image* sourceImage, Image* destinationImage, const mitk::ConstLabelVector& destinationLabels, const TimeStepType timeStep, mitk::Label::PixelType sourceBackground,
   mitk::Label::PixelType destinationBackground, bool destinationBackgroundLocked, LabelValueMappingVector labelMapping,
   MultiLabelSegmentation::MergeStyle mergeStyle, MultiLabelSegmentation::OverwriteStyle overwriteStlye)
 {
   if (nullptr == sourceImage)
   {
     mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; sourceImage must not be null.";
   }
   if (nullptr == destinationImage)
   {
     mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; destinationImage must not be null.";
   }
 
   if (sourceImage == destinationImage && labelMapping.size() > 1)
   {
     MITK_DEBUG << "Warning. Using TransferLabelContentAtTimeStep or TransferLabelContent with equal source and destination and more then on label to transfer, can lead to wrong results. Please see documentation and verify that the usage is OK.";
   }
 
   Image::ConstPointer sourceImageAtTimeStep = SelectImageByTimeStep(sourceImage, timeStep);
   Image::Pointer destinationImageAtTimeStep = SelectImageByTimeStep(destinationImage, timeStep);
 
   if (nullptr == sourceImageAtTimeStep)
   {
     mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; sourceImage does not have the requested time step: " << timeStep;
   }
+
   if (nullptr == destinationImageAtTimeStep)
   {
     mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; destinationImage does not have the requested time step: " << timeStep;
   }
 
+  if (!Equal(*(sourceImageAtTimeStep->GetGeometry()), *(destinationImageAtTimeStep->GetGeometry()), mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION))
+  {
+    if (IsSubGeometry(*(sourceImageAtTimeStep->GetGeometry()), *(destinationImageAtTimeStep->GetGeometry()), mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION))
+    {
+      //we have to pad the source image
+      //because ImageToImageFilters always check for origin matching even if
+      //the requested output region is fitting :(
+      auto padFilter = mitk::PadImageFilter::New();
+      padFilter->SetInput(0, sourceImageAtTimeStep);
+      padFilter->SetInput(1, destinationImageAtTimeStep);
+      padFilter->SetPadConstant(Label::UNLABELED_VALUE);
+      padFilter->SetBinaryFilter(false);
+
+      padFilter->Update();
+
+      sourceImageAtTimeStep = padFilter->GetOutput();
+    }
+    else
+    {
+      mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; source image has neither the same geometry than destination image nor has the source image a sub geometry.";
+    }
+  }
+
   auto destLabelMap = ConvertLabelVectorToMap(destinationLabels);
   for (const auto& [sourceLabel, newDestinationLabel] : labelMapping)
   {
     if (LabelSetImage::UNLABELED_VALUE!=newDestinationLabel && destLabelMap.end() == destLabelMap.find(newDestinationLabel))
     {
       mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep. Defined destination label does not exist in destinationImage. newDestinationLabel: " << newDestinationLabel;
     }
 
     AccessFixedPixelTypeByItk_n(sourceImageAtTimeStep, TransferLabelContentAtTimeStepHelper, (Label::PixelType), (destinationImageAtTimeStep, destinationLabels, sourceBackground, destinationBackground, destinationBackgroundLocked, sourceLabel, newDestinationLabel, mergeStyle, overwriteStlye));
   }
   destinationImage->Modified();
 }
 
 void mitk::TransferLabelContent(
   const Image* sourceImage, Image* destinationImage, const mitk::ConstLabelVector& destinationLabels, mitk::Label::PixelType sourceBackground,
   mitk::Label::PixelType destinationBackground, bool destinationBackgroundLocked, LabelValueMappingVector labelMapping,
   MultiLabelSegmentation::MergeStyle mergeStyle, MultiLabelSegmentation::OverwriteStyle overwriteStlye)
 {
   if (nullptr == sourceImage)
   {
     mitkThrow() << "Invalid call of TransferLabelContent; sourceImage must not be null.";
   }
   if (nullptr == destinationImage)
   {
     mitkThrow() << "Invalid call of TransferLabelContent; destinationImage must not be null.";
   }
 
   const auto sourceTimeStepCount = sourceImage->GetTimeGeometry()->CountTimeSteps();
   if (sourceTimeStepCount != destinationImage->GetTimeGeometry()->CountTimeSteps())
   {
     mitkThrow() << "Invalid call of TransferLabelContent; mismatch between images in number of time steps.";
   }
 
   for (mitk::TimeStepType i = 0; i < sourceTimeStepCount; ++i)
   {
     TransferLabelContentAtTimeStep(sourceImage, destinationImage, destinationLabels, i, sourceBackground,
       destinationBackground, destinationBackgroundLocked, labelMapping, mergeStyle, overwriteStlye);
   }
 }
 
 void mitk::TransferLabelContentAtTimeStep(
   const LabelSetImage* sourceImage, LabelSetImage* destinationImage, const TimeStepType timeStep,
   LabelValueMappingVector labelMapping,
   MultiLabelSegmentation::MergeStyle mergeStyle, MultiLabelSegmentation::OverwriteStyle overwriteStlye)
 {
   if (nullptr == sourceImage)
   {
     mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep; sourceImage must not be null.";
   }
 
   auto destinationLabels = destinationImage->GetConstLabelsByValue(destinationImage->GetLabelValuesByGroup(destinationImage->GetActiveLayer()));
 
   for (const auto& mappingElement : labelMapping)
   {
     if (LabelSetImage::UNLABELED_VALUE != mappingElement.first && !sourceImage->ExistLabel(mappingElement.first, sourceImage->GetActiveLayer()))
     {
       mitkThrow() << "Invalid call of TransferLabelContentAtTimeStep. Defined source label does not exist in sourceImage. SourceLabel: " << mappingElement.first;
     }
   }
 
   TransferLabelContentAtTimeStep(sourceImage, destinationImage, destinationLabels, timeStep, LabelSetImage::UNLABELED_VALUE, LabelSetImage::UNLABELED_VALUE, destinationImage->GetUnlabeledLabelLock(),
     labelMapping, mergeStyle, overwriteStlye);
 }
 
 void mitk::TransferLabelContent(
   const LabelSetImage* sourceImage, LabelSetImage* destinationImage,
   LabelValueMappingVector labelMapping,
   MultiLabelSegmentation::MergeStyle mergeStyle, MultiLabelSegmentation::OverwriteStyle overwriteStlye)
 {
   if (nullptr == sourceImage)
   {
     mitkThrow() << "Invalid call of TransferLabelContent; sourceImage must not be null.";
   }
   if (nullptr == destinationImage)
   {
     mitkThrow() << "Invalid call of TransferLabelContent; destinationImage must not be null.";
   }
 
   const auto sourceTimeStepCount = sourceImage->GetTimeGeometry()->CountTimeSteps();
   if (sourceTimeStepCount != destinationImage->GetTimeGeometry()->CountTimeSteps())
   {
     mitkThrow() << "Invalid call of TransferLabelContent; images have no equal number of time steps.";
   }
 
   for (mitk::TimeStepType i = 0; i < sourceTimeStepCount; ++i)
   {
     TransferLabelContentAtTimeStep(sourceImage, destinationImage, i, labelMapping, mergeStyle, overwriteStlye);
   }
 }
 
diff --git a/Modules/Multilabel/mitkLabelSetImage.h b/Modules/Multilabel/mitkLabelSetImage.h
index ad75094349..b68acdc3ab 100644
--- a/Modules/Multilabel/mitkLabelSetImage.h
+++ b/Modules/Multilabel/mitkLabelSetImage.h
@@ -1,667 +1,674 @@
 /*============================================================================
 
 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 mitkLabelSetImage_h
 #define mitkLabelSetImage_h
 
 #include <shared_mutex>
 #include <mitkImage.h>
 #include <mitkLabel.h>
 #include <mitkLookupTable.h>
 #include <mitkMultiLabelEvents.h>
 #include <mitkMessage.h>
 #include <mitkITKEventObserverGuard.h>
 
 #include <MitkMultilabelExports.h>
 
 namespace mitk
 {
   /** @brief LabelSetImage class for handling labels and layers in a segmentation session.
   *
   * Events that are potentially send by the class in regard to groups or labels:
   * - LabelAddedEvent is emitted whenever a new label has been added.
   * - LabelModifiedEvent is emitted whenever a label has been modified.
   * - LabelRemovedEvent is emitted whenever a label has been removed.
   * - LabelsChangedEvent is emitted when labels are changed (added, removed, modified). In difference to the other label events LabelsChanged is send only *one time* after the modification of the
   * MultiLableImage instance is finished. So e.g. even if 4 labels are changed by a merge operation, this event will
   * only be sent once (compared to LabelRemoved or LabelModified).
   * - GroupAddedEvent is emitted whenever a new group has been added.
   * - GroupModifiedEvent is emitted whenever a group has been modified.
   * - GroupRemovedEvent is emitted whenever a label has been removed.
   *
   * @ingroup Data
   */
   class MITKMULTILABEL_EXPORT LabelSetImage : public Image
   {
   public:
     /**
     * \brief BeforeChangeLayerEvent (e.g. used for GUI integration)
     * As soon as active labelset should be changed, the signal emits.
     * Emitted by SetActiveLayer(int layer);
     */
     Message<> BeforeChangeLayerEvent;
 
     /**
     * \brief AfterchangeLayerEvent (e.g. used for GUI integration)
     * As soon as active labelset was changed, the signal emits.
     * Emitted by SetActiveLayer(int layer);
     */
     Message<> AfterChangeLayerEvent;
 
     ///////////////////////////////////////////////////////////////////////////////////
     ///////////////////////////////////////////////////////////////////////////////////
     // FUTURE MultiLabelSegmentation:
     // Section that already contains declarations used in the new class.
     // So this part of the interface will stay after refactoring towards
     // the new MultiLabelSegmentation class (see T28524). This section was introduced
     // because some of the planned features are already urgently needed.
     ///////////////////////////////////////////////////////////////////////////////////
     ///////////////////////////////////////////////////////////////////////////////////
     mitkClassMacro(LabelSetImage, Image);
     itkNewMacro(Self);
 
     typedef mitk::Label::PixelType PixelType;
 
     using GroupIndexType = std::size_t;
     using LabelValueType = mitk::Label::PixelType;
     using ConstLabelVectorType = ConstLabelVector;
     using LabelVectorType = LabelVector;
     using LabelValueVectorType = std::vector<LabelValueType>;
 
     const static LabelValueType UNLABELED_VALUE;
 
     /** \brief Adds a label instance to a group of the multi label image.
     * @remark By default, if the pixel value of the label is already used in the image, the label
     * will get a new none conflicting value assigned. This can be controlled by correctLabelValue.
     * @param label Instance of an label that should be added or used as template
     * @param groupID The id of the group the label should be added to.
     * @param addAsClone Flag that controls, if the passed instance should be added (false; the image will then take ownership,
     * be aware that e.g. event observers will be added)
     * a clone of the instance (true).
     * @param correctLabelValue Flag that controls, if the value of the passed label should be correct, if this value is already used in
     * the multi label image. True: Conflicting values will be corrected, be assigning a none conflicting value. False: If the value is conflicting
     * an exception will be thrown.
     * @return Instance of the label as it was added to the label set.
     * @pre label must point to a valid instance.
     * @pre If correctLabelValue==false, label value must be non conflicting.
     * @pre groupID must indicate an existing group.
     */
     mitk::Label* AddLabel(mitk::Label* label, GroupIndexType groupID, bool addAsClone = true, bool correctLabelValue = true);
 
     /** \brief Adds a new label to a group of the image by providing name and color.
     * @param name (Class) name of the label instance that should be added.
     * @param color Color of the new label instance.
     * @param groupID The id of the group the label should be added to.
     * @return Instance of the label as it was added to the label set.
     * @pre groupID must indicate an existing group.
     */
     mitk::Label* AddLabel(const std::string& name, const Color& color, GroupIndexType groupID);
 
     /** \brief allows to adapt name and color of a certain label
     * @param labelValue Value of the label that should be changed
     * @param name New name for the label
     * @param color New color for the label
     * @pre Indicated label value must exist.
     */
     void RenameLabel(LabelValueType labelValue, const std::string& name, const Color& color);
 
     /**
      * @brief Removes the label with the given value.
      * The label is removed from the labelset and
      * the pixel with the value of the label are set to UNLABELED_VALUE.
      * @param labelValue the pixel value of the label to be removed. If the label is unknown,
      * the method will return without doing anything.
      */
     void RemoveLabel(LabelValueType labelValue);
 
     /**
      * @brief Removes labels from the mitk::MultiLabelSegmentation.
      * The label is removed from the labelset and
      * the pixel with the value of the label are set to UNLABELED_VALUE.
      * If a label value does not exist, it will be ignored.
      * @param vectorOfLabelPixelValues a list of labels to be removed
      */
     void RemoveLabels(const LabelValueVectorType& vectorOfLabelPixelValues);
 
     /**
      * @brief Erases the label with the given value from the labelset image.
      * The label itself will not be erased from the respective mitk::LabelSet. In order to
      * remove the label itself use mitk::LabelSetImage::RemoveLabels()
      * @param labelValue the pixel value of the label that will be erased from the labelset image
      * @pre labelValue must exist.
      */
     void EraseLabel(LabelValueType labelValue);
 
     /**
      * @brief Erases a list of labels with the given values from the labelset image.
      * @param labelValues the list of pixel values of the labels
      * that will be erased from the labelset image
      * @pre label values must exist
      */
     void EraseLabels(const LabelValueVectorType& labelValues);
 
     /**
      * @brief Removes a whole group including all its labels.
      * @remark with removing a group all groups with greater index will be re-indexed to
      * close the gap. Hence externally stored spatial group indices may become invalid.
      * @param group Group index of the spatial group that should be removed. If the spatial group does not exist, an
      * exception will be raised.
      * @pre group index must be valid.
      */
     void RemoveGroup(GroupIndexType group);
 
     /** \brief  Returns true if the value exists in the MultiLabelSegmentation instance*/
     bool ExistLabel(LabelValueType value) const;
 
     /**
      * @brief Checks if a label belongs in a certain spatial group
      * @param value the label value
      * @param groupIndex Index of the spacial group which should be checked for the label
      * @return true if the label exists otherwise false
      */
     bool ExistLabel(LabelValueType value, GroupIndexType groupIndex) const;
 
     /**
       * @brief  Returns true if the spatial group exists in the MultiLabelSegmentation instance.
       *
       * @param index Group index of the group that should be checked for existence.
       */
     bool ExistGroup(GroupIndexType index) const;
 
     /** Returns the group id of the based label value.
     * @pre label value must exists.
     */
     GroupIndexType GetGroupIndexOfLabel(LabelValueType value) const;
 
     /**
      * @brief Returns the mitk::Label with the given value.
      * @param value the pixel value of the label
      * @return the label instance if defined in the segmentation, otherwise nullptr.
      */
     const mitk::Label* GetLabel(LabelValueType value) const;
     mitk::Label* GetLabel(LabelValueType value);
 
     /** Returns a vector with pointers to all labels currently defined in the MultiLabelSegmentation
     instance.*/
     const ConstLabelVectorType GetLabels() const;
     const LabelVectorType GetLabels();
 
     /** Returns a vector of all label values currently defined in the MultiLabelSegmentation
     instance.*/
     const LabelValueVectorType GetAllLabelValues() const;
 
     /** @brief Returns a vector with pointers to all labels in the MultiLabelSegmentation indicated
     * by the passed label value vector.
     * @param labelValues Vector of values of labels that should be returned.
     * @param ignoreMissing If true (default), unknown labels Will be skipped in the result. If false,
     * an exception will be raised, if a label is requested.
     */
     const LabelVectorType GetLabelsByValue(const LabelValueVectorType& labelValues, bool ignoreMissing = true);
 
     /** @brief Returns a vector with const pointers to all labels in the MultiLabelSegmentation indicated
     * by the passed label value vector.
     * For details see GetLabelsByValue();
     */
     const ConstLabelVectorType GetConstLabelsByValue(const LabelValueVectorType& labelValues, bool ignoreMissing = false) const;
 
     /** Helper function that can be used to extract a vector of label values of a vector of label instance pointers.*/
     static LabelValueVectorType ExtractLabelValuesFromLabelVector(const ConstLabelVectorType& labels);
     /** Helper function that can be used to extract a vector of label values are vector of label instances.*/
     static LabelValueVectorType ExtractLabelValuesFromLabelVector(const LabelVectorType& labels);
 
     /** Helper function that converts a given vector of label instance pointers into a vector of const pointers.*/
     static ConstLabelVectorType ConvertLabelVectorConst(const LabelVectorType& labels);
 
     /**
      * @brief Returns a vector of all label values located on the specified group.
      * @param index the index of the group for which the vector of labels should be retrieved.
      * If an invalid index is passed an exception will be raised.
      * @return the respective vector of label values.
      * @pre group index must exist.
      */
     const LabelValueVectorType GetLabelValuesByGroup(GroupIndexType index) const;
 
     /**
      * @brief Returns a vector of all label values located on the specified group having a certain name.
      * @param index the index of the group for which the vector of labels should be retrieved.
      * If an invalid index is passed an exception will be raised.
      * @param name Name of the label instances one is looking for.
      * @return the respective vector of label values.
      * @pre group index must exist.
      */
     const LabelValueVectorType GetLabelValuesByName(GroupIndexType index, const std::string_view name) const;
 
     /**
     * Returns a vector with (class) names of all label instances used in the segmentation (over all groups)
     */
     std::vector<std::string> GetLabelClassNames() const;
 
     /**
     * Returns a vector with (class) names of all label instances present in a certain group.
     * @param index ID of the group, for which the label class names should be returned
     * @pre Indicated group must exist. */
     std::vector<std::string> GetLabelClassNamesByGroup(GroupIndexType index) const;
 
     /** Helper that returns an unused label value, that could be used e.g. if one wants to define a label externally
     * before adding it.
     * @return A label value currently not in use.
     * @remark is no unused label value can be provided an exception will be thrown.*/
     LabelValueType GetUnusedLabelValue() const;
 
     itkGetConstMacro(UnlabeledLabelLock, bool);
     itkSetMacro(UnlabeledLabelLock, bool);
     itkBooleanMacro(UnlabeledLabelLock);
 
     /** Set the visibility of all label instances accordingly to the passed state.
     */
     void SetAllLabelsVisible(bool visible);
 
     /** Set the visibility of all label instances in a group accordingly to the passed state.
     * @pre The specified group must exist.
     */
     void SetAllLabelsVisibleByGroup(GroupIndexType group, bool visible);
 
     /** Set the visibility of all label instances In a group with a given class name
     * accordingly to the passed state.
     * @pre The specified group must exist.
     */
     void SetAllLabelsVisibleByName(GroupIndexType group, const std::string_view name, bool visible);
 
     /** Returns the lock state of the label (including UnlabeledLabel value).
      @pre Requested label does exist.*/
     bool IsLabelLocked(LabelValueType value) const;
 
     /** Set the lock state of all label instances accordingly to the passed state.
     */
     void SetAllLabelsLocked(bool locked);
 
     /** Set the lock state of all label instances in a group accordingly to the passed state.
     * @pre The specified group must exist.
     */
     void SetAllLabelsLockedByGroup(GroupIndexType group, bool locked);
 
     /** Set the lock state of all label instances In a group with a given class name
     * accordingly to the passed state.
     * @pre The specified group must exist.
     */
     void SetAllLabelsLockedByName(GroupIndexType group, const std::string_view name, bool locked);
 
     /**
     * \brief Replaces the labels of a group with a given vector of labels.
     *
     * @remark The passed label instances will be cloned before added to ensure clear ownership
     * of the new labels.
     * @remark The pixel content of the old labels will not be removed.
     * @param groupID The index of the group that should have its labels replaced
     * @param newLabels The vector of new labels
     * @pre Group that should be replaced must exist.
     * @pre new label values must not be used in other groups.
     */
     void ReplaceGroupLabels(const GroupIndexType groupID, const ConstLabelVectorType& newLabels);
 
     void ReplaceGroupLabels(const GroupIndexType groupID, const LabelVectorType& newLabels);
 
     /** Returns the pointer to the image that contains the labeling of the indicate group.
      *@pre groupID must reference an existing group.*/
     mitk::Image* GetGroupImage(GroupIndexType groupID);
 
     /** Returns the pointer to the image that contains the labeling of the indicate group.
      *@pre groupID must reference an existing group.*/
     const mitk::Image* GetGroupImage(GroupIndexType groupID) const;
 
     itkGetModifiableObjectMacro(LookupTable, mitk::LookupTable);
     void SetLookupTable(LookupTable* lut);
     /** Updates the lookup table for a label indicated by the passed label value using the color of the label.
     * @pre labelValue must exist.
     */
     void UpdateLookupTable(PixelType pixelValue);
 
     protected:
 
       void OnLabelModified(const Object* sender, const itk::EventObject&);
 
       /** Helper to ensure that the maps are correctly populated for a new label instance.*/
       void AddLabelToMap(LabelValueType labelValue, Label* label, GroupIndexType groupID);
       void RemoveLabelFromMap(LabelValueType labelValue);
       /** Helper to ensure label events are correctly connected and lookup table is updated for a new label instance.*/
       void RegisterLabel(Label* label);
       /** Helper to ensure label events are unregistered.*/
       void ReleaseLabel(Label* label);
 
       /** Helper class used internally to apply lambda functions to the labels specified by the passed label value vector.
       */
       void ApplyToLabels(const LabelValueVectorType& values, std::function<void(Label*)>&& lambda);
       /** Helper class used internally to for visiting the labels specified by the passed label value vector
       * with the lambda function.
       */
       void VisitLabels(const LabelValueVectorType& values, std::function<void(const Label*)>&& lambda) const;
 
       LabelValueType m_ActiveLabelValue;
 
     private:
       using LabelMapType = std::map<LabelValueType, Label::Pointer>;
       /** Dictionary that holds all known labels (label value is the key).*/
       LabelMapType m_LabelMap;
 
       using GroupNameVectorType = std::vector<std::string>;
       /** Vector storing the names of all groups. If a group has no user name defined, string is empty.*/
       GroupNameVectorType m_Groups;
 
       /**This type is internally used to track which label is currently
        * associated with which layer.*/
       using GroupToLabelMapType = std::vector<LabelValueVectorType>;
       /* Dictionary that maps between group id (key) and label values in the group (vector of label value).*/
       GroupToLabelMapType m_GroupToLabelMap;
       using LabelToGroupMapType = std::map<LabelValueType, GroupIndexType>;
       /* Dictionary that maps between label value (key) and group id (value)*/
       LabelToGroupMapType m_LabelToGroupMap;
 
       using LabelEventGuardMapType = std::map<LabelValueType, ITKEventObserverGuard>;
       LabelEventGuardMapType m_LabelModEventGuardMap;
 
       LookupTable::Pointer m_LookupTable;
 
       /** Indicates if the MultiLabelSegmentation allows to overwrite unlabeled pixels in normal pixel manipulation operations (e.g. TransferLabelConent).*/
       bool m_UnlabeledLabelLock;
 
       /** Mutex used to secure manipulations of the internal state of label and group maps.*/
       std::shared_mutex m_LabelNGroupMapsMutex;
 
     public:
 
 
     ///////////////////////////////////////////////////////////////////////////////////
     ///////////////////////////////////////////////////////////////////////////////////
     // END FUTURE MultiLabelSegmentation
     ///////////////////////////////////////////////////////////////////////////////////
     ///////////////////////////////////////////////////////////////////////////////////
+
+    /** DON'T USE. WORKAROUND method that is used until the rework is finished to
+    ensure always getting a group image and not this.
+    @warning Don't use. This method is going to be removed as soon as T30194 is
+    solved.*/
+      const mitk::Image* GetGroupImageWorkaround(GroupIndexType groupID) const;
+
     /**
       * \brief  */
       void UpdateCenterOfMass(PixelType pixelValue);
 
     /**
      * @brief Initialize an empty mitk::LabelSetImage using the information
      *        of an mitk::Image
      * @param image the image which is used for initializing the mitk::LabelSetImage
      */
     using mitk::Image::Initialize;
     void Initialize(const mitk::Image *image) override;
 
     /**
       * \brief removes all pixel content form the active layer.*/
     void ClearBuffer();
 
     /**
      * @brief Merges the mitk::Label with a given target value with the active label
      *
      * @param pixelValue          the value of the label that should be the new merged label
      * @param sourcePixelValue    the value of the label that should be merged into the specified one
      */
     void MergeLabel(PixelType pixelValue, PixelType sourcePixelValue);
 
     /**
      * @brief Merges a list of mitk::Labels with the mitk::Label that has a specific value
      *
      * @param pixelValue                  the value of the label that should be the new merged label
      * @param vectorOfSourcePixelValues   the list of label values that should be merge into the specified one
      */
     void MergeLabels(PixelType pixelValue, const std::vector<PixelType>& vectorOfSourcePixelValues);
 
     /**
      * @brief Gets the ID of the currently active layer
      * @return the ID of the active layer
      * @pre at least on group must exist.
      */
     unsigned int GetActiveLayer() const;
 
     Label* GetActiveLabel();
 
     const Label* GetActiveLabel() const;
 
     /**
      * @brief Get the number of all existing mitk::Labels for a given layer
      * @param layer the layer ID for which the active mitk::Labels should be retrieved
      * @return the number of all existing mitk::Labels for the given layer
      */
     unsigned int GetNumberOfLabels(unsigned int layer) const;
 
     /**
      * @brief Returns the number of all labels summed up across all layers
      * @return the overall number of labels across all layers
      */
     unsigned int GetTotalNumberOfLabels() const;
 
-    mitk::Image::Pointer CreateLabelMask(PixelType index);
-
-    /**
      * @brief Initialize a new mitk::LabelSetImage by a given image.
      * For all distinct pixel values of the parameter image new labels will
      * be created. If the number of distinct pixel values exceeds mitk::Label::MAX_LABEL_VALUE
      * an exception will be raised.
      * @param image the image which is used for initialization
      */
     void InitializeByLabeledImage(mitk::Image::Pointer image);
 
     void MaskStamp(mitk::Image *mask, bool forceOverwrite);
 
     void SetActiveLayer(unsigned int layer);
     void SetActiveLabel(LabelValueType label);
 
     unsigned int GetNumberOfLayers() const;
 
     /**
      * \brief Adds a new layer to the LabelSetImage. The new layer will be set as the active one.
      * \param labels Labels that will be added to the new layer if provided
      * \return the layer ID of the new layer
      */
     GroupIndexType AddLayer(ConstLabelVector labels = {});
 
     /**
     * \brief Adds a layer based on a provided mitk::Image.
     * \param layerImage is added to the vector of label images
     * \param labels labels that will be cloned and added to the new layer if provided
     * \return the layer ID of the new layer
+    * \pre layerImage must be valid instance
+    * \pre layerImage needs to have the same geometry then the segmentation
+    * \pre layerImage must have the pixel value equal to LabelValueType.
     */
-    GroupIndexType AddLayer(mitk::Image::Pointer layerImage, ConstLabelVector labels = {});
+    GroupIndexType AddLayer(mitk::Image* layerImage, ConstLabelVector labels = {});
 
   protected:
     mitkCloneMacro(Self);
 
       LabelSetImage();
     LabelSetImage(const LabelSetImage &other);
     ~LabelSetImage() override;
 
     template <typename TPixel, unsigned int VImageDimension>
     void LayerContainerToImageProcessing(itk::Image<TPixel, VImageDimension> *source, unsigned int layer);
 
     template <typename TPixel, unsigned int VImageDimension>
-    void ImageToLayerContainerProcessing(itk::Image<TPixel, VImageDimension> *source, unsigned int layer) const;
+    void ImageToLayerContainerProcessing(const itk::Image<TPixel, VImageDimension> *source, unsigned int layer) const;
 
     template <typename ImageType>
     void CalculateCenterOfMassProcessing(ImageType *input, LabelValueType index);
 
     template <typename ImageType>
     void EraseLabelProcessing(ImageType *input, PixelType index);
 
     template <typename ImageType>
     void MergeLabelProcessing(ImageType *input, PixelType pixelValue, PixelType index);
 
     template <typename ImageType>
     void MaskStampProcessing(ImageType *input, mitk::Image *mask, bool forceOverwrite);
 
     template <typename LabelSetImageType, typename ImageType>
     void InitializeByLabeledImageProcessing(LabelSetImageType *input, ImageType *other);
 
     /** helper needed for ensuring unique values.
       returns a sorted list of all labels (including the value for Unlabeled pixels..*/
     LabelValueVectorType GetUsedLabelValues() const;
 
     std::vector<Image::Pointer> m_LayerContainer;
 
     int m_ActiveLayer;
     bool m_activeLayerInvalid;
   };
 
   /**
   * @brief Equal A function comparing two label set images for beeing equal in meta- and imagedata
   *
   * @ingroup MITKTestingAPI
   *
   * Following aspects are tested for equality:
   *  - LabelSetImage members
   *  - working image data
   *  - layer image data
   *  - labels in label set
   *
   * @param rightHandSide An image to be compared
   * @param leftHandSide An image to be compared
   * @param eps Tolerance for comparison. You can use mitk::eps in most cases.
   * @param verbose Flag indicating if the user wants detailed console output or not.
   * @return true, if all subsequent comparisons are true, false otherwise
   */
   MITKMULTILABEL_EXPORT bool Equal(const mitk::LabelSetImage &leftHandSide,
                                    const mitk::LabelSetImage &rightHandSide,
                                    ScalarType eps,
                                    bool verbose);
 
   /**
   * @brief Equal A function comparing two vectors of labels for being equal in data
   *
   * @ingroup MITKTestingAPI
   *
   * Following aspects are tested for equality:
   *  - Labels in vector
   *
   * @param rightHandSide An vector of labels to be compared
   * @param leftHandSide An vector of labels to be compared
   * @param eps Tolerance for comparison. You can use mitk::eps in most cases.
   * @param verbose Flag indicating if the user wants detailed console output or not.
   * @return true, if all subsequent comparisons are true, false otherwise
   */
   MITKMULTILABEL_EXPORT bool Equal(const mitk::LabelSetImage::ConstLabelVectorType& leftHandSide,
     const mitk::LabelSetImage::ConstLabelVectorType& rightHandSide,
     ScalarType eps,
     bool verbose);
 
 
   /** temporary namespace that is used until the new class MultiLabelSegmentation is
     introduced. It allows to already introduce/use some upcoming definitions, while
     refactoring code.*/
   namespace MultiLabelSegmentation
   {
     enum class MergeStyle
     {
       Replace, //The old label content of a label value will be replaced by its new label content.
                //Therefore pixels that are labeled might become unlabeled again.
                //(This means that a lock of the value is also ignored).
       Merge //The union of old and new label content will be generated.
     };
 
     enum class OverwriteStyle
     {
       RegardLocks, //Locked labels in the same spatial group will not be overwritten/changed.
       IgnoreLocks //Label locks in the same spatial group will be ignored, so these labels might be changed.
     };
   }
 
   using LabelValueMappingVector = std::vector < std::pair<Label::PixelType, Label::PixelType> >;
 
   /**Helper function that transfers pixels of the specified source label from source image to the destination image by using
   a specified destination label for a specific time step. Function processes the whole image volume of the specified time step.
   @remark in its current implementation the function only transfers contents of the active layer of the passed LabelSetImages.
   @remark the function assumes that it is only called with source and destination image of same geometry.
   @remark CAUTION: The function is not save if sourceImage and destinationImage are the same instance and more than one label is transferred,
   because the changes are made in-place for performance reasons in multiple passes. If a mapped value A equals an "old value"
   that occurs later in the mapping, one ends up with a wrong transfer, as a pixel would be first mapped to A and then later again, because
   it is also an "old" value in the mapping table.
   @param sourceImage Pointer to the LabelSetImage which active layer should be used as source for the transfer.
   @param destinationImage Pointer to the LabelSetImage which active layer should be used as destination for the transfer.
   @param labelMapping Map that encodes the mappings of all label pixel transfers that should be done. First element is the
   label in the source image. The second element is the label that transferred pixels should become in the destination image.
   The order in which the labels will be transfered is the same order of elements in the labelMapping.
   If you use a heterogeneous label mapping (e.g. (1,2); so changing the label while transferring), keep in mind that
   for the MergeStyle and OverwriteStyle only the destination label (second element) is relevant (e.g. what should be
   altered with MergeStyle Replace).
   @param mergeStyle indicates how the transfer should be done (merge or replace). For more details see documentation of
   MultiLabelSegmentation::MergeStyle.
   @param overwriteStlye indicates if label locks in the destination image should be regarded or not. For more details see
   documentation of MultiLabelSegmentation::OverwriteStyle.
   @param timeStep indicate the time step that should be transferred.
   @pre sourceImage and destinationImage must be valid
   @pre sourceImage and destinationImage must contain the indicated timeStep
   @pre sourceImage must contain all indicated sourceLabels in its active layer.
   @pre destinationImage must contain all indicated destinationLabels in its active layer.*/
   MITKMULTILABEL_EXPORT void TransferLabelContentAtTimeStep(const LabelSetImage* sourceImage, LabelSetImage* destinationImage,
     const TimeStepType timeStep, LabelValueMappingVector labelMapping = { {1,1} },
     MultiLabelSegmentation::MergeStyle mergeStyle = MultiLabelSegmentation::MergeStyle::Replace,
     MultiLabelSegmentation::OverwriteStyle overwriteStlye = MultiLabelSegmentation::OverwriteStyle::RegardLocks);
 
   /**Helper function that transfers pixels of the specified source label from source image to the destination image by using
   a specified destination label. Function processes the whole image volume for all time steps.
   For more details please see TransferLabelContentAtTimeStep for LabelSetImages.
   @sa TransferLabelContentAtTimeStep*/
   MITKMULTILABEL_EXPORT void TransferLabelContent(const LabelSetImage* sourceImage, LabelSetImage* destinationImage, LabelValueMappingVector labelMapping = { {1,1} },
     MultiLabelSegmentation::MergeStyle mergeStyle = MultiLabelSegmentation::MergeStyle::Replace,
     MultiLabelSegmentation::OverwriteStyle overwriteStlye = MultiLabelSegmentation::OverwriteStyle::RegardLocks);
 
 
   /**Helper function that transfers pixels of the specified source label from source image to the destination image by using
   a specified destination label for a specific time step. Function processes the whole image volume of the specified time step.
   @remark the function assumes that it is only called with source and destination image of same geometry.
   @remark CAUTION: The function is not save, if sourceImage and destinationImage are the same instance and you transfer more then one
   label, because the changes are made in-place for performance reasons but not in one pass. If a mapped value A equals a "old value"
   that is later in the mapping, one ends up with a wrong transfer, as a pixel would be first mapped to A and then latter again, because
   it is also an "old" value in the mapping table.
   @param sourceImage Pointer to the image that should be used as source for the transfer.
   @param destinationImage Pointer to the image that should be used as destination for the transfer.
   @param destinationLabelVector Reference to the vector of labels (incl. lock states) in the destination image. Unknown pixel
   values in the destinationImage will be assumed to be unlocked.
   @param sourceBackground Value indicating the background in the source image.
   @param destinationBackground Value indicating the background in the destination image.
   @param destinationBackgroundLocked Value indicating the lock state of the background in the destination image.
   @param labelMapping Map that encodes the mappings of all label pixel transfers that should be done. First element is the
   label in the source image. The second element is the label that transferred pixels should become in the destination image.
   The order in which the labels will be transfered is the same order of elements in the labelMapping.
   If you use a heterogeneous label mapping (e.g. (1,2); so changing the label while transferring), keep in mind that
   for the MergeStyle and OverwriteStyle only the destination label (second element) is relevant (e.g. what should be
   altered with MergeStyle Replace).
   @param mergeStyle indicates how the transfer should be done (merge or replace). For more details see documentation of
   MultiLabelSegmentation::MergeStyle.
   @param overwriteStlye indicates if label locks in the destination image should be regarded or not. For more details see
   documentation of MultiLabelSegmentation::OverwriteStyle.
   @param timeStep indicate the time step that should be transferred.
   @pre sourceImage, destinationImage and destinationLabelVector must be valid
   @pre sourceImage and destinationImage must contain the indicated timeStep
   @pre destinationLabelVector must contain all indicated destinationLabels for mapping.*/
   MITKMULTILABEL_EXPORT void TransferLabelContentAtTimeStep(const Image* sourceImage, Image* destinationImage, const mitk::ConstLabelVector& destinationLabelVector,
     const TimeStepType timeStep, mitk::Label::PixelType sourceBackground = LabelSetImage::UNLABELED_VALUE,
     mitk::Label::PixelType destinationBackground = LabelSetImage::UNLABELED_VALUE,
     bool destinationBackgroundLocked = false,
     LabelValueMappingVector labelMapping = { {1,1} },
     MultiLabelSegmentation::MergeStyle mergeStyle = MultiLabelSegmentation::MergeStyle::Replace,
     MultiLabelSegmentation::OverwriteStyle overwriteStlye = MultiLabelSegmentation::OverwriteStyle::RegardLocks);
 
   /**Helper function that transfers pixels of the specified source label from source image to the destination image by using
   a specified destination label. Function processes the whole image volume for all time steps.
   For more details please see TransferLabelContentAtTimeStep.
   @sa TransferLabelContentAtTimeStep*/
   MITKMULTILABEL_EXPORT void TransferLabelContent(const Image* sourceImage, Image* destinationImage, const mitk::ConstLabelVector& destinationLabelVector,
     mitk::Label::PixelType sourceBackground = LabelSetImage::UNLABELED_VALUE,
     mitk::Label::PixelType destinationBackground = LabelSetImage::UNLABELED_VALUE,
     bool destinationBackgroundLocked = false,
     LabelValueMappingVector labelMapping = { {1,1} },
     MultiLabelSegmentation::MergeStyle mergeStyle = MultiLabelSegmentation::MergeStyle::Replace,
     MultiLabelSegmentation::OverwriteStyle overwriteStlye = MultiLabelSegmentation::OverwriteStyle::RegardLocks);
 
 } // namespace mitk
 
 #endif
diff --git a/Modules/Multilabel/mitkLabelSetImageConverter.cpp b/Modules/Multilabel/mitkLabelSetImageConverter.cpp
index c571726cea..c37bd83a9c 100644
--- a/Modules/Multilabel/mitkLabelSetImageConverter.cpp
+++ b/Modules/Multilabel/mitkLabelSetImageConverter.cpp
@@ -1,194 +1,420 @@
 /*============================================================================
 
 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 <numeric>
+
 #include <mitkITKImageImport.h>
 #include <mitkImageAccessByItk.h>
 #include <mitkImageCast.h>
 #include <mitkLabelSetImageConverter.h>
+#include <mitkLabelSetImageHelper.h>
 
 #include <itkComposeImageFilter.h>
 #include <itkExtractImageFilter.h>
 #include <itkImageDuplicator.h>
 #include <itkVectorIndexSelectionCastImageFilter.h>
 
 template <typename TPixel, unsigned int VDimension>
 static void ConvertLabelSetImageToImage(const itk::Image<TPixel, VDimension> *,
                                         mitk::LabelSetImage::ConstPointer labelSetImage,
                                         mitk::Image::Pointer &image)
 {
   typedef itk::Image<TPixel, VDimension> ImageType;
   typedef itk::ComposeImageFilter<ImageType> ComposeFilterType;
   typedef itk::ImageDuplicator<ImageType> DuplicatorType;
 
   auto numberOfLayers = labelSetImage->GetNumberOfLayers();
 
   if (numberOfLayers > 1)
   {
     auto vectorImageComposer = ComposeFilterType::New();
 
     for (decltype(numberOfLayers) layer = 0; layer < numberOfLayers; ++layer)
     {
       auto layerImage = mitk::ImageToItkImage<TPixel, VDimension>(
         labelSetImage->GetGroupImage(layer));
 
       vectorImageComposer->SetInput(layer, layerImage);
     }
 
     vectorImageComposer->Update();
     // mitk::GrabItkImageMemory does not support 4D, this will handle 4D correctly
     // and create a memory managed copy
     image = mitk::ImportItkImage(vectorImageComposer->GetOutput())->Clone();
   }
   else
   {
     auto layerImage = mitk::ImageToItkImage<TPixel, VDimension>(labelSetImage);
 
     auto duplicator = DuplicatorType::New();
     duplicator->SetInputImage(layerImage);
     duplicator->Update();
 
     // mitk::GrabItkImageMemory does not support 4D, this will handle 4D correctly
     // and create a memory managed copy
     image = mitk::ImportItkImage(duplicator->GetOutput())->Clone();
   }
 }
 
 mitk::Image::Pointer mitk::ConvertLabelSetImageToImage(LabelSetImage::ConstPointer labelSetImage)
 {
   Image::Pointer image;
 
   if (labelSetImage->GetNumberOfLayers() > 0)
   {
     if (labelSetImage->GetDimension() == 4)
     {
       AccessFixedDimensionByItk_n(labelSetImage, ::ConvertLabelSetImageToImage, 4, (labelSetImage, image));
     }
     else
     {
       AccessByItk_2(labelSetImage->GetGroupImage(0), ::ConvertLabelSetImageToImage, labelSetImage, image);
     }
 
     image->SetTimeGeometry(labelSetImage->GetTimeGeometry()->Clone());
   }
 
   return image;
 }
 
 
 template <typename TPixel, unsigned int VDimensions>
 static void SplitVectorImage(const itk::VectorImage<TPixel, VDimensions>* image,
   std::vector<mitk::Image::Pointer>& result)
 {
   typedef itk::VectorImage<TPixel, VDimensions> VectorImageType;
   typedef itk::Image<TPixel, VDimensions> ImageType;
   typedef itk::VectorIndexSelectionCastImageFilter<VectorImageType, ImageType> VectorIndexSelectorType;
 
   auto numberOfLayers = image->GetVectorLength();
   for (decltype(numberOfLayers) layer = 0; layer < numberOfLayers; ++layer)
   {
     auto layerSelector = VectorIndexSelectorType::New();
     layerSelector->SetInput(image);
     layerSelector->SetIndex(layer);
     layerSelector->Update();
 
     mitk::Image::Pointer layerImage = mitk::GrabItkImageMemoryChannel(layerSelector->GetOutput(), nullptr, nullptr, false);
     result.push_back(layerImage);
   }
 }
 
 std::vector<mitk::Image::Pointer> mitk::SplitVectorImage(const Image* vecImage)
 {
   if (nullptr == vecImage)
   {
     mitkThrow() << "Invalid usage; nullptr passed to SplitVectorImage.";
   }
 
   if (vecImage->GetChannelDescriptor().GetPixelType().GetPixelType() != itk::IOPixelEnum::VECTOR)
   {
     mitkThrow() << "Invalid usage of SplitVectorImage; passed image is not a vector image. Present pixel type: "<< vecImage->GetChannelDescriptor().GetPixelType().GetPixelTypeAsString();
   }
 
   std::vector<mitk::Image::Pointer> result;
 
   if (4 == vecImage->GetDimension())
   {
     AccessVectorFixedDimensionByItk_n(vecImage, ::SplitVectorImage, 4, (result));
   }
   else
   {
     AccessVectorPixelTypeByItk_n(vecImage, ::SplitVectorImage, (result));
   }
 
   for (auto image : result)
   {
     image->SetTimeGeometry(vecImage->GetTimeGeometry()->Clone());
   }
 
   return result;
 }
 
 mitk::LabelSetImage::Pointer mitk::ConvertImageToLabelSetImage(Image::Pointer image)
 {
   std::vector<mitk::Image::Pointer> groupImages;
 
   if (image.IsNotNull())
   {
     if (image->GetChannelDescriptor().GetPixelType().GetPixelType() == itk::IOPixelEnum::VECTOR)
     {
       groupImages = SplitVectorImage(image);
     }
     else
     {
       groupImages.push_back(image);
     }
   }
   auto labelSetImage = ConvertImageVectorToLabelSetImage(groupImages, image->GetTimeGeometry());
 
   return labelSetImage;
 }
 
 mitk::LabelSetImage::Pointer mitk::ConvertImageVectorToLabelSetImage(const std::vector<mitk::Image::Pointer>& images, const mitk::TimeGeometry* timeGeometry)
 {
   LabelSetImage::Pointer labelSetImage = mitk::LabelSetImage::New();
 
   for (auto& groupImage : images)
   {
     if (groupImage== images.front())
     {
       labelSetImage->InitializeByLabeledImage(groupImage);
     }
     else
     {
       labelSetImage->AddLayer(groupImage);
     }
   }
 
   labelSetImage->SetTimeGeometry(timeGeometry->Clone());
   return labelSetImage;
 }
 
 mitk::LabelSetImage::LabelVectorType mitk::GenerateLabelSetWithMappedValues(const LabelSetImage::ConstLabelVectorType& sourceLabelset, LabelValueMappingVector labelMapping)
 {
   LabelSetImage::LabelVectorType result;
 
   for (auto oldLabel : sourceLabelset)
   {
     auto finding = std::find_if(labelMapping.begin(), labelMapping.end(), [oldLabel](const std::pair<Label::PixelType, Label::PixelType>& mapping) {return oldLabel->GetValue() == mapping.first; });
     if (finding != labelMapping.end())
     {
       auto clonedLabel = oldLabel->Clone();
       clonedLabel->SetValue(finding->second);
       result.push_back(clonedLabel);
     }
   }
   return result;
 }
+
+template <typename SourceImageType>
+void ConvertImageToGroupImageInternal(const SourceImageType* sourceImage, mitk::Image* groupImage, mitk::LabelSetImage::LabelValueVectorType& foundLabels)
+{
+  using GroupImageType = typename SourceImageType::template Rebind<mitk::LabelSetImage::LabelValueType>::Type;
+
+  using SourceIteratorType = itk::ImageRegionConstIteratorWithIndex<SourceImageType>;
+  using TargetIteratorType = itk::ImageRegionIterator<GroupImageType>;
+
+  auto targetImage = mitk::ImageToItkImage< mitk::LabelSetImage::LabelValueType, SourceImageType::ImageDimension>(groupImage);
+
+  TargetIteratorType targetIter(targetImage, targetImage->GetRequestedRegion());
+  targetIter.GoToBegin();
+
+  SourceIteratorType sourceIter(sourceImage, sourceImage->GetRequestedRegion());
+  sourceIter.GoToBegin();
+
+  std::set<mitk::LabelSetImage::LabelValueType> detectedValues;
+
+  while (!sourceIter.IsAtEnd())
+  {
+    const auto originalSourceValue = sourceIter.Get();
+    const auto sourceValue = static_cast<mitk::LabelSetImage::LabelValueType>(originalSourceValue);
+
+    if (originalSourceValue > mitk::Label::MAX_LABEL_VALUE)
+    {
+      mitkThrow() << "Cannot initialize MultiLabelSegmentation by image. Image contains a pixel value that exceeds the label value range. Invalid pixel value:" << originalSourceValue;
+    }
+
+    targetIter.Set(sourceValue);
+
+    if (sourceValue != mitk::Label::UNLABELED_VALUE)
+      detectedValues.insert(sourceValue);
+
+    ++sourceIter;
+    ++targetIter;
+  }
+
+  foundLabels.clear();
+  foundLabels.insert(foundLabels.begin(), detectedValues.begin(), detectedValues.end());
+}
+
+mitk::Image::Pointer mitk::ConvertImageToGroupImage(const Image* inputImage, mitk::LabelSetImage::LabelValueVectorType& foundLabels)
+{
+  if (nullptr == inputImage || inputImage->IsEmpty() || !inputImage->IsInitialized())
+    mitkThrow() << "Invalid labeled image.";
+
+  auto result = Image::New();
+  result->Initialize(mitk::MakePixelType<mitk::LabelSetImage::LabelValueType, mitk::LabelSetImage::LabelValueType, 1>(), *(inputImage->GetTimeGeometry()));
+
+  try
+  {
+    if (result->GetDimension() == 3)
+    {
+      AccessFixedDimensionByItk_2(inputImage, ConvertImageToGroupImageInternal, 3, result, foundLabels);
+    }
+    else if (result->GetDimension() == 4)
+    {
+      AccessFixedDimensionByItk_2(inputImage, ConvertImageToGroupImageInternal, 4, result, foundLabels);
+    }
+    else
+    {
+      mitkThrow() << result->GetDimension() << "-dimensional group images not yet supported";
+    }
+  }
+  catch (Exception& e)
+  {
+    mitkReThrow(e) << "Could not initialize by provided labeled image.";
+  }
+  catch (...)
+  {
+    mitkThrow() << "Could not initialize by provided labeled image due to unknown error.";
+  }
+
+  return result;
+}
+
+bool mitk::CheckForLabelValueConflictsAndResolve(const mitk::LabelSetImage::LabelValueVectorType& newValues, mitk::LabelSetImage::LabelValueVectorType& usedLabelValues, mitk::LabelSetImage::LabelValueVectorType& correctedLabelValues)
+{
+  bool corrected = false;
+  correctedLabelValues.clear();
+
+  for (const auto newV : newValues)
+  {
+    auto finding = std::find(usedLabelValues.begin(), usedLabelValues.end(), newV);
+    if (finding == usedLabelValues.end())
+    {
+      correctedLabelValues.push_back(newV);
+      usedLabelValues.push_back(newV);
+    }
+    else
+    {
+      const auto maxValue = *(std::max_element(usedLabelValues.begin(), usedLabelValues.end()));
+      if (maxValue == Label::MAX_LABEL_VALUE) mitkThrow() << "Cannot correct label values. All available values are used. A segmentation cannot contain more labels.";
+
+      const auto correctedV = maxValue+1;
+      correctedLabelValues.push_back(correctedV);
+      usedLabelValues.push_back(correctedV);
+      corrected = true;
+    }
+  }
+
+  return corrected;
+}
+
+namespace
+{
+  template <typename ImageType>
+  void ClearBufferProcessing(ImageType* itkImage)
+  {
+    itkImage->FillBuffer(0);
+  }
+
+  void ClearImageBuffer(mitk::Image* image)
+  {
+    if (image->GetDimension() == 4)
+    { //remark: this extra branch was added, because LabelSetImage instances can be
+      //dynamic (4D), but AccessByItk by support only supports 2D and 3D.
+      //The option to change the CMake default dimensions for AccessByItk was
+      //dropped (for details see discussion in T28756)
+      AccessFixedDimensionByItk(image, ClearBufferProcessing, 4);
+    }
+    else
+    {
+      AccessByItk(image, ClearBufferProcessing);
+    }
+  }
+}
+
+mitk::Image::Pointer mitk::CreateLabelMask(const LabelSetImage* segmentation, LabelSetImage::LabelValueType labelValue, bool createBinaryMap)
+{
+  if (nullptr==segmentation)
+    mitkThrow() << "Error, cannot create label mask. Passed segmentation is nullptr.";
+  
+  if (!segmentation->ExistLabel(labelValue))
+    mitkThrow() << "Error, cannot create label mask. Label ID is invalid. Invalid ID: " << labelValue;
+
+  auto mask = mitk::Image::New();
+
+  // mask->Initialize(segmentation) does not work here if this label set image has a single slice,
+  // since the mask would be automatically flattened to a 2-d image, whereas we expect the
+  // original dimension of this label set image. Hence, initialize the mask more explicitly:
+  mask->Initialize(segmentation->GetPixelType(), segmentation->GetDimension(), segmentation->GetDimensions());
+  mask->SetTimeGeometry(segmentation->GetTimeGeometry()->Clone());
+
+  ClearImageBuffer(mask);
+
+  const auto groupID = segmentation->GetGroupIndexOfLabel(labelValue);
+
+  auto destinationLabel = segmentation->GetLabel(labelValue)->Clone();
+  if (createBinaryMap) destinationLabel->SetValue(1);
+
+  TransferLabelContent(segmentation->GetGroupImage(groupID),
+    mask.GetPointer(),
+    { destinationLabel },
+    LabelSetImage::UNLABELED_VALUE,
+    LabelSetImage::UNLABELED_VALUE, false,
+    { { labelValue, destinationLabel->GetValue()} },
+    MultiLabelSegmentation::MergeStyle::Replace,
+    MultiLabelSegmentation::OverwriteStyle::IgnoreLocks);
+
+  return mask;
+}
+
+std::pair<mitk::Image::Pointer, mitk::IDToLabelClassNameMapType> mitk::CreateLabelClassMap(const LabelSetImage* segmentation, LabelSetImage::GroupIndexType groupID, const LabelSetImage::LabelValueVectorType& selectedLabels)
+{
+  if (nullptr == segmentation) mitkThrow() << "Error, cannot create label class map. Passed segmentation is nullptr.";
+  if (!segmentation->ExistGroup(groupID)) mitkThrow() << "Error, cannot create label  class map. GroupID is invalid. Invalid ID: " << groupID;
+
+  auto map = mitk::Image::New();
+
+  // map->Initialize(segmentation) does not work here if this label set image has a single slice,
+  // since the map would be automatically flattened to a 2-d image, whereas we expect the
+  // original dimension of this label set image. Hence, initialize the map more explicitly:
+  map->Initialize(segmentation->GetPixelType(), segmentation->GetDimension(), segmentation->GetDimensions());
+  map->SetTimeGeometry(segmentation->GetTimeGeometry()->Clone());
+
+  ClearImageBuffer(map);
+
+  // get relevant labels (as intersect of groupLabels and selectedLabels
+  auto groupValues = segmentation->GetLabelValuesByGroup(groupID);
+  auto relevantDetectLamba = [&selectedLabels](LabelSetImage::LabelValueVectorType& result, LabelSetImage::LabelValueType element)
+    {
+      if (std::find(selectedLabels.begin(), selectedLabels.end(), element) != selectedLabels.end())
+      {
+        result.push_back(element);
+      }
+      return result;
+    };
+
+  auto relevantGroupValues = std::accumulate(groupValues.begin(),
+    groupValues.end(),
+    LabelSetImage::LabelValueVectorType(),
+    relevantDetectLamba);
+
+  // construct class mapping
+  auto classToValueMap = LabelSetImageHelper::SplitLabelValuesByClassNamwe(segmentation, groupID, relevantGroupValues);
+
+  ConstLabelVector destLabels;
+  LabelValueMappingVector transferMapping;
+  IDToLabelClassNameMapType classLookUp;
+
+  for (const auto& [className, labelValues] : classToValueMap)
+  {
+    LabelSetImage::LabelValueType classValue = classLookUp.size() + 1;
+    classLookUp.insert(std::make_pair(classValue, className));
+    destLabels.push_back(Label::New(classValue, className));
+    for (const auto& labelValue : labelValues)
+    {
+      transferMapping.emplace_back(std::make_pair(labelValue, classValue));
+    }
+  }
+
+  TransferLabelContent(segmentation->GetGroupImage(groupID), map.GetPointer(),
+    destLabels, LabelSetImage::UNLABELED_VALUE, LabelSetImage::UNLABELED_VALUE, false, transferMapping, MultiLabelSegmentation::MergeStyle::Replace, MultiLabelSegmentation::OverwriteStyle::IgnoreLocks);
+
+  return std::make_pair(map, classLookUp);
+}
+
+std::pair<mitk::Image::Pointer, mitk::IDToLabelClassNameMapType> mitk::CreateLabelClassMap(const LabelSetImage* segmentation, LabelSetImage::GroupIndexType groupID)
+{
+  return CreateLabelClassMap(segmentation, groupID, segmentation->GetLabelValuesByGroup(groupID));
+}
diff --git a/Modules/Multilabel/mitkLabelSetImageConverter.h b/Modules/Multilabel/mitkLabelSetImageConverter.h
index 09121dd627..349560bc4e 100644
--- a/Modules/Multilabel/mitkLabelSetImageConverter.h
+++ b/Modules/Multilabel/mitkLabelSetImageConverter.h
@@ -1,40 +1,76 @@
 /*============================================================================
 
 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 mitkLabelSetImageConverter_h
 #define mitkLabelSetImageConverter_h
 
 #include <mitkLabelSetImage.h>
 
 namespace mitk
 {
   /**
    * \brief Convert mitk::LabelSetImage to mitk::Image (itk::VectorImage)
    */
   MITKMULTILABEL_EXPORT Image::Pointer ConvertLabelSetImageToImage(LabelSetImage::ConstPointer labelSetImage);
 
   /**
    * \brief Convert mitk::Image to mitk::LabelSetImage, templating and differentation between itk::Image and
    * itk::VectorImage is internal
    */
   MITKMULTILABEL_EXPORT LabelSetImage::Pointer ConvertImageToLabelSetImage(Image::Pointer image);
   MITKMULTILABEL_EXPORT LabelSetImage::Pointer ConvertImageVectorToLabelSetImage(const std::vector<mitk::Image::Pointer>& images, const TimeGeometry* timeGeometry);
 
   MITKMULTILABEL_EXPORT std::vector<mitk::Image::Pointer> SplitVectorImage(const Image* vecImage);
 
   /** Function takes a vector of labels and transfers all labels as clones with adapted label values to the result vector.
   The values will be adapted according to the provided mapping (key is the old value, value the new).
   @remark: Only labels will be transfered, nothing else. So things like message observers or m_ReservedLabelValuesFunctor must be copied explicitly.*/
   MITKMULTILABEL_EXPORT LabelSetImage::LabelVectorType GenerateLabelSetWithMappedValues(const LabelSetImage::ConstLabelVectorType&, LabelValueMappingVector labelMapping);
+
+  MITKMULTILABEL_EXPORT Image::Pointer ConvertImageToGroupImage(const Image* inputImage, mitk::LabelSetImage::LabelValueVectorType& foundLabels);
+
+  MITKMULTILABEL_EXPORT bool CheckForLabelValueConflictsAndResolve(const mitk::LabelSetImage::LabelValueVectorType& newValues, mitk::LabelSetImage::LabelValueVectorType& usedLabelValues, mitk::LabelSetImage::LabelValueVectorType& correctedLabelValues);
+
+  /** Function creates a binary mask representing only the specified label of the multi label segmentation.
+  * @param segmentation Pointer to the segmentation that is the source for the mask.
+  * @param labelValue the label that should be extracted.
+  * @param createBinaryMap indicates if the label pixels should be indicated by the value 1 (createBinaryMap==true) or by the value of the label
+  * (createBinaryMap==false).
+  * @pre segmentation must point to a valid instance.
+  * @pre labelValue must exist in segmentation.*/
+  MITKMULTILABEL_EXPORT Image::Pointer CreateLabelMask(const LabelSetImage* segmentation, LabelSetImage::LabelValueType labelValue, bool createBinaryMap = true);
+
+  /** Function creates a map of all label classes in a specified group.
+  * @param segmentation Pointer to the segmentation that is the source for the map.
+  * @param groupID the group that should be used.
+  * @param selectedLabels The selected labels that should be represented in the class map. This is meant as white list, therefore only
+  * label values listed in the list are used. Invalid label values (not existing in the group) will be ignored.
+  * @return Returns a pair where first is the pointer to the created map image and second is the look up table that indicated
+  * the pixel value of each found class in the map.
+  * @pre segmentation must point to a valid instance.
+  * @pre groupID must exist in segmentation.*/
+  using IDToLabelClassNameMapType = std::map<LabelSetImage::LabelValueType, std::string>;
+  MITKMULTILABEL_EXPORT std::pair<Image::Pointer, IDToLabelClassNameMapType> CreateLabelClassMap(const LabelSetImage* segmentation, LabelSetImage::GroupIndexType groupID, const LabelSetImage::LabelValueVectorType& selectedLabels);
+  /** Function creates a map of all label classes in a specified group.
+  * @overload
+  * This version always uses all labels of a group.
+  * @param segmentation Pointer to the segmentation that is the source for the map.
+  * @param groupID the group that should be used.
+  * @return Returns a pair where first is the pointer to the created map image and second is the look up table that indicated
+  * the pixel value of each found class in the map.
+  * @pre segmentation must point to a valid instance.
+  * @pre groupID must exist in segmentation.*/
+  MITKMULTILABEL_EXPORT std::pair<Image::Pointer, IDToLabelClassNameMapType> CreateLabelClassMap(const LabelSetImage* segmentation, LabelSetImage::GroupIndexType groupID);
+
 }
 
 #endif
diff --git a/Modules/Multilabel/mitkLabelSetImageHelper.cpp b/Modules/Multilabel/mitkLabelSetImageHelper.cpp
index 4dda62b8bb..e0f938d4e4 100644
--- a/Modules/Multilabel/mitkLabelSetImageHelper.cpp
+++ b/Modules/Multilabel/mitkLabelSetImageHelper.cpp
@@ -1,144 +1,201 @@
 /*============================================================================
 
 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 <mitkLabelSetImageHelper.h>
 
 #include <mitkLabelSetImage.h>
 #include <mitkExceptionMacro.h>
 #include <mitkProperties.h>
 
 #include <array>
 #include <regex>
 #include <vector>
 
 namespace
 {
   template <typename T>
   std::array<int, 3> QuantizeColor(const T* color)
   {
     return {
       static_cast<int>(std::round(color[0] * 255)),
       static_cast<int>(std::round(color[1] * 255)),
       static_cast<int>(std::round(color[2] * 255)) };
   }
 
   mitk::Color FromLookupTableColor(const double* lookupTableColor)
   {
     mitk::Color color;
     color.Set(
       static_cast<float>(lookupTableColor[0]),
       static_cast<float>(lookupTableColor[1]),
       static_cast<float>(lookupTableColor[2]));
     return color;
   }
 }
 
 mitk::DataNode::Pointer mitk::LabelSetImageHelper::CreateEmptySegmentationNode(const std::string& segmentationName)
 {
   auto newSegmentationNode = mitk::DataNode::New();
   newSegmentationNode->SetName(segmentationName);
 
   // initialize "showVolume"-property to false to prevent recalculating the volume while working on the segmentation
   newSegmentationNode->SetProperty("showVolume", mitk::BoolProperty::New(false));
 
   return newSegmentationNode;
 }
 
 
 mitk::DataNode::Pointer mitk::LabelSetImageHelper::CreateNewSegmentationNode(const DataNode* referenceNode,
   const Image* initialSegmentationImage, const std::string& segmentationName)
 {
   std::string newSegmentationName = segmentationName;
   if (newSegmentationName.empty())
   {
     newSegmentationName = referenceNode->GetName();
     newSegmentationName.append("-labels");
   }
 
   if (nullptr == initialSegmentationImage)
   {
     return nullptr;
   }
 
   auto newLabelSetImage = mitk::LabelSetImage::New();
   try
   {
     newLabelSetImage->Initialize(initialSegmentationImage);
   }
   catch (mitk::Exception &e)
   {
     mitkReThrow(e) << "Could not initialize new label set image.";
     return nullptr;
   }
 
   auto newSegmentationNode = CreateEmptySegmentationNode(newSegmentationName);
   newSegmentationNode->SetData(newLabelSetImage);
 
   return newSegmentationNode;
 }
 
-mitk::Label::Pointer mitk::LabelSetImageHelper::CreateNewLabel(const LabelSetImage* labelSetImage, const std::string& namePrefix)
+mitk::Label::Pointer mitk::LabelSetImageHelper::CreateNewLabel(const LabelSetImage* labelSetImage, const std::string& namePrefix, bool hideIDIfUnique)
 {
   if (nullptr == labelSetImage)
     return nullptr;
 
   const std::regex genericLabelNameRegEx(namePrefix + " ([1-9][0-9]*)");
   int maxGenericLabelNumber = 0;
 
   std::vector<std::array<int, 3>> colorsInUse = { {0,0,0} }; //black is always in use.
 
   for (auto & label : labelSetImage->GetLabels())
   {
     auto labelName = label->GetName();
     std::smatch match;
 
     if (std::regex_match(labelName, match, genericLabelNameRegEx))
       maxGenericLabelNumber = std::max(maxGenericLabelNumber, std::stoi(match[1].str()));
 
     const auto quantizedLabelColor = QuantizeColor(label->GetColor().data());
 
     if (std::find(colorsInUse.begin(), colorsInUse.end(), quantizedLabelColor) == std::end(colorsInUse))
       colorsInUse.push_back(quantizedLabelColor);
   }
 
   auto newLabel = mitk::Label::New();
-  newLabel->SetName(namePrefix + " " + std::to_string(maxGenericLabelNumber + 1));
+  if (hideIDIfUnique && 0 == maxGenericLabelNumber)
+  {
+    newLabel->SetName(namePrefix);
+  }
+  else
+  {
+    newLabel->SetName(namePrefix + " " + std::to_string(maxGenericLabelNumber + 1));
+  }
 
   auto lookupTable = mitk::LookupTable::New();
   lookupTable->SetType(mitk::LookupTable::LookupTableType::MULTILABEL);
 
   std::array<double, 3> lookupTableColor;
   const int maxTries = 25;
   bool newColorFound = false;
 
   for (int i = 0; i < maxTries; ++i)
   {
     lookupTable->GetColor(i, lookupTableColor.data());
 
     auto quantizedLookupTableColor = QuantizeColor(lookupTableColor.data());
 
     if (std::find(colorsInUse.begin(), colorsInUse.end(), quantizedLookupTableColor) == std::end(colorsInUse))
     {
       newLabel->SetColor(FromLookupTableColor(lookupTableColor.data()));
       newColorFound = true;
       break;
     }
   }
 
   if (!newColorFound)
   {
     lookupTable->GetColor(labelSetImage->GetTotalNumberOfLabels(), lookupTableColor.data());
     newLabel->SetColor(FromLookupTableColor(lookupTableColor.data()));
   }
 
   return newLabel;
 }
+
+mitk::LabelSetImageHelper::GroupIDToLabelValueMapType
+mitk::LabelSetImageHelper::SplitLabelValuesByGroup(const LabelSetImage* labelSetImage, const LabelSetImage::LabelValueVectorType& labelValues)
+{
+  if (nullptr == labelSetImage)
+    mitkThrow() << "Cannot split label values. Invalid LabelSetImage pointer passed";
+
+  GroupIDToLabelValueMapType result;
+
+  for (auto value : labelValues)
+  {
+    auto groupID = labelSetImage->GetGroupIndexOfLabel(value);
+
+    //if groupID does not exist in result this call will also init an empty vector.
+    result[groupID].push_back(value);
+  }
+
+  return result;
+}
+
+mitk::LabelSetImageHelper::LabelClassNameToLabelValueMapType
+mitk::LabelSetImageHelper::SplitLabelValuesByClassNamwe(const LabelSetImage* labelSetImage, LabelSetImage::GroupIndexType groupID)
+{
+  if (nullptr == labelSetImage)
+    mitkThrow() << "Cannot split label values. Invalid LabelSetImage pointer passed";
+
+  return SplitLabelValuesByClassNamwe(labelSetImage, groupID, labelSetImage->GetLabelValuesByGroup(groupID));
+}
+
+mitk::LabelSetImageHelper::LabelClassNameToLabelValueMapType
+mitk::LabelSetImageHelper::SplitLabelValuesByClassNamwe(const LabelSetImage* labelSetImage, LabelSetImage::GroupIndexType groupID, const LabelSetImage::LabelValueVectorType& labelValues)
+{
+  if (nullptr == labelSetImage)
+    mitkThrow() << "Cannot split label values. Invalid LabelSetImage pointer passed";
+
+  LabelClassNameToLabelValueMapType result;
+
+  for (const auto value : labelValues)
+  {
+    if (labelSetImage->GetGroupIndexOfLabel(value) == groupID)
+    {
+      auto className = labelSetImage->GetLabel(value)->GetName();
+
+      //if className does not exist in result this call will also init an empty vector.
+      result[className].push_back(value);
+    }
+  }
+
+  return result;
+}
diff --git a/Modules/Multilabel/mitkLabelSetImageHelper.h b/Modules/Multilabel/mitkLabelSetImageHelper.h
index 91c7f11d05..b2bc26daf1 100644
--- a/Modules/Multilabel/mitkLabelSetImageHelper.h
+++ b/Modules/Multilabel/mitkLabelSetImageHelper.h
@@ -1,71 +1,81 @@
 /*============================================================================
 
 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 mitkLabelSetImageHelper_h
 #define mitkLabelSetImageHelper_h
 
 #include <MitkMultilabelExports.h>
 
 #include <mitkDataNode.h>
 #include <mitkLabelSetImage.h>
 
 namespace mitk
 {
   /**
    *
    */
   namespace LabelSetImageHelper
   {
     /**
      * @brief This function creates and returns a new empty segmentation data node.
      * @remark The data is not set. Set it manually to have a properly setup node.
      * @param segmentationName A name for the new segmentation node.
      * @return The new segmentation node as a data node pointer.
      */
     MITKMULTILABEL_EXPORT mitk::DataNode::Pointer CreateEmptySegmentationNode(const std::string& segmentationName = std::string());
 
     /**
      * @brief This function creates and returns a new data node with a new empty segmentation
      * data structure.
      * The segmentation node is named according to the given reference data node, otherwise a name
      * is passed explicitly.
      * Some properties are set to ensure a proper setup segmentation and node
      * (e.g. link the segmentation node with its parent node).
      *
      * @param referenceNode             The reference node from which the name of the new segmentation node
      *                                  is derived.
      * @param initialSegmentationImage  The segmentation image that is used to initialize the label set image.
      * @param segmentationName          An optional name for the new segmentation node.
      *
      * @return                          The new segmentation node as a data node pointer.
      */
     MITKMULTILABEL_EXPORT mitk::DataNode::Pointer CreateNewSegmentationNode(const DataNode* referenceNode,
       const Image* initialSegmentationImage = nullptr, const std::string& segmentationName = std::string());
 
     /**
      * @brief This function creates and returns a new label. The label is automatically assigned an
      *        unused generic label name, depending on existing label names in all label sets of the
      *        given label set image.
      *        The color of the label is selected from the MULTILABEL lookup table, following the same
      *        rules of the naming to likely chose a unique color.
      *
      * @param labelSetImage   The label set image that the new label is added to
      * @param namePrefix      The prefix of the label name that is prepended by a sequential number
+     * @param hideIDIfUnique Indicates if the ID suffix should be added if the label name prefix would be already unique.
+     * true: only add if not unique; false: add always.
      *
      * @return                The new label.
      */
-    MITKMULTILABEL_EXPORT mitk::Label::Pointer CreateNewLabel(const LabelSetImage* labelSetImage, const std::string& namePrefix = "Label");
+    MITKMULTILABEL_EXPORT Label::Pointer CreateNewLabel(const LabelSetImage* labelSetImage, const std::string& namePrefix = "Label", bool hideIDIfUnique = false);
+
+    using GroupIDToLabelValueMapType = std::map<mitk::LabelSetImage::GroupIndexType, LabelSetImage::LabelValueVectorType>;
+    MITKMULTILABEL_EXPORT GroupIDToLabelValueMapType SplitLabelValuesByGroup(const LabelSetImage* labelSetImage, const LabelSetImage::LabelValueVectorType& labelValues);
+
+    using LabelClassNameToLabelValueMapType = std::map<std::string, LabelSetImage::LabelValueVectorType>;
+    MITKMULTILABEL_EXPORT LabelClassNameToLabelValueMapType SplitLabelValuesByClassNamwe(const LabelSetImage* labelSetImage, LabelSetImage::GroupIndexType groupID);
+    MITKMULTILABEL_EXPORT LabelClassNameToLabelValueMapType SplitLabelValuesByClassNamwe(const LabelSetImage* labelSetImage, LabelSetImage::GroupIndexType groupID, const LabelSetImage::LabelValueVectorType& labelValues);
+
 
   } // namespace LabelSetImageHelper
 } // namespace mitk
 
 #endif
diff --git a/Modules/Multilabel/mitkMultiLabelPredicateHelper.cpp b/Modules/Multilabel/mitkMultiLabelPredicateHelper.cpp
new file mode 100644
index 0000000000..9ad43a32d8
--- /dev/null
+++ b/Modules/Multilabel/mitkMultiLabelPredicateHelper.cpp
@@ -0,0 +1,60 @@
+/*============================================================================
+
+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 "mitkMultiLabelPredicateHelper.h"
+
+#include <mitkNodePredicateAnd.h>
+#include <mitkNodePredicateOr.h>
+#include <mitkNodePredicateDataType.h>
+#include <mitkNodePredicateProperty.h>
+#include <mitkNodePredicateNot.h>
+#include <mitkNodePredicateSubGeometry.h>
+#include <mitkLabelSetImage.h>
+
+mitk::NodePredicateBase::Pointer mitk::GetMultiLabelSegmentationPredicate(const mitk::BaseGeometry* referenceGeometry)
+{
+  auto segPredicate = mitk::NodePredicateAnd::New();
+  segPredicate->AddPredicate(mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
+  segPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
+  segPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
+
+  if (nullptr != referenceGeometry)
+    segPredicate = mitk::NodePredicateAnd::New(mitk::NodePredicateSubGeometry::New(referenceGeometry),
+      segPredicate.GetPointer()).GetPointer();
+
+  return segPredicate.GetPointer();
+}
+
+mitk::NodePredicateBase::Pointer mitk::GetSegmentationReferenceImagePredicate()
+{
+  auto isImage = mitk::TNodePredicateDataType<mitk::Image>::New();
+  auto isDwi = mitk::NodePredicateDataType::New("DiffusionImage");
+  auto isDti = mitk::NodePredicateDataType::New("TensorImage");
+  auto isOdf = mitk::NodePredicateDataType::New("OdfImage");
+  auto isSegment = mitk::NodePredicateDataType::New("Segment");
+
+  auto validImages = mitk::NodePredicateOr::New();
+  validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegment)));
+  validImages->AddPredicate(isDwi);
+  validImages->AddPredicate(isDti);
+  validImages->AddPredicate(isOdf);
+
+  auto referencePredicate = mitk::NodePredicateAnd::New();
+  referencePredicate->AddPredicate(validImages);
+  referencePredicate->AddPredicate(mitk::NodePredicateNot::New(GetMultiLabelSegmentationPredicate()));
+  referencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
+  referencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
+
+  return referencePredicate.GetPointer();
+}
+
+
diff --git a/Modules/Multilabel/mitkMultiLabelPredicateHelper.h b/Modules/Multilabel/mitkMultiLabelPredicateHelper.h
new file mode 100644
index 0000000000..2737616517
--- /dev/null
+++ b/Modules/Multilabel/mitkMultiLabelPredicateHelper.h
@@ -0,0 +1,33 @@
+/*============================================================================
+
+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 mitkMultiLabelPredicateHelper_h
+#define mitkMultiLabelPredicateHelper_h
+
+#include <MitkMultilabelExports.h>
+#include <mitkNodePredicateBase.h>
+#include <mitkBaseGeometry.h>
+
+namespace mitk
+{
+  /**
+  @brief Gets a predicate for a valid multi label segmentation node
+  @details Predicate: DataType:LabelSetImage && !(Property:binary) && !(Property:helper object) && isSubGeometry(referenceGeometry; if set) 
+  */
+  mitk::NodePredicateBase::Pointer MITKMULTILABEL_EXPORT GetMultiLabelSegmentationPredicate(const mitk::BaseGeometry* referenceGeometry = nullptr);
+  /**
+  @brief Gets a predicate for the images that can be used as reference for a segmentation.
+  */
+  mitk::NodePredicateBase::Pointer MITKMULTILABEL_EXPORT GetSegmentationReferenceImagePredicate();
+}
+
+#endif
diff --git a/Modules/QtWidgets/include/QmitkMultiNodeSelectionWidget.h b/Modules/QtWidgets/include/QmitkMultiNodeSelectionWidget.h
index 049f6bb643..54c9f87f0f 100644
--- a/Modules/QtWidgets/include/QmitkMultiNodeSelectionWidget.h
+++ b/Modules/QtWidgets/include/QmitkMultiNodeSelectionWidget.h
@@ -1,79 +1,82 @@
 /*============================================================================
 
 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 QmitkMultiNodeSelectionWidget_h
 #define QmitkMultiNodeSelectionWidget_h
 
 #include <MitkQtWidgetsExports.h>
 
 #include <ui_QmitkMultiNodeSelectionWidget.h>
 
 #include <mitkDataStorage.h>
 #include <mitkWeakPointer.h>
 #include <mitkNodePredicateBase.h>
 
 #include <QmitkAbstractNodeSelectionWidget.h>
 #include <QmitkSimpleTextOverlayWidget.h>
 
 class QmitkAbstractDataStorageModel;
 
 /**
 * @class QmitkMultiNodeSelectionWidget
 * @brief Widget that allows to perform and represents a multiple node selection.
 */
 class MITKQTWIDGETS_EXPORT QmitkMultiNodeSelectionWidget : public QmitkAbstractNodeSelectionWidget
 {
   Q_OBJECT
 
 public:
   explicit QmitkMultiNodeSelectionWidget(QWidget* parent = nullptr);
 
   using NodeList = QmitkAbstractNodeSelectionWidget::NodeList;
 
   /**
   * @brief Helper function that is used to check the given selection for consistency.
   *        Returning an empty string assumes that everything is alright and the selection
   *        is valid. If the string is not empty, the content of the string will be used
   *        as error message in the overlay to indicate the problem.
   */
   using SelectionCheckFunctionType = std::function<std::string(const NodeList &)>;
   /**
   * @brief A selection check function can be set. If set the widget uses this function to
   *        check the made/set selection. If the selection is valid, everything is fine.
   *        If selection is indicated as invalid, it will not be communicated by the widget
   *        (no signal emission).
   */
   void SetSelectionCheckFunction(const SelectionCheckFunctionType &checkFunction);
 
+  /** Returns if the current internal selection is violating the current check function, if set.*/
+  bool CurrentSelectionViolatesCheckFunction() const;
+
 public Q_SLOTS:
   void OnEditSelection();
 
 protected Q_SLOTS:
   void OnClearSelection(const mitk::DataNode* node);
 
 protected:
   void changeEvent(QEvent *event) override;
 
   void UpdateInfo() override;
   void OnInternalSelectionChanged() override;
 
   bool AllowEmissionOfSelection(const NodeList& emissionCandidates) const override;
 
   QmitkSimpleTextOverlayWidget* m_Overlay;
 
   SelectionCheckFunctionType m_CheckFunction;
   mutable std::string m_CheckResponse;
 
   Ui_QmitkMultiNodeSelectionWidget m_Controls;
 };
 
 #endif
diff --git a/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.cpp b/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.cpp
index 88bb1d389f..5bbf899831 100644
--- a/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.cpp
+++ b/Modules/QtWidgets/src/QmitkMultiNodeSelectionWidget.cpp
@@ -1,159 +1,164 @@
 /*============================================================================
 
 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 "QmitkMultiNodeSelectionWidget.h"
 
 #include <algorithm>
 
 #include <QmitkCustomVariants.h>
 #include <QmitkNodeSelectionDialog.h>
 #include <QmitkNodeSelectionListItemWidget.h>
 
 QmitkMultiNodeSelectionWidget::QmitkMultiNodeSelectionWidget(QWidget* parent)
   : QmitkAbstractNodeSelectionWidget(parent)
 {
   m_Controls.setupUi(this);
   m_Overlay = new QmitkSimpleTextOverlayWidget(m_Controls.list);
   m_Overlay->setVisible(false);
   m_CheckFunction = [](const NodeList &) { return ""; };
 
   this->OnInternalSelectionChanged();
   this->UpdateInfo();
 
   connect(m_Controls.btnChange, SIGNAL(clicked(bool)), this, SLOT(OnEditSelection()));
 }
 
 void QmitkMultiNodeSelectionWidget::SetSelectionCheckFunction(const SelectionCheckFunctionType &checkFunction)
 {
   m_CheckFunction = checkFunction;
 
   auto newEmission = this->CompileEmitSelection();
   auto newCheckResponse = m_CheckFunction(newEmission);
 
   if (newCheckResponse.empty() && !m_CheckResponse.empty())
   {
     this->EmitSelection(newEmission);
   }
   m_CheckResponse = newCheckResponse;
   this->UpdateInfo();
 }
 
 void QmitkMultiNodeSelectionWidget::OnEditSelection()
 {
   QmitkNodeSelectionDialog* dialog = new QmitkNodeSelectionDialog(this, m_PopUpTitel, m_PopUpHint);
 
   dialog->SetDataStorage(m_DataStorage.Lock());
   dialog->SetNodePredicate(m_NodePredicate);
   dialog->SetCurrentSelection(this->CompileEmitSelection());
   dialog->SetSelectOnlyVisibleNodes(m_SelectOnlyVisibleNodes);
   dialog->SetSelectionMode(QAbstractItemView::MultiSelection);
   dialog->SetSelectionCheckFunction(m_CheckFunction);
 
   m_Controls.btnChange->setChecked(true);
   if (dialog->exec())
   {
     this->HandleChangeOfInternalSelection(dialog->GetSelectedNodes());
   }
   m_Controls.btnChange->setChecked(false);
 
   delete dialog;
 }
 
 void QmitkMultiNodeSelectionWidget::UpdateInfo()
 {
   if (!m_Controls.list->count())
   {
     if (m_IsOptional)
     {
       if (this->isEnabled())
       {
         m_Overlay->SetOverlayText(QStringLiteral("<font class=\"normal\">") + m_EmptyInfo + QStringLiteral("</font>"));
       }
       else
       {
         m_Overlay->SetOverlayText(QStringLiteral("<font class=\"disabled\">") + m_EmptyInfo + QStringLiteral("</font>"));
       }
     }
     else
     {
       if (this->isEnabled())
       {
         m_Overlay->SetOverlayText(QStringLiteral("<font class=\"warning\">") + m_InvalidInfo + QStringLiteral("</font>"));
       }
       else
       {
         m_Overlay->SetOverlayText(QStringLiteral("<font class=\"disabled\">") + m_InvalidInfo + QStringLiteral("</font>"));
       }
     }
   }
   else
   {
     if (!m_CheckResponse.empty())
     {
       m_Overlay->SetOverlayText(QString::fromStdString(m_CheckResponse));
     }
   }
 
   m_Overlay->setVisible(m_Controls.list->count() == 0 || !m_CheckResponse.empty());
 
   for (auto i = 0; i < m_Controls.list->count(); ++i)
   {
     auto item = m_Controls.list->item(i);
     auto widget = qobject_cast<QmitkNodeSelectionListItemWidget*>(m_Controls.list->itemWidget(item));
     widget->SetClearAllowed(m_IsOptional || m_Controls.list->count() > 1);
   }
 }
 
 void QmitkMultiNodeSelectionWidget::OnInternalSelectionChanged()
 {
   m_Controls.list->clear();
   auto currentSelection = this->GetCurrentInternalSelection();
   for (auto& node : currentSelection)
   {
     if (m_NodePredicate.IsNull() || m_NodePredicate->CheckNode(node))
     {
       QListWidgetItem *newItem = new QListWidgetItem;
 
       newItem->setSizeHint(QSize(0, 40));
       QmitkNodeSelectionListItemWidget* widget = new QmitkNodeSelectionListItemWidget;
 
       widget->SetSelectedNode(node);
       widget->SetClearAllowed(m_IsOptional || currentSelection.size() > 1);
 
       connect(widget, &QmitkNodeSelectionListItemWidget::ClearSelection, this, &QmitkMultiNodeSelectionWidget::OnClearSelection);
       newItem->setData(Qt::UserRole, QVariant::fromValue<mitk::DataNode::Pointer>(node));
 
       m_Controls.list->addItem(newItem);
       m_Controls.list->setItemWidget(newItem, widget);
     }
   }
 }
 
 void QmitkMultiNodeSelectionWidget::OnClearSelection(const mitk::DataNode* node)
 {
   this->RemoveNodeFromSelection(node);
 }
 
 void QmitkMultiNodeSelectionWidget::changeEvent(QEvent *event)
 {
   if (event->type() == QEvent::EnabledChange)
   {
     this->UpdateInfo();
   }
   QmitkAbstractNodeSelectionWidget::changeEvent(event);
 }
 
 bool QmitkMultiNodeSelectionWidget::AllowEmissionOfSelection(const NodeList& emissionCandidates) const
 {
   m_CheckResponse = m_CheckFunction(emissionCandidates);
   return m_CheckResponse.empty();
 }
+
+bool QmitkMultiNodeSelectionWidget::CurrentSelectionViolatesCheckFunction() const
+{
+  return !m_CheckResponse.empty();
+}
diff --git a/Modules/Segmentation/Algorithms/mitkShowSegmentationAsSurface.cpp b/Modules/Segmentation/Algorithms/mitkShowSegmentationAsSurface.cpp
index 64efffee41..dec15b7e21 100644
--- a/Modules/Segmentation/Algorithms/mitkShowSegmentationAsSurface.cpp
+++ b/Modules/Segmentation/Algorithms/mitkShowSegmentationAsSurface.cpp
@@ -1,325 +1,326 @@
 /*============================================================================
 
 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 "mitkShowSegmentationAsSurface.h"
 #include "mitkManualSegmentationToSurfaceFilter.h"
 #include "mitkVtkRepresentationProperty.h"
 #include <mitkCoreObjectFactory.h>
 #include <mitkLabelSetImage.h>
+#include <mitkLabelSetImageConverter.h>
 #include <vtkPolyDataNormals.h>
 
 namespace mitk
 {
   ShowSegmentationAsSurface::ShowSegmentationAsSurface()
     : m_UIDGeneratorSurfaces("Surface_"),
       m_IsLabelSetImage(false)
   {
   }
 
   ShowSegmentationAsSurface::~ShowSegmentationAsSurface()
   {
   }
 
   void ShowSegmentationAsSurface::Initialize(const NonBlockingAlgorithm *other)
   {
     Superclass::Initialize(other);
 
     bool syncVisibility(false);
 
     if (other)
     {
       other->GetParameter("Sync visibility", syncVisibility);
     }
 
     SetParameter("Sync visibility", syncVisibility);
     SetParameter("Median kernel size", 3u);
     SetParameter("Apply median", true);
     SetParameter("Smooth", true);
     SetParameter("Gaussian SD", 1.5);
     SetParameter("Decimate mesh", true);
     SetParameter("Decimation rate", 0.8);
     SetParameter("Wireframe", false);
 
     m_SurfaceNodes.clear();
   }
 
   bool ShowSegmentationAsSurface::ReadyToRun()
   {
     try
     {
       Image::Pointer image;
       GetPointerParameter("Input", image);
 
       return image.IsNotNull() && GetGroupNode();
     }
     catch (std::invalid_argument &)
     {
       return false;
     }
   }
 
   bool ShowSegmentationAsSurface::ThreadedUpdateFunction()
   {
     Image::Pointer image;
     GetPointerParameter("Input", image);
 
     bool smooth(true);
     GetParameter("Smooth", smooth);
 
     bool applyMedian(true);
     GetParameter("Apply median", applyMedian);
 
     bool decimateMesh(true);
     GetParameter("Decimate mesh", decimateMesh);
 
     unsigned int medianKernelSize(3);
     GetParameter("Median kernel size", medianKernelSize);
 
     double gaussianSD(1.5);
     GetParameter("Gaussian SD", gaussianSD);
 
     double reductionRate(0.8);
     GetParameter("Decimation rate", reductionRate);
 
     MITK_INFO << "Creating polygon model with smoothing " << smooth << " gaussianSD " << gaussianSD << " median "
               << applyMedian << " median kernel " << medianKernelSize << " mesh reduction " << decimateMesh
               << " reductionRate " << reductionRate;
 
     auto labelSetImage = dynamic_cast<LabelSetImage *>(image.GetPointer());
 
     if (nullptr != labelSetImage)
     {
       const auto labels = labelSetImage->GetLabels();
 
       for (auto label : labels)
       {
-        auto labelImage = labelSetImage->CreateLabelMask(label->GetValue());
+        auto labelImage = CreateLabelMask(labelSetImage, label->GetValue());
 
         if (labelImage.IsNull())
           continue;
 
         auto labelSurface = this->ConvertBinaryImageToSurface(labelImage);
 
         if (labelSurface.IsNull())
           continue;
 
         auto* polyData = labelSurface->GetVtkPolyData();
 
         if (smooth && (polyData->GetNumberOfPoints() < 1 || polyData->GetNumberOfCells() < 1))
         {
           MITK_WARN << "Label \"" << label->GetName() << "\" didn't produce any smoothed surface data (try again without smoothing).";
           continue;
         }
 
         auto node = DataNode::New();
         node->SetData(labelSurface);
         node->SetColor(label->GetColor());
         node->SetName(label->GetName());
 
         m_SurfaceNodes.push_back(node);
       }
     }
     else
     {
       auto surface = this->ConvertBinaryImageToSurface(image);
 
       if (surface.IsNotNull())
       {
         auto* polyData = surface->GetVtkPolyData();
 
         if (smooth && (polyData->GetNumberOfPoints() < 1 || polyData->GetNumberOfCells() < 1))
         {
           MITK_WARN << "Could not produce smoothed surface data (try again without smoothing).";
         }
         else
         {
           auto node = DataNode::New();
           node->SetData(surface);
           m_SurfaceNodes.push_back(node);
         }
       }
     }
 
     m_IsLabelSetImage = nullptr != labelSetImage;
     return true;
   }
 
   void ShowSegmentationAsSurface::ThreadedUpdateSuccessful()
   {
     for (const auto &node : m_SurfaceNodes)
     {
       bool wireframe = false;
       GetParameter("Wireframe", wireframe);
 
       if (wireframe)
       {
         auto representation = dynamic_cast<VtkRepresentationProperty *>(node->GetProperty("material.representation"));
         if (nullptr != representation)
           representation->SetRepresentationToWireframe();
       }
 
       node->SetProperty("opacity", FloatProperty::New(0.3f));
       node->SetProperty("line width", FloatProperty::New(1.0f));
       node->SetProperty("scalar visibility", BoolProperty::New(false));
 
       auto name = node->GetName();
       auto groupNode = this->GetGroupNode();
 
       if (!m_IsLabelSetImage)
       {
         if ((name.empty() || DataNode::NO_NAME_VALUE() == name) && nullptr != groupNode)
           name = groupNode->GetName();
 
         if (name.empty())
           name = "Surface";
       }
 
       bool smooth = true;
       GetParameter("Smooth", smooth);
 
       if (smooth)
         name.append(" (smoothed)");
 
       node->SetName(name);
 
       if (!m_IsLabelSetImage)
       {
         auto colorProp = groupNode->GetProperty("color");
 
         if (nullptr != colorProp)
         {
           node->ReplaceProperty("color", colorProp->Clone());
         }
         else
         {
           node->SetProperty("color", ColorProperty::New(1.0, 1.0, 0.0));
         }
       }
 
       bool showResult = true;
       GetParameter("Show result", showResult);
 
       bool syncVisibility = false;
       GetParameter("Sync visibility", syncVisibility);
 
       auto visibleProp = groupNode->GetProperty("visible");
 
       if (nullptr != visibleProp && syncVisibility)
       {
         node->ReplaceProperty("visible", visibleProp->Clone());
       }
       else
       {
         node->SetProperty("visible", BoolProperty::New(showResult));
       }
 
       if (!m_IsLabelSetImage)
       {
         Image::Pointer image;
         GetPointerParameter("Input", image);
 
         if (image.IsNotNull())
         {
           auto organTypeProp = image->GetProperty("organ type");
 
           if (nullptr != organTypeProp)
             node->GetData()->SetProperty("organ type", organTypeProp);
         }
       }
 
       this->InsertBelowGroupNode(node);
     }
 
     Superclass::ThreadedUpdateSuccessful();
   }
 
   Surface::Pointer ShowSegmentationAsSurface::ConvertBinaryImageToSurface(Image::Pointer binaryImage)
   {
     bool smooth = true;
     GetParameter("Smooth", smooth);
 
     bool applyMedian = true;
     GetParameter("Apply median", applyMedian);
 
     bool decimateMesh = true;
     GetParameter("Decimate mesh", decimateMesh);
 
     unsigned int medianKernelSize = 3;
     GetParameter("Median kernel size", medianKernelSize);
 
     double gaussianSD = 1.5;
     GetParameter("Gaussian SD", gaussianSD);
 
     double reductionRate = 0.8;
     GetParameter("Decimation rate", reductionRate);
 
     auto filter = ManualSegmentationToSurfaceFilter::New();
     filter->SetInput(binaryImage);
     filter->SetThreshold(0.5);
     filter->SetUseGaussianImageSmooth(smooth);
     filter->SetSmooth(smooth);
     filter->SetMedianFilter3D(applyMedian);
 
     if (smooth)
     {
       filter->InterpolationOn();
       filter->SetGaussianStandardDeviation(gaussianSD);
     }
 
     if (applyMedian)
       filter->SetMedianKernelSize(medianKernelSize, medianKernelSize, medianKernelSize);
 
     // Fix to avoid VTK warnings (see T5390)
     if (binaryImage->GetDimension() > 3)
       decimateMesh = false;
 
     if (decimateMesh)
     {
       filter->SetDecimate(ImageToSurfaceFilter::QuadricDecimation);
       filter->SetTargetReduction(reductionRate);
     }
     else
     {
       filter->SetDecimate(ImageToSurfaceFilter::NoDecimation);
     }
 
     filter->UpdateLargestPossibleRegion();
 
     auto surface = filter->GetOutput();
     auto polyData = surface->GetVtkPolyData();
 
     if (nullptr == polyData)
       throw std::logic_error("Could not create polygon model");
 
     polyData->SetVerts(nullptr);
     polyData->SetLines(nullptr);
 
     if (smooth || applyMedian || decimateMesh)
     {
       auto normals = vtkSmartPointer<vtkPolyDataNormals>::New();
 
       normals->AutoOrientNormalsOn();
       normals->FlipNormalsOff();
       normals->SetInputData(polyData);
 
       normals->Update();
 
       surface->SetVtkPolyData(normals->GetOutput());
     }
     else
     {
       surface->SetVtkPolyData(polyData);
     }
 
     return surface;
   }
 }
diff --git a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspector.cpp b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspector.cpp
index fbcaf44727..569e15910e 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspector.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelInspector.cpp
@@ -1,1298 +1,1328 @@
 /*============================================================================
 
 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 <QmitkMultiLabelInspector.h>
 
 // mitk
 #include <mitkRenderingManager.h>
 #include <mitkLabelSetImageHelper.h>
 #include <mitkDICOMSegmentationPropertyHelper.h>
 
 // Qmitk
 #include <QmitkMultiLabelTreeModel.h>
 #include <QmitkLabelColorItemDelegate.h>
 #include <QmitkLabelToggleItemDelegate.h>
 #include <QmitkStyleManager.h>
 
 // Qt
 #include <QMenu>
 #include <QLabel>
 #include <QWidgetAction>
 #include <QMessageBox>
 
 #include <ui_QmitkMultiLabelInspectorControls.h>
 
 QmitkMultiLabelInspector::QmitkMultiLabelInspector(QWidget* parent/* = nullptr*/)
   : QWidget(parent), m_Controls(new Ui::QmitkMultiLabelInspector), m_SegmentationNodeDataMTime(0)
 {
   m_Controls->setupUi(this);
 
   m_Model = new QmitkMultiLabelTreeModel(this);
 
   m_Controls->view->setModel(m_Model);
 
   m_ColorItemDelegate = new QmitkLabelColorItemDelegate(this);
 
   auto visibleIcon = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg"));
   auto invisibleIcon = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/invisible.svg"));
   m_VisibilityItemDelegate = new QmitkLabelToggleItemDelegate(visibleIcon, invisibleIcon, this);
 
   auto lockIcon = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/lock.svg"));
   auto unlockIcon = QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/unlock.svg"));
   m_LockItemDelegate = new QmitkLabelToggleItemDelegate(lockIcon, unlockIcon, this);
 
   auto* view = this->m_Controls->view;
   view->setItemDelegateForColumn(1, m_LockItemDelegate);
   view->setItemDelegateForColumn(2, m_ColorItemDelegate);
   view->setItemDelegateForColumn(3, m_VisibilityItemDelegate);
 
   auto* header = view->header();
   header->setSectionResizeMode(0,QHeaderView::Stretch);
   header->setSectionResizeMode(1, QHeaderView::ResizeToContents);
   header->setSectionResizeMode(2, QHeaderView::ResizeToContents);
   header->setSectionResizeMode(3, QHeaderView::ResizeToContents);
   view->setContextMenuPolicy(Qt::CustomContextMenu);
 
   connect(m_Model, &QAbstractItemModel::modelReset, this, &QmitkMultiLabelInspector::OnModelReset);
   connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), SLOT(OnChangeModelSelection(const QItemSelection&, const QItemSelection&)));
   connect(view, &QAbstractItemView::customContextMenuRequested, this, &QmitkMultiLabelInspector::OnContextMenuRequested);
   connect(view, &QAbstractItemView::doubleClicked, this, &QmitkMultiLabelInspector::OnItemDoubleClicked);
 }
 
 QmitkMultiLabelInspector::~QmitkMultiLabelInspector()
 {
   delete m_Controls;
 }
 
 void QmitkMultiLabelInspector::Initialize()
 {
   m_LastValidSelectedLabels = {};
   m_ModelManipulationOngoing = false;
   m_Model->SetSegmentation(m_Segmentation);
   m_Controls->view->expandAll();
 
   m_LastValidSelectedLabels = {};
 
   //in singel selection mode, if at least one label exist select the first label of the mode.
   if (m_Segmentation.IsNotNull() && !this->GetMultiSelectionMode() && m_Segmentation->GetTotalNumberOfLabels() > 0)
   {
     auto firstIndex = m_Model->FirstLabelInstanceIndex(QModelIndex());
     auto labelVariant = firstIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
 
     if (labelVariant.isValid())
     {
       this->SetSelectedLabel(labelVariant.value<LabelValueType>());
       m_Controls->view->selectionModel()->setCurrentIndex(firstIndex, QItemSelectionModel::NoUpdate);
     }
   }
 }
 
 void QmitkMultiLabelInspector::SetMultiSelectionMode(bool multiMode)
 {
   m_Controls->view->setSelectionMode(multiMode
      ? QAbstractItemView::SelectionMode::MultiSelection
      : QAbstractItemView::SelectionMode::SingleSelection);
 }
 
 bool QmitkMultiLabelInspector::GetMultiSelectionMode() const
 {
   return QAbstractItemView::SelectionMode::MultiSelection == m_Controls->view->selectionMode();
 }
 
 void QmitkMultiLabelInspector::SetAllowVisibilityModification(bool visibilityMod)
 {
   m_AllowVisibilityModification = visibilityMod;
   this->m_Model->SetAllowVisibilityModification(visibilityMod);
 }
 
 void QmitkMultiLabelInspector::SetAllowLabelModification(bool labelMod)
 {
   m_AllowLabelModification = labelMod;
 }
 
 bool QmitkMultiLabelInspector::GetAllowVisibilityModification() const
 {
   return m_AllowVisibilityModification;
 }
 
 void QmitkMultiLabelInspector::SetAllowLockModification(bool lockMod)
 {
   m_AllowLockModification = lockMod;
   this->m_Model->SetAllowLockModification(lockMod);
 }
 
 bool QmitkMultiLabelInspector::GetAllowLockModification() const
 {
   return m_AllowLockModification;
 }
 
 bool QmitkMultiLabelInspector::GetAllowLabelModification() const
 {
   return m_AllowLabelModification;
 }
 
 void QmitkMultiLabelInspector::SetDefaultLabelNaming(bool defaultLabelNaming)
 {
   m_DefaultLabelNaming = defaultLabelNaming;
 }
 
 void QmitkMultiLabelInspector::SetMultiLabelSegmentation(mitk::LabelSetImage* segmentation)
 {
   if (segmentation != m_Segmentation)
   {
     m_Segmentation = segmentation;
     this->Initialize();
     emit SegmentationChanged();
   }
 }
 
 mitk::LabelSetImage* QmitkMultiLabelInspector::GetMultiLabelSegmentation() const
 {
   return m_Segmentation;
 }
 
 void QmitkMultiLabelInspector::SetMultiLabelNode(mitk::DataNode* node)
 {
   if (node != this->m_SegmentationNode.GetPointer())
   {
     m_SegmentationObserver.Reset();
     m_SegmentationNode = node;
     m_SegmentationNodeDataMTime = 0;
 
     if (m_SegmentationNode.IsNotNull())
     {
       auto& widget = *this;
       auto checkAndSetSeg = [&widget, node](const itk::EventObject&)
         {
           if (widget.m_SegmentationNodeDataMTime < node->GetDataReferenceChangedTime())
           {
             auto newSeg = dynamic_cast<mitk::LabelSetImage*>(node->GetData());
             if (nullptr == newSeg) mitkThrow() << "Invalid usage. Node set does not contain a segmentation.";
 
             widget.m_SegmentationNodeDataMTime = node->GetDataReferenceChangedTime();
             widget.SetMultiLabelSegmentation(newSeg);
           }
         };
 
       m_SegmentationObserver.Reset(node, itk::ModifiedEvent(), checkAndSetSeg);
       checkAndSetSeg(itk::ModifiedEvent());
     }
     else
     {
       this->SetMultiLabelSegmentation(nullptr);
     }
   }
 }
 
 mitk::DataNode* QmitkMultiLabelInspector::GetMultiLabelNode() const
 {
   return m_SegmentationNode;
 }
 
 
 bool QmitkMultiLabelInspector::GetModelManipulationOngoing() const
 {
   return m_ModelManipulationOngoing;
 }
 
 void QmitkMultiLabelInspector::OnModelReset()
 {
   m_LastValidSelectedLabels = {};
   m_ModelManipulationOngoing = false;
 }
 
 bool EqualLabelSelections(const QmitkMultiLabelInspector::LabelValueVectorType& selection1, const QmitkMultiLabelInspector::LabelValueVectorType& selection2)
 {
   if (selection1.size() == selection2.size())
   {
     // lambda to compare node pointer inside both lists
     return std::is_permutation(selection1.begin(), selection1.end(), selection2.begin());
   }
 
   return false;
 }
 
 void QmitkMultiLabelInspector::SetSelectedLabels(const LabelValueVectorType& selectedLabels)
 {
   if (EqualLabelSelections(this->GetSelectedLabels(), selectedLabels))
   {
     return;
   }
 
   this->UpdateSelectionModel(selectedLabels);
   m_LastValidSelectedLabels = selectedLabels;
 }
 
 void QmitkMultiLabelInspector::UpdateSelectionModel(const LabelValueVectorType& selectedLabels)
 {
   // create new selection by retrieving the corresponding indexes of the labels
   QItemSelection newCurrentSelection;
   for (const auto& labelID : selectedLabels)
   {
     QModelIndexList matched = m_Model->match(m_Model->index(0, 0), QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole, QVariant(labelID), 1, Qt::MatchRecursive);
     if (!matched.empty())
     {
       newCurrentSelection.select(matched.front(), matched.front());
     }
   }
 
   m_Controls->view->selectionModel()->select(newCurrentSelection, QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Current);
 }
 
 void QmitkMultiLabelInspector::SetSelectedLabel(mitk::LabelSetImage::LabelValueType selectedLabel)
 {
   this->SetSelectedLabels({ selectedLabel });
 }
 
 QmitkMultiLabelInspector::LabelValueVectorType QmitkMultiLabelInspector::GetSelectedLabelsFromSelectionModel() const
 {
   LabelValueVectorType result;
   QModelIndexList selectedIndexes = m_Controls->view->selectionModel()->selectedIndexes();
   for (const auto& index : std::as_const(selectedIndexes))
   {
     QVariant qvariantDataNode = m_Model->data(index, QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
     if (qvariantDataNode.canConvert<mitk::LabelSetImage::LabelValueType>())
     {
       result.push_back(qvariantDataNode.value<mitk::LabelSetImage::LabelValueType>());
     }
   }
   return result;
 }
 
 QmitkMultiLabelInspector::LabelValueVectorType QmitkMultiLabelInspector::GetSelectedLabels() const
 {
   return m_LastValidSelectedLabels;
 }
 
 mitk::Label* QmitkMultiLabelInspector::GetFirstSelectedLabelObject() const
 {
   if (m_LastValidSelectedLabels.empty() || m_Segmentation.IsNull())
     return nullptr;
 
   return m_Segmentation->GetLabel(m_LastValidSelectedLabels.front());
 }
 
 void QmitkMultiLabelInspector::OnChangeModelSelection(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/)
 {
   if (!m_ModelManipulationOngoing)
   {
     auto internalSelection = GetSelectedLabelsFromSelectionModel();
     if (internalSelection.empty())
     {
       //empty selections are not allowed by UI interactions, there should always be at least on label selected.
       //but selections are e.g. also cleared if the model is updated (e.g. due to addition of labels)
       UpdateSelectionModel(m_LastValidSelectedLabels);
     }
     else
     {
       m_LastValidSelectedLabels = internalSelection;
       emit CurrentSelectionChanged(GetSelectedLabels());
     }
   }
 }
 
 void QmitkMultiLabelInspector::WaitCursorOn() const
 {
   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 }
 
 void QmitkMultiLabelInspector::WaitCursorOff() const
 {
   this->RestoreOverrideCursor();
 }
 
 void QmitkMultiLabelInspector::RestoreOverrideCursor() const
 {
   QApplication::restoreOverrideCursor();
 }
 
 mitk::Label* QmitkMultiLabelInspector::GetCurrentLabel() const
 {
   auto currentIndex = this->m_Controls->view->currentIndex();
   auto labelVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelDataRole);
   mitk::Label::Pointer currentIndexLabel = nullptr;
 
   if (labelVariant.isValid())
   {
     auto uncastedLabel = labelVariant.value<void*>();
     currentIndexLabel = static_cast<mitk::Label*>(uncastedLabel);
   }
   return currentIndexLabel;
 }
 
 QmitkMultiLabelInspector::IndexLevelType QmitkMultiLabelInspector::GetCurrentLevelType() const
 {
   auto currentIndex = this->m_Controls->view->currentIndex();
   auto labelInstanceVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceDataRole);
   auto labelVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelDataRole);
 
   if (labelInstanceVariant.isValid() )
   {
     return IndexLevelType::LabelInstance;
   }
   else if (labelVariant.isValid())
   {
     return IndexLevelType::LabelClass;
   }
 
   return IndexLevelType::Group;
 }
 
 QmitkMultiLabelInspector::LabelValueVectorType QmitkMultiLabelInspector::GetCurrentlyAffactedLabelInstances() const
 {
   auto currentIndex = m_Controls->view->currentIndex();
   return m_Model->GetLabelsInSubTree(currentIndex);
 }
 
 QmitkMultiLabelInspector::LabelValueVectorType QmitkMultiLabelInspector::GetLabelInstancesOfSelectedFirstLabel() const
 {
   if (m_Segmentation.IsNull())
     return {};
 
   if (this->GetSelectedLabels().empty())
     return {};
 
   const auto index = m_Model->indexOfLabel(this->GetSelectedLabels().front());
   return m_Model->GetLabelInstancesOfSameLabelClass(index);
 }
 
 mitk::Label* QmitkMultiLabelInspector::AddNewLabelInstanceInternal(mitk::Label* templateLabel)
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of AddNewLabelInstance.";
 
   if (nullptr == templateLabel)
     mitkThrow() << "QmitkMultiLabelInspector is in an invalid state. AddNewLabelInstanceInternal was called with a non existing label as template";
 
   auto groupID = m_Segmentation->GetGroupIndexOfLabel(templateLabel->GetValue());
   m_ModelManipulationOngoing = true;
   auto newLabel = m_Segmentation->AddLabel(templateLabel, groupID, true);
   m_ModelManipulationOngoing = false;
   this->SetSelectedLabel(newLabel->GetValue());
 
   auto index = m_Model->indexOfLabel(newLabel->GetValue());
   if (index.isValid())
   {
     m_Controls->view->expand(index.parent());
   }
   else
   {
     mitkThrow() << "Segmentation or QmitkMultiLabelTreeModel is in an invalid state. Label is not present in the model after adding it to the segmentation. Label value: " << newLabel->GetValue();
   }
 
   emit ModelUpdated();
   return newLabel;
 }
 
 mitk::Label* QmitkMultiLabelInspector::AddNewLabelInstance()
 {
   auto currentLabel = this->GetFirstSelectedLabelObject();
   if (nullptr == currentLabel)
     return nullptr;
 
   auto result = this->AddNewLabelInstanceInternal(currentLabel);
 
   // this is needed as workaround for (T27307). It circumvents the fact that modifications
   // of data (here the segmentation) does not directly trigger the modification of the
   // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
   // listens to the datastorage for modification would not get notified.
   if (m_SegmentationNode.IsNotNull())
   {
     m_SegmentationNode->Modified();
   }
 
   return result;
 }
 
 mitk::Label* QmitkMultiLabelInspector::AddNewLabelInternal(const mitk::LabelSetImage::GroupIndexType& containingGroup)
 {
   auto newLabel = mitk::LabelSetImageHelper::CreateNewLabel(m_Segmentation);
 
   if (!m_DefaultLabelNaming)
     emit LabelRenameRequested(newLabel, false);
 
   m_ModelManipulationOngoing = true;
   m_Segmentation->AddLabel(newLabel, containingGroup, false);
   m_ModelManipulationOngoing = false;
 
   this->SetSelectedLabel(newLabel->GetValue());
 
   auto index = m_Model->indexOfLabel(newLabel->GetValue());
 
   if (!index.isValid())
     mitkThrow() << "Segmentation or QmitkMultiLabelTreeModel is in an invalid state. Label is not present in the "
                    "model after adding it to the segmentation. Label value: " << newLabel->GetValue();
 
   m_Controls->view->expand(index.parent());
 
   emit ModelUpdated();
 
   return newLabel;
 }
 
 mitk::Label* QmitkMultiLabelInspector::AddNewLabel()
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of AddNewLabel.";
 
   if (m_Segmentation.IsNull())
   {
     return nullptr;
   }
 
   auto currentLabel = this->GetFirstSelectedLabelObject();
   mitk::LabelSetImage::GroupIndexType groupID = nullptr != currentLabel
     ? m_Segmentation->GetGroupIndexOfLabel(currentLabel->GetValue())
     : 0;
 
   auto result = AddNewLabelInternal(groupID);
 
   // this is needed as workaround for (T27307). It circumvents the fact that modifications
   // of data (here the segmentation) does not directly trigger the modification of the
   // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
   // listens to the datastorage for modification would not get notified.
   if (m_SegmentationNode.IsNotNull())
   {
     m_SegmentationNode->Modified();
   }
 
   return result;
 }
 
 void QmitkMultiLabelInspector::DeleteLabelInstance()
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of DeleteLabelInstance.";
 
   if (m_Segmentation.IsNull())
     return;
 
   auto label = this->GetFirstSelectedLabelObject();
 
   if (nullptr == label)
     return;
 
   auto index = m_Model->indexOfLabel(label->GetValue());
   auto instanceName = index.data(Qt::DisplayRole);
 
   auto question = "Do you really want to delete label instance \"" + instanceName.toString() + "\"?";
   auto answer = QMessageBox::question(this, QString("Delete label instances"), question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
 
   if (answer == QMessageBox::Yes)
   {
     this->DeleteLabelInternal({ label->GetValue() });
 
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 }
 
 void QmitkMultiLabelInspector::DeleteLabel()
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of DeleteLabel.";
 
   if (m_Segmentation.IsNull())
     return;
 
   const auto label = this->GetFirstSelectedLabelObject();
 
   if (nullptr == label)
     return;
 
   const auto relevantLabels = this->GetLabelInstancesOfSelectedFirstLabel();
 
   if (relevantLabels.empty())
     return;
 
   auto question = "Do you really want to delete label \"" + QString::fromStdString(label->GetName());
   question = relevantLabels.size()==1 ? question + "\"?" : question + "\" with all "+QString::number(relevantLabels.size()) +" instances?";
 
   auto answer = QMessageBox::question(this, QString("Delete label"), question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
 
   if (answer == QMessageBox::Yes)
   {
     this->DeleteLabelInternal(relevantLabels);
 
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 }
 
 void QmitkMultiLabelInspector::DeleteLabelInternal(const LabelValueVectorType& labelValues)
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of DeleteLabelInternal.";
 
   if (m_Segmentation.IsNull())
   {
     return;
   }
 
   QVariant nextLabelVariant;
 
   this->WaitCursorOn();
   m_ModelManipulationOngoing = true;
   for (auto labelValue : labelValues)
   {
     if (labelValue == labelValues.back())
     {
       auto currentIndex = m_Model->indexOfLabel(labelValue);
       auto nextIndex = m_Model->ClosestLabelInstanceIndex(currentIndex);
       nextLabelVariant = nextIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
     }
 
     m_Segmentation->RemoveLabel(labelValue);
   }
   m_ModelManipulationOngoing = false;
   this->WaitCursorOff();
 
   if (nextLabelVariant.isValid())
   {
     auto newLabelValue = nextLabelVariant.value<LabelValueType>();
     this->SetSelectedLabel(newLabelValue);
 
     auto index = m_Model->indexOfLabel(newLabelValue); //we have to get index again, because it could have changed due to remove operation.
     if (index.isValid())
     {
       m_Controls->view->expand(index.parent());
     }
     else
     {
       mitkThrow() << "Segmentation or QmitkMultiLabelTreeModel is in an invalid state. Label is not present in the model after adding it to the segmentation. Label value: " << newLabelValue;
     }
   }
   else
   {
     this->SetSelectedLabels({});
   }
 
   emit ModelUpdated();
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 mitk::Label* QmitkMultiLabelInspector::AddNewGroup()
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of AddNewLabel.";
 
   if (m_Segmentation.IsNull())
   {
     return nullptr;
   }
 
   mitk::LabelSetImage::GroupIndexType groupID = 0;
   mitk::Label* newLabel = nullptr;
   m_ModelManipulationOngoing = true;
   try
   {
     this->WaitCursorOn();
     groupID = m_Segmentation->AddLayer();
     m_Segmentation->SetActiveLayer(groupID);
     this->WaitCursorOff();
     newLabel =  this->AddNewLabelInternal(groupID);
   }
   catch (mitk::Exception& e)
   {
     this->WaitCursorOff();
     m_ModelManipulationOngoing = false;
     MITK_ERROR << "Exception caught: " << e.GetDescription();
     QMessageBox::information(this, "Add group", "Could not add a new group. See error log for details.");
   }
   m_ModelManipulationOngoing = false;
 
   emit ModelUpdated();
 
   // this is needed as workaround for (T27307). It circumvents the fact that modifications
   // of data (here the segmentation) does not directly trigger the modification of the
   // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
   // listens to the datastorage for modification would not get notified.
   if (m_SegmentationNode.IsNotNull())
   {
     m_SegmentationNode->Modified();
   }
 
   return newLabel;
 }
 
 void QmitkMultiLabelInspector::RemoveGroupInternal(const mitk::LabelSetImage::GroupIndexType& groupID)
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of RemoveLabel.";
 
   if (m_Segmentation.IsNull())
     return;
 
   if (m_Segmentation->GetNumberOfLayers() < 2)
     return;
 
   auto currentIndex = m_Model->indexOfGroup(groupID);
   auto nextIndex = m_Model->ClosestLabelInstanceIndex(currentIndex);
   auto labelVariant = nextIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
 
   try
   {
     this->WaitCursorOn();
     m_ModelManipulationOngoing = true;
     m_Segmentation->RemoveGroup(groupID);
     m_ModelManipulationOngoing = false;
     this->WaitCursorOff();
   }
   catch (mitk::Exception& e)
   {
     m_ModelManipulationOngoing = false;
     this->WaitCursorOff();
     MITK_ERROR << "Exception caught: " << e.GetDescription();
     QMessageBox::information(this, "Delete group", "Could not delete the currently active group. See error log for details.");
     return;
   }
 
   if (labelVariant.isValid())
   {
     auto newLabelValue = labelVariant.value<LabelValueType>();
     this->SetSelectedLabel(newLabelValue);
 
     auto index = m_Model->indexOfLabel(newLabelValue); //we have to get index again, because it could have changed due to remove operation.
     if (index.isValid())
     {
       m_Controls->view->expand(index.parent());
     }
     else
     {
       mitkThrow() << "Segmentation or QmitkMultiLabelTreeModel is in an invalid state. Label is not present in the model after adding it to the segmentation. Label value: " << newLabelValue;
     }
   }
   else
   {
     this->SetSelectedLabels({});
   }
 
   emit ModelUpdated();
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkMultiLabelInspector::RemoveGroup()
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of RemoveLabel.";
 
   if (m_Segmentation.IsNull())
     return;
 
   if (m_Segmentation->GetNumberOfLayers() < 2)
   {
     QMessageBox::information(this, "Delete group", "Cannot delete last remaining group. A segmentation must contain at least a single group.");
     return;
   }
 
   const auto* selectedLabel = this->GetFirstSelectedLabelObject();
 
   if (selectedLabel == nullptr)
     return;
 
   const auto group = m_Segmentation->GetGroupIndexOfLabel(selectedLabel->GetValue());
 
   auto question = QStringLiteral("Do you really want to delete group %1 including all of its labels?").arg(group);
   auto answer = QMessageBox::question(this, QStringLiteral("Delete group %1").arg(group), question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
 
   if (answer != QMessageBox::Yes)
     return;
 
   this->RemoveGroupInternal(group);
 }
 
 void QmitkMultiLabelInspector::OnDeleteGroup()
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of RemoveLabel.";
 
   if (m_Segmentation.IsNull())
     return;
 
   auto currentIndex = this->m_Controls->view->currentIndex();
   auto groupIDVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::GroupIDRole);
 
   if (groupIDVariant.isValid())
   {
     auto groupID = groupIDVariant.value<mitk::LabelSetImage::GroupIndexType>();
 
     auto question = QStringLiteral("Do you really want to delete group %1 including all of its labels?").arg(groupID);
     auto answer = QMessageBox::question(this, QString("Delete group %1").arg(groupID), question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
 
     if (answer != QMessageBox::Yes)
       return;
 
     this->RemoveGroupInternal(groupID);
 
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 };
 
 
 void QmitkMultiLabelInspector::OnContextMenuRequested(const QPoint& /*pos*/)
 {
   if (m_Segmentation.IsNull() || !this->isEnabled())
     return;
 
   const auto indexLevel = this->GetCurrentLevelType();
 
   if (IndexLevelType::Group == indexLevel)
   {
     QMenu* menu = new QMenu(this);
 
     if (m_AllowLabelModification)
     {
       QAction* addInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add.svg")), "&Add label", this);
       QObject::connect(addInstanceAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnAddLabel);
       menu->addAction(addInstanceAction);
 
       if (m_Segmentation->GetNumberOfLayers() > 1)
       {
         QAction* removeAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_group_delete.svg")), "Delete group", this);
         QObject::connect(removeAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnDeleteGroup);
         menu->addAction(removeAction);
       }
     }
 
     if (m_AllowLockModification)
     {
       menu->addSeparator();
       QAction* lockAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/lock.svg")), "Lock group", this);
       QObject::connect(lockAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnLockAffectedLabels);
       menu->addAction(lockAllAction);
 
       QAction* unlockAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/unlock.svg")), "Unlock group", this);
       QObject::connect(unlockAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnUnlockAffectedLabels);
       menu->addAction(unlockAllAction);
     }
 
     if (m_AllowVisibilityModification)
     {
       menu->addSeparator();
 
       QAction* viewAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Show group", this);
       QObject::connect(viewAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnSetAffectedLabelsVisible);
       menu->addAction(viewAllAction);
 
       QAction* hideAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/invisible.svg")), "Hide group", this);
       QObject::connect(hideAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnSetAffectedLabelsInvisible);
       menu->addAction(hideAllAction);
 
       menu->addSeparator();
 
       auto opacityAction = this->CreateOpacityAction();
       if (nullptr != opacityAction)
         menu->addAction(opacityAction);
     }
     menu->popup(QCursor::pos());
   }
   else if (IndexLevelType::LabelClass == indexLevel)
   {
     QMenu* menu = new QMenu(this);
 
     if (m_AllowLabelModification)
     {
       QAction* addInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add_instance.svg")), "Add label instance", this);
       QObject::connect(addInstanceAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnAddLabelInstance);
       menu->addAction(addInstanceAction);
 
       QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "&Rename label", this);
       QObject::connect(renameAction, SIGNAL(triggered(bool)), this, SLOT(OnRenameLabel(bool)));
       menu->addAction(renameAction);
 
       QAction* removeAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete.svg")), "&Delete label", this);
       QObject::connect(removeAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnDeleteAffectedLabel);
       menu->addAction(removeAction);
     }
 
     if (m_AllowLockModification)
     {
       menu->addSeparator();
       QAction* lockAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/lock.svg")), "Lock label instances", this);
       QObject::connect(lockAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnLockAffectedLabels);
       menu->addAction(lockAllAction);
 
       QAction* unlockAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/unlock.svg")), "Unlock label instances", this);
       QObject::connect(unlockAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnUnlockAffectedLabels);
       menu->addAction(unlockAllAction);
     }
 
     if (m_AllowVisibilityModification)
     {
       menu->addSeparator();
 
       QAction* viewAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Show label instances", this);
       QObject::connect(viewAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnSetAffectedLabelsVisible);
       menu->addAction(viewAllAction);
 
       QAction* hideAllAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/invisible.svg")), "Hide label instances", this);
       QObject::connect(hideAllAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnSetAffectedLabelsInvisible);
       menu->addAction(hideAllAction);
 
       menu->addSeparator();
 
       auto opacityAction = this->CreateOpacityAction();
       if (nullptr!=opacityAction)
         menu->addAction(opacityAction);
     }
     menu->popup(QCursor::pos());
   }
   else
   {
     auto selectedLabelValues = this->GetSelectedLabels();
     if (selectedLabelValues.empty())
       return;
 
     QMenu* menu = new QMenu(this);
 
     if (this->GetMultiSelectionMode() && selectedLabelValues.size() > 1)
     {
-      QAction* mergeAction = new QAction(QIcon(":/Qmitk/MergeLabels.png"), "Merge selection on current label", this);
-      QObject::connect(mergeAction, SIGNAL(triggered(bool)), this, SLOT(OnMergeLabels(bool)));
-      menu->addAction(mergeAction);
+      if (m_AllowLabelModification)
+      {
+        QAction* mergeAction = new QAction(QIcon(":/Qmitk/MergeLabels.png"), "Merge selection on current label", this);
+        QObject::connect(mergeAction, SIGNAL(triggered(bool)), this, SLOT(OnMergeLabels(bool)));
+        menu->addAction(mergeAction);
+
+        QAction* removeLabelsAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete_instance.svg")), "&Delete selected labels", this);
+        QObject::connect(removeLabelsAction, SIGNAL(triggered(bool)), this, SLOT(OnDeleteLabels(bool)));
+        menu->addAction(removeLabelsAction);
+
+        QAction* clearLabelsAction = new QAction(QIcon(":/Qmitk/EraseLabel.png"), "&Clear selected labels", this);
+        QObject::connect(clearLabelsAction, SIGNAL(triggered(bool)), this, SLOT(OnClearLabels(bool)));
+        menu->addAction(clearLabelsAction);
+      }
 
-      QAction* removeLabelsAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete_instance.svg")), "&Delete selected labels", this);
-      QObject::connect(removeLabelsAction, SIGNAL(triggered(bool)), this, SLOT(OnDeleteLabels(bool)));
-      menu->addAction(removeLabelsAction);
+      if (m_AllowVisibilityModification)
+      {
+        if (m_AllowLabelModification) menu->addSeparator();
 
-      QAction* clearLabelsAction = new QAction(QIcon(":/Qmitk/EraseLabel.png"), "&Clear selected labels", this);
-      QObject::connect(clearLabelsAction, SIGNAL(triggered(bool)), this, SLOT(OnClearLabels(bool)));
-      menu->addAction(clearLabelsAction);
+        QAction* viewOnlyAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Hide everything but this", this);
+        QObject::connect(viewOnlyAction, SIGNAL(triggered(bool)), this, SLOT(OnSetOnlyActiveLabelVisible(bool)));
+        menu->addAction(viewOnlyAction);
+
+        menu->addSeparator();
+
+        auto opacityAction = this->CreateOpacityAction();
+        if (nullptr != opacityAction)
+          menu->addAction(opacityAction);
+      }
     }
     else
     {
       if (m_AllowLabelModification)
       {
         QAction* addInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add_instance.svg")), "&Add label instance", this);
         QObject::connect(addInstanceAction, &QAction::triggered, this, &QmitkMultiLabelInspector::OnAddLabelInstance);
         menu->addAction(addInstanceAction);
 
         const auto selectedLabelIndex = m_Model->indexOfLabel(selectedLabelValues.front());
 
         if (m_Model->GetLabelInstancesOfSameLabelClass(selectedLabelIndex).size() > 1) // Only labels that actually appear as instance (having additional instances)
         {
           QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "&Rename label instance", this);
           QObject::connect(renameAction, SIGNAL(triggered(bool)), this, SLOT(OnRenameLabel(bool)));
           menu->addAction(renameAction);
 
           QAction* removeInstanceAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete_instance.svg")), "&Delete label instance", this);
           QObject::connect(removeInstanceAction, &QAction::triggered, this, &QmitkMultiLabelInspector::DeleteLabelInstance);
           menu->addAction(removeInstanceAction);
         }
         else
         {
           QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "&Rename label", this);
           QObject::connect(renameAction, SIGNAL(triggered(bool)), this, SLOT(OnRenameLabel(bool)));
           menu->addAction(renameAction);
         }
 
         QAction* removeLabelAction = new QAction(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete.svg")), "Delete &label", this);
         QObject::connect(removeLabelAction, &QAction::triggered, this, &QmitkMultiLabelInspector::DeleteLabel);
         menu->addAction(removeLabelAction);
 
         QAction* clearAction = new QAction(QIcon(":/Qmitk/EraseLabel.png"), "&Clear content", this);
         QObject::connect(clearAction, SIGNAL(triggered(bool)), this, SLOT(OnClearLabel(bool)));
         menu->addAction(clearAction);
       }
 
       if (m_AllowVisibilityModification)
       {
-        menu->addSeparator();
-        QAction* viewOnlyAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Hide everything in group but this", this);
+        if (m_AllowLabelModification) menu->addSeparator();
+
+        QAction* viewOnlyAction = new QAction(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/visible.svg")), "Hide everything but this", this);
         QObject::connect(viewOnlyAction, SIGNAL(triggered(bool)), this, SLOT(OnSetOnlyActiveLabelVisible(bool)));
         menu->addAction(viewOnlyAction);
 
         menu->addSeparator();
 
         auto opacityAction = this->CreateOpacityAction();
         if (nullptr != opacityAction)
           menu->addAction(opacityAction);
       }
     }
     menu->popup(QCursor::pos());
   }
 }
 
 QWidgetAction* QmitkMultiLabelInspector::CreateOpacityAction()
 {
-  auto relevantLabelValues = this->GetCurrentlyAffactedLabelInstances();
+  auto selectedLabelValues = this->GetSelectedLabels();
+
+  auto relevantLabelValues = !this->GetMultiSelectionMode() || selectedLabelValues.size() <= 1
+    ? this->GetCurrentlyAffactedLabelInstances()
+    : selectedLabelValues;
+
   std::vector<mitk::Label*> relevantLabels;
 
   if (!relevantLabelValues.empty())
   {
     for (auto value : relevantLabelValues)
     {
       auto label = this->m_Segmentation->GetLabel(value);
       if (nullptr == label)
         mitkThrow() << "Invalid state. Internal model returned a label value that does not exist in segmentation. Invalid value:" << value;
       relevantLabels.emplace_back(label);
     }
 
     auto* opacitySlider = new QSlider;
     opacitySlider->setMinimum(0);
     opacitySlider->setMaximum(100);
     opacitySlider->setOrientation(Qt::Horizontal);
 
     auto opacity = relevantLabels.front()->GetOpacity();
     opacitySlider->setValue(static_cast<int>(opacity * 100));
     auto segmentation = m_Segmentation;
 
     QObject::connect(opacitySlider, &QSlider::valueChanged, this, [segmentation, relevantLabels](const int value)
     {
       auto opacity = static_cast<float>(value) / 100.0f;
       for (auto label : relevantLabels)
       {
         label->SetOpacity(opacity);
         segmentation->UpdateLookupTable(label->GetValue());
       }
       mitk::RenderingManager::GetInstance()->RequestUpdateAll();
     }
     );
 
     QLabel* opacityLabel = new QLabel("Opacity: ");
     QVBoxLayout* opacityWidgetLayout = new QVBoxLayout;
     opacityWidgetLayout->setContentsMargins(4, 4, 4, 4);
     opacityWidgetLayout->addWidget(opacityLabel);
     opacityWidgetLayout->addWidget(opacitySlider);
     QWidget* opacityWidget = new QWidget;
     opacityWidget->setLayout(opacityWidgetLayout);
     QWidgetAction* opacityAction = new QWidgetAction(this);
     opacityAction->setDefaultWidget(opacityWidget);
 
     return opacityAction;
   }
 
   return nullptr;
 }
 
 void QmitkMultiLabelInspector::OnClearLabels(bool /*value*/)
 {
   QString question = "Do you really want to clear the selected labels?";
 
   QMessageBox::StandardButton answerButton = QMessageBox::question(
     this, "Clear selected labels", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
 
   if (answerButton == QMessageBox::Yes)
   {
     this->WaitCursorOn();
     m_Segmentation->EraseLabels(this->GetSelectedLabels());
     this->WaitCursorOff();
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 }
 
 void QmitkMultiLabelInspector::OnDeleteAffectedLabel()
 {
   if (!m_AllowLabelModification)
     mitkThrow() << "QmitkMultiLabelInspector is configured incorrectly. Set AllowLabelModification to true to allow the usage of RemoveLabel.";
 
   if (m_Segmentation.IsNull())
   {
     return;
   }
 
   auto affectedLabels = GetCurrentlyAffactedLabelInstances();
   auto currentLabel = m_Segmentation->GetLabel(affectedLabels.front());
   QString question = "Do you really want to delete all instances of label \"" + QString::fromStdString(currentLabel->GetName()) + "\"?";
 
   QMessageBox::StandardButton answerButton =
     QMessageBox::question(this, "Delete label", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
 
   if (answerButton == QMessageBox::Yes)
   {
     this->DeleteLabelInternal(affectedLabels);
 
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 }
 
 void QmitkMultiLabelInspector::OnDeleteLabels(bool /*value*/)
 {
   QString question = "Do you really want to remove the selected labels?";
   QMessageBox::StandardButton answerButton = QMessageBox::question(
     this, "Remove selected labels", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
 
   if (answerButton == QMessageBox::Yes)
   {
     this->WaitCursorOn();
     m_Segmentation->RemoveLabels(this->GetSelectedLabels());
     this->WaitCursorOff();
 
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 }
 
 void QmitkMultiLabelInspector::OnMergeLabels(bool /*value*/)
 {
   auto currentLabel = GetCurrentLabel();
   QString question = "Do you really want to merge selected labels into \"" + QString::fromStdString(currentLabel->GetName())+"\"?";
 
   QMessageBox::StandardButton answerButton = QMessageBox::question(
     this, "Merge selected label", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
 
   if (answerButton == QMessageBox::Yes)
   {
     this->WaitCursorOn();
     m_Segmentation->MergeLabels(currentLabel->GetValue(), this->GetSelectedLabels());
     this->WaitCursorOff();
 
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 }
 
 void QmitkMultiLabelInspector::OnAddLabel()
 {
   auto currentIndex = this->m_Controls->view->currentIndex();
   auto groupIDVariant = currentIndex.data(QmitkMultiLabelTreeModel::ItemModelRole::GroupIDRole);
 
   if (groupIDVariant.isValid())
   {
     auto groupID = groupIDVariant.value<mitk::LabelSetImage::GroupIndexType>();
     this->AddNewLabelInternal(groupID);
 
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 }
 
 void QmitkMultiLabelInspector::OnAddLabelInstance()
 {
   auto currentLabel = this->GetCurrentLabel();
   if (nullptr == currentLabel)
     return;
 
   this->AddNewLabelInstanceInternal(currentLabel);
 
   // this is needed as workaround for (T27307). It circumvents the fact that modifications
   // of data (here the segmentation) does not directly trigger the modification of the
   // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
   // listens to the datastorage for modification would not get notified.
   if (m_SegmentationNode.IsNotNull())
   {
     m_SegmentationNode->Modified();
   }
 }
 
 void QmitkMultiLabelInspector::OnClearLabel(bool /*value*/)
 {
   auto currentLabel = GetFirstSelectedLabelObject();
   QString question = "Do you really want to clear the contents of label \"" + QString::fromStdString(currentLabel->GetName())+"\"?";
 
   QMessageBox::StandardButton answerButton =
     QMessageBox::question(this, "Clear label", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
 
   if (answerButton == QMessageBox::Yes)
   {
     this->WaitCursorOn();
     m_Segmentation->EraseLabel(currentLabel->GetValue());
     this->WaitCursorOff();
 
     // this is needed as workaround for (T27307). It circumvents the fact that modifications
     // of data (here the segmentation) does not directly trigger the modification of the
     // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
     // listens to the datastorage for modification would not get notified.
     if (m_SegmentationNode.IsNotNull())
     {
       m_SegmentationNode->Modified();
     }
   }
 }
 
 void QmitkMultiLabelInspector::OnRenameLabel(bool /*value*/)
 {
   auto relevantLabelValues = this->GetCurrentlyAffactedLabelInstances();
   auto currentLabel = this->GetCurrentLabel();
 
   emit LabelRenameRequested(currentLabel, true);
 
   for (auto value : relevantLabelValues)
   {
     if (value != currentLabel->GetValue())
     {
       auto label = this->m_Segmentation->GetLabel(value);
       if (nullptr == label)
         mitkThrow() << "Invalid state. Internal model returned a label value that does not exist in segmentation. Invalid value:" << value;
 
       label->SetName(currentLabel->GetName());
       label->SetColor(currentLabel->GetColor());
       m_Segmentation->UpdateLookupTable(label->GetValue());
       mitk::DICOMSegmentationPropertyHelper::SetDICOMSegmentProperties(label);
 
       // this is needed as workaround for (T27307). It circumvents the fact that modifications
       // of data (here the segmentation) does not directly trigger the modification of the
       // owning node (see T27307). Therefore other code (like renderers or model views) that e.g.
       // listens to the datastorage for modification would not get notified.
       if (m_SegmentationNode.IsNotNull())
       {
         m_SegmentationNode->Modified();
       }
     }
   }
   emit ModelUpdated();
 }
 
 
 void QmitkMultiLabelInspector::SetLockOfAffectedLabels(bool locked) const
 {
   auto relevantLabelValues = this->GetCurrentlyAffactedLabelInstances();
 
   if (!relevantLabelValues.empty())
   {
     for (auto value : relevantLabelValues)
     {
       auto label = this->m_Segmentation->GetLabel(value);
       if (nullptr == label)
         mitkThrow() << "Invalid state. Internal model returned a label value that does not exist in segmentation. Invalid value:" << value;
       label->SetLocked(locked);
     }
     mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   }
 }
 
 void QmitkMultiLabelInspector::OnUnlockAffectedLabels()
 {
   this->SetLockOfAffectedLabels(false);
 }
 
 void QmitkMultiLabelInspector::OnLockAffectedLabels()
 {
   this->SetLockOfAffectedLabels(true);
 }
 
 void QmitkMultiLabelInspector::SetVisibilityOfAffectedLabels(bool visible) const
 {
   auto relevantLabelValues = this->GetCurrentlyAffactedLabelInstances();
 
   if (!relevantLabelValues.empty())
   {
     for (auto value : relevantLabelValues)
     {
       auto label = this->m_Segmentation->GetLabel(value);
       if (nullptr == label)
         mitkThrow() << "Invalid state. Internal model returned a label value that does not exist in segmentation. Invalid value:" << value;
       label->SetVisible(visible);
       m_Segmentation->UpdateLookupTable(label->GetValue());
     }
     mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   }
 }
 
 void QmitkMultiLabelInspector::OnSetAffectedLabelsVisible()
 {
   this->SetVisibilityOfAffectedLabels(true);
 }
 
 void QmitkMultiLabelInspector::OnSetAffectedLabelsInvisible()
 {
   this->SetVisibilityOfAffectedLabels(false);
 }
 
 void QmitkMultiLabelInspector::OnSetOnlyActiveLabelVisible(bool /*value*/)
 {
-  auto currentLabel = GetFirstSelectedLabelObject();
-  const auto labelID = currentLabel->GetValue();
+  auto selectedLabelValues = this->GetSelectedLabels();
+
+  if (selectedLabelValues.empty()) return;
+
   m_Segmentation->SetAllLabelsVisible(false);
 
-  currentLabel->SetVisible(true);
-  m_Segmentation->UpdateLookupTable(labelID);
-  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+  for (auto selectedValue : selectedLabelValues)
+  {
+    auto currentLabel = m_Segmentation->GetLabel(selectedValue);
+    currentLabel->SetVisible(true);
+    m_Segmentation->UpdateLookupTable(selectedValue);
+  }
 
-  this->PrepareGoToLabel(labelID);
+  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+  this->PrepareGoToLabel(selectedLabelValues.front());
 }
 
 void QmitkMultiLabelInspector::OnItemDoubleClicked(const QModelIndex& index)
 {
   if (!index.isValid()) return;
   if (index.column() > 0) return;
 
   auto labelVariant = index.data(QmitkMultiLabelTreeModel::ItemModelRole::LabelInstanceValueRole);
 
   if (!labelVariant.isValid()) return;
 
   const auto labelID = labelVariant.value<mitk::Label::PixelType>();
 
   if (QApplication::queryKeyboardModifiers().testFlag(Qt::AltModifier))
   {
     this->OnRenameLabel(false);
     return;
   }
 
   this->PrepareGoToLabel(labelID);
 }
 
 void QmitkMultiLabelInspector::PrepareGoToLabel(mitk::Label::PixelType labelID) const
 {
   this->WaitCursorOn();
   m_Segmentation->UpdateCenterOfMass(labelID);
   const auto currentLabel = m_Segmentation->GetLabel(labelID);
   const mitk::Point3D& pos = currentLabel->GetCenterOfMassCoordinates();
   this->WaitCursorOff();
 
   if (pos.GetVnlVector().max_value() > 0.0)
   {
     emit GoToLabel(currentLabel->GetValue(), pos);
   }
 }
 
diff --git a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelManager.cpp b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelManager.cpp
index 9b80e30d37..410fd5f329 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelManager.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelManager.cpp
@@ -1,555 +1,556 @@
 /*============================================================================
 
 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 <QmitkMultiLabelManager.h>
 
 // mitk
 #include <mitkAutoCropImageFilter.h>
 #include <mitkCoreObjectFactory.h>
 #include <mitkIOUtil.h>
 #include <mitkLabelSetImage.h>
 #include <mitkLabelSetImageToSurfaceThreadedFilter.h>
+#include <mitkLabelSetImageConverter.h>
 #include <mitkRenderingManager.h>
 #include <mitkShowSegmentationAsSurface.h>
 #include <mitkStatusBar.h>
 #include <mitkToolManagerProvider.h>
 
 // Qmitk
 #include <QmitkStyleManager.h>
 #include <QmitkMultiLabelPresetHelper.h>
 
 // Qt
 #include <QLabel>
 #include <QWidgetAction>
 #include <QColorDialog>
 #include <QCompleter>
 #include <QDateTime>
 #include <QFileDialog>
 #include <QMenu>
 #include <QMessageBox>
 #include <QPushButton>
 #include <QShortcut>
 #include <QStringListModel>
 
 // itk
 #include <itksys/SystemTools.hxx>
 
 #include <ui_QmitkMultiLabelManagerControls.h>
 
 
 QmitkMultiLabelManager::QmitkMultiLabelManager(QWidget *parent)
   : QWidget(parent), m_Controls(new Ui::QmitkMultiLabelManagerControls), m_Completer(nullptr), m_ProcessingManualSelection(false), m_DataStorage(nullptr)
 {
   m_Controls->setupUi(this);
 
   m_Controls->labelSearchBox->setAlwaysShowClearIcon(true);
   m_Controls->labelSearchBox->setShowSearchIcon(true);
 
   QStringList completionList;
   completionList << "";
   m_Completer = new QCompleter(completionList, this);
   m_Completer->setCaseSensitivity(Qt::CaseInsensitive);
   m_Controls->labelSearchBox->setCompleter(m_Completer);
 
   m_Controls->labelInspector->SetAllowLabelModification(true);
 
   connect(m_Controls->labelSearchBox, SIGNAL(returnPressed()), this, SLOT(OnSearchLabel()));
 
   QStringListModel *completeModel = static_cast<QStringListModel *>(m_Completer->model());
   completeModel->setStringList(GetLabelStringList());
 
   // See T29549
   m_Controls->labelSearchBox->hide();
 
   m_Controls->btnSavePreset->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/document-save.svg")));
   m_Controls->btnLoadPreset->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/document-open.svg")));
   m_Controls->btnAddLabel->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add.svg")));
   m_Controls->btnAddInstance->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_add_instance.svg")));
   m_Controls->btnAddGroup->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_group_add.svg")));
   m_Controls->btnRemoveLabel->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete.svg")));
   m_Controls->btnRemoveInstance->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_label_delete_instance.svg")));
   m_Controls->btnRemoveGroup->setIcon(QmitkStyleManager::ThemeIcon(QStringLiteral(":/Qmitk/icon_group_delete.svg")));
 
   connect(m_Controls->btnAddLabel, &QToolButton::clicked, this->m_Controls->labelInspector, &QmitkMultiLabelInspector::AddNewLabel);
   connect(m_Controls->btnRemoveLabel, &QToolButton::clicked, this->m_Controls->labelInspector, &QmitkMultiLabelInspector::DeleteLabel);
   connect(m_Controls->btnAddInstance, &QToolButton::clicked, this->m_Controls->labelInspector, &QmitkMultiLabelInspector::AddNewLabelInstance);
   connect(m_Controls->btnRemoveInstance, &QToolButton::clicked, this->m_Controls->labelInspector, &QmitkMultiLabelInspector::DeleteLabelInstance);
   connect(m_Controls->btnAddGroup, &QToolButton::clicked, this->m_Controls->labelInspector, &QmitkMultiLabelInspector::AddNewGroup);
   connect(m_Controls->btnRemoveGroup, &QToolButton::clicked, this->m_Controls->labelInspector, &QmitkMultiLabelInspector::RemoveGroup);
   connect(m_Controls->btnSavePreset, &QToolButton::clicked, this, &QmitkMultiLabelManager::OnSavePreset);
   connect(m_Controls->btnLoadPreset, &QToolButton::clicked, this, &QmitkMultiLabelManager::OnLoadPreset);
 
   connect(this->m_Controls->labelInspector, &QmitkMultiLabelInspector::GoToLabel, this, &QmitkMultiLabelManager::OnGoToLabel);
   connect(this->m_Controls->labelInspector, &QmitkMultiLabelInspector::LabelRenameRequested, this, &QmitkMultiLabelManager::OnLabelRenameRequested);
   connect(this->m_Controls->labelInspector, &QmitkMultiLabelInspector::CurrentSelectionChanged, this, &QmitkMultiLabelManager::OnSelectedLabelChanged);
   connect(this->m_Controls->labelInspector, &QmitkMultiLabelInspector::ModelUpdated, this, &QmitkMultiLabelManager::OnModelUpdated);
   connect(this->m_Controls->labelInspector, &QmitkMultiLabelInspector::SegmentationChanged, this, &QmitkMultiLabelManager::OnSegmentationChanged);
 
   auto* renameLabelShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key::Key_L, Qt::CTRL | Qt::Key::Key_R), this);
   connect(renameLabelShortcut, &QShortcut::activated, this, &QmitkMultiLabelManager::OnRenameLabelShortcutActivated);
 
   auto* newLabelShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key::Key_L, Qt::CTRL | Qt::Key::Key_A), this);
   connect(newLabelShortcut, &QShortcut::activated, this->m_Controls->labelInspector, &QmitkMultiLabelInspector::AddNewLabel);
 
   this->UpdateControls();
 }
 
 QmitkMultiLabelManager::~QmitkMultiLabelManager()
 {
   this->SetMultiLabelSegmentation(nullptr);
   delete m_Controls;
 }
 
 QmitkMultiLabelManager::LabelValueVectorType QmitkMultiLabelManager::GetSelectedLabels() const
 {
   return m_Controls->labelInspector->GetSelectedLabels();
 }
 
 
 void QmitkMultiLabelManager::OnRenameLabelShortcutActivated()
 {
   auto selectedLabels = this->GetSelectedLabels();
 
   for (auto labelValue : selectedLabels)
   {
     auto currentLabel = this->GetMultiLabelSegmentation()->GetLabel(labelValue);
     emit LabelRenameRequested(currentLabel, true);
   }
 }
 
 void QmitkMultiLabelManager::OnSelectedLabelChanged(const LabelValueVectorType& labels)
 {
   this->UpdateControls();
   if (labels.empty() || labels.size() > 1) return;
 
   emit CurrentSelectionChanged(labels);
 }
 
 QStringList &QmitkMultiLabelManager::GetLabelStringList()
 {
   return m_LabelStringList;
 }
 
 void QmitkMultiLabelManager::SetDefaultLabelNaming(bool defaultLabelNaming)
 {
   this->m_Controls->labelInspector->SetDefaultLabelNaming(defaultLabelNaming);
 }
 
 void QmitkMultiLabelManager::setEnabled(bool enabled)
 {
   QWidget::setEnabled(enabled);
   UpdateControls();
 }
 
 void QmitkMultiLabelManager::SetSelectedLabels(const LabelValueVectorType& selectedLabels)
 {
   this->m_Controls->labelInspector->SetSelectedLabels(selectedLabels);
   UpdateControls();
 }
 
 void QmitkMultiLabelManager::SetSelectedLabel(mitk::LabelSetImage::LabelValueType selectedLabel)
 {
   this->m_Controls->labelInspector->SetSelectedLabel(selectedLabel);
   UpdateControls();
 }
 
 void QmitkMultiLabelManager::SetMultiLabelSegmentation(mitk::LabelSetImage* segmentation)
 {
   this->m_Controls->labelInspector->SetMultiLabelSegmentation(segmentation);
 
   //Update of controls and observers is done in OnSegmentationChanged()
   // which is triggered by the inspector when setting the segmentation or node 
 }
 
 mitk::LabelSetImage* QmitkMultiLabelManager::GetMultiLabelSegmentation() const
 {
   return this->m_Controls->labelInspector->GetMultiLabelSegmentation();
 }
 
 void QmitkMultiLabelManager::SetMultiLabelNode(mitk::DataNode* node)
 {
   this->m_Controls->labelInspector->SetMultiLabelNode(node);
 }
 
 mitk::DataNode* QmitkMultiLabelManager::GetMultiLabelNode() const
 {
   return this->m_Controls->labelInspector->GetMultiLabelNode();
 }
 
 void QmitkMultiLabelManager::SetDataStorage(mitk::DataStorage *storage)
 {
   m_DataStorage = storage;
 }
 
 void QmitkMultiLabelManager::OnSearchLabel()
 {
   //std::string text = m_Controls->labelSearchBox->text().toStdString();
   //int pixelValue = -1;
   //int row = -1;
   //for (int i = 0; i < m_Controls->m_LabelSetTableWidget->rowCount(); ++i)
   //{
   //  if (m_Controls->m_LabelSetTableWidget->item(i, 0)->text().toStdString().compare(text) == 0)
   //  {
   //    pixelValue = m_Controls->m_LabelSetTableWidget->item(i, 0)->data(Qt::UserRole).toInt();
   //    row = i;
   //    break;
   //  }
   //}
   //if (pixelValue == -1)
   //{
   //  return;
   //}
 
   //GetWorkingImage()->GetActiveLabelSet()->SetActiveLabel(pixelValue);
 
   //QTableWidgetItem *nameItem = m_Controls->m_LabelSetTableWidget->item(row, NAME_COL);
   //if (!nameItem)
   //{
   //  return;
   //}
 
   //m_Controls->m_LabelSetTableWidget->clearSelection();
   //m_Controls->m_LabelSetTableWidget->selectRow(row);
   //m_Controls->m_LabelSetTableWidget->scrollToItem(nameItem);
 
   //GetWorkingImage()->GetActiveLabelSet()->SetActiveLabel(pixelValue);
 
   //this->WaitCursorOn();
   //mitk::Point3D pos =
   //  GetWorkingImage()->GetLabel(pixelValue, GetWorkingImage()->GetActiveLayer())->GetCenterOfMassCoordinates();
 
   //m_ToolManager->WorkingDataChanged();
 
   //if (pos.GetVnlVector().max_value() > 0.0)
   //{
   //  emit goToLabel(pos);
   //}
   //else
   //{
   //  GetWorkingImage()->UpdateCenterOfMass(pixelValue, GetWorkingImage()->GetActiveLayer());
   //  mitk::Point3D pos =
   //    GetWorkingImage()->GetLabel(pixelValue, GetWorkingImage()->GetActiveLayer())->GetCenterOfMassCoordinates();
   //  emit goToLabel(pos);
   //}
 
   //this->WaitCursorOff();
 }
 
 void QmitkMultiLabelManager::UpdateControls()
 {
   bool hasWorkingData = this->GetMultiLabelSegmentation() != nullptr;
 
   auto labels = this->m_Controls->labelInspector->GetSelectedLabels();
   bool hasMultipleInstances = this->m_Controls->labelInspector->GetLabelInstancesOfSelectedFirstLabel().size() > 1;
   m_Controls->labelSearchBox->setEnabled(hasWorkingData);
   m_Controls->btnAddGroup->setEnabled(hasWorkingData);
   m_Controls->btnAddInstance->setEnabled(hasWorkingData && labels.size()==1);
   m_Controls->btnAddLabel->setEnabled(hasWorkingData);
   m_Controls->btnLoadPreset->setEnabled(hasWorkingData);
   m_Controls->btnRemoveGroup->setEnabled(hasWorkingData && !labels.empty() && this->GetMultiLabelSegmentation()->GetNumberOfLayers()>1);
   m_Controls->btnRemoveLabel->setEnabled(hasWorkingData && !labels.empty());
   m_Controls->btnRemoveInstance->setEnabled(hasWorkingData && !labels.empty() && hasMultipleInstances);
   m_Controls->btnSavePreset->setEnabled(hasWorkingData);
 
   if (!hasWorkingData)
     return;
 
   QStringListModel *completeModel = dynamic_cast<QStringListModel *>(m_Completer->model());
   completeModel->setStringList(GetLabelStringList());
 }
 
 void QmitkMultiLabelManager::OnCreateCroppedMask(bool)
 {
   mitk::ToolManagerProvider::GetInstance()->GetToolManager()->ActivateTool(-1);
 
   mitk::Image::Pointer maskImage;
   auto currentLabel = this->GetMultiLabelSegmentation()->GetLabel(this->GetSelectedLabels().front());
   auto pixelValue = currentLabel->GetValue();
   try
   {
     this->WaitCursorOn();
 
     mitk::AutoCropImageFilter::Pointer cropFilter = mitk::AutoCropImageFilter::New();
-    cropFilter->SetInput(this->GetMultiLabelSegmentation()->CreateLabelMask(pixelValue));
+    cropFilter->SetInput(mitk::CreateLabelMask(this->GetMultiLabelSegmentation(),pixelValue));
     cropFilter->SetBackgroundValue(0);
     cropFilter->SetMarginFactor(1.15);
     cropFilter->Update();
 
     maskImage = cropFilter->GetOutput();
 
     this->WaitCursorOff();
   }
   catch (mitk::Exception &e)
   {
     this->WaitCursorOff();
     MITK_ERROR << "Exception caught: " << e.GetDescription();
     QMessageBox::information(this, "Create Mask", "Could not create a mask out of the selected label.\n");
     return;
   }
 
   if (maskImage.IsNull())
   {
     QMessageBox::information(this, "Create Mask", "Could not create a mask out of the selected label.\n");
     return;
   }
 
   mitk::DataNode::Pointer maskNode = mitk::DataNode::New();
   std::string name = currentLabel->GetName();
   name += "-mask";
   maskNode->SetName(name);
   maskNode->SetData(maskImage);
   maskNode->SetBoolProperty("binary", true);
   maskNode->SetBoolProperty("outline binary", true);
   maskNode->SetBoolProperty("outline binary shadow", true);
   maskNode->SetFloatProperty("outline width", 2.0);
   maskNode->SetColor(currentLabel->GetColor());
   maskNode->SetOpacity(1.0);
 
   m_DataStorage->Add(maskNode, this->GetMultiLabelNode());
 }
 
 void QmitkMultiLabelManager::OnCreateMask(bool /*triggered*/)
 {
   mitk::ToolManagerProvider::GetInstance()->GetToolManager()->ActivateTool(-1);
 
   auto currentLabel = this->GetMultiLabelSegmentation()->GetLabel(this->GetSelectedLabels().front());
   auto pixelValue = currentLabel->GetValue();
   mitk::Image::Pointer maskImage;
   try
   {
     this->WaitCursorOn();
-    maskImage = GetMultiLabelSegmentation()->CreateLabelMask(pixelValue);
+    maskImage = mitk::CreateLabelMask(GetMultiLabelSegmentation(),pixelValue);
     this->WaitCursorOff();
   }
   catch (mitk::Exception &e)
   {
     this->WaitCursorOff();
     MITK_ERROR << "Exception caught: " << e.GetDescription();
     QMessageBox::information(this, "Create Mask", "Could not create a mask out of the selected label.\n");
     return;
   }
 
   if (maskImage.IsNull())
   {
     QMessageBox::information(this, "Create Mask", "Could not create a mask out of the selected label.\n");
     return;
   }
 
   mitk::DataNode::Pointer maskNode = mitk::DataNode::New();
   std::string name = currentLabel->GetName();
   name += "-mask";
   maskNode->SetName(name);
   maskNode->SetData(maskImage);
   maskNode->SetBoolProperty("binary", true);
   maskNode->SetBoolProperty("outline binary", true);
   maskNode->SetBoolProperty("outline binary shadow", true);
   maskNode->SetFloatProperty("outline width", 2.0);
   maskNode->SetColor(currentLabel->GetColor());
   maskNode->SetOpacity(1.0);
 
   m_DataStorage->Add(maskNode, this->GetMultiLabelNode());
 }
 
 void QmitkMultiLabelManager::OnCreateSmoothedSurface(bool /*triggered*/)
 {
   mitk::ToolManagerProvider::GetInstance()->GetToolManager()->ActivateTool(-1);
 
   auto currentLabel = this->GetMultiLabelSegmentation()->GetLabel(this->GetSelectedLabels().front());
   auto pixelValue = currentLabel->GetValue();
 
   mitk::LabelSetImageToSurfaceThreadedFilter::Pointer surfaceFilter = mitk::LabelSetImageToSurfaceThreadedFilter::New();
 
   itk::SimpleMemberCommand<QmitkMultiLabelManager>::Pointer successCommand =
     itk::SimpleMemberCommand<QmitkMultiLabelManager>::New();
   successCommand->SetCallbackFunction(this, &QmitkMultiLabelManager::OnThreadedCalculationDone);
   surfaceFilter->AddObserver(mitk::ResultAvailable(), successCommand);
 
   itk::SimpleMemberCommand<QmitkMultiLabelManager>::Pointer errorCommand =
     itk::SimpleMemberCommand<QmitkMultiLabelManager>::New();
   errorCommand->SetCallbackFunction(this, &QmitkMultiLabelManager::OnThreadedCalculationDone);
   surfaceFilter->AddObserver(mitk::ProcessingError(), errorCommand);
 
   mitk::DataNode::Pointer groupNode = this->GetMultiLabelNode();
   surfaceFilter->SetPointerParameter("Group node", groupNode);
   surfaceFilter->SetPointerParameter("Input", this->GetMultiLabelSegmentation());
   surfaceFilter->SetParameter("RequestedLabel", pixelValue);
   surfaceFilter->SetParameter("Smooth", true);
   surfaceFilter->SetDataStorage(*m_DataStorage);
 
   mitk::StatusBar::GetInstance()->DisplayText("Surface creation is running in background...");
 
   try
   {
     surfaceFilter->StartAlgorithm();
   }
   catch (mitk::Exception &e)
   {
     MITK_ERROR << "Exception caught: " << e.GetDescription();
     QMessageBox::information(this,
                              "Create Surface",
                              "Could not create a surface mesh out of the selected label. See error log for details.\n");
   }
 }
 
 void QmitkMultiLabelManager::OnCreateDetailedSurface(bool /*triggered*/)
 {
   mitk::ToolManagerProvider::GetInstance()->GetToolManager()->ActivateTool(-1);
 
   auto currentLabel = this->GetMultiLabelSegmentation()->GetLabel(this->GetSelectedLabels().front());
   auto pixelValue = currentLabel->GetValue();
 
   mitk::LabelSetImageToSurfaceThreadedFilter::Pointer surfaceFilter = mitk::LabelSetImageToSurfaceThreadedFilter::New();
 
   itk::SimpleMemberCommand<QmitkMultiLabelManager>::Pointer successCommand =
     itk::SimpleMemberCommand<QmitkMultiLabelManager>::New();
   successCommand->SetCallbackFunction(this, &QmitkMultiLabelManager::OnThreadedCalculationDone);
   surfaceFilter->AddObserver(mitk::ResultAvailable(), successCommand);
 
   itk::SimpleMemberCommand<QmitkMultiLabelManager>::Pointer errorCommand =
     itk::SimpleMemberCommand<QmitkMultiLabelManager>::New();
   errorCommand->SetCallbackFunction(this, &QmitkMultiLabelManager::OnThreadedCalculationDone);
   surfaceFilter->AddObserver(mitk::ProcessingError(), errorCommand);
 
   mitk::DataNode::Pointer groupNode = this->GetMultiLabelNode();
   surfaceFilter->SetPointerParameter("Group node", groupNode);
   surfaceFilter->SetPointerParameter("Input", this->GetMultiLabelSegmentation());
   surfaceFilter->SetParameter("RequestedLabel", pixelValue);
   surfaceFilter->SetParameter("Smooth", false);
   surfaceFilter->SetDataStorage(*m_DataStorage);
 
   mitk::StatusBar::GetInstance()->DisplayText("Surface creation is running in background...");
 
   try
   {
     surfaceFilter->StartAlgorithm();
   }
   catch (mitk::Exception &e)
   {
     MITK_ERROR << "Exception caught: " << e.GetDescription();
     QMessageBox::information(this,
                              "Create Surface",
                              "Could not create a surface mesh out of the selected label. See error log for details.\n");
   }
 }
 
 void QmitkMultiLabelManager::OnSavePreset()
 {
   QmitkSaveMultiLabelPreset(this->GetMultiLabelSegmentation());
 }
 
 void QmitkMultiLabelManager::OnLoadPreset()
 {
   QmitkLoadMultiLabelPreset({ this->GetMultiLabelSegmentation() });
 }
 
 void QmitkMultiLabelManager::OnGoToLabel(mitk::LabelSetImage::LabelValueType label, const mitk::Point3D& position) const
 {
   emit GoToLabel(label, position);
 }
 
 void QmitkMultiLabelManager::OnLabelRenameRequested(mitk::Label* label, bool rename) const
 {
   emit LabelRenameRequested(label, rename);
 }
 
 void QmitkMultiLabelManager::WaitCursorOn()
 {
   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 }
 
 void QmitkMultiLabelManager::WaitCursorOff()
 {
   this->RestoreOverrideCursor();
 }
 
 void QmitkMultiLabelManager::RestoreOverrideCursor()
 {
   QApplication::restoreOverrideCursor();
 }
 
 void QmitkMultiLabelManager::OnThreadedCalculationDone()
 {
   mitk::StatusBar::GetInstance()->Clear();
 }
 
 void QmitkMultiLabelManager::AddSegmentationObserver()
 {
   if (this->GetMultiLabelSegmentation() != nullptr)
   {
     auto& widget = *this;
     m_LabelAddedObserver.Reset(this->GetMultiLabelSegmentation(), mitk::LabelAddedEvent(), [&widget](const itk::EventObject& event)
       {
         auto labelEvent = dynamic_cast<const mitk::AnyLabelEvent*>(&event);
         widget.OnLabelEvent(labelEvent->GetLabelValue());
       });
     m_LabelModifiedObserver.Reset(this->GetMultiLabelSegmentation(), mitk::LabelModifiedEvent(), [&widget](const itk::EventObject& event)
       {
         auto labelEvent = dynamic_cast<const mitk::AnyLabelEvent*>(&event);
         widget.OnLabelEvent(labelEvent->GetLabelValue());
       });
     m_LabelRemovedObserver.Reset(this->GetMultiLabelSegmentation(), mitk::LabelRemovedEvent(), [&widget](const itk::EventObject& event)
       {
         auto labelEvent = dynamic_cast<const mitk::AnyLabelEvent*>(&event);
         widget.OnLabelEvent(labelEvent->GetLabelValue());
       });
 
     m_GroupAddedObserver.Reset(this->GetMultiLabelSegmentation(), mitk::GroupAddedEvent(), [&widget](const itk::EventObject& event)
       {
         auto groupEvent = dynamic_cast<const mitk::AnyGroupEvent*>(&event);
         widget.OnGroupEvent(groupEvent->GetGroupID());
       });
     m_GroupModifiedObserver.Reset(this->GetMultiLabelSegmentation(), mitk::GroupModifiedEvent(), [&widget](const itk::EventObject& event)
       {
         auto groupEvent = dynamic_cast<const mitk::AnyGroupEvent*>(&event);
         widget.OnGroupEvent(groupEvent->GetGroupID());
       });
     m_GroupRemovedObserver.Reset(this->GetMultiLabelSegmentation(), mitk::GroupRemovedEvent(), [&widget](const itk::EventObject& event)
       {
         auto groupEvent = dynamic_cast<const mitk::AnyGroupEvent*>(&event);
         widget.OnGroupEvent(groupEvent->GetGroupID());
       });
   }
 }
 
 void QmitkMultiLabelManager::RemoveSegmentationObserver()
 {
   m_LabelAddedObserver.Reset();
   m_LabelModifiedObserver.Reset();
   m_LabelRemovedObserver.Reset();
   m_GroupAddedObserver.Reset();
   m_GroupModifiedObserver.Reset();
   m_GroupRemovedObserver.Reset();
 }
 
 void QmitkMultiLabelManager::OnLabelEvent(mitk::LabelSetImage::LabelValueType /*labelValue*/)
 {
   if (!m_Controls->labelInspector->GetModelManipulationOngoing())
     this->UpdateControls();
 }
 
 void QmitkMultiLabelManager::OnGroupEvent(mitk::LabelSetImage::GroupIndexType /*groupIndex*/)
 {
   if (!m_Controls->labelInspector->GetModelManipulationOngoing())
     this->UpdateControls();
 }
 
 void QmitkMultiLabelManager::OnModelUpdated()
 {
   this->UpdateControls();
 }
 
 void QmitkMultiLabelManager::OnSegmentationChanged()
 {
     this->RemoveSegmentationObserver();
     this->AddSegmentationObserver();
     UpdateControls();
 }
diff --git a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelTreeModel.cpp b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelTreeModel.cpp
index 574f44d36f..83003dc693 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkMultiLabelTreeModel.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkMultiLabelTreeModel.cpp
@@ -1,1024 +1,1026 @@
 /*============================================================================
 
 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 "QmitkMultiLabelTreeModel.h"
 
 #include <mitkMultiLabelEvents.h>
 #include <mitkRenderingManager.h>
 
 #include <QmitkStyleManager.h>
 
 
 class QmitkMultiLabelSegTreeItem
 {
 public:
   enum class ItemType
   {
     Group,
     Label,
     Instance
   };
 
   QmitkMultiLabelSegTreeItem()
   {
   };
 
   explicit QmitkMultiLabelSegTreeItem(ItemType type, QmitkMultiLabelSegTreeItem* parentItem,
     mitk::Label* label = nullptr, std::string className = ""): m_parentItem(parentItem), m_ItemType(type), m_Label(label), m_ClassName(className)
   {
   };
 
   ~QmitkMultiLabelSegTreeItem()
   {
     for (auto item : m_childItems)
     {
       delete item;
     }
   };
 
   void AppendChild(QmitkMultiLabelSegTreeItem* child)
   {
       m_childItems.push_back(child);
   };
 
   void RemoveChild(std::size_t row)
   {
     if (row < m_childItems.size())
     {
       delete m_childItems[row];
       m_childItems.erase(m_childItems.begin() + row);
     }
   };
 
   int Row() const
   {
     if (m_parentItem)
     {
       auto finding = std::find(m_parentItem->m_childItems.begin(), m_parentItem->m_childItems.end(), this);
       if (finding != m_parentItem->m_childItems.end())
       {
         return std::distance(m_parentItem->m_childItems.begin(), finding);
       }
     }
 
     return 0;
   };
 
   QmitkMultiLabelSegTreeItem* ParentItem()
   {
     return m_parentItem;
   };
 
   const QmitkMultiLabelSegTreeItem* ParentItem() const
   {
     return m_parentItem;
   };
 
   const QmitkMultiLabelSegTreeItem* NextSibblingItem() const
   {
     if (m_parentItem)
     {
       const std::vector<QmitkMultiLabelSegTreeItem*>::size_type row = this->Row();
       if (row + 1 < m_parentItem->m_childItems.size())
         return m_parentItem->m_childItems[row+1];
     }
 
     return nullptr;
   };
 
   const QmitkMultiLabelSegTreeItem* PrevSibblingItem() const
   {
     if (m_parentItem)
     {
       const std::vector<QmitkMultiLabelSegTreeItem*>::size_type row = this->Row();
       if (row > 0)
         return m_parentItem->m_childItems[row-1];
     }
 
     return nullptr;
   };
 
   const QmitkMultiLabelSegTreeItem* RootItem() const
   {
     auto item = this;
     while (item->m_parentItem != nullptr)
     {
       item = item->m_parentItem;
     }
     return item;
   };
 
   std::size_t GetGroupID() const
   {
     auto root = this->RootItem();
     auto item = this;
     if (root == this) return 0;
 
     while (root != item->m_parentItem)
     {
       item = item->m_parentItem;
     }
 
     auto iter = std::find(root->m_childItems.begin(), root->m_childItems.end(), item);
 
     if (root->m_childItems.end() == iter) mitkThrow() << "Invalid internal state of QmitkMultiLabelTreeModel. Root does not have an currentItem as child that has root as parent.";
 
     return std::distance(root->m_childItems.begin(), iter);
   }
 
   bool HandleAsInstance() const
   {
     return (ItemType::Instance == m_ItemType) || ((ItemType::Label == m_ItemType) && (m_childItems.size() == 1));
   }
 
   mitk::Label* GetLabel() const
   {
     if (ItemType::Instance == m_ItemType)
     {
       return m_Label;
     }
     if (ItemType::Label == m_ItemType)
     {
       if (m_childItems.empty()) mitkThrow() << "Invalid internal state of QmitkMultiLabelTreeModel. Internal label currentItem has no instance currentItem.";
       return m_childItems[0]->GetLabel();
     }
 
     return nullptr;
   };
 
   mitk::LabelSetImage::LabelValueType GetLabelValue() const
   {
     auto label = this->GetLabel();
 
     if (nullptr == label)
     {
       mitkThrow() << "Invalid internal state of QmitkMultiLabelTreeModel. Called GetLabelValue on an group currentItem.";
     }
 
     return label->GetValue();
   };
 
   /** returns a vector containing all label values of referenced by this item or its child items.*/
   std::vector< mitk::LabelSetImage::LabelValueType> GetLabelsInSubTree() const
   {
     if (this->m_ItemType == ItemType::Instance)
     {
       return { this->GetLabelValue() };
     }
 
     std::vector< mitk::LabelSetImage::LabelValueType> result;
     for (const auto child : this->m_childItems)
     {
       auto childresult = child->GetLabelsInSubTree();
       result.reserve(result.size() + childresult.size());
       result.insert(result.end(), childresult.begin(), childresult.end());
     }
 
     return result;
   }
 
   std::vector<QmitkMultiLabelSegTreeItem*> m_childItems;
   QmitkMultiLabelSegTreeItem* m_parentItem = nullptr;
   ItemType m_ItemType = ItemType::Group;
   mitk::Label::Pointer m_Label;
   std::string m_ClassName;
 };
 
 QModelIndex GetIndexByItem(const QmitkMultiLabelSegTreeItem* start, const QmitkMultiLabelTreeModel* model)
 {
   QModelIndex parentIndex = QModelIndex();
   if (nullptr != start->m_parentItem)
   {
     parentIndex = GetIndexByItem(start->m_parentItem, model);
   }
   else
   {
     return parentIndex;
   }
 
   return model->index(start->Row(), 0, parentIndex);
 }
 
 QmitkMultiLabelSegTreeItem* GetGroupItem(QmitkMultiLabelTreeModel::GroupIndexType groupIndex, QmitkMultiLabelSegTreeItem* root)
 {
   if (nullptr != root && groupIndex < root->m_childItems.size())
   {
     return root->m_childItems[groupIndex];
   }
 
   return nullptr;
 }
 
 QmitkMultiLabelSegTreeItem* GetInstanceItem(QmitkMultiLabelTreeModel::LabelValueType labelValue, QmitkMultiLabelSegTreeItem* root)
 {
   QmitkMultiLabelSegTreeItem* result = nullptr;
 
   for (auto item : root->m_childItems)
   {
     result = GetInstanceItem(labelValue, item);
     if (nullptr != result) return result;
   }
 
   if (root->m_ItemType == QmitkMultiLabelSegTreeItem::ItemType::Instance && root->GetLabelValue() == labelValue)
   {
     return root;
   }
 
   return nullptr;
 }
 
 const QmitkMultiLabelSegTreeItem* GetFirstInstanceLikeItem(const QmitkMultiLabelSegTreeItem* startItem)
 {
   const QmitkMultiLabelSegTreeItem* result = nullptr;
 
   if (nullptr != startItem)
   {
     if (startItem->HandleAsInstance())
     {
       result = startItem;
     }
     else if (!startItem->m_childItems.empty())
     {
       result = GetFirstInstanceLikeItem(startItem->m_childItems.front());
     }
   }
 
   return result;
 }
 
 QmitkMultiLabelSegTreeItem* GetLabelItemInGroup(const std::string& labelName, QmitkMultiLabelSegTreeItem* group)
 {
   if (nullptr != group)
   {
     auto predicate = [labelName](const QmitkMultiLabelSegTreeItem* item) { return labelName == item->m_ClassName; };
     auto finding = std::find_if(group->m_childItems.begin(), group->m_childItems.end(), predicate);
     if (group->m_childItems.end() != finding)
     {
       return *finding;
     }
   }
 
   return nullptr;
 }
 
 QmitkMultiLabelTreeModel::QmitkMultiLabelTreeModel(QObject *parent) : QAbstractItemModel(parent)
 {
   m_RootItem = std::make_unique<QmitkMultiLabelSegTreeItem>();
 }
 
 QmitkMultiLabelTreeModel ::~QmitkMultiLabelTreeModel()
 {
   this->SetSegmentation(nullptr);
 };
 
 int QmitkMultiLabelTreeModel::columnCount(const QModelIndex& /*parent*/) const
 {
   return 4;
 }
 
 int QmitkMultiLabelTreeModel::rowCount(const QModelIndex &parent) const
 {
   if (parent.column() > 0)
     return 0;
 
   if (m_Segmentation.IsNull())
     return 0;
 
   QmitkMultiLabelSegTreeItem* parentItem = m_RootItem.get();
 
   if (parent.isValid())
     parentItem = static_cast<QmitkMultiLabelSegTreeItem *>(parent.internalPointer());
 
   if (parentItem->HandleAsInstance())
   {
     return 0;
   }
 
   return parentItem->m_childItems.size();
 }
 
 QVariant QmitkMultiLabelTreeModel::data(const QModelIndex &index, int role) const
 {
   if (!index.isValid())
     return QVariant();
 
   auto item = static_cast<QmitkMultiLabelSegTreeItem*>(index.internalPointer());
 
   if (!item)
     return QVariant();
 
   if (role == Qt::DisplayRole||role == Qt::EditRole)
   {
     if (TableColumns::NAME_COL == index.column())
     {
       switch (item->m_ItemType)
       {
         case QmitkMultiLabelSegTreeItem::ItemType::Group:
           return QVariant(QString("Group %1").arg(item->GetGroupID()));
 
         case QmitkMultiLabelSegTreeItem::ItemType::Label:
         {
           auto label = item->GetLabel();
 
           if (nullptr == label)
             mitkThrow() << "Invalid internal state. QmitkMultiLabelTreeModel currentItem is refering to a label that does not exist.";
 
           QString name = QString::fromStdString(label->GetName());
 
           if (!item->HandleAsInstance())
             name = name + QString(" (%1 instances)").arg(item->m_childItems.size());
 
           return QVariant(name);
         }
 
         case QmitkMultiLabelSegTreeItem::ItemType::Instance:
         {
           auto label = item->GetLabel();
 
           if (nullptr == label)
             mitkThrow() << "Invalid internal state. QmitkMultiLabelTreeModel currentItem is refering to a label that does not exist.";
 
           return QVariant(QString::fromStdString(label->GetName()) + QString(" [%1]").arg(item->GetLabelValue()));
         }
       }
     }
     else
     {
       if (item->HandleAsInstance())
       {
         auto label = item->GetLabel();
 
         if (TableColumns::LOCKED_COL == index.column())
         {
           return QVariant(label->GetLocked());
         }
         else if (TableColumns::COLOR_COL == index.column())
         {
           return QVariant(QColor(label->GetColor().GetRed() * 255, label->GetColor().GetGreen() * 255, label->GetColor().GetBlue() * 255));
         }
         else if (TableColumns::VISIBLE_COL == index.column())
         {
           return QVariant(label->GetVisible());
         }
       }
     }
   }
   else if (role == ItemModelRole::LabelDataRole)
   {
     auto label = item->GetLabel();
     if (nullptr!=label)  return QVariant::fromValue<void*>(label);
   }
   else if (role == ItemModelRole::LabelValueRole)
   {
     auto label = item->GetLabel();
     if (nullptr != label)  return QVariant(label->GetValue());
   }
   else if (role == ItemModelRole::LabelInstanceDataRole)
   {
     if (item->HandleAsInstance())
     {
       auto label = item->GetLabel();
       return QVariant::fromValue<void*>(label);
     }
   }
   else if (role == ItemModelRole::LabelInstanceValueRole)
   {
     if (item->HandleAsInstance())
     {
       auto label = item->GetLabel();
       return QVariant(label->GetValue());
     }
   }
   else if (role == ItemModelRole::GroupIDRole)
   {
     QVariant v;
     v.setValue(item->GetGroupID());
     return v;
   }
 
   return QVariant();
 }
 
 mitk::Color QtToMitk(const QColor& color)
 {
   mitk::Color mitkColor;
 
   mitkColor.SetRed(color.red() / 255.0f);
   mitkColor.SetGreen(color.green() / 255.0f);
   mitkColor.SetBlue(color.blue() / 255.0f);
 
   return mitkColor;
 }
 
 bool QmitkMultiLabelTreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
 {
   if (!index.isValid())
     return false;
 
   auto item = static_cast<QmitkMultiLabelSegTreeItem*>(index.internalPointer());
 
   if (!item)
     return false;
 
   if (role == Qt::EditRole)
   {
     if (TableColumns::NAME_COL != index.column())
     {
       if (item->HandleAsInstance())
       {
         auto label = item->GetLabel();
 
         if (TableColumns::LOCKED_COL == index.column())
         {
           label->SetLocked(value.toBool());
         }
         else if (TableColumns::COLOR_COL == index.column())
         {
           label->SetColor(QtToMitk(value.value<QColor>()));
         }
         else if (TableColumns::VISIBLE_COL == index.column())
         {
           label->SetVisible(value.toBool());
         }
         m_Segmentation->UpdateLookupTable(label->GetValue());
         m_Segmentation->Modified();
         mitk::RenderingManager::GetInstance()->RequestUpdateAll();
       }
       else
       {
 
       }
       return true;
     }
   }
   return false;
 }
 
 QModelIndex QmitkMultiLabelTreeModel::index(int row, int column, const QModelIndex &parent) const
 {
   if (!hasIndex(row, column, parent))
     return QModelIndex();
 
   auto parentItem = m_RootItem.get();
 
   if (parent.isValid())
     parentItem = static_cast<QmitkMultiLabelSegTreeItem *>(parent.internalPointer());
 
   QmitkMultiLabelSegTreeItem *childItem = parentItem->m_childItems[row];
   if (childItem)
     return createIndex(row, column, childItem);
   else
     return QModelIndex();
 }
 
 QModelIndex QmitkMultiLabelTreeModel::indexOfLabel(mitk::Label::PixelType labelValue) const
 {
   if (labelValue == mitk::LabelSetImage::UNLABELED_VALUE) return QModelIndex();
   auto relevantItem = GetInstanceItem(labelValue, this->m_RootItem.get());
 
   if (nullptr == relevantItem)
     return QModelIndex();
 
   auto labelItem = relevantItem->ParentItem();
 
   if (labelItem->m_childItems.size() == 1)
   { //was the only instance of the label, therefor return the label item instat.
     relevantItem = labelItem;
   }
 
   return GetIndexByItem(relevantItem, this);
 }
 
 QModelIndex QmitkMultiLabelTreeModel::indexOfGroup(mitk::LabelSetImage::GroupIndexType groupIndex) const
 {
   auto relevantItem = GetGroupItem(groupIndex, this->m_RootItem.get());
 
   if (nullptr == relevantItem) QModelIndex();
 
   return GetIndexByItem(relevantItem, this);
 }
 
 QModelIndex QmitkMultiLabelTreeModel::parent(const QModelIndex &child) const
 {
   if (!child.isValid())
     return QModelIndex();
 
   QmitkMultiLabelSegTreeItem *childItem = static_cast<QmitkMultiLabelSegTreeItem *>(child.internalPointer());
   QmitkMultiLabelSegTreeItem *parentItem = childItem->ParentItem();
 
   if (parentItem == m_RootItem.get())
     return QModelIndex();
 
   return createIndex(parentItem->Row(), 0, parentItem);
 }
 
 QModelIndex QmitkMultiLabelTreeModel::ClosestLabelInstanceIndex(const QModelIndex& currentIndex) const
 {
   if (!currentIndex.isValid()) return QModelIndex();
 
   auto currentItem = static_cast<const QmitkMultiLabelSegTreeItem*>(currentIndex.internalPointer());
   if (!currentItem) return QModelIndex();
 
   if (currentItem->RootItem() != this->m_RootItem.get()) mitkThrow() << "Invalid call. Passed currentIndex does not seem to be a valid index of this model. It is either outdated or from another model.";
 
   const QmitkMultiLabelSegTreeItem* resultItem = nullptr;
   auto searchItem = currentItem;
   const auto rootItem = currentItem->RootItem();
 
   while (searchItem != rootItem)
   {
     const auto* sibling = searchItem;
 
     while (sibling != nullptr)
     {
       sibling = sibling->NextSibblingItem();
       resultItem = GetFirstInstanceLikeItem(sibling);
 
       if (nullptr != resultItem)
         break;
     }
 
     if (nullptr != resultItem)
       break;
 
     // No next closest label instance on this level -> check for closest before
     sibling = searchItem;
 
     while (sibling != nullptr)
     {
       sibling = sibling->PrevSibblingItem();
       resultItem = GetFirstInstanceLikeItem(sibling);
 
       if (nullptr != resultItem)
         break;
     }
 
     if (nullptr != resultItem)
       break;
 
     // No closest label instance before current on this level -> moeve one level up
     searchItem = searchItem->ParentItem();
   }
 
   if (nullptr == resultItem)
     return QModelIndex();
 
   return GetIndexByItem(resultItem, this);
 }
 
 QModelIndex QmitkMultiLabelTreeModel::FirstLabelInstanceIndex(const QModelIndex& currentIndex) const
 {
   const QmitkMultiLabelSegTreeItem* currentItem = nullptr;
 
   if (!currentIndex.isValid())
   {
     currentItem = this->m_RootItem.get();
   }
   else
   {
     currentItem = static_cast<const QmitkMultiLabelSegTreeItem*>(currentIndex.internalPointer());
   }
 
   if (!currentItem) return QModelIndex();
 
   if (currentItem->RootItem() != this->m_RootItem.get()) mitkThrow() << "Invalid call. Passed currentIndex does not seem to be a valid index of this model. It is either outdated or from another model.";
 
   const QmitkMultiLabelSegTreeItem* resultItem = nullptr;
   resultItem = GetFirstInstanceLikeItem(currentItem);
 
   if (nullptr == resultItem)
     return QModelIndex();
 
   return GetIndexByItem(resultItem, this);
 }
 
 ///** Returns the index to the next node in the tree that behaves like an instance (label node with only one instance
 //or instance node). If current index is at the end, an invalid index is returned.*/
 //QModelIndex QmitkMultiLabelTreeModel::PrevLabelInstanceIndex(const QModelIndex& currentIndex) const;
 
 std::vector <QmitkMultiLabelTreeModel::LabelValueType> QmitkMultiLabelTreeModel::GetLabelsInSubTree(const QModelIndex& currentIndex) const
 {
   const QmitkMultiLabelSegTreeItem* currentItem = nullptr;
 
   if (!currentIndex.isValid())
   {
     currentItem = this->m_RootItem.get();
   }
   else
   {
     currentItem = static_cast<const QmitkMultiLabelSegTreeItem*>(currentIndex.internalPointer());
   }
 
   if (!currentItem) return {};
 
   return currentItem->GetLabelsInSubTree();
 }
 
 std::vector <QmitkMultiLabelTreeModel::LabelValueType> QmitkMultiLabelTreeModel::GetLabelInstancesOfSameLabelClass(const QModelIndex& currentIndex) const
 {
   const QmitkMultiLabelSegTreeItem* currentItem = nullptr;
 
   if (currentIndex.isValid())
   {
     currentItem = static_cast<const QmitkMultiLabelSegTreeItem*>(currentIndex.internalPointer());
   }
 
   if (!currentItem)
     return {};
 
   if (QmitkMultiLabelSegTreeItem::ItemType::Group == currentItem->m_ItemType)
     return {};
 
   if (QmitkMultiLabelSegTreeItem::ItemType::Instance == currentItem->m_ItemType)
     currentItem = currentItem->ParentItem();
 
   return currentItem->GetLabelsInSubTree();
 }
 
 Qt::ItemFlags QmitkMultiLabelTreeModel::flags(const QModelIndex &index) const
 {
   if (!index.isValid())
     return Qt::NoItemFlags;
 
   if (!index.isValid())
     return Qt::NoItemFlags;
 
   auto item = static_cast<QmitkMultiLabelSegTreeItem*>(index.internalPointer());
 
   if (!item)
     return Qt::NoItemFlags;
 
   if (TableColumns::NAME_COL != index.column())
   {
     if (item->HandleAsInstance() &&
       ((TableColumns::VISIBLE_COL == index.column() && m_AllowVisibilityModification) ||
        (TableColumns::COLOR_COL == index.column() && m_AllowVisibilityModification) || //m_AllowVisibilityModification controls visibility and color
        (TableColumns::LOCKED_COL == index.column() && m_AllowLockModification)))
     {
       return Qt::ItemIsEnabled | Qt::ItemIsEditable;
     }
     else
     {
       return Qt::ItemIsEnabled;
     }
   }
   else
   {
     if (item->HandleAsInstance())
     {
       return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
     }
     else
     {
       return Qt::ItemIsEnabled;
     }
   }
 
   return Qt::NoItemFlags;
 }
 
 QVariant QmitkMultiLabelTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
 {
   if ((Qt::DisplayRole == role) && (Qt::Horizontal == orientation))
   {
     if (TableColumns::NAME_COL == section)
     {
       return "Name";
     }
     else if (TableColumns::LOCKED_COL == section)
     {
       return "Locked";
     }
     else if (TableColumns::COLOR_COL == section)
     {
       return "Color";
     }
     else if (TableColumns::VISIBLE_COL == section)
     {
       return "Visibility";
     }
   }
   return QVariant();
 }
 
 const mitk::LabelSetImage* QmitkMultiLabelTreeModel::GetSegmentation() const
 {
   return m_Segmentation;
 }
 
 
 void QmitkMultiLabelTreeModel::SetSegmentation(mitk::LabelSetImage* segmentation)
 {
   if (m_Segmentation != segmentation)
   {
     this->m_Segmentation = segmentation;
     this->AddObserver();
 
     this->UpdateInternalTree();
   }
 }
 
 
 /**Helper function that adds a labek into the item tree. Passes back the new created instance iten*/
 QmitkMultiLabelSegTreeItem* AddLabelToGroupTree(mitk::Label* label, QmitkMultiLabelSegTreeItem* groupItem, bool& newLabelItemCreated)
 {
   if (nullptr == groupItem) return nullptr;
   if (nullptr == label) return nullptr;
 
   newLabelItemCreated = false;
 
   std::set<std::string> labelNames;
   for (auto labelItem : groupItem->m_childItems)
   {
     labelNames.emplace(labelItem->GetLabel()->GetName());
   }
 
   QmitkMultiLabelSegTreeItem* labelItem = nullptr;
   auto finding = labelNames.find(label->GetName());
   if (finding != labelNames.end())
   { //other label with same name exists
     labelItem = groupItem->m_childItems[std::distance(labelNames.begin(), finding)];
   }
   else
   {
     newLabelItemCreated = true;
     labelItem = new QmitkMultiLabelSegTreeItem(QmitkMultiLabelSegTreeItem::ItemType::Label, groupItem, nullptr, label->GetName());
 
     auto predicate = [label](const std::string& name) { return name > label->GetName(); };
     auto insertFinding = std::find_if(labelNames.begin(), labelNames.end(), predicate);
 
     groupItem->m_childItems.insert(groupItem->m_childItems.begin() + std::distance(labelNames.begin(), insertFinding), labelItem);
   }
 
   auto instanceItem = new QmitkMultiLabelSegTreeItem(QmitkMultiLabelSegTreeItem::ItemType::Instance, labelItem, label);
 
   auto predicate = [label](const QmitkMultiLabelSegTreeItem* item) { return item->GetLabelValue() > label->GetValue(); };
   auto insertFinding = std::find_if(labelItem->m_childItems.begin(), labelItem->m_childItems.end(), predicate);
   labelItem->m_childItems.insert(labelItem->m_childItems.begin() + std::distance(labelItem->m_childItems.begin(), insertFinding), instanceItem);
 
   return instanceItem;
 }
 
 void QmitkMultiLabelTreeModel::GenerateInternalGroupTree(unsigned int groupID, QmitkMultiLabelSegTreeItem* groupItem)
 {
   auto labels = m_Segmentation->GetLabelsByValue(m_Segmentation->GetLabelValuesByGroup(groupID));
 
   for (auto& label : labels)
   {
     if (label->GetValue()== mitk::LabelSetImage::UNLABELED_VALUE) continue;
 
     bool newItemCreated = false;
     AddLabelToGroupTree(label, groupItem, newItemCreated);
   }
 }
 
 QmitkMultiLabelSegTreeItem* QmitkMultiLabelTreeModel::GenerateInternalTree()
 {
   auto rootItem = new QmitkMultiLabelSegTreeItem();
 
   if (m_Segmentation.IsNotNull())
   {
     for (unsigned int groupID = 0; groupID < m_Segmentation->GetNumberOfLayers(); ++groupID)
     {
       auto groupItem = new QmitkMultiLabelSegTreeItem(QmitkMultiLabelSegTreeItem::ItemType::Group, rootItem);
       rootItem->AppendChild(groupItem);
 
       GenerateInternalGroupTree(groupID, groupItem);
     }
   }
 
   return rootItem;
 }
 
 void QmitkMultiLabelTreeModel::UpdateInternalTree()
 {
   emit beginResetModel();
   auto newTree = this->GenerateInternalTree();
   this->m_RootItem.reset(newTree);
   emit endResetModel();
   emit modelChanged();
 }
 
 void QmitkMultiLabelTreeModel::ITKEventHandler(const itk::EventObject& e)
 {
   if (mitk::LabelAddedEvent().CheckEvent(&e))
   {
     auto labelEvent = dynamic_cast<const mitk::AnyLabelEvent*>(&e);
     this->OnLabelAdded(labelEvent->GetLabelValue());
   }
   else if (mitk::LabelModifiedEvent().CheckEvent(&e))
   {
     auto labelEvent = dynamic_cast<const mitk::AnyLabelEvent*>(&e);
     this->OnLabelModified(labelEvent->GetLabelValue());
   }
   else if (mitk::LabelRemovedEvent().CheckEvent(&e))
   {
     auto labelEvent = dynamic_cast<const mitk::AnyLabelEvent*>(&e);
     this->OnLabelRemoved(labelEvent->GetLabelValue());
   }
   else if (mitk::GroupAddedEvent().CheckEvent(&e))
   {
     auto labelEvent = dynamic_cast<const mitk::AnyGroupEvent*>(&e);
     this->OnGroupAdded(labelEvent->GetGroupID());
   }
   else if (mitk::GroupModifiedEvent().CheckEvent(&e))
   {
     auto labelEvent = dynamic_cast<const mitk::AnyGroupEvent*>(&e);
     this->OnGroupModified(labelEvent->GetGroupID());
   }
   else if (mitk::GroupRemovedEvent().CheckEvent(&e))
   {
     auto labelEvent = dynamic_cast<const mitk::AnyGroupEvent*>(&e);
     this->OnGroupRemoved(labelEvent->GetGroupID());
   }
 }
 
 void QmitkMultiLabelTreeModel::AddObserver()
 {
   m_LabelAddedObserver.Reset();
   m_LabelModifiedObserver.Reset();
   m_LabelRemovedObserver.Reset();
   m_GroupAddedObserver.Reset();
   m_GroupModifiedObserver.Reset();
   m_GroupRemovedObserver.Reset();
 
   if (this->m_Segmentation.IsNotNull())
   {
     auto& model = *this;
 
     m_LabelAddedObserver.Reset(m_Segmentation, mitk::LabelAddedEvent(), [&model](const itk::EventObject& event){model.ITKEventHandler(event);});
     m_LabelModifiedObserver.Reset(m_Segmentation, mitk::LabelModifiedEvent(), [&model](const itk::EventObject& event) {model.ITKEventHandler(event); });
     m_LabelRemovedObserver.Reset(m_Segmentation, mitk::LabelRemovedEvent(), [&model](const itk::EventObject& event) {model.ITKEventHandler(event); });
     m_GroupAddedObserver.Reset(m_Segmentation, mitk::GroupAddedEvent(), [&model](const itk::EventObject& event) {
       model.ITKEventHandler(event); });
     m_GroupModifiedObserver.Reset(m_Segmentation, mitk::GroupModifiedEvent(), [&model](const itk::EventObject& event) {model.ITKEventHandler(event); });
     m_GroupRemovedObserver.Reset(m_Segmentation, mitk::GroupRemovedEvent(), [&model](const itk::EventObject& event) {model.ITKEventHandler(event); });
   }
 }
 
 void QmitkMultiLabelTreeModel::OnLabelAdded(LabelValueType labelValue)
 {
   GroupIndexType groupIndex = m_Segmentation->GetGroupIndexOfLabel(labelValue);
   auto label = m_Segmentation->GetLabel(labelValue);
   if (nullptr == label) mitkThrow() << "Invalid internal state. Segmentation signaled the addition of an label that does not exist in the segmentation. Invalid label value:" << labelValue;
   if (labelValue == mitk::LabelSetImage::UNLABELED_VALUE) return;
 
   auto groupItem = GetGroupItem(groupIndex, this->m_RootItem.get());
 
   bool newLabelCreated = false;
   auto instanceItem = AddLabelToGroupTree(label, groupItem, newLabelCreated);
 
   if (newLabelCreated)
   {
     if (groupItem->m_childItems.size() == 1)
     { //first label added
       auto groupIndex = GetIndexByItem(groupItem, this);
       emit dataChanged(groupIndex, groupIndex);
       this->beginInsertRows(groupIndex, instanceItem->ParentItem()->Row(), instanceItem->ParentItem()->Row());
       this->endInsertRows();
     }
     else
     { //whole new label level added to group item
       auto groupIndex = GetIndexByItem(groupItem, this);
       this->beginInsertRows(groupIndex, instanceItem->ParentItem()->Row(), instanceItem->ParentItem()->Row());
       this->endInsertRows();
     }
   }
   else
   {
     if (instanceItem->ParentItem()->m_childItems.size() < 3)
-    { //second instance item was added, so label item will now able to colapse
+    { //second instance item was added, so label item will now able to collapse
       // -> the whole label node has to be updated.
       auto labelIndex = GetIndexByItem(instanceItem->ParentItem(), this);
       emit dataChanged(labelIndex, labelIndex);
       this->beginInsertRows(labelIndex, 0, instanceItem->ParentItem()->m_childItems.size()-1);
       this->endInsertRows();
     }
     else
     {
       // instance item was added to existing label item with multiple instances
       //-> just notify the row insertion
       auto labelIndex = GetIndexByItem(instanceItem->ParentItem(), this);
       this->beginInsertRows(labelIndex, instanceItem->Row(), instanceItem->Row());
       this->endInsertRows();
     }
   }
 }
 
 void QmitkMultiLabelTreeModel::OnLabelModified(LabelValueType labelValue)
 {
   if (labelValue == mitk::LabelSetImage::UNLABELED_VALUE) return;
 
   auto instanceItem = GetInstanceItem(labelValue, this->m_RootItem.get());
 
   if (nullptr == instanceItem)
   {
-    mitkThrow() << "Internal invalid state. QmitkMultiLabelTreeModel recieved a LabelModified signal for a label that is not represented in the model. Invalid label: " << labelValue;
+    mitkThrow() << "Internal invalid state. QmitkMultiLabelTreeModel received a LabelModified signal for a label that is not represented in the model. Invalid label: " << labelValue;
   }
 
   auto labelItem = instanceItem->ParentItem();
 
   if (labelItem->m_ClassName == instanceItem->GetLabel()->GetName())
   { //only the state of the label changed, but not its position in the model tree.
 
     auto index = GetIndexByItem(labelItem, this);
-    emit dataChanged(index, index);
+    auto rightIndex = index.sibling(index.row(), this->columnCount() - 1);
+    emit dataChanged(index, rightIndex);
   }
   else
   { //the name of the label changed and thus its place in the model tree, delete the current item and add a new one
     this->OnLabelRemoved(labelValue);
     this->OnLabelAdded(labelValue);
   }
 }
 
 void QmitkMultiLabelTreeModel::OnLabelRemoved(LabelValueType labelValue)
 {
   if (labelValue == mitk::LabelSetImage::UNLABELED_VALUE) return;
   auto instanceItem = GetInstanceItem(labelValue, this->m_RootItem.get());
 
-  if (nullptr == instanceItem) mitkThrow() << "Internal invalid state. QmitkMultiLabelTreeModel recieved a LabelRemoved signal for a label that is not represented in the model. Invalid label: " << labelValue;
+  if (nullptr == instanceItem)
+    mitkThrow() << "Internal invalid state. QmitkMultiLabelTreeModel received a LabelRemoved signal for a label that is not represented in the model. Invalid label: " << labelValue;
 
   auto labelItem = instanceItem->ParentItem();
 
   if (labelItem->m_childItems.size() > 2)
   {
     auto labelIndex = GetIndexByItem(labelItem, this);
     this->beginRemoveRows(labelIndex, instanceItem->Row(), instanceItem->Row());
     labelItem->RemoveChild(instanceItem->Row());
     this->endRemoveRows();
   }
   else if (labelItem->m_childItems.size() == 2)
   { //After removal only one label is left -> the whole label node is about to be changed (no instances are shown any more).
     auto labelIndex = GetIndexByItem(labelItem, this);
     this->beginRemoveRows(labelIndex, instanceItem->Row(), instanceItem->Row());
     labelItem->RemoveChild(instanceItem->Row());
     this->endRemoveRows();
     emit dataChanged(labelIndex, labelIndex);
   }
   else
   { //was the only instance of the label, therefor also remove the label node from the tree.
     auto groupItem = labelItem->ParentItem();
     auto groupIndex = GetIndexByItem(groupItem, this);
     this->beginRemoveRows(groupIndex, labelItem->Row(), labelItem->Row());
     groupItem->RemoveChild(labelItem->Row());
     this->endRemoveRows();
   }
 }
 
 void QmitkMultiLabelTreeModel::OnGroupAdded(GroupIndexType groupIndex)
 {
   if (m_ShowGroups)
   {
     this->beginInsertRows(QModelIndex(), groupIndex, groupIndex);
     auto rootItem = m_RootItem.get();
     auto groupItem = new QmitkMultiLabelSegTreeItem(QmitkMultiLabelSegTreeItem::ItemType::Group, rootItem);
     rootItem->AppendChild(groupItem);
     this->GenerateInternalGroupTree(groupIndex, groupItem);
     this->endInsertRows();
   }
 }
 
 void QmitkMultiLabelTreeModel::OnGroupModified(GroupIndexType /*groupIndex*/)
 {
   //currently not needed
 }
 
 void QmitkMultiLabelTreeModel::OnGroupRemoved(GroupIndexType groupIndex)
 {
   if (m_ShowGroups)
   {
     this->beginRemoveRows(QModelIndex(), groupIndex, groupIndex);
     auto root = m_RootItem.get();
     root->RemoveChild(groupIndex);
     this->endRemoveRows();
   }
 }
 
 void QmitkMultiLabelTreeModel::SetAllowVisibilityModification(bool vmod)
 {
   m_AllowVisibilityModification = vmod;
 }
 
 bool QmitkMultiLabelTreeModel::GetAllowVisibilityModification() const
 {
   return m_AllowVisibilityModification;
 }
 
 void QmitkMultiLabelTreeModel::SetAllowLockModification(bool lmod)
 {
   m_AllowLockModification = lmod;
 }
 
 bool QmitkMultiLabelTreeModel::GetAllowLockModification() const
 {
   return m_AllowLockModification;
 }
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
index 58dc2c7acc..eeffaaf1f9 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
@@ -1,1499 +1,1500 @@
 /*============================================================================
 
 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 "QmitkSlicesInterpolator.h"
 #include "QmitkRenderWindow.h"
 #include "QmitkRenderWindowWidget.h"
 
 #include "mitkApplyDiffImageOperation.h"
 #include "mitkColorProperty.h"
 #include "mitkCoreObjectFactory.h"
 #include "mitkDiffImageApplier.h"
 #include "mitkInteractionConst.h"
 #include "mitkLevelWindowProperty.h"
 #include "mitkOperationEvent.h"
 #include "mitkProgressBar.h"
 #include "mitkProperties.h"
 #include "mitkRenderingManager.h"
 #include "mitkSegTool2D.h"
 #include "mitkSliceNavigationController.h"
 #include "mitkSurfaceToImageFilter.h"
 #include <mitkTimeNavigationController.h>
 #include "mitkToolManager.h"
 #include "mitkUndoController.h"
 
 #include <mitkExtractSliceFilter.h>
 #include <mitkPlanarCircle.h>
 #include <mitkImageReadAccessor.h>
 #include <mitkImageTimeSelector.h>
 #include <mitkImageWriteAccessor.h>
 #include <mitkPlaneProposer.h>
 #include <mitkUnstructuredGridClusteringFilter.h>
 #include <mitkVtkImageOverwrite.h>
 #include <mitkShapeBasedInterpolationAlgorithm.h>
 #include <itkCommand.h>
 
 #include <mitkImageToContourFilter.h>
 #include <mitkImagePixelReadAccessor.h>
 
 //  Includes for the merge operation
 #include "mitkImageToContourFilter.h"
 #include <mitkLabelSetImage.h>
+#include <mitkLabelSetImageConverter.h>
 
 #include <QCheckBox>
 #include <QCursor>
 #include <QMenu>
 #include <QMessageBox>
 #include <QPushButton>
 #include <QVBoxLayout>
 
 #include <vtkDoubleArray.h>
 #include <vtkFieldData.h>
 #include <vtkPolyVertex.h>
 #include <vtkUnstructuredGrid.h>
 #include <vtkPolyData.h>
 
 #include <array>
 #include <atomic>
 #include <thread>
 #include <vector>
 
 namespace
 {
   template <typename T = mitk::BaseData>
   itk::SmartPointer<T> GetData(const mitk::DataNode* dataNode)
   {
     return nullptr != dataNode
       ? dynamic_cast<T*>(dataNode->GetData())
       : nullptr;
   }
 }
 
 float SURFACE_COLOR_RGB[3] = {0.49f, 1.0f, 0.16f};
 
 const QmitkSlicesInterpolator::ActionToSliceDimensionMapType QmitkSlicesInterpolator::CreateActionToSlicer(const QList<QmitkRenderWindow*>& windows)
 {
   std::map<QAction *, mitk::SliceNavigationController *> actionToSliceDimension;
   for (auto* window : windows)
   {
     std::string windowName;
     auto renderWindowWidget = dynamic_cast<QmitkRenderWindowWidget*>(window->parentWidget());
     if (renderWindowWidget)
     {
       windowName = renderWindowWidget->GetCornerAnnotationText();
     }
     else
     {
       windowName = window->GetRenderer()->GetName();
     }
     auto slicer = window->GetSliceNavigationController();
     actionToSliceDimension[new QAction(QString::fromStdString(windowName), nullptr)] = slicer;
   }
 
   return actionToSliceDimension;
 }
 
 mitk::Image::Pointer ExtractSliceFromImage(mitk::Image* image,
                                           const mitk::PlaneGeometry * contourPlane,
                                           unsigned int timeStep)
 {
   vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
   // set to false to extract a slice
   reslice->SetOverwriteMode(false);
   reslice->Modified();
 
   mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
   extractor->SetInput(image);
   extractor->SetTimeStep(timeStep);
   extractor->SetWorldGeometry(contourPlane);
   extractor->SetVtkOutputRequest(false);
   extractor->SetResliceTransformByGeometry(image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep));
   extractor->Update();
   mitk::Image::Pointer slice = extractor->GetOutput();
   return slice;
 }
 
 QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget *parent, const char * /*name*/)
   : QWidget(parent),
     m_Interpolator(mitk::SegmentationInterpolationController::New()),
     m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()),
     m_ToolManager(nullptr),
     m_Initialized(false),
     m_LastSNC(nullptr),
     m_LastSliceIndex(0),
     m_2DInterpolationEnabled(false),
     m_3DInterpolationEnabled(false),
     m_CurrentActiveLabelValue(0),
     m_FirstRun(true)
 {
   m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this);
 
   QVBoxLayout *vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode);
 
   m_EdgeDetector = mitk::FeatureBasedEdgeDetectionFilter::New();
   m_PointScorer = mitk::PointCloudScoringFilter::New();
 
   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("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApply2D);
 
   m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApplyForAllSlices2D);
 
   m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApply3D);
 
   m_BtnReinit3DInterpolation = new QPushButton("Reinit Interpolation", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnReinit3DInterpolation);
 
   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_BtnReinit3DInterpolation, SIGNAL(clicked()), this, SLOT(OnReinit3DInterpolation()));
   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<QmitkSlicesInterpolator>::Pointer command =
     itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged);
   InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver(itk::ModifiedEvent(), command);
 
   itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command2 =
     itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command2->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged);
   SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver(itk::ModifiedEvent(), command2);
 
   auto command3 = itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command3->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationAborted);
   InterpolationAbortedObserverTag = m_Interpolator->AddObserver(itk::AbortEvent(), command3);
 
   // 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(SURFACE_COLOR_RGB));
   m_InterpolatedSurfaceNode->SetProperty("name", mitk::StringProperty::New("Surface Interpolation feedback"));
   m_InterpolatedSurfaceNode->SetProperty("opacity", mitk::FloatProperty::New(0.5));
   m_InterpolatedSurfaceNode->SetProperty("line width", mitk::FloatProperty::New(4.0f));
   m_InterpolatedSurfaceNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
   m_InterpolatedSurfaceNode->SetProperty("helper object", mitk::BoolProperty::New(true));
   m_InterpolatedSurfaceNode->SetVisibility(false);
 
   QWidget::setContentsMargins(0, 0, 0, 0);
   if (QWidget::layout() != nullptr)
   {
     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)
 {
   if (m_DataStorage == storage)
   {
     return;
   }
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.RemoveListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
   }
 
   m_DataStorage = storage;
   m_SurfaceInterpolator->SetDataStorage(storage);
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.AddListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
   }
 }
 
 void QmitkSlicesInterpolator::SetActiveLabelValue(mitk::LabelSetImage::LabelValueType labelValue)
 {
   bool changedValue = labelValue != this->m_CurrentActiveLabelValue;
 
   this->m_CurrentActiveLabelValue = labelValue;
 
   if (changedValue) this->OnActiveLabelChanged(labelValue);
 };
 
 
 mitk::DataStorage *QmitkSlicesInterpolator::GetDataStorage()
 {
   if (m_DataStorage.IsNotNull())
   {
     return m_DataStorage;
   }
   else
   {
     return nullptr;
   }
 }
 
 void QmitkSlicesInterpolator::InitializeWindow(QmitkRenderWindow* window)
 {
   auto slicer = window->GetSliceNavigationController();
 
   if (slicer == nullptr)
   {
     MITK_WARN << "Tried setting up interpolation for a render window that does not have a slice navigation controller set";
     return;
   }
 
   // Has to be initialized
   m_LastSNC = slicer;
 
   itk::MemberCommand<QmitkSlicesInterpolator>::Pointer deleteCommand =
     itk::MemberCommand<QmitkSlicesInterpolator>::New();
   deleteCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted);
   m_ControllerToDeleteObserverTag[slicer] = slicer->AddObserver(itk::DeleteEvent(), deleteCommand);
 
   itk::MemberCommand<QmitkSlicesInterpolator>::Pointer sliceChangedCommand =
     itk::MemberCommand<QmitkSlicesInterpolator>::New();
   sliceChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceChanged);
   m_ControllerToSliceObserverTag[slicer] = slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), sliceChangedCommand);
 }
 
 void QmitkSlicesInterpolator::Initialize(mitk::ToolManager *toolManager,
                                          const QList<QmitkRenderWindow*>& windows)
 {
   Q_ASSERT(!windows.empty());
 
   if (m_Initialized)
   {
     // remove old observers
     this->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 != nullptr);
 
     // react whenever the set of selected segmentation changes
     m_ToolManager->WorkingDataChanged +=
       mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
     m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate<QmitkSlicesInterpolator>(
       this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
 
     auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
     itk::MemberCommand<QmitkSlicesInterpolator>::Pointer timeChangedCommand =
       itk::MemberCommand<QmitkSlicesInterpolator>::New();
     timeChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnTimeChanged);
     m_ControllerToTimeObserverTag =
       timeNavigationController->AddObserver(mitk::TimeNavigationController::TimeEvent(0), timeChangedCommand);
 
     m_TimePoint = timeNavigationController->GetSelectedTimePoint();
 
     // connect to the slice navigation controller. after each change, call the interpolator
     for (auto* window : windows)
     {
       this->InitializeWindow(window);
     }
 
     m_ActionToSlicerMap = CreateActionToSlicer(windows);
   }
 
   m_Initialized = true;
 }
 
 void QmitkSlicesInterpolator::Uninitialize()
 {
   if (m_ToolManager.IsNotNull())
   {
     m_ToolManager->WorkingDataChanged -=
       mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
     m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
       this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
   }
 
   auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
   timeNavigationController->RemoveObserver(m_ControllerToTimeObserverTag);
 
 for (auto* slicer : m_ControllerToSliceObserverTag.keys())
   {
     slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer));
     slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer));
   }
 
   m_ActionToSlicerMap.clear();
   m_ToolManager = nullptr;
 
   m_Initialized = false;
 }
 
 QmitkSlicesInterpolator::~QmitkSlicesInterpolator()
 {
   if (m_Initialized)
   {
     // remove old observers
     this->Uninitialize();
   }
 
   WaitForFutures();
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.RemoveListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
 
     if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
       m_DataStorage->Remove(m_InterpolatedSurfaceNode);
   }
 
   // remove observer
   m_Interpolator->RemoveObserver(InterpolationAbortedObserverTag);
   m_Interpolator->RemoveObserver(InterpolationInfoChangedObserverTag);
   m_SurfaceInterpolator->RemoveObserver(SurfaceInterpolationInfoChangedObserverTag);
 
   m_SurfaceInterpolator->SetCurrentInterpolationSession(nullptr);
 
   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);
   m_BtnReinit3DInterpolation->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);
       m_Interpolator->Activate2DInterpolation(false);
       break;
 
     case 1: // 2D
       m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
       this->HideAllInterpolationControls();
       this->Show2DInterpolationControls(true);
       this->OnInterpolationActivated(true);
       this->On3DInterpolationActivated(false);
       this->Show3DInterpolationResult(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);
       m_Interpolator->Activate2DInterpolation(false);
       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) != nullptr)
   {
     m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
     m_BtnReinit3DInterpolation->setEnabled(true);
   }
   else
   {
     // If no workingdata is set, remove the interpolation feedback
     this->GetDataStorage()->Remove(m_FeedbackNode);
     m_FeedbackNode->SetData(nullptr);
     this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode);
     m_InterpolatedSurfaceNode->SetData(nullptr);
     m_BtnReinit3DInterpolation->setEnabled(false);
     m_CmbInterpolation->setCurrentIndex(0);
     return;
   }
   // Updating the current selected segmentation for the 3D interpolation
   this->SetCurrentContourListID();
 
   if (m_2DInterpolationEnabled)
   {
     OnInterpolationActivated(true); // re-initialize if needed
   }
 }
 
 void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified()
 {
 }
 
 void QmitkSlicesInterpolator::OnTimeChanged(itk::Object *sender, const itk::EventObject &e)
 {
   if (!dynamic_cast<const mitk::TimeNavigationController::TimeEvent*>(&e))
   {
     return;
   }
 
   const auto* timeNavigationController = dynamic_cast<mitk::TimeNavigationController*>(sender);
   if (nullptr == timeNavigationController)
   {
     return;
   }
 
   bool timeChanged = m_TimePoint != timeNavigationController->GetSelectedTimePoint();
   m_TimePoint = timeNavigationController->GetSelectedTimePoint();
 
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (timeChanged)
   {
     if (m_3DInterpolationEnabled)
     {
       m_InterpolatedSurfaceNode->SetData(nullptr);
     }
     m_SurfaceInterpolator->Modified();
   }
 
   if (nullptr == m_LastSNC)
   {
     return;
   }
 
   if (TranslateAndInterpolateChangedSlice(m_LastSNC->GetCreatedWorldGeometry()))
   {
     m_LastSNC->GetRenderer()->RequestUpdate();
   }
 }
 
 void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e)
 {
   if (!dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e))
   {
     return;
   }
 
   auto sliceNavigationController = dynamic_cast<mitk::SliceNavigationController*>(sender);
   if (nullptr == sliceNavigationController)
   {
     return;
   }
 
   if(m_2DInterpolationEnabled)
   {
     this->On2DInterpolationEnabled(m_2DInterpolationEnabled);
   }  
 
   if (TranslateAndInterpolateChangedSlice(e, sliceNavigationController))
   {
     sliceNavigationController->GetRenderer()->RequestUpdate();
   }
 }
 
 bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e,
   mitk::SliceNavigationController* sliceNavigationController)
 {
   const mitk::SliceNavigationController::GeometrySliceEvent* event =
     dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e);
 
   mitk::TimeGeometry* timeGeometry = event->GetTimeGeometry();
   m_LastSNC = sliceNavigationController;
 
   return this->TranslateAndInterpolateChangedSlice(timeGeometry);
 }
 
 bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const mitk::TimeGeometry* timeGeometry)
 {
   if (!m_2DInterpolationEnabled)
   {
     return false;
   }
 
   if (nullptr == timeGeometry)
   {
     return false;
   }
 
   if (!timeGeometry->IsValidTimePoint(m_TimePoint))
   {
     return false;
   }
 
   mitk::SlicedGeometry3D* slicedGeometry =
     dynamic_cast<mitk::SlicedGeometry3D*>(timeGeometry->GetGeometryForTimePoint(m_TimePoint).GetPointer());
   if (nullptr == slicedGeometry)
   {
     return false;
   }
 
   mitk::PlaneGeometry* plane = dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry->GetPlaneGeometry(m_LastSNC->GetStepper()->GetPos()));
   if (nullptr == plane)
   {
     return false;
   }
 
   this->Interpolate(plane);
   return true;
 }
 
 void QmitkSlicesInterpolator::Interpolate(mitk::PlaneGeometry *plane)
 {
   if (nullptr == m_ToolManager)
   {
     return;
   }
 
   mitk::DataNode* node = m_ToolManager->GetWorkingData(0);
   if (nullptr == node)
   {
     return;
   }
 
   m_Segmentation = dynamic_cast<mitk::Image*>(node->GetData());
   if (nullptr == m_Segmentation)
   {
     return;
   }
 
   if (!m_Segmentation->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot interpolate WorkingImage. Passed time point is not within the time bounds of WorkingImage. "
                  "Time point: "
               << m_TimePoint;
     return;
   }
 
   const auto timeStep = m_Segmentation->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
 
   int clickedSliceDimension = -1;
   int clickedSliceIndex = -1;
 
   // calculate real slice position, i.e. slice of the image
   mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex);
 
   mitk::Image::Pointer interpolation =
     m_Interpolator->Interpolate(clickedSliceDimension, clickedSliceIndex, plane, timeStep);
   m_FeedbackNode->SetData(interpolation);
 
   //  maybe just have a variable that stores the active label color.
   if (m_ToolManager)
   {
     auto* workingNode = m_ToolManager->GetWorkingData(0);
     if (workingNode != nullptr)
     {
       auto* activeLabel = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabel();
       if (nullptr != activeLabel)
       {
         auto activeColor = activeLabel->GetColor();
         m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
       }
     }
   }
 
   m_LastSliceIndex = clickedSliceIndex;
 }
 
 void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished()
 {
   mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
 
   if (workingNode && workingNode->GetData())
   {
     const auto segmentation = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
 
     if (segmentation == nullptr)
     {
       MITK_ERROR << "Run3DInterpolation triggered with no MultiLabelSegmentation as working data.";
       return;
     }
     mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult(segmentation, m_CurrentActiveLabelValue, segmentation->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint));
 
     if (interpolatedSurface.IsNotNull())
     {
       m_BtnApply3D->setEnabled(true);;
 
       m_InterpolatedSurfaceNode->SetData(interpolatedSurface);
       this->Show3DInterpolationResult(true);
 
       if (!m_DataStorage->Exists(m_InterpolatedSurfaceNode))
       {
         m_DataStorage->Add(m_InterpolatedSurfaceNode);
       }
     }
     else
     {
       m_BtnApply3D->setEnabled(false);
 
       if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
       {
         this->Show3DInterpolationResult(false);
       }
     }
   }
 
   m_BtnReinit3DInterpolation->setEnabled(true);
 
   for (auto* slicer : m_ControllerToSliceObserverTag.keys())
   {
     slicer->GetRenderer()->RequestUpdate();
   }
 }
 
 void QmitkSlicesInterpolator::OnAcceptInterpolationClicked()
 {
   auto* workingNode = m_ToolManager->GetWorkingData(0);
   auto* planeGeometry = m_LastSNC->GetCurrentPlaneGeometry();
   auto* interpolatedPreview = dynamic_cast<mitk::Image*>(m_FeedbackNode->GetData());
   if (nullptr == workingNode || nullptr == interpolatedPreview)
     return;
 
   auto* segmentationImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
   if (nullptr == segmentationImage)
     return;
 
   if (!segmentationImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the "
       "time bounds of segmentation. Time point: "
       << m_TimePoint;
     return;
   }
 
   const auto timeStep = segmentationImage->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
 
   auto interpolatedSlice = mitk::SegTool2D::GetAffectedImageSliceAs2DImage(planeGeometry, segmentationImage, timeStep)->Clone();
   auto activeValue = segmentationImage->GetActiveLabel()->GetValue();
   mitk::TransferLabelContentAtTimeStep(
     interpolatedPreview,
     interpolatedSlice,
     segmentationImage->GetConstLabelsByValue(segmentationImage->GetLabelValuesByGroup(segmentationImage->GetActiveLayer())),
     timeStep,
     0,
     mitk::LabelSetImage::UNLABELED_VALUE,
     false,
     { {0, mitk::LabelSetImage::UNLABELED_VALUE}, {1, activeValue} }
   );
 
   mitk::SegTool2D::WriteBackSegmentationResult(workingNode, planeGeometry, interpolatedSlice, timeStep);
   m_FeedbackNode->SetData(nullptr);
 }
 
 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)
   {
     mitk::Image::Pointer segmentation3D = m_Segmentation;
     unsigned int timeStep = 0;
 
     if (4 == m_Segmentation->GetDimension())
     {
       const auto* geometry = m_Segmentation->GetTimeGeometry();
 
       if (!geometry->IsValidTimePoint(m_TimePoint))
       {
         MITK_WARN << "Cannot accept all interpolations. Time point selected by passed SliceNavigationController is not "
                      "within the time bounds of segmentation. Time point: "
                   << m_TimePoint;
         return;
       }
 
       mitk::Image::Pointer activeLabelImage;
       try
       {
         auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation);
-        activeLabelImage = labelSetImage->CreateLabelMask(labelSetImage->GetActiveLabel()->GetValue());
+        activeLabelImage = mitk::CreateLabelMask(labelSetImage, labelSetImage->GetActiveLabel()->GetValue());
       }
       catch (const std::exception& e)
       {
         MITK_ERROR << e.what() << " | NO LABELSETIMAGE IN WORKING NODE\n";
       }
 
       m_Interpolator->SetSegmentationVolume(activeLabelImage);
 
       timeStep = geometry->TimePointToTimeStep(m_TimePoint);
 
       auto timeSelector = mitk::ImageTimeSelector::New();
       timeSelector->SetInput(m_Segmentation);
       timeSelector->SetTimeNr(timeStep);
       timeSelector->Update();
 
       segmentation3D = timeSelector->GetOutput();
     }
 
     // Create an empty diff image for the undo operation
     auto diffImage = mitk::Image::New();
     diffImage->Initialize(segmentation3D);
 
     // Create scope for ImageWriteAccessor so that the accessor is destroyed right after use
     {
       mitk::ImageWriteAccessor accessor(diffImage);
 
       // Set all pixels to zero
       auto pixelType = mitk::MakeScalarPixelType<mitk::Tool::DefaultSegmentationDataType>();
 
       // For legacy purpose support former pixel type of segmentations (before multilabel)
       if (itk::IOComponentEnum::UCHAR == m_Segmentation->GetImageDescriptor()->GetChannelDescriptor().GetPixelType().GetComponentType())
         pixelType = mitk::MakeScalarPixelType<unsigned char>();
 
       memset(accessor.GetData(), 0, pixelType.GetSize() * 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
     auto slicedGeometry = m_Segmentation->GetSlicedGeometry();
     auto planeGeometry = slicer->GetCurrentPlaneGeometry()->Clone();
     int sliceDimension = -1;
     int sliceIndex = -1;
 
     mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, planeGeometry, sliceDimension, sliceIndex);
 
     const auto numSlices = m_Segmentation->GetDimension(sliceDimension);
     mitk::ProgressBar::GetInstance()->AddStepsToDo(numSlices);
 
     std::atomic_uint totalChangedSlices;
 
     // Reuse interpolation algorithm instance for each slice to cache boundary calculations
     auto algorithm = mitk::ShapeBasedInterpolationAlgorithm::New();
 
     // Distribute slice interpolations to multiple threads
     const auto numThreads = std::min(std::thread::hardware_concurrency(), numSlices);
     std::vector<std::vector<unsigned int>> sliceIndices(numThreads);
 
     for (std::remove_const_t<decltype(numSlices)> sliceIndex = 0; sliceIndex < numSlices; ++sliceIndex)
       sliceIndices[sliceIndex % numThreads].push_back(sliceIndex);
 
     std::vector<std::thread> threads;
     threads.reserve(numThreads);
 
     // This lambda will be executed by the threads
     auto interpolate = [=, &interpolator = m_Interpolator, &totalChangedSlices](unsigned int threadIndex)
     {
       auto clonedPlaneGeometry = planeGeometry->Clone();
       auto origin = clonedPlaneGeometry->GetOrigin();
 
       //  Go through the sliced indices
       for (auto sliceIndex : sliceIndices[threadIndex])
       {
         slicedGeometry->WorldToIndex(origin, origin);
         origin[sliceDimension] = sliceIndex;
         slicedGeometry->IndexToWorld(origin, origin);
         clonedPlaneGeometry->SetOrigin(origin);
 
         auto interpolation = interpolator->Interpolate(sliceDimension, sliceIndex, clonedPlaneGeometry, timeStep, algorithm);
 
         if (interpolation.IsNotNull())
         {
           // Setting up the reslicing pipeline which allows us to write the interpolation results back into the image volume
           auto reslicer = vtkSmartPointer<mitkVtkImageOverwrite>::New();
 
           // Set overwrite mode to true to write back to the image volume
           reslicer->SetInputSlice(interpolation->GetSliceData()->GetVtkImageAccessor(interpolation)->GetVtkImageData());
           reslicer->SetOverwriteMode(true);
           reslicer->Modified();
 
           auto diffSliceWriter = mitk::ExtractSliceFilter::New(reslicer);
 
           diffSliceWriter->SetInput(diffImage);
           diffSliceWriter->SetTimeStep(0);
           diffSliceWriter->SetWorldGeometry(clonedPlaneGeometry);
           diffSliceWriter->SetVtkOutputRequest(true);
           diffSliceWriter->SetResliceTransformByGeometry(diffImage->GetTimeGeometry()->GetGeometryForTimeStep(0));
           diffSliceWriter->Modified();
           diffSliceWriter->Update();
 
           ++totalChangedSlices;
         }
 
         mitk::ProgressBar::GetInstance()->Progress();
       }
     };
     m_Interpolator->EnableSliceImageCache();
 
     //  Do the interpolation here.
     for (size_t threadIndex = 0; threadIndex < numThreads; ++threadIndex)
     {
       interpolate(threadIndex);
     }
 
     m_Interpolator->DisableSliceImageCache();
 
     const mitk::Label::PixelType newDestinationLabel = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation)->GetActiveLabel()->GetValue();
 
     //  Do and Undo Operations
     if (totalChangedSlices > 0)
     {
       // Create do/undo operations
       auto* doOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
 
       auto* undoOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
       undoOp->SetFactor(-1.0);
 
       auto comment = "Confirm all interpolations (" + std::to_string(totalChangedSlices) + ")";
       auto* undoStackItem = new mitk::OperationEvent(mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment);
 
       mitk::OperationEvent::IncCurrGroupEventId();
       mitk::OperationEvent::IncCurrObjectEventId();
       mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent(undoStackItem);
       mitk::DiffImageApplier::GetInstanceForUndo()->SetDestinationLabel(newDestinationLabel);
       // Apply the changes to the original image
       mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation(doOp);
     }
     m_FeedbackNode->SetData(nullptr);
   }
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController *slicer)
 {
   // this redirect is for calling from outside
   if (slicer == nullptr)
     OnAcceptAllInterpolationsClicked();
   else
     AcceptAllInterpolations(slicer);
 }
 
 void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked()
 {
   QMenu orientationPopup(this);
   for (auto it = m_ActionToSlicerMap.begin(); it != m_ActionToSlicerMap.end(); ++it)
   {
     orientationPopup.addAction(it->first);
   }
 
   connect(&orientationPopup, SIGNAL(triggered(QAction *)), this, SLOT(OnAcceptAllPopupActivated(QAction *)));
   orientationPopup.exec(QCursor::pos());
 }
 
 void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked()
 {
   auto referenceImage = GetData<mitk::Image>(m_ToolManager->GetReferenceData(0));
 
   auto* segmentationDataNode = m_ToolManager->GetWorkingData(0);
 
   auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(segmentationDataNode->GetData());
   auto activeLabelColor = labelSetImage->GetActiveLabel()->GetColor();
   std::string activeLabelName = labelSetImage->GetActiveLabel()->GetName();
 
   auto segmentation = GetData<mitk::Image>(segmentationDataNode);
 
   if (referenceImage.IsNull() || segmentation.IsNull())
     return;
 
   const auto* segmentationGeometry = segmentation->GetTimeGeometry();
 
   if (!referenceImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint) ||
       !segmentationGeometry->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot accept interpolation. Current time point is not within the time bounds of the patient image and segmentation.";
     return;
   }
 
   auto interpolatedSurface = GetData<mitk::Surface>(m_InterpolatedSurfaceNode);
 
   if (interpolatedSurface.IsNull())
     return;
 
   auto surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
 
   surfaceToImageFilter->SetImage(referenceImage);
   surfaceToImageFilter->SetMakeOutputBinary(true);
   surfaceToImageFilter->SetUShortBinaryPixelType(itk::IOComponentEnum::USHORT == segmentation->GetPixelType().GetComponentType());
   surfaceToImageFilter->SetInput(interpolatedSurface);
   surfaceToImageFilter->Update();
 
   mitk::Image::Pointer interpolatedSegmentation = surfaceToImageFilter->GetOutput();
   auto timeStep = segmentationGeometry->TimePointToTimeStep(m_TimePoint);
   const mitk::Label::PixelType newDestinationLabel = labelSetImage->GetActiveLabel()->GetValue();
 
   TransferLabelContentAtTimeStep(
     interpolatedSegmentation,
     labelSetImage,
     labelSetImage->GetConstLabelsByValue(labelSetImage->GetLabelValuesByGroup(labelSetImage->GetActiveLayer())),
     timeStep,
     0,
     0,
     false,
     {{1, newDestinationLabel}},
     mitk::MultiLabelSegmentation::MergeStyle::Merge,
     mitk::MultiLabelSegmentation::OverwriteStyle::RegardLocks);
 
   this->Show3DInterpolationResult(false);
 
   std::string name = segmentationDataNode->GetName() + " 3D-interpolation - " + activeLabelName;
   mitk::TimeBounds timeBounds;
 
   if (1 < interpolatedSurface->GetTimeSteps())
   {
     name += "_t" + std::to_string(timeStep);
 
     auto* polyData = vtkPolyData::New();
     polyData->DeepCopy(interpolatedSurface->GetVtkPolyData(timeStep));
 
     auto surface = mitk::Surface::New();
     surface->SetVtkPolyData(polyData);
 
     interpolatedSurface = surface;
     timeBounds = segmentationGeometry->GetTimeBounds(timeStep);
   }
   else
   {
     timeBounds = segmentationGeometry->GetTimeBounds(0);
   }
 
   auto* surfaceGeometry = static_cast<mitk::ProportionalTimeGeometry*>(interpolatedSurface->GetTimeGeometry());
   surfaceGeometry->SetFirstTimePoint(timeBounds[0]);
   surfaceGeometry->SetStepDuration(timeBounds[1] - timeBounds[0]);
 
   // Typical file formats for surfaces do not save any time-related information. As a workaround at least for MITK scene files, we have the
   // possibility to seralize this information as properties.
 
   interpolatedSurface->SetProperty("ProportionalTimeGeometry.FirstTimePoint", mitk::FloatProperty::New(surfaceGeometry->GetFirstTimePoint()));
   interpolatedSurface->SetProperty("ProportionalTimeGeometry.StepDuration", mitk::FloatProperty::New(surfaceGeometry->GetStepDuration()));
 
   auto interpolatedSurfaceDataNode = mitk::DataNode::New();
 
   interpolatedSurfaceDataNode->SetData(interpolatedSurface);
   interpolatedSurfaceDataNode->SetName(name);
   interpolatedSurfaceDataNode->SetOpacity(0.7f);
 
   interpolatedSurfaceDataNode->SetColor(activeLabelColor);
   m_DataStorage->Add(interpolatedSurfaceDataNode, segmentationDataNode);
 }
 
 void QmitkSlicesInterpolator::OnReinit3DInterpolation()
 {
   //  Step 1. Load from the isContourPlaneGeometry nodes the contourNodes.
   mitk::NodePredicateProperty::Pointer pred =
     mitk::NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
   mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
     m_DataStorage->GetDerivations(m_ToolManager->GetWorkingData(0), pred);
 
   if (contourNodes->Size() != 0)
   {
     if (m_ToolManager->GetWorkingData(0) != nullptr)
     {
       try
       {
         auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
         if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
         {
           MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
           return;
         }
 
         mitk::SurfaceInterpolationController::CPIVector newCPIs;
         //  Adding label and timeStep information for the contourNodes.
         for (auto it = contourNodes->Begin(); it != contourNodes->End(); ++it)
         {
           auto contourNode = it->Value();
           auto labelID = dynamic_cast<mitk::UShortProperty *>(contourNode->GetProperty("labelID"))->GetValue();
           auto timeStep = dynamic_cast<mitk::IntProperty *>(contourNode->GetProperty("timeStep"))->GetValue();
 
           auto planeGeometry = dynamic_cast<mitk::PlanarFigure *>(contourNode->GetData())->GetPlaneGeometry();
           auto groupID = labelSetImage->GetGroupIndexOfLabel(labelID);
           auto sliceImage = ExtractSliceFromImage(labelSetImage->GetGroupImage(groupID), planeGeometry, timeStep);
           mitk::ImageToContourFilter::Pointer contourExtractor = mitk::ImageToContourFilter::New();
           contourExtractor->SetInput(sliceImage);
           contourExtractor->SetContourValue(labelID);
           contourExtractor->Update();
           mitk::Surface::Pointer contour = contourExtractor->GetOutput();
 
           if (contour->GetVtkPolyData()->GetNumberOfPoints() == 0)
             continue;
 
           contour->DisconnectPipeline();
           newCPIs.emplace_back(contour, planeGeometry->Clone(),labelID,timeStep);
         }
         m_SurfaceInterpolator->CompleteReinitialization(newCPIs);
       }
       catch(const std::exception& e)
       {
         MITK_ERROR << "Exception thrown casting toolmanager working data to labelsetImage";
       }
     }
   }
   else
   {
     m_BtnApply3D->setEnabled(false);
     QMessageBox errorInfo;
     errorInfo.setWindowTitle("Reinitialize surface interpolation");
     errorInfo.setIcon(QMessageBox::Information);
     errorInfo.setText("No contours available for the selected segmentation!");
     errorInfo.exec();
   }
 }
 
 void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction *action)
 {
   try
   {
     auto iter = m_ActionToSlicerMap.find(action);
     if (iter != m_ActionToSlicerMap.end())
     {
       mitk::SliceNavigationController *slicer = iter->second;
       this->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();
 
     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 != nullptr);
 
     m_BtnApply2D->setEnabled(on);
     m_FeedbackNode->SetVisibility(on);
 
     if (!on)
     {
       mitk::RenderingManager::GetInstance()->RequestUpdateAll();
       return;
     }
 
     if (workingNode)
     {
       auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
       if (nullptr == labelSetImage)
       {
         MITK_ERROR << "NO LABELSETIMAGE IN WORKING NODE\n";
         mitk::RenderingManager::GetInstance()->RequestUpdateAll();
         return;
       }
 
       const auto* activeLabel = labelSetImage->GetActiveLabel();
       const auto* segmentation = dynamic_cast<mitk::Image*>(workingNode->GetData());
       if (nullptr != activeLabel && nullptr != segmentation)
       {
-        auto activeLabelImage = labelSetImage->CreateLabelMask(activeLabel->GetValue());
+        auto activeLabelImage = mitk::CreateLabelMask(labelSetImage, activeLabel->GetValue());
         m_Interpolator->SetSegmentationVolume(activeLabelImage);
 
         if (referenceNode)
         {
           mitk::Image *referenceImage = dynamic_cast<mitk::Image *>(referenceNode->GetData());
           m_Interpolator->SetReferenceVolume(referenceImage); // may be nullptr
         }
       }
     }
   }
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::Run3DInterpolation()
 {
   auto workingNode = m_ToolManager->GetWorkingData(0);
 
   if (workingNode == nullptr)
   {
     MITK_ERROR << "Run3DInterpolation triggered with no working data set.";
     return;
   }
 
   const auto segmentation = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
 
   if (segmentation == nullptr)
   {
     MITK_ERROR << "Run3DInterpolation triggered with no MultiLabelSegmentation as working data.";
     return;
   }
 
   if (!segmentation->ExistLabel(m_CurrentActiveLabelValue))
   {
     MITK_ERROR << "Run3DInterpolation triggered with no valid label selected. Currently selected invalid label: "<<m_CurrentActiveLabelValue;
     return;
   }
 
   m_SurfaceInterpolator->Interpolate(segmentation,m_CurrentActiveLabelValue,segmentation->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint));
 }
 
 void QmitkSlicesInterpolator::StartUpdateInterpolationTimer()
 {
   m_Timer->start(500);
 }
 
 void QmitkSlicesInterpolator::StopUpdateInterpolationTimer()
 {
   if(m_ToolManager)
   {
     const auto* workingNode = m_ToolManager->GetWorkingData(0);
     const auto activeColor = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabel()->GetColor();
     m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
   }
 
   m_Timer->stop();
 }
 
 void QmitkSlicesInterpolator::ChangeSurfaceColor()
 {
   float currentColor[3];
   m_InterpolatedSurfaceNode->GetColor(currentColor);
 
     m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
   m_InterpolatedSurfaceNode->Update();
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS);
 }
 
 void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on)
 {
   m_3DInterpolationEnabled = on;
   try
   {
     // this->PrepareInputsFor3DInterpolation();
     m_SurfaceInterpolator->Modified();
   }
   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
   this->On3DInterpolationActivated(on);
 }
 
 void QmitkSlicesInterpolator::UpdateVisibleSuggestion()
 {
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject & /*e*/)
 {
   // something (e.g. undo) changed the interpolation info, we should refresh our display
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::OnInterpolationAborted(const itk::EventObject& /*e*/)
 {
   m_CmbInterpolation->setCurrentIndex(0);
   m_FeedbackNode->SetData(nullptr);
 }
 
 void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject & /*e*/)
 {
   auto workingNode = m_ToolManager->GetWorkingData(0);
 
   if (workingNode == nullptr)
   {
     MITK_DEBUG << "OnSurfaceInterpolationInfoChanged triggered with no working data set.";
     return;
   }
 
   const auto segmentation = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
 
   if (segmentation == nullptr)
   {
     MITK_DEBUG << "OnSurfaceInterpolationInfoChanged triggered with no MultiLabelSegmentation as working data.";
     return;
   }
 
   if (!segmentation->ExistLabel(m_CurrentActiveLabelValue))
   {
     MITK_DEBUG << "OnSurfaceInterpolationInfoChanged triggered with no valid label selected. Currently selected invalid label: " << m_CurrentActiveLabelValue;
     return;
   }
 
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (m_3DInterpolationEnabled)
   {
     m_InterpolatedSurfaceNode->SetData(nullptr);
     m_Future = QtConcurrent::run(&QmitkSlicesInterpolator::Run3DInterpolation, this);
     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)
     {
       QWidget::setEnabled(true);
 
       if (!workingNode->GetData()->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
       {
         MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the time bounds of WorkingImage. Time point: " << m_TimePoint;
         return;
       }
 
       m_SurfaceInterpolator->SetDistanceImageVolume(50000);
 
       auto segmentationImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
       m_SurfaceInterpolator->SetCurrentInterpolationSession(segmentationImage);
     }
     else
     {
       QWidget::setEnabled(false);
     }
   }
 }
 
 void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status)
 {
   if (m_InterpolatedSurfaceNode.IsNotNull())
     m_InterpolatedSurfaceNode->SetVisibility(status);
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::OnActiveLabelChanged(mitk::Label::PixelType)
 {
   m_FeedbackNode->SetData(nullptr);
   m_InterpolatedSurfaceNode->SetData(nullptr);
 
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (m_3DInterpolationEnabled)
   {
     m_SurfaceInterpolator->Modified();
   }
 
   if (m_2DInterpolationEnabled)
   {
     m_FeedbackNode->SetData(nullptr);
     this->OnInterpolationActivated(true);
 
     m_LastSNC->SendSlice();
   }
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::CheckSupportedImageDimension()
 {
   if (m_ToolManager->GetWorkingData(0))
   {
     m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
 
     if (m_3DInterpolationEnabled && m_Segmentation && ((m_Segmentation->GetDimension() != 3) || (m_Segmentation->GetDimension() != 4)) )
     {
       QMessageBox info;
       info.setWindowTitle("3D Interpolation Process");
       info.setIcon(QMessageBox::Information);
       info.setText("3D Interpolation is only supported for 3D/4D images at the moment!");
       info.exec();
       m_CmbInterpolation->setCurrentIndex(0);
     }
   }
 }
 
 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<mitk::SliceNavigationController *>(const_cast<itk::Object *>(sender));
   if (slicer)
   {
     m_ControllerToSliceObserverTag.remove(slicer);
     m_ControllerToDeleteObserverTag.remove(slicer);
   }
 }
 
 void QmitkSlicesInterpolator::WaitForFutures()
 {
   if (m_Watcher.isRunning())
   {
     m_Watcher.waitForFinished();
   }
 
   if (m_PlaneWatcher.isRunning())
   {
     m_PlaneWatcher.waitForFinished();
   }
 }
 
 void QmitkSlicesInterpolator::NodeRemoved(const mitk::DataNode* node)
 {
   if ((m_ToolManager && m_ToolManager->GetWorkingData(0) == node) ||
       node == m_FeedbackNode ||
       node == m_InterpolatedSurfaceNode)
   {
     WaitForFutures();
   }
 }
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp
deleted file mode 100644
index 42b465fe46..0000000000
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/*============================================================================
-
-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 "QmitkContourModelToImageWidget.h"
-#include <ui_QmitkContourModelToImageWidgetControls.h>
-
-#include <mitkDataStorage.h>
-#include <mitkImage.h>
-
-#include <mitkContourModelSet.h>
-#include <mitkContourModelSetToImageFilter.h>
-#include <mitkLabelSetImage.h>
-#include <mitkRenderingManager.h>
-#include <mitkTimeNavigationController.h>
-
-#include <QtConcurrentRun>
-#include <QFuture>
-#include <QFutureWatcher>
-#include <qmessagebox.h>
-
-static const char* const HelpText = "Select a image and a contour(set)";
-
-class QmitkContourModelToImageWidgetPrivate
-{
-public:
-  QmitkContourModelToImageWidgetPrivate();
-  ~QmitkContourModelToImageWidgetPrivate();
-
-  /** @brief Check if selections is valid. */
-  void SelectionControl( unsigned int index, const mitk::DataNode* selection);
-
-  /** @brief Enable buttons if data selection is valid. */
-  void EnableButtons(bool enable = true);
-
-  /** @brief Does the actual contour filling */
-  mitk::LabelSetImage::Pointer FillContourModelSetIntoImage(mitk::Image *image, mitk::ContourModelSet *contourSet, mitk::TimePointType timePoint);
-
-  Ui::QmitkContourModelToImageWidgetControls m_Controls;
-  QFutureWatcher<mitk::LabelSetImage::Pointer> m_Watcher;
-};
-
-QmitkContourModelToImageWidgetPrivate::QmitkContourModelToImageWidgetPrivate()
-{
-}
-
-QmitkContourModelToImageWidgetPrivate::~QmitkContourModelToImageWidgetPrivate()
-{
-}
-
-void QmitkContourModelToImageWidgetPrivate::EnableButtons(bool enable)
-{
-  m_Controls.btnProcess->setEnabled(enable);
-}
-
-void QmitkContourModelToImageWidgetPrivate::SelectionControl(unsigned int index, const mitk::DataNode* /*selection*/)
-{
-  QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
-  mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index);
-
-  dataSelectionWidget->SetHelpText("");
-  this->EnableButtons();
-}
-
-mitk::LabelSetImage::Pointer QmitkContourModelToImageWidgetPrivate::FillContourModelSetIntoImage(mitk::Image* image, mitk::ContourModelSet* contourSet, mitk::TimePointType timePoint)
-{
-  // Use mitk::ContourModelSetToImageFilter to fill the ContourModelSet into the image
-  mitk::ContourModelSetToImageFilter::Pointer contourFiller = mitk::ContourModelSetToImageFilter::New();
-  auto timeStep = image->GetTimeGeometry()->TimePointToTimeStep(timePoint);
-  contourFiller->SetTimeStep(timeStep);
-  contourFiller->SetImage(image);
-  contourFiller->SetInput(contourSet);
-  contourFiller->MakeOutputBinaryOn();
-
-  try
-  {
-    contourFiller->Update();
-  }
-  catch (const std::exception & e)
-  {
-    MITK_ERROR << "Error while converting contour model. "<< e.what();
-  }
-  catch (...)
-  {
-    MITK_ERROR << "Unknown error while converting contour model.";
-  }
-
-  if (nullptr == contourFiller->GetOutput())
-  {
-    MITK_ERROR<<"Could not write the selected contours into the image!";
-  }
-
-  auto result = mitk::LabelSetImage::New();
-  result->InitializeByLabeledImage(contourFiller->GetOutput());
-
-  return result;
-}
-
-void QmitkContourModelToImageWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection)
-{
-  Q_D(QmitkContourModelToImageWidget);
-  QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
-  mitk::DataNode::Pointer node0 = dataSelectionWidget->GetSelection(0);
-  mitk::DataNode::Pointer node1 = dataSelectionWidget->GetSelection(1);
-
-  if (node0.IsNull() || node1.IsNull() )
-  {
-    d->EnableButtons(false);
-    dataSelectionWidget->SetHelpText(HelpText);
-  }
-  else
-  {
-    d->SelectionControl(index, selection);
-  }
-}
-
-void QmitkContourModelToImageWidget::OnProcessingFinished()
-{
-  // Called when processing finished
-  // Adding the result to the data storage
-
-  Q_D(QmitkContourModelToImageWidget);
-
-  // Adding the result to the data storage
-  auto result = d->m_Watcher.result();
-  if (result.IsNotNull())
-  {
-    QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
-    mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
-    mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1);
-
-    mitk::DataNode::Pointer filled = mitk::DataNode::New();
-    std::stringstream stream;
-    stream << imageNode->GetName();
-    stream << "_";
-    stream << contourNode->GetName();
-    filled->SetName(stream.str());
-    filled->SetData(result);
-
-    auto dataStorage = dataSelectionWidget->GetDataStorage();
-    if (dataStorage.IsNull())
-    {
-      std::string exception = "Cannot add result to the data storage. Data storage invalid.";
-      MITK_ERROR << "Error filling contours into an image: " << exception;
-      QMessageBox::information(nullptr, "Error filling contours into an image", QString::fromStdString(exception));
-    }
-
-    dataStorage->Add(filled, imageNode);
-    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
-  }
-  else
-  {
-    MITK_ERROR<<"Error filling contours into an image!";
-  }
-
-  d->EnableButtons();
-}
-
-void QmitkContourModelToImageWidget::OnProcessPressed()
-{
-  Q_D(QmitkContourModelToImageWidget);
-
-  QmitkDataSelectionWidget* dataSelectionWidget = d->m_Controls.dataSelectionWidget;
-
-  mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
-  mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1);
-
-  // Check if data nodes are valid
-  if(imageNode.IsNull() || contourNode.IsNull() )
-  {
-    MITK_ERROR << "Selection does not contain valid data";
-    QMessageBox::information( this, "Contour To Image",
-                              "Selection does not contain valid data, please select a binary image and a contour(set)",
-                              QMessageBox::Ok );
-    d->m_Controls.btnProcess->setEnabled(false);
-    return;
-  }
-
-  mitk::Image::Pointer image = static_cast<mitk::Image*>(imageNode->GetData());
-
-  // Check if the image is valid
-  if (image.IsNull())
-  {
-    MITK_ERROR<<"Error writing contours into image! Invalid image data selected!";
-    return;
-  }
-
-  const mitk::TimePointType timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint();
-  if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint))
-  {
-    MITK_ERROR << "Error writing contours into image! Currently selected time point is not supported by selected image data.";
-    return;
-  }
-
-  // Check if the selected contours are valid
-  mitk::ContourModelSet::Pointer contourSet;
-  mitk::ContourModel::Pointer contour = dynamic_cast<mitk::ContourModel*>(contourNode->GetData());
-  if (contour.IsNotNull())
-  {
-    contourSet = mitk::ContourModelSet::New();
-    contourSet->AddContourModel(contour);
-  }
-  else
-  {
-    contourSet = static_cast<mitk::ContourModelSet*>(contourNode->GetData());
-    if (contourSet.IsNull())
-    {
-      MITK_ERROR<<"Error writing contours into binary image! Invalid contour data selected!";
-      return;
-    }
-  }
-
-  //Disable Buttons during calculation and initialize Progressbar
-  d->EnableButtons(false);
-
-  // Start the computation in a background thread
-  auto future = QtConcurrent::run(&QmitkContourModelToImageWidgetPrivate::FillContourModelSetIntoImage, d, image, contourSet, timePoint);
-  d->m_Watcher.setFuture(future);
-}
-
-QmitkContourModelToImageWidget::QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent)
-  : QWidget(parent)
-  , d_ptr(new QmitkContourModelToImageWidgetPrivate())
-{
-  Q_D(QmitkContourModelToImageWidget);
-
-  // Set up UI
-  d->m_Controls.setupUi(this);
-  d->m_Controls.dataSelectionWidget->SetDataStorage(dataStorage);
-  d->m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImageAndSegmentationPredicate);
-  d->m_Controls.dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ContourModelPredicate);
-  d->m_Controls.dataSelectionWidget->SetHelpText(HelpText);
-  d->EnableButtons(false);
-
-  // Create connections
-  connect (d->m_Controls.btnProcess, SIGNAL(pressed()), this, SLOT(OnProcessPressed()));
-  connect(d->m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)),
-          this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
-  connect(&d->m_Watcher, SIGNAL(finished()), this, SLOT(OnProcessingFinished()));
-
-  if( d->m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull() &&
-      d->m_Controls.dataSelectionWidget->GetSelection(1).IsNotNull() )
-  {
-    OnSelectionChanged(0, d->m_Controls.dataSelectionWidget->GetSelection(0));
-  }
-}
-
-QmitkContourModelToImageWidget::~QmitkContourModelToImageWidget()
-{
-}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h
deleted file mode 100644
index fb346b446d..0000000000
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidget.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*============================================================================
-
-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 QmitkContourModelToImageWidget_h
-#define QmitkContourModelToImageWidget_h
-
-#include <MitkSegmentationUIExports.h>
-
-#include <QScopedPointer>
-#include <QWidget>
-
-class QmitkContourModelToImageWidgetPrivate;
-
-namespace mitk
-{
-  class DataNode;
-  class DataStorage;
-  class Image;
-  class ContourModelSet;
-  class ContourModel;
-  class Geometry3D;
-  class PlaneGeometry;
-}
-
-/*!
-  \brief QmitkContourModelToImageWidget
-
-  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 MITKSEGMENTATIONUI_EXPORT QmitkContourModelToImageWidget : public QWidget
-{
-  Q_OBJECT
-
-public:
-
-  /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
-  explicit QmitkContourModelToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
-  /** @brief Default destructor. */
-  ~QmitkContourModelToImageWidget() 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 button to mask an image. */
-  void OnProcessPressed();
-
-  /** @brief This slot is called after processing is finished */
-  void OnProcessingFinished();
-
-private:
-
-  QScopedPointer<QmitkContourModelToImageWidgetPrivate> d_ptr;
-
-  Q_DECLARE_PRIVATE(QmitkContourModelToImageWidget)
-  Q_DISABLE_COPY(QmitkContourModelToImageWidget)
-};
-
-#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidgetControls.ui b/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidgetControls.ui
deleted file mode 100644
index 3409e8ae5b..0000000000
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkContourModelToImageWidgetControls.ui
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QmitkContourModelToImageWidgetControls</class>
- <widget class="QWidget" name="QmitkContourModelToImageWidgetControls">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>98</width>
-    <height>62</height>
-   </rect>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <widget class="QmitkDataSelectionWidget" name="dataSelectionWidget" native="true">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <widget class="QPushButton" name="btnProcess">
-     <property name="text">
-      <string>Process</string>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <spacer name="verticalSpacer">
-     <property name="orientation">
-      <enum>Qt::Vertical</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>20</width>
-       <height>40</height>
-      </size>
-     </property>
-    </spacer>
-   </item>
-  </layout>
- </widget>
- <customwidgets>
-  <customwidget>
-   <class>QmitkDataSelectionWidget</class>
-   <extends>QWidget</extends>
-   <header>QmitkDataSelectionWidget.h</header>
-   <container>1</container>
-  </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.cpp
new file mode 100644
index 0000000000..f4975aac24
--- /dev/null
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.cpp
@@ -0,0 +1,543 @@
+/*============================================================================
+
+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 "QmitkConvertToMultiLabelSegmentationWidget.h"
+#include <ui_QmitkConvertToMultiLabelSegmentationWidgetControls.h>
+
+#include <mitkDataStorage.h>
+#include <mitkException.h>
+#include <mitkExceptionMacro.h>
+#include <mitkProgressBar.h>
+#include <mitkProperties.h>
+#include <mitkSurfaceToImageFilter.h>
+#include <mitkSurface.h>
+#include <mitkContourModel.h>
+#include <mitkContourModelSet.h>
+#include <mitkContourModelSetToImageFilter.h>
+#include <mitkLabelSetImage.h>
+#include <mitkMultiLabelPredicateHelper.h>
+#include <mitkNodePredicateOr.h>
+#include <mitkNodePredicateNot.h>
+#include <mitkNodePredicateAnd.h>
+#include <mitkNodePredicateDataType.h>
+#include <mitkNodePredicateSubGeometry.h>
+#include <mitkNodePredicateGeometry.h>
+#include <mitkNodePredicateProperty.h>
+#include <mitkLabelSetImageHelper.h>
+#include <mitkLabelSetImageConverter.h>
+
+#include <QmitkNodeSelectionDialog.h>
+
+mitk::NodePredicateBase::Pointer GetInputPredicate()
+{
+  auto isImage = mitk::TNodePredicateDataType<mitk::Image>::New();
+  auto isNotSeg = mitk::NodePredicateNot::New(mitk::GetMultiLabelSegmentationPredicate());
+
+  auto isSurface = mitk::TNodePredicateDataType<mitk::Surface>::New();
+  auto isContourModel = mitk::TNodePredicateDataType<mitk::ContourModel>::New();
+  auto isContourModelSet = mitk::TNodePredicateDataType<mitk::ContourModelSet>::New();
+
+  auto isData = mitk::NodePredicateOr::New(isImage, isContourModel, isContourModelSet);
+  isData->AddPredicate(isSurface);
+
+  auto isValidInput = mitk::NodePredicateAnd::New(isNotSeg, isData);
+  isValidInput->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
+  isValidInput->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
+  return isValidInput.GetPointer();
+}
+
+const mitk::DataNode* GetNodeWithLargestImageGeometry(const QmitkNodeSelectionDialog::NodeList& nodes)
+{
+  mitk::BaseGeometry::ConstPointer refGeometry;
+  mitk::DataNode* result = nullptr;
+
+  for (auto& node : nodes)
+  {
+    auto castedData = dynamic_cast<const mitk::Image*>(node->GetData());
+    if (castedData != nullptr)
+    {
+      if (refGeometry.IsNull() || mitk::IsSubGeometry(*refGeometry, *(castedData->GetGeometry()), mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION))
+      {
+        refGeometry = castedData->GetGeometry();
+        result = node;
+      }
+    }
+  }
+  return result;
+}
+
+QmitkNodeSelectionDialog::NodeList GetNonimageNodes(const QmitkNodeSelectionDialog::NodeList& nodes)
+{
+  QmitkNodeSelectionDialog::NodeList result;
+
+  for (auto& node : nodes)
+  {
+    auto castedData = dynamic_cast<const mitk::Image*>(node->GetData());
+    if (castedData == nullptr)
+    {
+      result.push_back(node);
+    }
+  }
+  return result;
+}
+
+QmitkNodeSelectionDialog::NodeList GetImageNodes(const QmitkNodeSelectionDialog::NodeList& nodes)
+{
+  QmitkNodeSelectionDialog::NodeList result;
+
+  for (auto& node : nodes)
+  {
+    auto castedData = dynamic_cast<const mitk::Image*>(node->GetData());
+    if (castedData != nullptr)
+    {
+      result.push_back(node);
+    }
+  }
+  return result;
+}
+
+QmitkNodeSelectionDialog::SelectionCheckFunctionType CheckForSameGeometry(const mitk::DataNode* refNode)
+{
+  mitk::DataNode::ConstPointer refNodeLambda = refNode;
+
+  auto lambda = [refNodeLambda](const QmitkNodeSelectionDialog::NodeList& nodes)
+  {
+    if (nodes.empty())
+    {
+      return std::string();
+    }
+
+    mitk::NodePredicateSubGeometry::Pointer geoPredicate;
+    bool usedExternalGeo = false;
+    std::string refNodeName;
+
+    if (refNodeLambda.IsNotNull() && nullptr != refNodeLambda->GetData())
+    {
+      geoPredicate = mitk::NodePredicateSubGeometry::New(refNodeLambda->GetData()->GetGeometry());
+      usedExternalGeo = true;
+      refNodeName = refNodeLambda->GetName();
+    }
+
+    if (geoPredicate.IsNull())
+    {
+      auto imageNode = GetNodeWithLargestImageGeometry(nodes);
+      if (nullptr != imageNode)
+      {
+        geoPredicate = mitk::NodePredicateSubGeometry::New(imageNode->GetData()->GetGeometry());
+        refNodeName = imageNode->GetName();
+      }
+    }
+
+    for (auto& node : nodes)
+    {
+      auto castedImageData = dynamic_cast<const mitk::Image*>(node->GetData());
+
+      if (nullptr != castedImageData)
+      {
+        if (!geoPredicate->CheckNode(node))
+        {
+          std::stringstream ss;
+          ss << "<font class=\"warning\"><p>Invalid selection: All selected images must have the same geometry or a sub geometry ";
+          if (usedExternalGeo) ss << "of the selected reference/output";
+          ss << ".< / p><p>Uses reference data: \"";
+          ss << refNodeName << "\"</p>";
+          ss << "<p>Differing data selections i.a.: \"";
+          ss << node->GetName() << "\"</p></font>";
+          return ss.str();
+        }
+      }
+    }
+
+    return std::string();
+  };
+
+  return lambda;
+}
+
+QmitkConvertToMultiLabelSegmentationWidget::QmitkConvertToMultiLabelSegmentationWidget(mitk::DataStorage* dataStorage, QWidget* parent)
+  : QWidget(parent), m_DataStorage(dataStorage)
+{
+  m_Controls = new Ui::QmitkConvertToMultiLabelSegmentationWidgetControls;
+  m_Controls->setupUi(this);
+
+  m_Controls->inputNodesSelector->SetDataStorage(dataStorage);
+  m_Controls->inputNodesSelector->SetNodePredicate(GetInputPredicate());
+  m_Controls->inputNodesSelector->SetSelectionCheckFunction(CheckForSameGeometry(nullptr));
+  m_Controls->inputNodesSelector->SetSelectionIsOptional(false);
+  m_Controls->inputNodesSelector->SetInvalidInfo(QStringLiteral("Please select inputs (images, surfaces or contours) for conversion"));
+  m_Controls->inputNodesSelector->SetPopUpTitel(QStringLiteral("Select inputs"));
+  m_Controls->inputNodesSelector->SetPopUpHint(QStringLiteral("You may select multiple inputs for conversion. But all selected images must have the same geometry or a sub geometry."));
+
+  m_Controls->outputSegSelector->SetDataStorage(dataStorage);
+  m_Controls->outputSegSelector->SetNodePredicate(mitk::GetMultiLabelSegmentationPredicate());
+  m_Controls->outputSegSelector->SetSelectionIsOptional(false);
+  m_Controls->outputSegSelector->SetInvalidInfo(QStringLiteral("Please select the target segmentation"));
+  m_Controls->outputSegSelector->SetPopUpTitel(QStringLiteral("Select target segmentation"));
+  m_Controls->outputSegSelector->SetPopUpHint(QStringLiteral("Select the segmentation to which the converted inputs should be added."));
+  m_Controls->outputSegSelector->SetAutoSelectNewNodes(true);
+
+  m_Controls->refNodeSelector->SetDataStorage(dataStorage);
+  m_Controls->refNodeSelector->SetNodePredicate(mitk::NodePredicateOr::New(GetInputPredicate(),mitk::GetMultiLabelSegmentationPredicate()));
+  m_Controls->refNodeSelector->SetSelectionIsOptional(false);
+  m_Controls->refNodeSelector->SetInvalidInfo(QStringLiteral("Please select a reference image or segmentation"));
+  m_Controls->refNodeSelector->SetPopUpTitel(QStringLiteral("Select a reference image or segmentation"));
+  m_Controls->refNodeSelector->SetPopUpHint(QStringLiteral("Select the image or segmentation that defines the geometry of the conversion result."));
+
+
+  this->ConfigureWidgets();
+
+  connect (m_Controls->btnConvert, &QAbstractButton::clicked, this, &QmitkConvertToMultiLabelSegmentationWidget::OnConvertPressed);
+  connect(m_Controls->inputNodesSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
+    this, &QmitkConvertToMultiLabelSegmentationWidget::OnInputSelectionChanged);
+  connect(m_Controls->refNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
+    this, &QmitkConvertToMultiLabelSegmentationWidget::OnRefSelectionChanged);
+  connect(m_Controls->outputSegSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
+    this, &QmitkConvertToMultiLabelSegmentationWidget::OnOutputSelectionChanged);
+  auto widget = this;
+  connect(m_Controls->radioAddToSeg, &QRadioButton::toggled,
+    m_Controls->outputSegSelector, [widget](bool) {widget->ConfigureWidgets(); });
+  connect(m_Controls->checkMultipleOutputs, &QCheckBox::toggled,
+    m_Controls->outputSegSelector, [widget](bool) {widget->ConfigureWidgets(); });
+}
+
+QmitkConvertToMultiLabelSegmentationWidget::~QmitkConvertToMultiLabelSegmentationWidget()
+{
+}
+
+void QmitkConvertToMultiLabelSegmentationWidget::ConfigureWidgets()
+{
+  m_InternalEvent = true;
+
+  if (m_Controls->radioAddToSeg->isChecked())
+  {
+    auto selectedNode = m_Controls->outputSegSelector->GetSelectedNode();
+    m_Controls->inputNodesSelector->SetSelectionCheckFunction(CheckForSameGeometry(selectedNode));
+  }
+  else
+  {
+    m_Controls->inputNodesSelector->SetSelectionCheckFunction(CheckForSameGeometry(nullptr));
+  }
+  m_Controls->outputSegSelector->setVisible(m_Controls->radioAddToSeg->isChecked());
+
+  if (m_Controls->radioNewSeg->isChecked())
+  {
+    auto selectedNode = m_Controls->refNodeSelector->GetSelectedNode();
+  }
+  m_Controls->checkMultipleOutputs->setVisible(m_Controls->radioNewSeg->isChecked());
+  bool refNeeded = m_Controls->radioNewSeg->isChecked() && !m_Controls->inputNodesSelector->GetSelectedNodes().empty() && nullptr == GetNodeWithLargestImageGeometry(m_Controls->inputNodesSelector->GetSelectedNodes());
+  m_Controls->refNodeSelector->setVisible(refNeeded);
+
+  if (refNeeded) m_Controls->inputNodesSelector->SetSelectionCheckFunction(CheckForSameGeometry(m_Controls->refNodeSelector->GetSelectedNode()));
+
+  m_Controls->groupGrouping->setVisible(m_Controls->radioAddToSeg->isChecked() || !(m_Controls->checkMultipleOutputs->isChecked()));
+
+  bool inputIsOK = !m_Controls->inputNodesSelector->GetSelectedNodes().empty() &&
+    !m_Controls->inputNodesSelector->CurrentSelectionViolatesCheckFunction();
+  bool outputIsOK = !m_Controls->radioAddToSeg->isChecked() || m_Controls->outputSegSelector->GetSelectedNode().IsNotNull();
+  bool refIsOK = !m_Controls->radioNewSeg->isChecked() || !m_Controls->refNodeSelector->isVisible() || m_Controls->refNodeSelector->GetSelectedNode().IsNotNull();
+
+  m_Controls->btnConvert->setEnabled(inputIsOK && outputIsOK && refIsOK);
+  m_InternalEvent = false;
+}
+
+void QmitkConvertToMultiLabelSegmentationWidget::OnInputSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/)
+{
+  if (!m_InternalEvent) this->ConfigureWidgets();
+}
+
+void QmitkConvertToMultiLabelSegmentationWidget::OnOutputSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/)
+{
+  if (!m_InternalEvent) this->ConfigureWidgets();
+}
+
+void QmitkConvertToMultiLabelSegmentationWidget::OnRefSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/)
+{
+  if (!m_InternalEvent) this->ConfigureWidgets();
+}
+
+
+void QmitkConvertToMultiLabelSegmentationWidget::OnConvertPressed()
+{
+  auto dataStorage = m_DataStorage.Lock();
+  if (dataStorage.IsNull())
+  {
+    mitkThrow() << "QmitkConvertToMultiLabelSegmentationWidget is in invalid state. No datastorage is set.";
+  }
+
+  auto nodes = m_Controls->inputNodesSelector->GetSelectedNodes();
+  mitk::ProgressBar::GetInstance()->Reset();
+  mitk::ProgressBar::GetInstance()->AddStepsToDo(3 * nodes.size() + 1);
+
+  if (m_Controls->radioNewSeg->isChecked() && m_Controls->checkMultipleOutputs->isChecked())
+  {
+    for (auto& node : nodes)
+    {
+      this->ConvertNodes({ node });
+    }
+  }
+  else
+  {
+    this->ConvertNodes(nodes);
+  }
+}
+
+
+mitk::Image::Pointer ConvertSurfaceToImage(const mitk::Image* refImage, const mitk::Surface* surface)
+{
+  mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
+  surfaceToImageFilter->MakeOutputBinaryOn();
+  surfaceToImageFilter->UShortBinaryPixelTypeOn();
+  surfaceToImageFilter->SetInput(surface);
+  surfaceToImageFilter->SetImage(refImage);
+  try
+  {
+    surfaceToImageFilter->Update();
+  }
+  catch (itk::ExceptionObject& excpt)
+  {
+    MITK_ERROR << excpt.GetDescription();
+    return nullptr;
+  }
+
+  return surfaceToImageFilter->GetOutput();
+}
+
+mitk::Image::Pointer ConvertContourModelSetToImage(mitk::Image* refImage, mitk::ContourModelSet* contourSet)
+{
+  // Use mitk::ContourModelSetToImageFilter to fill the ContourModelSet into the image
+  mitk::ContourModelSetToImageFilter::Pointer contourFiller = mitk::ContourModelSetToImageFilter::New();
+  contourFiller->SetImage(refImage);
+  contourFiller->SetInput(contourSet);
+  contourFiller->MakeOutputLabelPixelTypeOn();
+
+  try
+  {
+    contourFiller->Update();
+  }
+  catch (const std::exception& e)
+  {
+    MITK_ERROR << "Error while converting contour model. " << e.what();
+  }
+  catch (...)
+  {
+    MITK_ERROR << "Unknown error while converting contour model.";
+  }
+
+  return contourFiller->GetOutput();
+}
+
+void CheckForLabelCollision(const QmitkNodeSelectionDialog::NodeList& nodes,
+  const std::map<const mitk::DataNode*, mitk::LabelSetImage::LabelValueVectorType>& foundLabelsMap,
+  mitk::LabelSetImage::LabelValueVectorType& usedLabelValues,
+  std::map<const mitk::DataNode*, mitk::LabelValueMappingVector>& labelsMappingMap)
+{
+  for (const auto& node : nodes)
+  {
+    mitk::ProgressBar::GetInstance()->Progress();
+
+    const auto& foundLabels = foundLabelsMap.at(node);
+    mitk::LabelSetImage::LabelValueVectorType correctedLabelValues;
+    mitk::CheckForLabelValueConflictsAndResolve(foundLabels, usedLabelValues, correctedLabelValues);
+
+    mitk::LabelValueMappingVector mapping;
+    std::transform(foundLabels.begin(), foundLabels.end(), correctedLabelValues.begin(), std::back_inserter(mapping),
+      [](mitk::LabelSetImage::LabelValueType a, mitk::LabelSetImage::LabelValueType b) { return std::make_pair(a, b); });
+    labelsMappingMap.emplace(node, mapping);
+  }
+}
+
+void QmitkConvertToMultiLabelSegmentationWidget::ConvertNodes(const QmitkNodeSelectionDialog::NodeList& nodes)
+{
+  QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
+
+  auto nonimageNodes = GetNonimageNodes(nodes);
+  auto imageNodes = GetImageNodes(nodes);
+
+  mitk::LabelSetImage::Pointer outputSeg;
+  mitk::Image::Pointer refImage;
+  const mitk::DataNode* refNode;
+
+  if (m_Controls->radioAddToSeg->isChecked())
+  {
+    outputSeg = dynamic_cast<mitk::LabelSetImage*>(m_Controls->outputSegSelector->GetSelectedNode()->GetData());
+
+    if (outputSeg->GetNumberOfLayers() > 0)
+    {
+      refImage = outputSeg->GetGroupImage(0);
+    }
+    else
+    {
+      //in case we work with a output seg, we need to generate a template image
+      //reason is that the conversion filters used for surfaces or contours need images
+      //as reference and MultiLabelSegmentations is currently empty.
+      refImage = mitk::Image::New();
+      refImage->Initialize(mitk::MakePixelType<mitk::LabelSetImage::LabelValueType, mitk::LabelSetImage::LabelValueType, 1>(), *(outputSeg->GetTimeGeometry()));
+    }
+  }
+  else
+  {
+    outputSeg = mitk::LabelSetImage::New();
+
+    auto inputNode = GetNodeWithLargestImageGeometry(m_Controls->inputNodesSelector->GetSelectedNodes());
+    if (nullptr != inputNode)
+    {
+      refNode = inputNode;
+      refImage = dynamic_cast<mitk::Image*>(inputNode->GetData());
+      outputSeg->Initialize(refImage);
+    }
+    else
+    {
+      refNode = m_Controls->refNodeSelector->GetSelectedNode();
+      refImage = dynamic_cast<mitk::Image*>(refNode->GetData());
+      outputSeg->Initialize(refImage);
+    }
+  }
+
+  //convert non-image nodes to images
+  std::map<const mitk::DataNode*, mitk::Image::Pointer> preparedImageMap;
+  std::map<const mitk::DataNode*, mitk::LabelSetImage::LabelValueVectorType> foundLabelsMap;
+  for (const auto& node : nonimageNodes)
+  {
+    mitk::ProgressBar::GetInstance()->Progress();
+    mitk::Image::Pointer convertedImage;
+
+    auto surface = dynamic_cast<mitk::Surface*>(node->GetData());
+    auto contourModel = dynamic_cast<mitk::ContourModel*>(node->GetData());
+    auto contourModelSet = dynamic_cast<mitk::ContourModelSet*>(node->GetData());
+    if (nullptr != surface)
+    {
+      convertedImage = ConvertSurfaceToImage(refImage, surface);
+    }
+    else if (nullptr != contourModelSet)
+    {
+      convertedImage = ConvertContourModelSetToImage(refImage, contourModelSet);
+    }
+    else if (nullptr != contourModel)
+    {
+      auto contourModelSet = mitk::ContourModelSet::New();
+      contourModelSet->AddContourModel(contourModel);
+      convertedImage = ConvertContourModelSetToImage(refImage, contourModelSet);
+    }
+    else
+    {
+      mitkThrow() << "Invalid state of QmitkConvertToMultiLabelSegmentationWidget. At least one input is of invalid type, that should not be possible to select. Invalid node: " << *(node.GetPointer());
+    }
+
+    if (convertedImage.IsNotNull())
+    {
+      preparedImageMap.emplace(node, convertedImage);
+      //all non-image data is converted to binary maps
+      foundLabelsMap.emplace(node, mitk::LabelSetImage::LabelValueVectorType({ 1 }));
+    }
+    else
+    {
+      mitkThrow() << "Failed to convert an input. Failed node: " << *(node.GetPointer());
+    }
+  }
+
+  //prepare image nodes and get contained labels
+  for (const auto& node : imageNodes)
+  {
+    mitk::ProgressBar::GetInstance()->Progress();
+    mitk::LabelSetImage::LabelValueVectorType foundLabels;
+
+    mitk::ProgressBar::GetInstance()->Progress();
+    mitk::Image::Pointer convertedImage = mitk::ConvertImageToGroupImage(dynamic_cast<mitk::Image*>(node->GetData()), foundLabels);
+    preparedImageMap.emplace(node, convertedImage);
+    foundLabelsMap.emplace(node, foundLabels);
+  }
+
+  //check for label collision and fix if needed
+  mitk::LabelSetImage::LabelValueVectorType usedLabelValues = outputSeg->GetAllLabelValues();
+  std::map<const mitk::DataNode*, mitk::LabelValueMappingVector> labelsMappingMap;
+  CheckForLabelCollision(imageNodes, foundLabelsMap, usedLabelValues, labelsMappingMap);
+  CheckForLabelCollision(nonimageNodes, foundLabelsMap, usedLabelValues, labelsMappingMap);
+
+  //Ensure that we have the first layer to add
+  mitk::LabelSetImage::GroupIndexType currentGroupIndex = 0;
+  if (m_Controls->radioAddToSeg->isChecked() || 0 == outputSeg->GetNumberOfLayers())
+  {
+    currentGroupIndex = outputSeg->AddLayer();
+  }
+
+  //Transfer content and add labels
+  for (const auto& node : imageNodes)
+  {
+    mitk::ProgressBar::GetInstance()->Progress();
+
+    if (m_Controls->radioSingleGroup->isChecked() && node != imageNodes.front())
+      currentGroupIndex = outputSeg->AddLayer();
+
+    const auto& labelsMapping = labelsMappingMap.at(node);
+    for (auto [oldV, correctedV] : labelsMapping)
+    {
+      std::string name = "Value " + std::to_string(oldV);
+      if (m_Controls->radioMergeGroup->isChecked())
+        name = node->GetName() + " " + name;
+
+      auto label = mitk::LabelSetImageHelper::CreateNewLabel(outputSeg, name, true);
+      label->SetValue(correctedV);
+
+      outputSeg->AddLabel(label, currentGroupIndex, false, false);
+    }
+
+    mitk::TransferLabelContent(preparedImageMap.at(node), outputSeg->GetGroupImage(currentGroupIndex),
+      outputSeg->GetConstLabelsByValue(outputSeg->GetLabelValuesByGroup(currentGroupIndex)),
+      mitk::LabelSetImage::UNLABELED_VALUE, mitk::LabelSetImage::UNLABELED_VALUE, false, labelsMapping);
+  }
+
+  for (const auto& node : nonimageNodes)
+  {
+    mitk::ProgressBar::GetInstance()->Progress();
+
+    if (m_Controls->radioSingleGroup->isChecked() && (node != nonimageNodes.front() || !imageNodes.empty()))
+      currentGroupIndex = outputSeg->AddLayer();
+
+    const auto& labelsMapping = labelsMappingMap.at(node);
+    for (auto [oldV, correctedV] : labelsMapping)
+    {
+      auto label = mitk::LabelSetImageHelper::CreateNewLabel(outputSeg, node->GetName(), true);
+      label->SetValue(correctedV);
+      mitk::ColorProperty::ConstPointer colorProp = dynamic_cast<const mitk::ColorProperty*>(node->GetConstProperty("color").GetPointer());
+      if (colorProp.IsNotNull())
+        label->SetColor(colorProp->GetColor());
+
+      outputSeg->AddLabel(label, currentGroupIndex, false, false);
+    }
+
+    mitk::TransferLabelContent(preparedImageMap.at(node), outputSeg->GetGroupImage(currentGroupIndex),
+      outputSeg->GetConstLabelsByValue(outputSeg->GetLabelValuesByGroup(currentGroupIndex)),
+      mitk::LabelSetImage::UNLABELED_VALUE, mitk::LabelSetImage::UNLABELED_VALUE, false, labelsMapping);
+  }
+
+  if (m_Controls->radioAddToSeg->isChecked())
+  {
+    m_Controls->outputSegSelector->GetSelectedNode()->Modified();
+  }
+  else
+  {
+    mitk::DataNode::Pointer outNode = mitk::DataNode::New();
+    std::stringstream stream;
+    stream << "ConvertedSeg";
+    if (nodes.size() == 1)
+    {
+      stream << "_" << nodes.front()->GetName();
+    }
+    outNode->SetName(stream.str());
+    outNode->SetData(outputSeg);
+
+    auto dataStorage = m_DataStorage.Lock();
+    dataStorage->Add(outNode);
+  }
+  mitk::ProgressBar::GetInstance()->Reset();
+  QApplication::restoreOverrideCursor();
+}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.h
new file mode 100644
index 0000000000..c94c991210
--- /dev/null
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.h
@@ -0,0 +1,80 @@
+/*============================================================================
+
+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 QmitkConvertToMultiLabelSegmentationWidget_h
+#define QmitkConvertToMultiLabelSegmentationWidget_h
+
+#include <MitkSegmentationUIExports.h>
+#include <QmitkAbstractNodeSelectionWidget.h>
+#include <QmitkNodeSelectionDialog.h>
+
+#include <QWidget>
+
+namespace Ui
+{
+  class QmitkConvertToMultiLabelSegmentationWidgetControls;
+}
+
+namespace mitk
+{
+  class DataNode;
+  class DataStorage;
+  class Surface;
+  class Image;
+  class LabelSetImage;
+}
+
+/*!
+  \brief QmitkConvertToMultiLabelSegmentationWidget
+
+  Widget that offers the GUI and logic to convert different inputs (images, surfaces and contour models)
+  into a multi label segmentation (by generating a new or adding the converted inputs to an existing
+  segmentation).
+*/
+class MITKSEGMENTATIONUI_EXPORT QmitkConvertToMultiLabelSegmentationWidget : public QWidget
+{
+  Q_OBJECT
+
+public:
+
+  /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
+  explicit QmitkConvertToMultiLabelSegmentationWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
+
+  /** @brief Default destructor. */
+  ~QmitkConvertToMultiLabelSegmentationWidget() override;
+
+private slots:
+
+  /** @brief This slot is called if the selection in the workbench is changed. */
+  void OnInputSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/);
+
+  void OnOutputSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/);
+
+  void OnRefSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/);
+
+
+  /** @brief This slot is called if user activates the button to convert a surface into a binary image. */
+  void OnConvertPressed();
+
+private:
+  void ConvertNodes(const QmitkNodeSelectionDialog::NodeList& nodes);
+
+  bool m_InternalEvent = false;
+  mitk::WeakPointer<mitk::DataStorage> m_DataStorage;
+
+  /** @brief Enable buttons if data selection is valid. */
+  void ConfigureWidgets();
+
+  Ui::QmitkConvertToMultiLabelSegmentationWidgetControls* m_Controls;
+};
+
+#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidgetControls.ui b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidgetControls.ui
new file mode 100644
index 0000000000..91296e98e4
--- /dev/null
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidgetControls.ui
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QmitkConvertToMultiLabelSegmentationWidgetControls</class>
+ <widget class="QWidget" name="QmitkConvertToMultiLabelSegmentationWidgetControls">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>408</width>
+    <height>316</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Inputs;</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QmitkMultiNodeSelectionWidget" name="inputNodesSelector" native="true"/>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupOutput">
+     <property name="title">
+      <string>Output:</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <widget class="QRadioButton" name="radioNewSeg">
+        <property name="text">
+         <string>Convert to new segmentation</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout_5">
+        <property name="leftMargin">
+         <number>20</number>
+        </property>
+        <item>
+         <widget class="QmitkSingleNodeSelectionWidget" name="refNodeSelector" native="true"/>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="checkMultipleOutputs">
+          <property name="toolTip">
+           <string>If activated, the conversion will generate separate multi label segmentations for each input instead of joining all inputs in one multi label segmentation.</string>
+          </property>
+          <property name="text">
+           <string>Convert inputs separatly</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="radioAddToSeg">
+        <property name="text">
+         <string>Add to existing segmentation</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QmitkSingleNodeSelectionWidget" name="outputSegSelector" native="true"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupGrouping">
+     <property name="title">
+      <string>Grouping:</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_3">
+      <property name="spacing">
+       <number>4</number>
+      </property>
+      <property name="leftMargin">
+       <number>4</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>4</number>
+      </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
+      <item>
+       <widget class="QRadioButton" name="radioMergeGroup">
+        <property name="text">
+         <string>Merge all inputs in new group</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="radioSingleGroup">
+        <property name="text">
+         <string>New group per input</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="btnConvert">
+     <property name="text">
+      <string>Convert</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+  <zorder>label</zorder>
+  <zorder>inputNodesSelector</zorder>
+  <zorder>groupGrouping</zorder>
+  <zorder>btnConvert</zorder>
+  <zorder>groupOutput</zorder>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QmitkMultiNodeSelectionWidget</class>
+   <extends>QWidget</extends>
+   <header location="global">QmitkMultiNodeSelectionWidget.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>QmitkSingleNodeSelectionWidget</class>
+   <extends>QWidget</extends>
+   <header location="global">QmitkSingleNodeSelectionWidget.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.cpp
new file mode 100644
index 0000000000..e426b07e26
--- /dev/null
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.cpp
@@ -0,0 +1,159 @@
+/*============================================================================
+
+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 "QmitkExtractFromMultiLabelSegmentationWidget.h"
+#include <ui_QmitkExtractFromMultiLabelSegmentationWidgetControls.h>
+
+#include <mitkDataStorage.h>
+#include <mitkException.h>
+#include <mitkExceptionMacro.h>
+#include <mitkProgressBar.h>
+#include <mitkProperties.h>
+#include <mitkLabelSetImage.h>
+#include <mitkMultiLabelPredicateHelper.h>
+#include <mitkLabelSetImageHelper.h>
+#include <mitkLabelSetImageConverter.h>
+
+#include <QmitkNodeSelectionDialog.h>
+
+QmitkExtractFromMultiLabelSegmentationWidget::QmitkExtractFromMultiLabelSegmentationWidget(mitk::DataStorage* dataStorage, QWidget* parent)
+  : QWidget(parent), m_DataStorage(dataStorage)
+{
+  m_Controls = new Ui::QmitkExtractFromMultiLabelSegmentationWidgetControls;
+  m_Controls->setupUi(this);
+
+  m_Controls->segNodeSelector->SetDataStorage(dataStorage);
+  m_Controls->segNodeSelector->SetNodePredicate(mitk::GetMultiLabelSegmentationPredicate());
+  m_Controls->segNodeSelector->SetSelectionIsOptional(false);
+  m_Controls->segNodeSelector->SetInvalidInfo(QStringLiteral("Please select segmentation for extraction."));
+  m_Controls->segNodeSelector->SetPopUpTitel(QStringLiteral("Select segmentation"));
+  m_Controls->segNodeSelector->SetPopUpHint(QStringLiteral("Select the segmentation that should be used as source for extraction."));
+
+  m_Controls->labelInspector->SetMultiSelectionMode(true);
+
+  m_Controls->checkExtractSelected->setChecked(false);
+
+  m_Controls->checkClassMap->setChecked(false);
+  m_Controls->checkInstanceMap->setChecked(true);
+  m_Controls->checkInstanceMask->setChecked(true);
+
+  this->ConfigureWidgets();
+
+  connect (m_Controls->btnExtract, &QAbstractButton::clicked, this, &QmitkExtractFromMultiLabelSegmentationWidget::OnExtractPressed);
+
+  connect(m_Controls->segNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
+    this, &QmitkExtractFromMultiLabelSegmentationWidget::OnSegSelectionChanged);
+
+  auto widget = this;
+  connect(m_Controls->checkInstanceMap, &QCheckBox::toggled,
+    this, [widget](bool) {widget->ConfigureWidgets(); });
+  connect(m_Controls->checkClassMap, &QCheckBox::toggled,
+    this, [widget](bool) {widget->ConfigureWidgets(); });
+  connect(m_Controls->checkInstanceMask, &QCheckBox::toggled,
+    this, [widget](bool) {widget->ConfigureWidgets(); });
+  connect(m_Controls->checkExtractSelected, &QCheckBox::toggled,
+    this, [widget](bool) {widget->ConfigureWidgets(); });
+
+  m_Controls->segNodeSelector->SetAutoSelectNewNodes(true);
+}
+
+QmitkExtractFromMultiLabelSegmentationWidget::~QmitkExtractFromMultiLabelSegmentationWidget()
+{
+  m_Controls->labelInspector->SetMultiLabelNode(nullptr);
+}
+
+void QmitkExtractFromMultiLabelSegmentationWidget::ConfigureWidgets()
+{
+  m_InternalEvent = true;
+  m_Controls->labelInspector->setVisible(m_Controls->checkExtractSelected->isChecked());
+
+  bool isOK = (m_Controls->checkInstanceMap->isChecked() || m_Controls->checkInstanceMask->isChecked() || m_Controls->checkClassMap->isChecked());
+  m_Controls->btnExtract->setEnabled(isOK);
+
+  m_InternalEvent = false;
+}
+
+void QmitkExtractFromMultiLabelSegmentationWidget::OnSegSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/)
+{
+  if (!m_InternalEvent)
+  {
+    m_Controls->labelInspector->SetMultiLabelNode(m_Controls->segNodeSelector->GetSelectedNode());
+    this->ConfigureWidgets();
+  }
+}
+
+void QmitkExtractFromMultiLabelSegmentationWidget::StoreToDataStorage(mitk::Image* image, const std::string& name, mitk::DataNode* parent)
+{
+  auto dataStorage = m_DataStorage.Lock();
+  if (dataStorage.IsNull())
+  {
+    mitkThrow() << "QmitkExtractFromMultiLabelSegmentationWidget is in invalid state. No datastorage is set.";
+  }
+
+  mitk::DataNode::Pointer outNode = mitk::DataNode::New();
+  outNode->SetName(name);
+  outNode->SetData(image);
+
+  dataStorage->Add(outNode, parent);
+}
+
+void QmitkExtractFromMultiLabelSegmentationWidget::OnExtractPressed()
+{
+  QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
+  auto node = m_Controls->segNodeSelector->GetSelectedNodes().front();
+
+  auto seg = dynamic_cast<mitk::LabelSetImage*>(node->GetData());
+
+  auto selectedLabelValues = seg->GetAllLabelValues();
+  if (m_Controls->checkExtractSelected->isChecked())
+    selectedLabelValues = m_Controls->labelInspector->GetSelectedLabels();
+
+  auto groupLabelValueMap = mitk::LabelSetImageHelper::SplitLabelValuesByGroup(seg,selectedLabelValues);
+
+  unsigned int numSteps = 0;
+  if (m_Controls->checkInstanceMap->isChecked()) numSteps += groupLabelValueMap.size();
+  if (m_Controls->checkInstanceMask->isChecked()) numSteps += selectedLabelValues.size();
+  if (m_Controls->checkClassMap->isChecked()) numSteps += groupLabelValueMap.size();
+
+  mitk::ProgressBar::GetInstance()->Reset();
+  mitk::ProgressBar::GetInstance()->AddStepsToDo(numSteps);
+
+  for (auto& [groupID, labelValues] : groupLabelValueMap)
+  {
+    if (m_Controls->checkInstanceMap->isChecked())
+    {
+      auto image = seg->GetGroupImageWorkaround(groupID)->Clone();
+      std::string name = "InstanceMap group "+std::to_string(groupID);
+      this->StoreToDataStorage(image, name, node);
+      mitk::ProgressBar::GetInstance()->Progress();
+    }
+    if (m_Controls->checkClassMap->isChecked())
+    {
+      auto [image,lookup] = mitk::CreateLabelClassMap(seg, groupID, labelValues);
+      std::string name = "ClassMap group " + std::to_string(groupID);
+      this->StoreToDataStorage(image, name, node);
+      mitk::ProgressBar::GetInstance()->Progress();
+    }
+    if (m_Controls->checkInstanceMask->isChecked())
+    {
+      for (auto& labelValue : labelValues)
+      {
+        auto image = mitk::CreateLabelMask(seg,labelValue,false);
+        std::string name = "LabelMask " + seg->GetLabel(labelValue)->GetName() + " [" + std::to_string(labelValue) + "]";
+        this->StoreToDataStorage(image, name, node);
+        mitk::ProgressBar::GetInstance()->Progress();
+      }
+    }
+  }
+  mitk::ProgressBar::GetInstance()->Reset();
+  QApplication::restoreOverrideCursor();
+}
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.h
new file mode 100644
index 0000000000..5ef5fb93df
--- /dev/null
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.h
@@ -0,0 +1,73 @@
+/*============================================================================
+
+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 QmitkExtractFromMultiLabelSegmentationWidget_h
+#define QmitkExtractFromMultiLabelSegmentationWidget_h
+
+#include <MitkSegmentationUIExports.h>
+#include <QmitkNodeSelectionDialog.h>
+#include <QmitkAbstractNodeSelectionWidget.h>
+
+#include <QWidget>
+
+namespace Ui
+{
+  class QmitkExtractFromMultiLabelSegmentationWidgetControls;
+}
+
+namespace mitk
+{
+  class DataNode;
+  class DataStorage;
+  class Surface;
+  class Image;
+  class LabelSetImage;
+}
+
+/*!
+  \brief QmitkExtractFromMultiLabelSegmentationWidget
+
+  Widget that offers the GUI and logic to extract different images (class maps, instance maps
+  and instance masks) from a multi label segmentation.
+*/
+class MITKSEGMENTATIONUI_EXPORT QmitkExtractFromMultiLabelSegmentationWidget : public QWidget
+{
+  Q_OBJECT
+
+public:
+
+  /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
+  explicit QmitkExtractFromMultiLabelSegmentationWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
+
+  /** @brief Default destructor. */
+  ~QmitkExtractFromMultiLabelSegmentationWidget() override;
+
+private slots:
+
+  /** @brief This slot is called if the selection in the workbench is changed. */
+  void OnSegSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/);
+
+  /** @brief This slot is called if user activates the button to convert a surface into a binary image. */
+  void OnExtractPressed();
+
+private:
+  bool m_InternalEvent = false;
+  mitk::WeakPointer<mitk::DataStorage> m_DataStorage;
+
+  void ConfigureWidgets();
+
+  void StoreToDataStorage(mitk::Image* image, const std::string& name, mitk::DataNode* parent);
+
+  Ui::QmitkExtractFromMultiLabelSegmentationWidgetControls* m_Controls;
+};
+
+#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidgetControls.ui b/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidgetControls.ui
new file mode 100644
index 0000000000..3635ba4792
--- /dev/null
+++ b/Modules/SegmentationUI/SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidgetControls.ui
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QmitkExtractFromMultiLabelSegmentationWidgetControls</class>
+ <widget class="QWidget" name="QmitkExtractFromMultiLabelSegmentationWidgetControls">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>313</width>
+    <height>316</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Segmentation;</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QmitkSingleNodeSelectionWidget" name="segNodeSelector" native="true"/>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="checkExtractSelected">
+     <property name="text">
+      <string>Extract only selected label(s)</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QmitkMultiLabelInspector" name="labelInspector" native="true"/>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupOutput">
+     <property name="title">
+      <string>Outputs:</string>
+     </property>
+     <property name="flat">
+      <bool>false</bool>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <property name="spacing">
+       <number>4</number>
+      </property>
+      <property name="leftMargin">
+       <number>4</number>
+      </property>
+      <property name="topMargin">
+       <number>4</number>
+      </property>
+      <property name="rightMargin">
+       <number>4</number>
+      </property>
+      <property name="bottomMargin">
+       <number>4</number>
+      </property>
+      <item>
+       <widget class="QCheckBox" name="checkInstanceMask">
+        <property name="toolTip">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If checked, a binary mask image is generated for each selected label.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="text">
+         <string>Label instance mask(s)</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="checkInstanceMap">
+        <property name="toolTip">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If checked, an image is generated for each selected group containing all selected label instances of that group.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="text">
+         <string>Label instance map(s)</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="checkClassMap">
+        <property name="toolTip">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If checked, an image is generated for each selected group containing all classes of selected label instances of that group.&lt;/p&gt;&lt;p&gt;So basically all label instances with the same label name will get the same pixel value in the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="text">
+         <string>Label class map(s)</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="btnExtract">
+     <property name="text">
+      <string>Extract</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QmitkSingleNodeSelectionWidget</class>
+   <extends>QWidget</extends>
+   <header location="global">QmitkSingleNodeSelectionWidget.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>QmitkMultiLabelInspector</class>
+   <extends>QWidget</extends>
+   <header location="global">QmitkMultiLabelInspector.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp
deleted file mode 100644
index 7e6ad451b1..0000000000
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*============================================================================
-
-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 "QmitkSurfaceToImageWidget.h"
-#include <ui_QmitkSurfaceToImageWidgetControls.h>
-
-#include <mitkDataStorage.h>
-#include <mitkException.h>
-#include <mitkExceptionMacro.h>
-#include <mitkProgressBar.h>
-#include <mitkProperties.h>
-#include <mitkSurfaceToImageFilter.h>
-#include <mitkSurface.h>
-#include <mitkImage.h>
-#include <mitkLabelSetImage.h>
-
-#include <qmessagebox.h>
-
-static const char* const HelpText = "Select an image and a surface above";
-
-QmitkSurfaceToImageWidget::QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent)
-  : QWidget(parent)
-{
-  m_Controls = new Ui::QmitkSurfaceToImageWidgetControls;
-  m_Controls->setupUi(this);
-
-  m_Controls->dataSelectionWidget->SetDataStorage(dataStorage);
-  m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::ImageAndSegmentationPredicate);
-  m_Controls->dataSelectionWidget->AddDataSelection(QmitkDataSelectionWidget::SurfacePredicate);
-  m_Controls->dataSelectionWidget->SetHelpText(HelpText);
-
-  this->EnableButtons(false);
-
-  connect (m_Controls->btnSurface2Image, SIGNAL(pressed()), this, SLOT(OnSurface2ImagePressed()));
-  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));
-  }
-}
-
-QmitkSurfaceToImageWidget::~QmitkSurfaceToImageWidget()
-{
-}
-
-void QmitkSurfaceToImageWidget::EnableButtons(bool enable)
-{
-  m_Controls->btnSurface2Image->setEnabled(enable);
-}
-
-void QmitkSurfaceToImageWidget::OnSelectionChanged(unsigned int, const mitk::DataNode*)
-{
-  QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
-  mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
-  mitk::DataNode::Pointer surfaceNode = dataSelectionWidget->GetSelection(1);
-
-  if (imageNode.IsNull() || surfaceNode.IsNull() )
-  {
-    dataSelectionWidget->SetHelpText(HelpText);
-    this->EnableButtons(false);
-  }
-  else
-  {
-    mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( dataSelectionWidget->GetSelection(0)->GetData() );
-    mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface*>( dataSelectionWidget->GetSelection(1)->GetData() );
-    if( image->GetTimeSteps() != surface->GetTimeSteps() )
-    {
-      dataSelectionWidget->SetHelpText("Image and surface are of different size");
-      this->EnableButtons(false);
-    }
-    else
-    {
-      dataSelectionWidget->SetHelpText("");
-      this->EnableButtons();
-    }
-  }
-}
-
-void QmitkSurfaceToImageWidget::OnSurface2ImagePressed()
-{
-  this->EnableButtons(false);
-
-  QmitkDataSelectionWidget* dataSelectionWidget = m_Controls->dataSelectionWidget;
-  mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( dataSelectionWidget->GetSelection(0)->GetData() );
-  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface*>( dataSelectionWidget->GetSelection(1)->GetData() );
-
-  if( image.IsNull() || surface.IsNull())
-  {
-    MITK_ERROR << "Selection does not contain an image and/or a surface";
-    QMessageBox::information( this, "Surface To Image", "Selection does not contain an image and/or a surface", QMessageBox::Ok );
-    this->EnableButtons();
-    return;
-  }
-
-  mitk::Image::Pointer resultImage(nullptr);
-  resultImage = this->ConvertSurfaceToImage( image, surface );
-
-  if( resultImage.IsNull() )
-  {
-    MITK_ERROR << "Convert Surface to binary image failed";
-    QMessageBox::information( this, "Surface To Image", "Convert Surface to binary image failed", QMessageBox::Ok );
-    this->EnableButtons();
-    return;
-  }
-
-  //create name for result node
-  std::string nameOfResultImage = dataSelectionWidget->GetSelection(0)->GetName();
-  nameOfResultImage.append("_");
-  nameOfResultImage.append(dataSelectionWidget->GetSelection(1)->GetName());
-
-  //create data node and add to data storage
-  mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
-  resultNode->SetData( resultImage );
-  resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) );
-//  resultNode->SetProperty("binary", mitk::BoolProperty::New(true) );
-
-  auto dataStorage = dataSelectionWidget->GetDataStorage();
-  if (dataStorage.IsNull())
-  {
-    std::string exception = "Cannot add result to the data storage. Data storage invalid.";
-    MITK_ERROR << "Error converting surface to binary image: " << exception;
-    QMessageBox::information(nullptr, "Error converting surface to binary image", QString::fromStdString(exception));
-  }
-
-  dataStorage->Add(resultNode, dataSelectionWidget->GetSelection(0));
-  this->EnableButtons();
-}
-
-mitk::LabelSetImage::Pointer QmitkSurfaceToImageWidget::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 = surfaceToImageFilter->GetOutput();
-  mitk::LabelSetImage::Pointer multilabelImage = mitk::LabelSetImage::New();
-  multilabelImage->InitializeByLabeledImage(resultImage);
-
-  return multilabelImage;
-}
-
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h
deleted file mode 100644
index 030a8cb8a7..0000000000
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidget.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*============================================================================
-
-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 QmitkSurfaceToImageWidget_h
-#define QmitkSurfaceToImageWidget_h
-
-#include <MitkSegmentationUIExports.h>
-
-#include "itkSmartPointer.h"
-
-#include <QWidget>
-
-namespace Ui
-{
-  class QmitkSurfaceToImageWidgetControls;
-}
-
-namespace mitk
-{
-  class DataNode;
-  class DataStorage;
-  class Surface;
-  class Image;
-  class LabelSetImage;
-}
-
-/*!
-  \brief QmitkSurfaceToImageWidget
-
-  The Tool converts a surface to a binary image. The Method requires
-  a surface and an image, which header information defines the output
-  image. The resulting binary image has the same dimension, size, and
-  Geometry3D as the input image.
-*/
-class MITKSEGMENTATIONUI_EXPORT QmitkSurfaceToImageWidget : public QWidget
-{
-  Q_OBJECT
-
-public:
-
-  /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
-  explicit QmitkSurfaceToImageWidget(mitk::DataStorage* dataStorage, QWidget* parent = nullptr);
-
-  /** @brief Default destructor. */
-  ~QmitkSurfaceToImageWidget() 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 button to convert a surface into a binary image. */
-  void OnSurface2ImagePressed();
-
-private:
-
-  /** @brief Enable buttons if data selection is valid. */
-  void EnableButtons(bool enable = true);
-
-  /** @brief Convert a surface into an binary image. */
-  itk::SmartPointer<mitk::LabelSetImage> ConvertSurfaceToImage( itk::SmartPointer<mitk::Image> image, itk::SmartPointer<mitk::Surface> surface );
-
-  Ui::QmitkSurfaceToImageWidgetControls* m_Controls;
-};
-
-#endif
diff --git a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidgetControls.ui b/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidgetControls.ui
deleted file mode 100644
index e617a3205b..0000000000
--- a/Modules/SegmentationUI/SegmentationUtilities/QmitkSurfaceToImageWidgetControls.ui
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QmitkSurfaceToImageWidgetControls</class>
- <widget class="QWidget" name="QmitkSurfaceToImageWidgetControls">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>98</width>
-    <height>62</height>
-   </rect>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <widget class="QmitkDataSelectionWidget" name="dataSelectionWidget" native="true">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <widget class="QPushButton" name="btnSurface2Image">
-     <property name="text">
-      <string>Convert</string>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <spacer name="verticalSpacer">
-     <property name="orientation">
-      <enum>Qt::Vertical</enum>
-     </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>20</width>
-       <height>40</height>
-      </size>
-     </property>
-    </spacer>
-   </item>
-  </layout>
- </widget>
- <customwidgets>
-  <customwidget>
-   <class>QmitkDataSelectionWidget</class>
-   <extends>QWidget</extends>
-   <header>QmitkDataSelectionWidget.h</header>
-   <container>1</container>
-  </customwidget>
- </customwidgets>
- <resources/>
- <connections/>
-</ui>
diff --git a/Modules/SegmentationUI/files.cmake b/Modules/SegmentationUI/files.cmake
index d230e65769..b775a8af5a 100644
--- a/Modules/SegmentationUI/files.cmake
+++ b/Modules/SegmentationUI/files.cmake
@@ -1,126 +1,126 @@
 set(CPP_FILES
   Qmitk/QmitkSegWithPreviewToolGUIBase.cpp
   Qmitk/QmitkMultiLabelSegWithPreviewToolGUIBase.cpp
   Qmitk/QmitkBinaryThresholdToolGUIBase.cpp
   Qmitk/QmitkBinaryThresholdToolGUI.cpp
   Qmitk/QmitkBinaryThresholdULToolGUI.cpp
   Qmitk/QmitkConfirmSegmentationDialog.cpp
   Qmitk/QmitkCopyToClipBoardDialog.cpp
   Qmitk/QmitkDrawPaintbrushToolGUI.cpp
   Qmitk/QmitkErasePaintbrushToolGUI.cpp
   Qmitk/QmitkEditableContourToolGUIBase.cpp
   Qmitk/QmitkGrowCutToolGUI.cpp
   Qmitk/QmitkLiveWireTool2DGUI.cpp
   Qmitk/QmitkLassoToolGUI.cpp
   Qmitk/QmitkOtsuTool3DGUI.cpp
   Qmitk/QmitkPaintbrushToolGUI.cpp
   Qmitk/QmitkPickingToolGUI.cpp
   Qmitk/QmitkSlicesInterpolator.cpp
   Qmitk/QmitkToolGUI.cpp
   Qmitk/QmitkToolGUIArea.cpp
   Qmitk/QmitkToolSelectionBox.cpp
   Qmitk/QmitknnUNetFolderParser.cpp
   Qmitk/QmitknnUNetToolGUI.cpp
   Qmitk/QmitknnUNetWorker.cpp
   Qmitk/QmitknnUNetGPU.cpp
   Qmitk/QmitkSurfaceStampWidget.cpp
   Qmitk/QmitkMaskStampWidget.cpp
   Qmitk/QmitkStaticDynamicSegmentationDialog.cpp
   Qmitk/QmitkSimpleLabelSetListWidget.cpp
   Qmitk/QmitkSegmentationTaskListWidget.cpp
   Qmitk/QmitkTotalSegmentatorToolGUI.cpp
   Qmitk/QmitkSetupVirtualEnvUtil.cpp
   Qmitk/QmitkMultiLabelInspector.cpp
   Qmitk/QmitkMultiLabelManager.cpp
   Qmitk/QmitkMultiLabelTreeModel.cpp
   Qmitk/QmitkMultiLabelTreeView.cpp
   Qmitk/QmitkMultiLabelPresetHelper.cpp
   Qmitk/QmitkLabelColorItemDelegate.cpp
   Qmitk/QmitkLabelToggleItemDelegate.cpp
   Qmitk/QmitkFindSegmentationTaskDialog.cpp
   Qmitk/QmitkSegmentAnythingToolGUI.cpp
   SegmentationUtilities/QmitkBooleanOperationsWidget.cpp
-  SegmentationUtilities/QmitkContourModelToImageWidget.cpp
   SegmentationUtilities/QmitkImageMaskingWidget.cpp
   SegmentationUtilities/QmitkMorphologicalOperationsWidget.cpp
-  SegmentationUtilities/QmitkSurfaceToImageWidget.cpp
   SegmentationUtilities/QmitkDataSelectionWidget.cpp
+  SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.cpp
+  SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.cpp
 )
 
 set(H_FILES
   Qmitk/QmitkMultiLabelPresetHelper.h
 )
 set(MOC_H_FILES
   Qmitk/QmitkSegWithPreviewToolGUIBase.h
   Qmitk/QmitkMultiLabelSegWithPreviewToolGUIBase.h
   Qmitk/QmitkBinaryThresholdToolGUIBase.h
   Qmitk/QmitkBinaryThresholdToolGUI.h
   Qmitk/QmitkBinaryThresholdULToolGUI.h
   Qmitk/QmitkConfirmSegmentationDialog.h
   Qmitk/QmitkCopyToClipBoardDialog.h
   Qmitk/QmitkDrawPaintbrushToolGUI.h
   Qmitk/QmitkErasePaintbrushToolGUI.h
   Qmitk/QmitkEditableContourToolGUIBase.h
   Qmitk/QmitkGrowCutToolGUI.h
   Qmitk/QmitkLiveWireTool2DGUI.h
   Qmitk/QmitkLassoToolGUI.h
   Qmitk/QmitkOtsuTool3DGUI.h
   Qmitk/QmitkPaintbrushToolGUI.h
   Qmitk/QmitkPickingToolGUI.h
   Qmitk/QmitkSlicesInterpolator.h
   Qmitk/QmitkToolGUI.h
   Qmitk/QmitkToolGUIArea.h
   Qmitk/QmitkToolSelectionBox.h
   Qmitk/QmitknnUNetFolderParser.h
   Qmitk/QmitknnUNetToolGUI.h
   Qmitk/QmitknnUNetGPU.h
   Qmitk/QmitknnUNetWorker.h
   Qmitk/QmitknnUNetEnsembleLayout.h
   Qmitk/QmitkSurfaceStampWidget.h
   Qmitk/QmitkMaskStampWidget.h
   Qmitk/QmitkStaticDynamicSegmentationDialog.h
   Qmitk/QmitkSimpleLabelSetListWidget.h
   Qmitk/QmitkSegmentationTaskListWidget.h
   Qmitk/QmitkTotalSegmentatorToolGUI.h
   Qmitk/QmitkSetupVirtualEnvUtil.h
   Qmitk/QmitkMultiLabelInspector.h
   Qmitk/QmitkMultiLabelManager.h
   Qmitk/QmitkMultiLabelTreeModel.h
   Qmitk/QmitkMultiLabelTreeView.h
   Qmitk/QmitkLabelColorItemDelegate.h
   Qmitk/QmitkLabelToggleItemDelegate.h
   Qmitk/QmitkFindSegmentationTaskDialog.h
   Qmitk/QmitkSegmentAnythingToolGUI.h
   SegmentationUtilities/QmitkBooleanOperationsWidget.h
-  SegmentationUtilities/QmitkContourModelToImageWidget.h
   SegmentationUtilities/QmitkImageMaskingWidget.h
   SegmentationUtilities/QmitkMorphologicalOperationsWidget.h
-  SegmentationUtilities/QmitkSurfaceToImageWidget.h
   SegmentationUtilities/QmitkDataSelectionWidget.h
+  SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidget.h
+  SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidget.h
 )
 
 set(UI_FILES
   Qmitk/QmitkConfirmSegmentationDialog.ui
   Qmitk/QmitkGrowCutToolWidgetControls.ui
   Qmitk/QmitkOtsuToolWidgetControls.ui
   Qmitk/QmitkSurfaceStampWidgetGUIControls.ui
   Qmitk/QmitkMaskStampWidgetGUIControls.ui
   Qmitk/QmitknnUNetToolGUIControls.ui
   Qmitk/QmitkEditableContourToolGUIControls.ui
   Qmitk/QmitkSegmentationTaskListWidget.ui
   Qmitk/QmitkTotalSegmentatorGUIControls.ui
   Qmitk/QmitkMultiLabelInspectorControls.ui
   Qmitk/QmitkMultiLabelManagerControls.ui
   Qmitk/QmitkFindSegmentationTaskDialog.ui
   Qmitk/QmitkSegmentAnythingGUIControls.ui
   SegmentationUtilities/QmitkBooleanOperationsWidgetControls.ui
-  SegmentationUtilities/QmitkContourModelToImageWidgetControls.ui
   SegmentationUtilities/QmitkImageMaskingWidgetControls.ui
   SegmentationUtilities/QmitkMorphologicalOperationsWidgetControls.ui
-  SegmentationUtilities/QmitkSurfaceToImageWidgetControls.ui
   SegmentationUtilities/QmitkDataSelectionWidgetControls.ui
+  SegmentationUtilities/QmitkConvertToMultiLabelSegmentationWidgetControls.ui
+  SegmentationUtilities/QmitkExtractFromMultiLabelSegmentationWidgetControls.ui
 )
 
 set(QRC_FILES
   resources/SegmentationUI.qrc
 )
diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp
index ec0aea40e9..28437999a1 100644
--- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp
+++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp
@@ -1,494 +1,494 @@
 /*============================================================================
 
 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 "QmitkImageStatisticsView.h"
 
 #include <utility>
 
 // berry includes
 #include <berryIQtStyleManager.h>
 #include <berryWorkbenchPlugin.h>
 
 #include <QmitkChartWidget.h>
 #include <mitkImageStatisticsContainerNodeHelper.h>
 #include <mitkImageStatisticsPredicateHelper.h>
 #include <mitkImageTimeSelector.h>
 #include <mitkIntensityProfile.h>
 #include <mitkNodePredicateAnd.h>
 #include <mitkNodePredicateGeometry.h>
 #include <mitkNodePredicateSubGeometry.h>
 #include <mitkNodePredicateOr.h>
 #include <mitkNodePredicateFunction.h>
 #include <mitkSliceNavigationController.h>
 #include <mitkStatusBar.h>
 #include <mitkPlanarFigure.h>
 #include "mitkPlanarFigureMaskGenerator.h"
 
 #include "QmitkImageStatisticsDataGenerator.h"
 
 #include "mitkImageStatisticsContainerManager.h"
 #include <mitkPlanarFigureInteractor.h>
 
 const std::string QmitkImageStatisticsView::VIEW_ID = "org.mitk.views.imagestatistics";
 
 namespace {
   bool CheckPlanarFigureMatchesGeometry(const mitk::PlanarFigure* planarFigure, const mitk::BaseGeometry* imageGeometry)
   {
     if (!planarFigure || !imageGeometry)
       return false;
 
     if (!mitk::PlanarFigureMaskGenerator::CheckPlanarFigureIsNotTilted(planarFigure->GetPlaneGeometry(), imageGeometry))
       return false;
 
     // The rest from here on is only needed until T30279 has been solved.
     if (planarFigure->IsClosed())
       return true;
 
     const auto numControlPoints = planarFigure->GetNumberOfControlPoints();
     for (unsigned int i = 0; i < numControlPoints; ++i)
     {
       if (!imageGeometry->IsInside(planarFigure->GetWorldControlPoint(i)))
         return false;
     }
 
     return true;
   }
 } // unnamed namespace
 
 QmitkImageStatisticsView::~QmitkImageStatisticsView()
 {
 }
 
 void QmitkImageStatisticsView::CreateQtPartControl(QWidget *parent)
 {
   m_Controls.setupUi(parent);
   m_Controls.widget_intensityProfile->SetTheme(GetColorTheme());
   m_Controls.groupBox_histogram->setVisible(false);
   m_Controls.groupBox_intensityProfile->setVisible(false);
   m_Controls.label_currentlyComputingStatistics->setVisible(false);
   m_Controls.sliderWidget_histogram->setPrefix("Time: ");
   m_Controls.sliderWidget_histogram->setDecimals(0);
   m_Controls.sliderWidget_histogram->setVisible(false);
   m_Controls.sliderWidget_intensityProfile->setPrefix("Time: ");
   m_Controls.sliderWidget_intensityProfile->setDecimals(0);
   m_Controls.sliderWidget_intensityProfile->setVisible(false);
   ResetGUI();
 
   m_DataGenerator = new QmitkImageStatisticsDataGenerator(parent);
   m_DataGenerator->SetDataStorage(this->GetDataStorage());
   m_DataGenerator->SetAutoUpdate(true);
   m_Controls.widget_statistics->SetDataStorage(this->GetDataStorage());
 
   m_Controls.imageNodesSelector->SetDataStorage(this->GetDataStorage());
   m_Controls.imageNodesSelector->SetNodePredicate(mitk::GetImageStatisticsImagePredicate());
   m_Controls.imageNodesSelector->SetSelectionCheckFunction(this->CheckForSameGeometry());
   m_Controls.imageNodesSelector->SetSelectionIsOptional(false);
   m_Controls.imageNodesSelector->SetInvalidInfo(QStringLiteral("Please select images for statistics"));
   m_Controls.imageNodesSelector->SetPopUpTitel(QStringLiteral("Select input images"));
-  m_Controls.roiNodesSelector->SetPopUpHint(QStringLiteral("You may select multiple images for the statistics computation. But all selected images must have the same geometry."));
+  m_Controls.imageNodesSelector->SetPopUpHint(QStringLiteral("You may select multiple images for the statistics computation. But all selected images must have the same geometry."));
 
   m_Controls.roiNodesSelector->SetDataStorage(this->GetDataStorage());
   m_Controls.roiNodesSelector->SetNodePredicate(this->GenerateROIPredicate());
   m_Controls.roiNodesSelector->SetSelectionIsOptional(true);
   m_Controls.roiNodesSelector->SetEmptyInfo(QStringLiteral("Please select ROIs"));
   m_Controls.roiNodesSelector->SetPopUpTitel(QStringLiteral("Select ROIs for statistics computation"));
   m_Controls.roiNodesSelector->SetPopUpHint(QStringLiteral("You may select ROIs (e.g. planar figures, segmentations) that should be used for the statistics computation. The statistics will only computed for the image parts defined by the ROIs."));
 
   CreateConnections();
 
   this->m_TimePointChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
   connect(&m_TimePointChangeListener, &QmitkSliceNavigationListener::SelectedTimePointChanged, this, & QmitkImageStatisticsView::OnSelectedTimePointChanged);
 }
 
 void QmitkImageStatisticsView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
 {
   this->m_TimePointChangeListener.RenderWindowPartActivated(renderWindowPart);
 }
 
 void QmitkImageStatisticsView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart)
 {
   this->m_TimePointChangeListener.RenderWindowPartDeactivated(renderWindowPart);
 }
 
 void QmitkImageStatisticsView::CreateConnections()
 {
   connect(m_Controls.widget_statistics, &QmitkImageStatisticsWidget::IgnoreZeroValuedVoxelStateChanged,
     this, &QmitkImageStatisticsView::OnIgnoreZeroValuedVoxelStateChanged);
   connect(m_Controls.buttonSelection, &QAbstractButton::clicked,
     this, &QmitkImageStatisticsView::OnButtonSelectionPressed);
 
   connect(m_Controls.widget_histogram, &QmitkHistogramVisualizationWidget::RequestHistogramUpdate,
     this, &QmitkImageStatisticsView::OnRequestHistogramUpdate);
 
   connect(m_DataGenerator, &QmitkImageStatisticsDataGenerator::DataGenerationStarted,
     this, &QmitkImageStatisticsView::OnGenerationStarted);
   connect(m_DataGenerator, &QmitkImageStatisticsDataGenerator::GenerationFinished,
     this, &QmitkImageStatisticsView::OnGenerationFinished);
   connect(m_DataGenerator, &QmitkImageStatisticsDataGenerator::JobError,
     this, &QmitkImageStatisticsView::OnJobError);
 
   connect(m_Controls.imageNodesSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
     this, &QmitkImageStatisticsView::OnImageSelectionChanged);
   connect(m_Controls.roiNodesSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
     this, &QmitkImageStatisticsView::OnROISelectionChanged);
 
   connect(m_Controls.sliderWidget_intensityProfile, &ctkSliderWidget::valueChanged, this, &QmitkImageStatisticsView::UpdateIntensityProfile);
 }
 
 void QmitkImageStatisticsView::UpdateIntensityProfile()
 {
   m_Controls.groupBox_intensityProfile->setVisible(false);
 
   const auto selectedImageNodes = m_Controls.imageNodesSelector->GetSelectedNodes();
   const auto selectedROINodes = m_Controls.roiNodesSelector->GetSelectedNodes();
 
   if (selectedImageNodes.size()==1 && selectedROINodes.size()==1)
   { //only supported for one image and roi currently
     auto image = dynamic_cast<mitk::Image*>(selectedImageNodes.front()->GetData());
 
     auto maskPlanarFigure = dynamic_cast<mitk::PlanarFigure*>(selectedROINodes.front()->GetData());
 
     if (maskPlanarFigure != nullptr)
     {
       if (!maskPlanarFigure->IsClosed())
       {
         mitk::Image::Pointer inputImage;
         if (image->GetDimension() == 4)
         {
           m_Controls.sliderWidget_intensityProfile->setVisible(true);
           unsigned int maxTimestep = image->GetTimeSteps();
           m_Controls.sliderWidget_intensityProfile->setMaximum(maxTimestep - 1);
           // Intensity profile can only be calculated on 3D, so extract if 4D
           mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
           int currentTimestep = static_cast<int>(m_Controls.sliderWidget_intensityProfile->value());
           timeSelector->SetInput(image);
           timeSelector->SetTimeNr(currentTimestep);
           timeSelector->Update();
 
           inputImage = timeSelector->GetOutput();
         }
         else
         {
           m_Controls.sliderWidget_intensityProfile->setVisible(false);
           inputImage = image;
         }
 
         auto intensityProfile = mitk::ComputeIntensityProfile(inputImage, maskPlanarFigure);
         m_Controls.groupBox_intensityProfile->setVisible(true);
         m_Controls.widget_intensityProfile->Reset();
         m_Controls.widget_intensityProfile->SetIntensityProfile(intensityProfile.GetPointer(),
           "Intensity Profile of " + selectedImageNodes.front()->GetName());
       }
     }
   }
 }
 
 void QmitkImageStatisticsView::UpdateHistogramWidget()
 {
   m_Controls.groupBox_histogram->setVisible(false);
 
   const auto selectedImageNodes = m_Controls.imageNodesSelector->GetSelectedNodes();
   const auto selectedMaskNodes = m_Controls.roiNodesSelector->GetSelectedNodes();
 
   if (selectedImageNodes.size() == 1 && selectedMaskNodes.size()<=1)
   { //currently only supported for one image and roi due to histogram widget limitations.
     auto imageNode = selectedImageNodes.front();
     const mitk::DataNode* roiNode = nullptr;
     const mitk::PlanarFigure* planarFigure = nullptr;
     if (!selectedMaskNodes.empty())
     {
       roiNode = selectedMaskNodes.front();
       planarFigure = dynamic_cast<const mitk::PlanarFigure*>(roiNode->GetData());
     }
 
     if ((planarFigure == nullptr || planarFigure->IsClosed())
         && imageNode->GetData()->GetTimeGeometry()->IsValidTimePoint(m_TimePointChangeListener.GetCurrentSelectedTimePoint()))
     { //if a planar figure is not closed, we show the intensity profile instead of the histogram.
       auto statisticsNode = m_DataGenerator->GetLatestResult(imageNode, roiNode, true);
 
       if (statisticsNode.IsNotNull())
       {
         auto statistics = dynamic_cast<const mitk::ImageStatisticsContainer*>(statisticsNode->GetData());
 
         if (statistics && !statistics->IsWIP())
         {
           //currently only supports rois with one label due to histogram widget limitations.
           auto labelValues = statistics->GetExistingLabelValues();
           if (labelValues.size() == 1)
           {
             auto labelValue = labelValues.empty() ? mitk::ImageStatisticsContainer::NO_MASK_LABEL_VALUE : labelValues.front();
 
             const auto timeStep = imageNode->GetData()->GetTimeGeometry()->TimePointToTimeStep(m_TimePointChangeListener.GetCurrentSelectedTimePoint());
 
             if (statistics->StatisticsExist(labelValue, timeStep))
             {
               std::stringstream label;
               label << imageNode->GetName();
               if (imageNode->GetData()->GetTimeSteps() > 1)
               {
                 label << "[" << timeStep << "]";
               }
 
               if (roiNode)
               {
                 label << " with " << roiNode->GetName();
               }
 
               //Hardcoded labels are currently needed because the current histogram widget (and ChartWidget)
               //do not allow correct removal or sound update/insertion of several charts.
               //only thing that works for now is always to update/overwrite the same data label
               //This is a quick fix for T28223 and T28221
               m_Controls.widget_histogram->SetHistogram(statistics->GetHistogram(labelValue, timeStep), "histogram");
               m_Controls.groupBox_histogram->setVisible(true);
             }
           }
         }
       }
     }
   }
 }
 
 QmitkChartWidget::ColorTheme QmitkImageStatisticsView::GetColorTheme() const
 {
   ctkPluginContext *context = berry::WorkbenchPlugin::GetDefault()->GetPluginContext();
   ctkServiceReference styleManagerRef = context->getServiceReference<berry::IQtStyleManager>();
   if (styleManagerRef)
   {
     auto styleManager = context->getService<berry::IQtStyleManager>(styleManagerRef);
     if (styleManager->GetStyle().name == "Dark")
     {
       return QmitkChartWidget::ColorTheme::darkstyle;
     }
     else
     {
       return QmitkChartWidget::ColorTheme::lightstyle;
     }
   }
   return QmitkChartWidget::ColorTheme::darkstyle;
 }
 
 void QmitkImageStatisticsView::ResetGUI()
 {
   m_Controls.widget_statistics->Reset();
   m_Controls.widget_statistics->setEnabled(false);
   m_Controls.widget_histogram->Reset();
   m_Controls.widget_histogram->setEnabled(false);
   m_Controls.widget_histogram->SetTheme(GetColorTheme());
 }
 
 void QmitkImageStatisticsView::OnGenerationStarted(const mitk::DataNode* /*imageNode*/, const mitk::DataNode* /*roiNode*/, const QmitkDataGenerationJobBase* /*job*/)
 {
   m_Controls.label_currentlyComputingStatistics->setVisible(true);
 }
 
 void QmitkImageStatisticsView::OnGenerationFinished()
 {
   m_Controls.label_currentlyComputingStatistics->setVisible(false);
 
   mitk::StatusBar::GetInstance()->Clear();
 
   this->UpdateIntensityProfile();
   this->UpdateHistogramWidget();
 }
 
 void QmitkImageStatisticsView::OnSelectedTimePointChanged(const mitk::TimePointType& /*newTimePoint*/)
 {
   this->UpdateHistogramWidget();
 }
 
 void QmitkImageStatisticsView::OnJobError(QString error, const QmitkDataGenerationJobBase* /*failedJob*/)
 {
   mitk::StatusBar::GetInstance()->DisplayErrorText(error.toStdString().c_str());
   MITK_WARN << "Error when calculating statistics: " << error;
 }
 
 void QmitkImageStatisticsView::OnRequestHistogramUpdate(unsigned int nbins)
 {
   m_Controls.widget_statistics->SetHistogramNBins(nbins);
   m_DataGenerator->SetHistogramNBins(nbins);
   this->UpdateIntensityProfile();
   this->UpdateHistogramWidget();
 }
 
 void QmitkImageStatisticsView::OnIgnoreZeroValuedVoxelStateChanged(int state)
 {
   auto ignoreZeroValueVoxel = (state == Qt::Unchecked) ? false : true;
   m_Controls.widget_statistics->SetIgnoreZeroValueVoxel(ignoreZeroValueVoxel);
   m_DataGenerator->SetIgnoreZeroValueVoxel(ignoreZeroValueVoxel);
   this->UpdateIntensityProfile();
   this->UpdateHistogramWidget();
 }
 
 void QmitkImageStatisticsView::OnImageSelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/)
 {
   auto images = m_Controls.imageNodesSelector->GetSelectedNodesStdVector();
   m_Controls.widget_statistics->SetImageNodes(images);
 
   m_Controls.widget_statistics->setEnabled(!images.empty());
 
   m_Controls.roiNodesSelector->SetNodePredicate(this->GenerateROIPredicate());
 
   m_DataGenerator->SetAutoUpdate(false);
   m_DataGenerator->SetImageNodes(images);
   m_DataGenerator->Generate();
   m_DataGenerator->SetAutoUpdate(true);
 
   this->UpdateHistogramWidget();
   this->UpdateIntensityProfile();
 }
 
 void QmitkImageStatisticsView::OnROISelectionChanged(QmitkAbstractNodeSelectionWidget::NodeList /*nodes*/)
 {
   auto rois = m_Controls.roiNodesSelector->GetSelectedNodesStdVector();
 
   m_Controls.widget_statistics->SetMaskNodes(rois);
 
   m_DataGenerator->SetAutoUpdate(false);
   m_DataGenerator->SetROINodes(rois);
   m_DataGenerator->Generate();
   m_DataGenerator->SetAutoUpdate(true);
 
   this->UpdateHistogramWidget();
   this->UpdateIntensityProfile();
 }
 
 void QmitkImageStatisticsView::OnButtonSelectionPressed()
 {
   QmitkNodeSelectionDialog* dialog = new QmitkNodeSelectionDialog(nullptr, "Select input for the statistic","You may select images and ROIs to compute their statistic. ROIs may be segmentations or planar figures.");
   dialog->SetDataStorage(GetDataStorage());
   dialog->SetSelectionCheckFunction(CheckForSameGeometry());
 
   // set predicates
   auto isPlanarFigurePredicate = mitk::GetImageStatisticsPlanarFigurePredicate();
   auto isMaskPredicate = mitk::GetImageStatisticsMaskPredicate();
   auto isImagePredicate = mitk::GetImageStatisticsImagePredicate();
   auto isMaskOrPlanarFigurePredicate = mitk::NodePredicateOr::New(isPlanarFigurePredicate, isMaskPredicate);
   auto isImageOrMaskOrPlanarFigurePredicate = mitk::NodePredicateOr::New(isMaskOrPlanarFigurePredicate, isImagePredicate);
   dialog->SetNodePredicate(isImageOrMaskOrPlanarFigurePredicate);
   dialog->SetSelectionMode(QAbstractItemView::MultiSelection);
   dialog->SetCurrentSelection(m_Controls.imageNodesSelector->GetSelectedNodes()+m_Controls.roiNodesSelector->GetSelectedNodes());
 
   if (dialog->exec())
   {
     auto selectedNodeList = dialog->GetSelectedNodes();
 
     m_Controls.imageNodesSelector->SetCurrentSelection(selectedNodeList);
     m_Controls.roiNodesSelector->SetCurrentSelection(selectedNodeList);
   }
 
   delete dialog;
 }
 
 QmitkNodeSelectionDialog::SelectionCheckFunctionType QmitkImageStatisticsView::CheckForSameGeometry() const
 {
   auto isMaskPredicate = mitk::GetImageStatisticsMaskPredicate();
 
   auto lambda = [isMaskPredicate](const QmitkNodeSelectionDialog::NodeList& nodes)
   {
     if (nodes.empty())
     {
       return std::string();
     }
 
     const mitk::Image* imageNodeData = nullptr;
     for (auto& node : nodes)
     {
       auto castedData = dynamic_cast<const mitk::Image*>(node->GetData());
       if (castedData != nullptr && !isMaskPredicate->CheckNode(node))
       {
         imageNodeData = castedData;
         break;
       }
     }
 
     if (imageNodeData == nullptr)
     {
       std::stringstream ss;
       ss << "<font class=\"warning\"><p>Select at least one image.</p></font>";
       return ss.str();
     }
 
     auto imageGeoPredicate = mitk::NodePredicateGeometry::New(imageNodeData->GetGeometry());
     auto maskGeoPredicate = mitk::NodePredicateSubGeometry::New(imageNodeData->GetGeometry());
 
     for (auto& rightNode : nodes)
     {
       if (imageNodeData != rightNode->GetData())
       {
         bool validGeometry = true;
 
         if (isMaskPredicate->CheckNode(rightNode))
         {
           validGeometry = maskGeoPredicate->CheckNode(rightNode);
         }
         else if (dynamic_cast<const mitk::Image*>(rightNode->GetData()))
         {
           validGeometry = imageGeoPredicate->CheckNode(rightNode);
         }
         else
         {
           const auto planarFigure = dynamic_cast<const mitk::PlanarFigure*>(rightNode->GetData());
           const auto imageGeometry = imageNodeData->GetGeometry();
           validGeometry = CheckPlanarFigureMatchesGeometry(planarFigure, imageGeometry);
         }
 
         if (!validGeometry)
         {
           std::stringstream ss;
           ss << "<font class=\"warning\"><p>Invalid selection: All selected nodes must have the same geometry.</p><p>Differing node i.a.: \"";
           ss << rightNode->GetName() <<"\"</p></font>";
           return ss.str();
         }
       }
     }
 
     return std::string();
   };
 
   return lambda;
 }
 
 mitk::NodePredicateBase::Pointer QmitkImageStatisticsView::GenerateROIPredicate() const
 {
   auto isPlanarFigurePredicate = mitk::GetImageStatisticsPlanarFigurePredicate();
   auto isMaskPredicate = mitk::GetImageStatisticsMaskPredicate();
   auto isMaskOrPlanarFigurePredicate = mitk::NodePredicateOr::New(isPlanarFigurePredicate, isMaskPredicate);
 
   mitk::NodePredicateBase::Pointer result = isMaskOrPlanarFigurePredicate.GetPointer();
 
   if(!m_Controls.imageNodesSelector->GetSelectedNodes().empty())
   {
     auto image = m_Controls.imageNodesSelector->GetSelectedNodes().front()->GetData();
     auto imageGeoPredicate = mitk::NodePredicateSubGeometry::New(image->GetGeometry());
 
     auto lambda = [image, imageGeoPredicate](const mitk::DataNode* node)
     {
       bool sameGeometry = true;
 
       if (dynamic_cast<const mitk::Image*>(node->GetData()) != nullptr)
       {
         sameGeometry = imageGeoPredicate->CheckNode(node);
       }
       else
       {
         const auto planarFigure = dynamic_cast<const mitk::PlanarFigure*>(node->GetData());
         sameGeometry = CheckPlanarFigureMatchesGeometry(planarFigure, image->GetGeometry());
       }
 
       return sameGeometry;
     };
 
     result = mitk::NodePredicateAnd::New(isMaskOrPlanarFigurePredicate, mitk::NodePredicateFunction::New(lambda)).GetPointer();
   }
 
   return result;
 }
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 a55ac22c09..731dd23efb 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox
+++ b/Plugins/org.mitk.gui.qt.segmentation/documentation/UserManual/QmitkSegmentationUtilities.dox
@@ -1,84 +1,99 @@
 /**
 \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 <b>Segmentation Utilities View</b> allows to postprocess existing segmentations. Currently five different operations exist:
 
 <ul>
 	<li> \ref org_mitk_views_segmentationUtilitiesBooleanOperations
-	<li> \ref org_mitk_views_segmentationUtilitiesContourToImage
 	<li> \ref org_mitk_views_segmentationUtilitiesImageMasking
 	<li> \ref org_mitk_views_segmentationUtilitiesMorphologicalOperations
-	<li> \ref org_mitk_views_segmentationUtilitiesSurfaceToImage
+	<li> \ref org_mitk_views_segmentationUtilitiesConvertToSegmentation
+	<li> \ref org_mitk_views_segmentationUtilitiesExtractFromSegmentation
 </ul>
 
 \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:
 
 <ul>
 	<li> <b>Difference:</b> Subtracts the second segmentation from the first segmentation.
 	<li> <b>Intersection:</b> Extracts the overlapping areas of the two selected segmentations.
 	<li> <b>Union:</b> Combines the two existing segmentations.
 </ul>
 
 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 segmentation or a surface.
 The result will be an image containing only the pixels that are covered by the respective mask.
 
 The default background pixel value is zero.
 It can be changed to the minimum existing pixel value of the image or to a custom pixel value.
 If the custom pixel value is out of the valid bounds of the pixel type, it is optionally clamped accordingly.
 
 \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 modified.
 The plugin provides a <b>ball</b> and a <b>cross</b> as structuring elements. The follow operations are available:
 
 <ul>
 	<li> <b>Dilation:</b> Each labeled pixel within the segmentation will be dilated based on the selected structuring element.
 	<li> <b>Erosion:</b> Each labeled pixel within the segmentation will be eroded based on the selected structuring element.
 	<li> <b>Opening:</b> A dilation followed by an erosion, used for smoothing edges or eliminating small objects.
 	<li> <b>Closing:</b> An erosion followed by an dilation, used for filling small holes.
 	<li> <b>Fill Holes:</b> Fills bigger holes within a segmentation.
 </ul>
 
 \imageMacro{QmitkSegmentationUtilities_MorphologicalOperations.png,"Morphological operations",6.00}
 
-\section org_mitk_views_segmentationUtilitiesSurfaceToImage Surface to image
+\section org_mitk_views_segmentationUtilitiesConvertToSegmentation Convert to Segmentation
+
+Convert to segmentation allows to convert one or multiple input data into a multi-label segmentation. The supported input data types are surfaces, contour models and images. Surfaces and contour models will be converted into a new label (with the same color then the respective input data). Input images will be analyzed for their pixel content. Each pixel value (different to 0; which marks unlabeled pixels) will be associated with the new label.
+The conversion can have the following outputs:
+<ul>
+	<li> <b>Convert to new segmentation:</b> The inputs will be converted and integrated in a new segmentation. The geometry of the output segmentation is determined by the largest geometry of the input images. If no images are selected as input, one has to specify an image or segmentation as reference. If sub mode "Convert inputs separately" is selected, each input will be converted into its own multi-label segmentation output.
+	<li> <b>Add to existing segmentation:</b> The inputs will be converted and integrated as new group(s) in a selected segmentation.
+</ul>
 
-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).
+For the output the following grouping modes can be selected (if the output is not new separate segmentation):
+<ul>
+	<li> <b>Merge all inputs ...:</b> All inputs will be merged into a new group. Remark: If inputs overlap the inputs might overwrite each other.
+	<li> <b>New group per input:</b> Each input will be added as a new group to the multi-label segmentation.
+</ul>
 
-\imageMacro{QmitkSegmentationUtilities_SurfaceToImage.png,"Surface to image",6.00}
+<b>Remark on label values:</b> when converting inputs into a multi-labels segmentation the conversion process tries to keep the label value the same like the original value. In cases of surfaces or contour models it would be 1. In case of images it would be the respective pixel value. In cases of the label value collision (the label value is already used in the segmentation) a new value will be assigned to resolve the conflict. Therefore it is only guaranteed that values are kept, if you convert only one input into a new or empty segmentation.
+
+<b>Remark unsupported geometries:</b> if you select images as input, these images have to have either the same geometry or must be a sub geometry. If an reference is defined or you want to add them to an existing segmentation, the imports images also have to have the same geometry like the target or be a sub geometry of it. 
+
+
+\section org_mitk_views_segmentationUtilitiesExtractFromSegmentation Extract from Segmentation
+
+Extract from segmentation allows to extract the content of a multi-label segmentation (either all labeled or a selection of labels) in various ways and stores it as simple images in the data storage.
+
+The following output options are available (at least one must be selected):
+<ul>
+	<li> <b>label class map(s):</b> This generates an image where each pixel value (different from 0, which indicates unlabeled pixels) indicates a label class. Label class comprises all label instances that have the same label name. One can also see that has the semantic segmentation result. This mode will generate an output for each group indicated by the selected labels (or all groups).
+	<li> <b>Label instance map(s):</b> This generates an image where each pixel value (different from 0, which indicates unlabeled pixels) indicates a label instance. The used pixel values are equivalent to the label value of each instance. This mode will generate an output for each group indicated by the selected labels (or all groups).
+	<li> <b>Label instance mask(s):</b> This generates an image for one label instance where each pixel value (different from 0, which indicates unlabeled pixels) indicates the label instance. The used pixel value is equivalent to the label value of the label instance.
+</ul>
 
 **/
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp
index 4a96a422a7..64449df9fd 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.cpp
@@ -1,68 +1,68 @@
 /*============================================================================
 
 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 "QmitkSegmentationUtilitiesView.h"
 
 #include <QmitkBooleanOperationsWidget.h>
-#include <QmitkContourModelToImageWidget.h>
 #include <QmitkImageMaskingWidget.h>
 #include <QmitkMorphologicalOperationsWidget.h>
-#include <QmitkSurfaceToImageWidget.h>
+#include <QmitkConvertToMultiLabelSegmentationWidget.h>
+#include <QmitkExtractFromMultiLabelSegmentationWidget.h>
 
 QmitkSegmentationUtilitiesView::QmitkSegmentationUtilitiesView()
   : m_BooleanOperationsWidget(nullptr),
-    m_ContourModelToImageWidget(nullptr),
     m_ImageMaskingWidget(nullptr),
     m_MorphologicalOperationsWidget(nullptr),
-    m_SurfaceToImageWidget(nullptr)
+    m_ConvertToSegWidget(nullptr),
+    m_ExtractFromSegWidget(nullptr)
 {
 }
 
 QmitkSegmentationUtilitiesView::~QmitkSegmentationUtilitiesView()
 {
 }
 
 void QmitkSegmentationUtilitiesView::CreateQtPartControl(QWidget* parent)
 {
   m_Controls.setupUi(parent);
 
   auto dataStorage = this->GetDataStorage();
   m_BooleanOperationsWidget = new QmitkBooleanOperationsWidget(dataStorage, parent);
-  m_ContourModelToImageWidget = new QmitkContourModelToImageWidget(dataStorage, parent);
   m_ImageMaskingWidget = new QmitkImageMaskingWidget(dataStorage, parent);
   m_MorphologicalOperationsWidget = new QmitkMorphologicalOperationsWidget(dataStorage, parent);
-  m_SurfaceToImageWidget = new QmitkSurfaceToImageWidget(dataStorage, parent);
+  m_ConvertToSegWidget = new QmitkConvertToMultiLabelSegmentationWidget(dataStorage, parent);
+  m_ExtractFromSegWidget = new QmitkExtractFromMultiLabelSegmentationWidget(dataStorage, parent);
 
   this->AddUtilityWidget(m_BooleanOperationsWidget, QIcon(":/SegmentationUtilities/BooleanOperations_48x48.png"), "Boolean Operations");
-  this->AddUtilityWidget(m_ContourModelToImageWidget, QIcon(":/SegmentationUtilities/ContourModelSetToImage_48x48.png"), "Contour to Image");
   this->AddUtilityWidget(m_ImageMaskingWidget, QIcon(":/SegmentationUtilities/ImageMasking_48x48.png"), "Image Masking");
   this->AddUtilityWidget(m_MorphologicalOperationsWidget, QIcon(":/SegmentationUtilities/MorphologicalOperations_48x48.png"), "Morphological Operations");
-  this->AddUtilityWidget(m_SurfaceToImageWidget, QIcon(":/SegmentationUtilities/SurfaceToImage_48x48.png"), "Surface to Image");
+  this->AddUtilityWidget(m_ConvertToSegWidget, QIcon(":/SegmentationUtilities/SurfaceToImage_48x48.png"), "Convert to Segmentation");
+  this->AddUtilityWidget(m_ExtractFromSegWidget, QIcon(":/SegmentationUtilities/SurfaceToImage_48x48.png"), "Extract from Segmentation");
 }
 
 void QmitkSegmentationUtilitiesView::AddUtilityWidget(QWidget* widget, const QIcon& icon, const QString& text)
 {
   m_Controls.toolBox->addItem(widget, icon, text);
 }
 
 void QmitkSegmentationUtilitiesView::SetFocus()
 {
   m_Controls.toolBox->setFocus();
 }
 
 void QmitkSegmentationUtilitiesView::RenderWindowPartActivated(mitk::IRenderWindowPart*)
 {
 }
 
 void QmitkSegmentationUtilitiesView::RenderWindowPartDeactivated(mitk::IRenderWindowPart*)
 {
 }
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.h
index 05099face4..cbbc5d7504 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.h
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationUtilitiesView.h
@@ -1,51 +1,51 @@
 /*============================================================================
 
 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 QmitkSegmentationUtilitiesView_h
 #define QmitkSegmentationUtilitiesView_h
 
 #include <ui_QmitkSegmentationUtilitiesViewControls.h>
 #include <mitkIRenderWindowPartListener.h>
 #include <QmitkAbstractView.h>
 
 class QmitkBooleanOperationsWidget;
-class QmitkContourModelToImageWidget;
 class QmitkImageMaskingWidget;
 class QmitkMorphologicalOperationsWidget;
-class QmitkSurfaceToImageWidget;
+class QmitkConvertToMultiLabelSegmentationWidget;
+class QmitkExtractFromMultiLabelSegmentationWidget;
 
 class QmitkSegmentationUtilitiesView : public QmitkAbstractView, public mitk::IRenderWindowPartListener
 {
   Q_OBJECT
 
 public:
   QmitkSegmentationUtilitiesView();
   ~QmitkSegmentationUtilitiesView() override;
 
   void CreateQtPartControl(QWidget* parent) override;
   void SetFocus() override;
 
   void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) override;
   void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) override;
 
 private:
   void AddUtilityWidget(QWidget* widget, const QIcon& icon, const QString& text);
 
   Ui::QmitkSegmentationUtilitiesViewControls m_Controls;
   QmitkBooleanOperationsWidget* m_BooleanOperationsWidget;
-  QmitkContourModelToImageWidget* m_ContourModelToImageWidget;
   QmitkImageMaskingWidget* m_ImageMaskingWidget;
   QmitkMorphologicalOperationsWidget* m_MorphologicalOperationsWidget;
-  QmitkSurfaceToImageWidget* m_SurfaceToImageWidget;
+  QmitkConvertToMultiLabelSegmentationWidget* m_ConvertToSegWidget;
+  QmitkExtractFromMultiLabelSegmentationWidget* m_ExtractFromSegWidget;
 };
 
 #endif
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
index 190e081391..56dc7f4545 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.cpp
@@ -1,1107 +1,1087 @@
 /*============================================================================
 
 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 "QmitkSegmentationView.h"
 #include "mitkPluginActivator.h"
 
 // blueberry
 #include <berryIWorkbenchPage.h>
 
 // mitk
 #include <mitkApplicationCursor.h>
 #include <mitkBaseApplication.h>
 #include <mitkBaseRendererHelper.h>
 #include <mitkCameraController.h>
 #include <mitkLabelSetImage.h>
 #include <mitkLabelSetImageHelper.h>
 #include <mitkMultiLabelIOHelper.h>
 #include <mitkManualPlacementAnnotationRenderer.h>
 #include <mitkNodePredicateSubGeometry.h>
 #include <mitkSegmentationObjectFactory.h>
 #include <mitkSegTool2D.h>
 #include <mitkStatusBar.h>
 #include <mitkToolManagerProvider.h>
 #include <mitkVtkResliceInterpolationProperty.h>
 #include <mitkWorkbenchUtil.h>
 #include <mitkIPreferences.h>
+#include <mitkMultiLabelPredicateHelper.h>
 
 // Qmitk
 #include <QmitkRenderWindow.h>
 #include <QmitkStaticDynamicSegmentationDialog.h>
 #include <QmitkNewSegmentationDialog.h>
 #include <QmitkMultiLabelManager.h>
 
 // us
 #include <usModuleResource.h>
 #include <usModuleResourceStream.h>
 
 // Qt
 #include <QMessageBox>
 #include <QShortcut>
 #include <QDir>
 
 // vtk
 #include <vtkQImageToImageSource.h>
 
 #include <regex>
 
 namespace
 {
   QList<QmitkRenderWindow*> Get2DWindows(const QList<QmitkRenderWindow*> allWindows)
   {
     QList<QmitkRenderWindow*> all2DWindows;
     for (auto* window : allWindows)
     {
       if (window->GetRenderer()->GetMapperID() == mitk::BaseRenderer::Standard2D)
       {
         all2DWindows.append(window);
       }
     }
     return all2DWindows;
   }
 }
 
 const std::string QmitkSegmentationView::VIEW_ID = "org.mitk.views.segmentation";
 
 QmitkSegmentationView::QmitkSegmentationView()
   : m_Parent(nullptr)
   , m_Controls(nullptr)
   , m_RenderWindowPart(nullptr)
   , m_ToolManager(nullptr)
   , m_ReferenceNode(nullptr)
   , m_WorkingNode(nullptr)
   , m_DrawOutline(true)
   , m_SelectionMode(false)
   , m_MouseCursorSet(false)
   , m_DefaultLabelNaming(true)
   , m_SelectionChangeIsAlreadyBeingHandled(false)
 {
-  auto isImage = mitk::TNodePredicateDataType<mitk::Image>::New();
-  auto isDwi = mitk::NodePredicateDataType::New("DiffusionImage");
-  auto isDti = mitk::NodePredicateDataType::New("TensorImage");
-  auto isOdf = mitk::NodePredicateDataType::New("OdfImage");
-  auto isSegment = mitk::NodePredicateDataType::New("Segment");
-
-  auto validImages = mitk::NodePredicateOr::New();
-  validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegment)));
-  validImages->AddPredicate(isDwi);
-  validImages->AddPredicate(isDti);
-  validImages->AddPredicate(isOdf);
-
-  m_SegmentationPredicate = mitk::NodePredicateAnd::New();
-  m_SegmentationPredicate->AddPredicate(mitk::TNodePredicateDataType<mitk::LabelSetImage>::New());
-  m_SegmentationPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
-  m_SegmentationPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
-
-  m_ReferencePredicate = mitk::NodePredicateAnd::New();
-  m_ReferencePredicate->AddPredicate(validImages);
-  m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(m_SegmentationPredicate));
-  m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")));
-  m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("hidden object")));
+  m_SegmentationPredicate = mitk::GetMultiLabelSegmentationPredicate();
+
+  m_ReferencePredicate = mitk::GetSegmentationReferenceImagePredicate();
 }
 
 QmitkSegmentationView::~QmitkSegmentationView()
 {
   if (nullptr != m_Controls)
   {
     // deactivate all tools
     m_ToolManager->ActivateTool(-1);
 
     // removing all observers from working data
     for (NodeTagMapType::iterator dataIter = m_WorkingDataObserverTags.begin(); dataIter != m_WorkingDataObserverTags.end(); ++dataIter)
     {
       (*dataIter).first->GetProperty("visible")->RemoveObserver((*dataIter).second);
     }
     m_WorkingDataObserverTags.clear();
 
     this->RemoveObserversFromWorkingImage();
 
     // removing all observers from reference data
     for (NodeTagMapType::iterator dataIter = m_ReferenceDataObserverTags.begin(); dataIter != m_ReferenceDataObserverTags.end(); ++dataIter)
     {
       (*dataIter).first->GetProperty("visible")->RemoveObserver((*dataIter).second);
     }
     m_ReferenceDataObserverTags.clear();
 
     mitk::RenderingManager::GetInstance()->RemoveObserver(m_RenderingManagerObserverTag);
 
     ctkPluginContext* context = mitk::PluginActivator::getContext();
     ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
     mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
     service->RemoveAllPlanePositions();
     context->ungetService(ppmRef);
 
     m_ToolManager->SetReferenceData(nullptr);
     m_ToolManager->SetWorkingData(nullptr);
   }
 
   m_ToolManager->ActiveToolChanged -=
     mitk::MessageDelegate<Self>(this, &Self::ActiveToolChanged);
 
   delete m_Controls;
 }
 
 /**********************************************************************/
 /* private Q_SLOTS                                                    */
 /**********************************************************************/
 void QmitkSegmentationView::OnReferenceSelectionChanged(QList<mitk::DataNode::Pointer>)
 {
   this->OnAnySelectionChanged();
 }
 
 void QmitkSegmentationView::OnSegmentationSelectionChanged(QList<mitk::DataNode::Pointer>)
 {
   this->OnAnySelectionChanged();
 }
 
 void QmitkSegmentationView::OnAnySelectionChanged()
 {
   // When only a segmentation has been selected and the method is then called by a reference image selection,
   // the already selected segmentation may not match the geometry predicate of the new reference image anymore.
   // This will trigger a recursive call of this method further below. While it would be resolved gracefully, we
   // can spare the extra call with an early-out. The original call of this method will handle the segmentation
   // selection change afterwards anyway.
 
   if (m_SelectionChangeIsAlreadyBeingHandled)
     return;
 
   auto selectedReferenceNode = m_Controls->referenceNodeSelector->GetSelectedNode();
   bool referenceNodeChanged = false;
 
   m_ToolManager->ActivateTool(-1);
 
   if (m_ReferenceNode != selectedReferenceNode)
   {
     referenceNodeChanged = true;
 
     // Remove visibility observer for the current reference node
     if (m_ReferenceDataObserverTags.find(m_ReferenceNode) != m_ReferenceDataObserverTags.end())
     {
       m_ReferenceNode->GetProperty("visible")->RemoveObserver(m_ReferenceDataObserverTags[m_ReferenceNode]);
       m_ReferenceDataObserverTags.erase(m_ReferenceNode);
     }
 
     // Set new reference node
     m_ReferenceNode = selectedReferenceNode;
     m_ToolManager->SetReferenceData(m_ReferenceNode);
 
     // Prepare for a potential recursive call when changing node predicates of the working node selector
     m_SelectionChangeIsAlreadyBeingHandled = true;
 
     if (m_ReferenceNode.IsNull())
     {
       // Without a reference image, allow all segmentations to be selected
       m_Controls->workingNodeSelector->SetNodePredicate(m_SegmentationPredicate);
       m_SelectionChangeIsAlreadyBeingHandled = false;
     }
     else
     {
       // With a reference image, only allow segmentations that fit the geometry of the reference image to be selected.
-      m_Controls->workingNodeSelector->SetNodePredicate(mitk::NodePredicateAnd::New(
-        mitk::NodePredicateSubGeometry::New(m_ReferenceNode->GetData()->GetGeometry()),
-        m_SegmentationPredicate.GetPointer()));
+      m_Controls->workingNodeSelector->SetNodePredicate(mitk::GetMultiLabelSegmentationPredicate(m_ReferenceNode->GetData()->GetGeometry()));
 
       m_SelectionChangeIsAlreadyBeingHandled = false;
 
       this->ApplySelectionModeOnReferenceNode();
 
       // Add visibility observer for the new reference node
       auto command = itk::SimpleMemberCommand<Self>::New();
       command->SetCallbackFunction(this, &Self::ValidateSelectionInput);
 
       m_ReferenceDataObserverTags[m_ReferenceNode] =
         m_ReferenceNode->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command);
     }
   }
 
   auto selectedWorkingNode = m_Controls->workingNodeSelector->GetSelectedNode();
   bool workingNodeChanged = false;
 
   if (m_WorkingNode != selectedWorkingNode)
   {
     workingNodeChanged = true;
 
     this->RemoveObserversFromWorkingImage();
 
     // Remove visibility observer for the current working node
     if (m_WorkingDataObserverTags.find(m_WorkingNode) != m_WorkingDataObserverTags.end())
     {
       m_WorkingNode->GetProperty("visible")->RemoveObserver(m_WorkingDataObserverTags[m_WorkingNode]);
       m_WorkingDataObserverTags.erase(m_WorkingNode);
     }
 
     // Set new working node
     m_WorkingNode = selectedWorkingNode;
     m_ToolManager->SetWorkingData(m_WorkingNode);
 
     if (m_WorkingNode.IsNotNull())
     {
       this->ApplySelectionModeOnWorkingNode();
 
       // Add visibility observer for the new segmentation node
       auto command = itk::SimpleMemberCommand<Self>::New();
       command->SetCallbackFunction(this, &Self::ValidateSelectionInput);
 
       m_WorkingDataObserverTags[m_WorkingNode] =
         m_WorkingNode->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command);
 
       this->AddObserversToWorkingImage();
     }
   }
 
   // Reset camera if any selection changed but only if both reference node and working node are set
   if ((referenceNodeChanged || workingNodeChanged) && (m_ReferenceNode.IsNotNull() && m_WorkingNode.IsNotNull()))
   {
     if (nullptr != m_RenderWindowPart)
     {
       m_RenderWindowPart->InitializeViews(m_ReferenceNode->GetData()->GetTimeGeometry(), false);
     }
   }
 
   this->UpdateGUI();
 }
 
 void QmitkSegmentationView::OnLabelAdded(mitk::LabelSetImage::LabelValueType)
 {
   this->ValidateSelectionInput();
 }
 
 void QmitkSegmentationView::OnLabelRemoved(mitk::LabelSetImage::LabelValueType)
 {
   this->ValidateSelectionInput();
 }
 
 void QmitkSegmentationView::OnGroupRemoved(mitk::LabelSetImage::GroupIndexType)
 {
   this->ValidateSelectionInput();
 }
 
 mitk::LabelSetImage* QmitkSegmentationView::GetWorkingImage()
 {
   if (m_WorkingNode.IsNull())
     return nullptr;
 
   return dynamic_cast<mitk::LabelSetImage*>(m_WorkingNode->GetData());
 }
 
 void QmitkSegmentationView::AddObserversToWorkingImage()
 {
   auto* workingImage = this->GetWorkingImage();
 
   if (workingImage != nullptr)
   {
     auto& widget = *this;
     m_LabelAddedObserver.Reset(workingImage, mitk::LabelAddedEvent(), [&widget](const itk::EventObject& event)
       {
         auto labelEvent = dynamic_cast<const mitk::AnyLabelEvent*>(&event);
         widget.OnLabelAdded(labelEvent->GetLabelValue());
       });
     m_LabelRemovedObserver.Reset(workingImage, mitk::LabelRemovedEvent(), [&widget](const itk::EventObject& event)
       {
         auto labelEvent = dynamic_cast<const mitk::AnyLabelEvent*>(&event);
         widget.OnLabelRemoved(labelEvent->GetLabelValue());
       });
 
     m_GroupRemovedObserver.Reset(workingImage, mitk::GroupRemovedEvent(), [&widget](const itk::EventObject& event)
       {
         auto groupEvent = dynamic_cast<const mitk::AnyGroupEvent*>(&event);
         widget.OnGroupRemoved(groupEvent->GetGroupID());
       });
   }
 }
 
 void QmitkSegmentationView::RemoveObserversFromWorkingImage()
 {
   m_LabelAddedObserver.Reset();
   m_LabelRemovedObserver.Reset();
   m_GroupRemovedObserver.Reset();
 }
 
 void QmitkSegmentationView::OnVisibilityShortcutActivated()
 {
   if (m_WorkingNode.IsNull())
   {
     return;
   }
 
   bool isVisible = false;
   m_WorkingNode->GetBoolProperty("visible", isVisible);
   m_WorkingNode->SetVisibility(!isVisible);
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSegmentationView::OnLabelToggleShortcutActivated()
 {
   if (m_WorkingNode.IsNull())
   {
     return;
   }
 
   auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_WorkingNode->GetData());
   if (nullptr == workingImage)
   {
     return;
   }
 
   this->WaitCursorOn();
   auto labels = workingImage->GetLabelValuesByGroup(workingImage->GetActiveLayer());
   auto it = std::find(labels.begin(), labels.end(), workingImage->GetActiveLabel()->GetValue());
 
   if (it != labels.end())
     ++it;
 
   if (it == labels.end())
   {
     it = labels.begin();
   }
 
   workingImage->SetActiveLabel(*it);
   this->WaitCursorOff();
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSegmentationView::OnNewSegmentation()
 {
   m_ToolManager->ActivateTool(-1);
 
   if (m_ReferenceNode.IsNull())
   {
     MITK_ERROR << "'Create new segmentation' button should never be clickable unless a reference image is selected.";
     return;
   }
 
   mitk::Image::ConstPointer referenceImage = dynamic_cast<mitk::Image*>(m_ReferenceNode->GetData());
   if (referenceImage.IsNull())
   {
     QMessageBox::information(
       m_Parent, "New segmentation", "Please load and select an image before starting some action.");
     return;
   }
 
   if (referenceImage->GetDimension() <= 1)
   {
     QMessageBox::information(
       m_Parent, "New segmentation", "Segmentation is currently not supported for 2D images");
     return;
   }
 
   auto segTemplateImage = referenceImage;
   if (referenceImage->GetDimension() > 3)
   {
     QmitkStaticDynamicSegmentationDialog dialog(m_Parent);
     dialog.SetReferenceImage(referenceImage.GetPointer());
     dialog.exec();
     segTemplateImage = dialog.GetSegmentationTemplate();
   }
 
   mitk::DataNode::Pointer newSegmentationNode;
   try
   {
     this->WaitCursorOn();
     newSegmentationNode = mitk::LabelSetImageHelper::CreateNewSegmentationNode(m_ReferenceNode, segTemplateImage);
     this->WaitCursorOff();
   }
   catch (mitk::Exception& e)
   {
     this->WaitCursorOff();
     MITK_ERROR << "Exception caught: " << e.GetDescription();
     QMessageBox::warning(m_Parent, "New segmentation", "Could not create a new segmentation.");
     return;
   }
 
   auto newLabelSetImage = dynamic_cast<mitk::LabelSetImage*>(newSegmentationNode->GetData());
   if (nullptr == newLabelSetImage)
   {
     // something went wrong
     return;
   }
 
   const auto labelSetPreset = this->GetDefaultLabelSetPreset();
 
   if (labelSetPreset.empty() || !mitk::MultiLabelIOHelper::LoadLabelSetImagePreset(labelSetPreset, newLabelSetImage))
   {
     auto newLabel = mitk::LabelSetImageHelper::CreateNewLabel(newLabelSetImage);
 
     if (!m_DefaultLabelNaming)
       QmitkNewSegmentationDialog::DoRenameLabel(newLabel, nullptr, m_Parent);
 
     newLabelSetImage->AddLabel(newLabel, newLabelSetImage->GetActiveLayer());
   }
 
   if (!this->GetDataStorage()->Exists(newSegmentationNode))
   {
     this->GetDataStorage()->Add(newSegmentationNode, m_ReferenceNode);
   }
 
   if (m_ToolManager->GetWorkingData(0))
   {
     m_ToolManager->GetWorkingData(0)->SetSelected(false);
   }
 
   newSegmentationNode->SetSelected(true);
   m_Controls->workingNodeSelector->SetCurrentSelectedNode(newSegmentationNode);
 }
 
 std::string QmitkSegmentationView::GetDefaultLabelSetPreset() const
 {
   auto labelSetPreset = mitk::BaseApplication::instance().config().getString(mitk::BaseApplication::ARG_SEGMENTATION_LABELSET_PRESET.toStdString(), "");
 
   if (labelSetPreset.empty())
     labelSetPreset = m_LabelSetPresetPreference.toStdString();
 
   return labelSetPreset;
 }
 
 void QmitkSegmentationView::OnManualTool2DSelected(int id)
 {
   this->ResetMouseCursor();
   mitk::StatusBar::GetInstance()->DisplayText("");
 
   if (id >= 0)
   {
     std::string text = "Active Tool: \"";
     text += m_ToolManager->GetToolById(id)->GetName();
     text += "\"";
     mitk::StatusBar::GetInstance()->DisplayText(text.c_str());
 
     us::ModuleResource resource = m_ToolManager->GetToolById(id)->GetCursorIconResource();
     this->SetMouseCursor(resource, 0, 0);
   }
 }
 
 void QmitkSegmentationView::OnShowMarkerNodes(bool state)
 {
   mitk::SegTool2D::Pointer manualSegmentationTool;
 
   unsigned int numberOfExistingTools = m_ToolManager->GetTools().size();
 
   for (unsigned int i = 0; i < numberOfExistingTools; i++)
   {
     manualSegmentationTool = dynamic_cast<mitk::SegTool2D*>(m_ToolManager->GetToolById(i));
     if (nullptr == manualSegmentationTool)
     {
       continue;
     }
 
     manualSegmentationTool->SetShowMarkerNodes(state);
   }
 }
 
 void QmitkSegmentationView::OnCurrentLabelSelectionChanged(QmitkMultiLabelManager::LabelValueVectorType labels)
 {
   auto segmentation = this->GetCurrentSegmentation();
 
   const auto labelValue = labels.front();
   if (nullptr == segmentation->GetActiveLabel() || labelValue != segmentation->GetActiveLabel()->GetValue())
   {
     segmentation->SetActiveLabel(labelValue);
     mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   }
   m_Controls->slicesInterpolator->SetActiveLabelValue(labelValue);
 }
 
 void QmitkSegmentationView::OnGoToLabel(mitk::LabelSetImage::LabelValueType /*label*/, const mitk::Point3D& pos)
 {
   if (m_RenderWindowPart)
   {
     m_RenderWindowPart->SetSelectedPosition(pos);
   }
 }
 
 void QmitkSegmentationView::OnLabelRenameRequested(mitk::Label* label, bool rename) const
 {
   auto segmentation = this->GetCurrentSegmentation();
 
   if (rename)
   {
     QmitkNewSegmentationDialog::DoRenameLabel(label, segmentation, this->m_Parent, QmitkNewSegmentationDialog::Mode::RenameLabel);
     return;
   }
 
   QmitkNewSegmentationDialog::DoRenameLabel(label, nullptr, this->m_Parent, QmitkNewSegmentationDialog::Mode::NewLabel);
 }
 
 mitk::LabelSetImage* QmitkSegmentationView::GetCurrentSegmentation() const
 {
   auto workingNode = m_Controls->workingNodeSelector->GetSelectedNode();
   if (workingNode.IsNull()) mitkThrow() << "Segmentation view is in an invalid state. Working node is null, but a label selection change has been triggered.";
 
   auto segmentation = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
   if (nullptr == segmentation) mitkThrow() << "Segmentation view is in an invalid state. Working node contains no segmentation, but a label selection change has been triggered.";
 
   return segmentation;
 }
 
 /**********************************************************************/
 /* private                                                            */
 /**********************************************************************/
 void QmitkSegmentationView::CreateQtPartControl(QWidget* parent)
 {
    m_Parent = parent;
 
    m_Controls = new Ui::QmitkSegmentationViewControls;
    m_Controls->setupUi(parent);
 
    // *------------------------
    // * SHORTCUTS
    // *------------------------
    QShortcut* visibilityShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key::Key_H), parent);
    connect(visibilityShortcut, &QShortcut::activated, this, &Self::OnVisibilityShortcutActivated);
    QShortcut* labelToggleShortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key::Key_L, Qt::CTRL | Qt::Key::Key_I), parent);
    connect(labelToggleShortcut, &QShortcut::activated, this, &Self::OnLabelToggleShortcutActivated);
 
    // *------------------------
    // * DATA SELECTION WIDGETS
    // *------------------------
    m_Controls->referenceNodeSelector->SetDataStorage(GetDataStorage());
    m_Controls->referenceNodeSelector->SetNodePredicate(m_ReferencePredicate);
    m_Controls->referenceNodeSelector->SetInvalidInfo("Select an image");
    m_Controls->referenceNodeSelector->SetPopUpTitel("Select an image");
    m_Controls->referenceNodeSelector->SetPopUpHint("Select an image that should be used to define the geometry and bounds of the segmentation.");
 
    m_Controls->workingNodeSelector->SetDataStorage(GetDataStorage());
    m_Controls->workingNodeSelector->SetNodePredicate(m_SegmentationPredicate);
    m_Controls->workingNodeSelector->SetInvalidInfo("Select a segmentation");
    m_Controls->workingNodeSelector->SetPopUpTitel("Select a segmentation");
    m_Controls->workingNodeSelector->SetPopUpHint("Select a segmentation that should be modified. Only segmentation with the same geometry and within the bounds of the reference image are selected.");
 
    connect(m_Controls->referenceNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
            this, &Self::OnReferenceSelectionChanged);
    connect(m_Controls->workingNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged,
            this, &Self::OnSegmentationSelectionChanged);
 
    // *------------------------
    // * TOOLMANAGER
    // *------------------------
    m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager();
    m_ToolManager->SetDataStorage(*(this->GetDataStorage()));
    m_ToolManager->InitializeTools();
 
    QString segTools2D = tr("Add Subtract Lasso Fill Erase Close Paint Wipe 'Region Growing' 'Live Wire' 'Segment Anything'");
    QString segTools3D = tr("Threshold 'UL Threshold' Otsu 'Region Growing 3D' Picking GrowCut TotalSegmentator");
 
 #ifdef __linux__
    segTools3D.append(" nnUNet"); // plugin not enabled for MacOS / Windows
 #endif
    std::regex extSegTool2DRegEx("SegTool2D$");
    std::regex extSegTool3DRegEx("SegTool3D$");
 
    auto tools = m_ToolManager->GetTools();
    for (const auto &tool : tools)
    {
      if (std::regex_search(tool->GetNameOfClass(), extSegTool2DRegEx))
      {
        segTools2D.append(QString(" '%1'").arg(tool->GetName()));
      }
      else if (std::regex_search(tool->GetNameOfClass(), extSegTool3DRegEx))
      {
        segTools3D.append(QString(" '%1'").arg(tool->GetName()));
      }
    }
 
    // setup 2D tools
    m_Controls->toolSelectionBox2D->SetToolManager(*m_ToolManager);
    m_Controls->toolSelectionBox2D->SetGenerateAccelerators(true);
    m_Controls->toolSelectionBox2D->SetToolGUIArea(m_Controls->toolGUIArea2D);
    m_Controls->toolSelectionBox2D->SetDisplayedToolGroups(segTools2D.toStdString());
    connect(m_Controls->toolSelectionBox2D, &QmitkToolSelectionBox::ToolSelected,
            this, &Self::OnManualTool2DSelected);
 
    // setup 3D Tools
    m_Controls->toolSelectionBox3D->SetToolManager(*m_ToolManager);
    m_Controls->toolSelectionBox3D->SetGenerateAccelerators(true);
    m_Controls->toolSelectionBox3D->SetToolGUIArea(m_Controls->toolGUIArea3D);
    m_Controls->toolSelectionBox3D->SetDisplayedToolGroups(segTools3D.toStdString());
 
    m_Controls->slicesInterpolator->SetDataStorage(this->GetDataStorage());
 
    // create general signal / slot connections
    connect(m_Controls->newSegmentationButton, &QToolButton::clicked, this, &Self::OnNewSegmentation);
 
    connect(m_Controls->slicesInterpolator, &QmitkSlicesInterpolator::SignalShowMarkerNodes, this, &Self::OnShowMarkerNodes);
 
    connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::CurrentSelectionChanged, this, &Self::OnCurrentLabelSelectionChanged);
    connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::GoToLabel, this, &Self::OnGoToLabel);
    connect(m_Controls->multiLabelWidget, &QmitkMultiLabelManager::LabelRenameRequested, this, &Self::OnLabelRenameRequested);
 
    auto command = itk::SimpleMemberCommand<Self>::New();
    command->SetCallbackFunction(this, &Self::ValidateSelectionInput);
    m_RenderingManagerObserverTag =
      mitk::RenderingManager::GetInstance()->AddObserver(mitk::RenderingManagerViewsInitializedEvent(), command);
 
    m_RenderWindowPart = this->GetRenderWindowPart();
    if (nullptr != m_RenderWindowPart)
    {
      this->RenderWindowPartActivated(m_RenderWindowPart);
    }
 
    // Make sure the GUI notices if appropriate data is already present on creation.
    // Should be done last, if everything else is configured because it triggers the autoselection of data.
    m_Controls->referenceNodeSelector->SetAutoSelectNewNodes(true);
    m_Controls->workingNodeSelector->SetAutoSelectNewNodes(true);
 
    this->UpdateGUI();
 }
 
 void QmitkSegmentationView::ActiveToolChanged()
 {
   if (nullptr == m_RenderWindowPart)
   {
     return;
   }
 
   mitk::TimeGeometry* interactionReferenceGeometry = nullptr;
   auto activeTool = m_ToolManager->GetActiveTool();
   if (nullptr != activeTool && m_ReferenceNode.IsNotNull())
   {
     mitk::Image::ConstPointer referenceImage = dynamic_cast<mitk::Image *>(m_ReferenceNode->GetData());
     if (referenceImage.IsNotNull())
     {
       // tool activated, reference image available: set reference geometry
       interactionReferenceGeometry = m_ReferenceNode->GetData()->GetTimeGeometry();
     }
   }
 
   // set the interaction reference geometry for the render window part (might be nullptr)
   m_RenderWindowPart->SetInteractionReferenceGeometry(interactionReferenceGeometry);
 }
 
 void QmitkSegmentationView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)
 {
   if (m_RenderWindowPart != renderWindowPart)
   {
     m_RenderWindowPart = renderWindowPart;
   }
 
   if (nullptr != m_Parent)
   {
     m_Parent->setEnabled(true);
   }
 
   if (nullptr == m_Controls)
   {
     return;
   }
 
   if (nullptr != m_RenderWindowPart)
   {
     auto all2DWindows = Get2DWindows(m_RenderWindowPart->GetQmitkRenderWindows().values());
     m_Controls->slicesInterpolator->Initialize(m_ToolManager, all2DWindows);
 
     if (!m_RenderWindowPart->HasCoupledRenderWindows())
     {
       // react if the active tool changed, only if a render window part with decoupled render windows is used
       m_ToolManager->ActiveToolChanged +=
         mitk::MessageDelegate<Self>(this, &Self::ActiveToolChanged);
     }
   }
 }
 
 void QmitkSegmentationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/)
 {
   m_RenderWindowPart = nullptr;
   if (nullptr != m_Parent)
   {
     m_Parent->setEnabled(false);
   }
 
   // remove message-connection to make sure no message is processed if no render window part is available
   m_ToolManager->ActiveToolChanged -=
     mitk::MessageDelegate<Self>(this, &Self::ActiveToolChanged);
 
   m_Controls->slicesInterpolator->Uninitialize();
 }
 
 void QmitkSegmentationView::RenderWindowPartInputChanged(mitk::IRenderWindowPart* /*renderWindowPart*/)
 {
   if (nullptr == m_RenderWindowPart)
   {
     return;
   }
 
   m_Controls->slicesInterpolator->Uninitialize();
   auto all2DWindows = Get2DWindows(m_RenderWindowPart->GetQmitkRenderWindows().values());
   m_Controls->slicesInterpolator->Initialize(m_ToolManager, all2DWindows);
 }
 
 void QmitkSegmentationView::OnPreferencesChanged(const mitk::IPreferences* prefs)
 {
   auto labelSuggestions = mitk::BaseApplication::instance().config().getString(mitk::BaseApplication::ARG_SEGMENTATION_LABEL_SUGGESTIONS.toStdString(), "");
 
   m_DefaultLabelNaming = labelSuggestions.empty()
     ? prefs->GetBool("default label naming", true)
     : false; // No default label naming when label suggestions are enforced via command-line argument
 
   if (nullptr != m_Controls)
   {
     m_Controls->multiLabelWidget->SetDefaultLabelNaming(m_DefaultLabelNaming);
 
     bool compactView = prefs->GetBool("compact view", false);
     int numberOfColumns = compactView ? 6 : 4;
 
     m_Controls->toolSelectionBox2D->SetLayoutColumns(numberOfColumns);
     m_Controls->toolSelectionBox2D->SetShowNames(!compactView);
 
     m_Controls->toolSelectionBox3D->SetLayoutColumns(numberOfColumns);
     m_Controls->toolSelectionBox3D->SetShowNames(!compactView);
   }
 
   m_DrawOutline = prefs->GetBool("draw outline", true);
   m_SelectionMode = prefs->GetBool("selection mode", false);
 
   m_LabelSetPresetPreference = QString::fromStdString(prefs->Get("label set preset", ""));
 
   this->ApplyDisplayOptions();
   this->ApplySelectionMode();
 }
 
 void QmitkSegmentationView::NodeAdded(const mitk::DataNode* node)
 {
   if (m_SegmentationPredicate->CheckNode(node))
     this->ApplyDisplayOptions(const_cast<mitk::DataNode*>(node));
 
   this->ApplySelectionMode();
 }
 
 void QmitkSegmentationView::NodeRemoved(const mitk::DataNode* node)
 {
   if (!m_SegmentationPredicate->CheckNode(node))
   {
     return;
   }
 
   // remove all possible contour markers of the segmentation
   mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = this->GetDataStorage()->GetDerivations(
     node, mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true)));
 
   ctkPluginContext* context = mitk::PluginActivator::getContext();
   ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
   mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
 
   for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it)
   {
     std::string nodeName = node->GetName();
     unsigned int t = nodeName.find_last_of(" ");
     unsigned int id = atof(nodeName.substr(t + 1).c_str()) - 1;
 
     service->RemovePlanePosition(id);
 
     this->GetDataStorage()->Remove(it->Value());
   }
 
   context->ungetService(ppmRef);
   service = nullptr;
 
   auto image = dynamic_cast<mitk::LabelSetImage*>(node->GetData());
   mitk::SurfaceInterpolationController::GetInstance()->RemoveInterpolationSession(image);
 }
 
 void QmitkSegmentationView::ApplyDisplayOptions()
 {
   if (nullptr == m_Parent)
   {
     return;
   }
 
   if (nullptr == m_Controls)
   {
     return; // might happen on initialization (preferences loaded)
   }
 
   mitk::DataStorage::SetOfObjects::ConstPointer allImages = this->GetDataStorage()->GetSubset(m_SegmentationPredicate);
   for (mitk::DataStorage::SetOfObjects::const_iterator iter = allImages->begin(); iter != allImages->end(); ++iter)
   {
     this->ApplyDisplayOptions(*iter);
   }
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSegmentationView::ApplyDisplayOptions(mitk::DataNode* node)
 {
   if (nullptr == node)
   {
     return;
   }
 
   auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(node->GetData());
   if (nullptr == labelSetImage)
   {
     return;
   }
 
   // the outline property can be set in the segmentation preference page
   node->SetProperty("labelset.contour.active", mitk::BoolProperty::New(m_DrawOutline));
 
   // force render window update to show outline
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSegmentationView::ApplySelectionMode()
 {
   if (!m_SelectionMode)
     return;
 
   this->ApplySelectionModeOnReferenceNode();
   this->ApplySelectionModeOnWorkingNode();
 }
 
 void QmitkSegmentationView::ApplySelectionModeOnReferenceNode()
 {
   this->ApplySelectionMode(m_ReferenceNode, m_ReferencePredicate);
 }
 
 void QmitkSegmentationView::ApplySelectionModeOnWorkingNode()
 {
   this->ApplySelectionMode(m_WorkingNode, m_SegmentationPredicate);
 }
 
 void QmitkSegmentationView::ApplySelectionMode(mitk::DataNode* node, mitk::NodePredicateBase* predicate)
 {
   if (!m_SelectionMode || node == nullptr || predicate == nullptr)
     return;
 
   auto nodes = this->GetDataStorage()->GetSubset(predicate);
 
   for (auto iter = nodes->begin(); iter != nodes->end(); ++iter)
     (*iter)->SetVisibility(*iter == node);
 }
 
 void QmitkSegmentationView::OnContourMarkerSelected(const mitk::DataNode* node)
 {
   QmitkRenderWindow* selectedRenderWindow = nullptr;
   auto* renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN);
   auto* axialRenderWindow = renderWindowPart->GetQmitkRenderWindow("axial");
   auto* sagittalRenderWindow = renderWindowPart->GetQmitkRenderWindow("sagittal");
   auto* coronalRenderWindow = renderWindowPart->GetQmitkRenderWindow("coronal");
   auto* threeDRenderWindow = renderWindowPart->GetQmitkRenderWindow("3d");
   bool PlanarFigureInitializedWindow = false;
 
   // find initialized renderwindow
   if (node->GetBoolProperty("PlanarFigureInitializedWindow",
     PlanarFigureInitializedWindow, axialRenderWindow->GetRenderer()))
   {
     selectedRenderWindow = axialRenderWindow;
   }
   if (!selectedRenderWindow && node->GetBoolProperty(
     "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
     sagittalRenderWindow->GetRenderer()))
   {
     selectedRenderWindow = sagittalRenderWindow;
   }
   if (!selectedRenderWindow && node->GetBoolProperty(
     "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
     coronalRenderWindow->GetRenderer()))
   {
     selectedRenderWindow = coronalRenderWindow;
   }
   if (!selectedRenderWindow && node->GetBoolProperty(
     "PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
     threeDRenderWindow->GetRenderer()))
   {
     selectedRenderWindow = threeDRenderWindow;
   }
 
   // make node visible
   if (nullptr != selectedRenderWindow)
   {
     std::string nodeName = node->GetName();
     unsigned int t = nodeName.find_last_of(" ");
     unsigned int id = atof(nodeName.substr(t + 1).c_str()) - 1;
 
     ctkPluginContext* context = mitk::PluginActivator::getContext();
     ctkServiceReference ppmRef = context->getServiceReference<mitk::PlanePositionManagerService>();
     mitk::PlanePositionManagerService* service = context->getService<mitk::PlanePositionManagerService>(ppmRef);
     selectedRenderWindow->GetSliceNavigationController()->ExecuteOperation(service->GetPlanePosition(id));
     context->ungetService(ppmRef);
 
     selectedRenderWindow->GetRenderer()->GetCameraController()->Fit();
     mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   }
 }
 
 void QmitkSegmentationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
 {
   if (0 == nodes.size())
   {
     return;
   }
 
   std::string markerName = "Position";
   unsigned int numberOfNodes = nodes.size();
   std::string nodeName = nodes.at(0)->GetName();
   if ((numberOfNodes == 1) && (nodeName.find(markerName) == 0))
   {
     this->OnContourMarkerSelected(nodes.at(0));
     return;
   }
 }
 
 void QmitkSegmentationView::ResetMouseCursor()
 {
   if (m_MouseCursorSet)
   {
     mitk::ApplicationCursor::GetInstance()->PopCursor();
     m_MouseCursorSet = false;
   }
 }
 
 void QmitkSegmentationView::SetMouseCursor(const us::ModuleResource& resource, int hotspotX, int hotspotY)
 {
   // Remove previously set mouse cursor
   if (m_MouseCursorSet)
   {
     this->ResetMouseCursor();
   }
 
   if (resource)
   {
     us::ModuleResourceStream cursor(resource, std::ios::binary);
     mitk::ApplicationCursor::GetInstance()->PushCursor(cursor, hotspotX, hotspotY);
     m_MouseCursorSet = true;
   }
 }
 
 void QmitkSegmentationView::UpdateGUI()
 {
   mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0);
   bool hasReferenceNode = referenceNode != nullptr;
 
   mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0);
   bool hasWorkingNode = workingNode != nullptr;
 
   m_Controls->newSegmentationButton->setEnabled(false);
 
   if (hasReferenceNode)
   {
     m_Controls->newSegmentationButton->setEnabled(true);
   }
 
   if (hasWorkingNode && hasReferenceNode)
   {
     int layer = -1;
     referenceNode->GetIntProperty("layer", layer);
     workingNode->SetIntProperty("layer", layer + 1);
   }
 
   this->ValidateSelectionInput();
 }
 
 void QmitkSegmentationView::ValidateSelectionInput()
 {
   auto referenceNode = m_Controls->referenceNodeSelector->GetSelectedNode();
   auto workingNode = m_Controls->workingNodeSelector->GetSelectedNode();
 
   bool hasReferenceNode = referenceNode.IsNotNull();
   bool hasWorkingNode = workingNode.IsNotNull();
   bool hasBothNodes = hasReferenceNode && hasWorkingNode;
 
   QString warning;
   bool toolSelectionBoxesEnabled = hasReferenceNode && hasWorkingNode;
   unsigned int numberOfLabels = 0;
 
   m_Controls->multiLabelWidget->setEnabled(hasWorkingNode);
 
   m_Controls->toolSelectionBox2D->setEnabled(hasBothNodes);
   m_Controls->toolSelectionBox3D->setEnabled(hasBothNodes);
 
   m_Controls->slicesInterpolator->setEnabled(false);
   m_Controls->interpolatorWarningLabel->hide();
 
   if (hasReferenceNode)
   {
     if (nullptr != m_RenderWindowPart && m_RenderWindowPart->HasCoupledRenderWindows() && !referenceNode->IsVisible(nullptr))
     {
       warning += tr("The selected reference image is currently not visible!");
       toolSelectionBoxesEnabled = false;
     }
   }
 
   if (hasWorkingNode)
   {
     if (nullptr != m_RenderWindowPart && m_RenderWindowPart->HasCoupledRenderWindows() && !workingNode->IsVisible(nullptr))
     {
       warning += (!warning.isEmpty() ? "<br>" : "") + tr("The selected segmentation is currently not visible!");
       toolSelectionBoxesEnabled = false;
     }
 
     m_ToolManager->SetReferenceData(referenceNode);
     m_ToolManager->SetWorkingData(workingNode);
     m_Controls->multiLabelWidget->setEnabled(true);
     m_Controls->toolSelectionBox2D->setEnabled(true);
     m_Controls->toolSelectionBox3D->setEnabled(true);
 
     auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
     numberOfLabels = labelSetImage->GetTotalNumberOfLabels();
 
     if (numberOfLabels > 0)
       m_Controls->slicesInterpolator->setEnabled(true);
 
     m_Controls->multiLabelWidget->SetMultiLabelNode(workingNode);
 
     if (!m_Controls->multiLabelWidget->GetSelectedLabels().empty())
     {
       m_Controls->slicesInterpolator->SetActiveLabelValue(m_Controls->multiLabelWidget->GetSelectedLabels().front());
     }
   }
   else
   {
     m_Controls->multiLabelWidget->SetMultiLabelNode(nullptr);
   }
 
   toolSelectionBoxesEnabled &= numberOfLabels > 0;
 
   // Here we need to check whether the geometry of the selected segmentation image (working image geometry)
   // is aligned with the geometry of the 3D render window.
   // It is not allowed to use a geometry different from the working image geometry for segmenting.
   // We only need to this if the tool selection box would be enabled without this check.
   // Additionally this check only has to be performed for render window parts with coupled render windows.
   // For different render window parts the user is given the option to reinitialize each render window individually
   // (see QmitkRenderWindow::ShowOverlayMessage).
   if (toolSelectionBoxesEnabled && nullptr != m_RenderWindowPart && m_RenderWindowPart->HasCoupledRenderWindows())
   {
     const mitk::BaseGeometry* workingNodeGeometry = workingNode->GetData()->GetGeometry();
     const mitk::BaseGeometry* renderWindowGeometry =
       m_RenderWindowPart->GetQmitkRenderWindow("3d")->GetSliceNavigationController()->GetCurrentGeometry3D();
     if (nullptr != workingNodeGeometry && nullptr != renderWindowGeometry)
     {
       if (!mitk::Equal(*workingNodeGeometry->GetBoundingBox(), *renderWindowGeometry->GetBoundingBox(), mitk::eps, true))
       {
         warning += (!warning.isEmpty() ? "<br>" : "") + tr("Please reinitialize the selected segmentation image!");
         toolSelectionBoxesEnabled = false;
       }
     }
   }
 
   m_Controls->toolSelectionBox2D->setEnabled(toolSelectionBoxesEnabled);
   m_Controls->toolSelectionBox3D->setEnabled(toolSelectionBoxesEnabled);
 
   this->UpdateWarningLabel(warning);
 
   m_ToolManager->SetReferenceData(referenceNode);
   m_ToolManager->SetWorkingData(workingNode);
 }
 
 void QmitkSegmentationView::UpdateWarningLabel(QString text)
 {
   if (text.isEmpty())
   {
     m_Controls->selectionWarningLabel->hide();
   }
   else
   {
     m_Controls->selectionWarningLabel->setText("<font color=\"red\">" + text + "</font>");
     m_Controls->selectionWarningLabel->show();
   }
 }
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h
index 3f0596941c..1144bf3f21 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkSegmentationView.h
@@ -1,180 +1,180 @@
 /*============================================================================
 
 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 QmitkSegmentationView_h
 #define QmitkSegmentationView_h
 
 #include "ui_QmitkSegmentationViewControls.h"
 
 #include <QmitkAbstractView.h>
 #include <mitkITKEventObserverGuard.h>
 #include <mitkIRenderWindowPartListener.h>
 
 /**
 * @brief The segmentation view provides a set of tool to use different segmentation algorithms.
 *        It provides two selection widgets to load an image node and a segmentation node
 *        on which to perform the segmentation. Creating new segmentation nodes is also possible.
 *        The available segmentation tools are grouped into "2D"- and "3D"-tools.
 *
 *        Most segmentation tools / algorithms need some kind of user interaction, where the
 *        user is asked to draw something in the image display or set some seed points / start values.
 *        The tools also often provide additional properties so that a user can modify the
 *        algorithm's behavior.
 *
 *        This class additionally provides options to work with different layers (create new layers,
 *        switch between layers).
 *        Moreover, a multilabel widget displays all the existing labels of a multilabel segmentation
 *        for the currently active layer.
 *        The multilabel widget allows to control the labels by creating new ones, removing existing ones,
 *        showing / hiding single labels, merging labels, (re-)naming them etc.
 *
 *        Additionally the view provides an option to create "2D"- and "3D"-interpolations between
 *        neighboring segmentation masks on unsegmented slices.
 *        Interpolation for multilabel segmentations is currently not implemented.
 */
 class QmitkSegmentationView : public QmitkAbstractView, public mitk::IRenderWindowPartListener
 {
   Q_OBJECT
 
 public:
 
   static const std::string VIEW_ID;
 
   QmitkSegmentationView();
   ~QmitkSegmentationView() override;
 
 private Q_SLOTS:
 
   // reaction to the selection of a new reference image in the selection widget
   void OnReferenceSelectionChanged(QList<mitk::DataNode::Pointer> nodes);
 
   // reaction to the selection of a new segmentation image in the selection widget
   void OnSegmentationSelectionChanged(QList<mitk::DataNode::Pointer> nodes);
 
   // reaction to the shortcut ("CTRL+H") for toggling the visibility of the working node
   void OnVisibilityShortcutActivated();
 
   // reaction to the shortcut ("CTRL+L") for iterating over all labels
   void OnLabelToggleShortcutActivated();
 
   // reaction to the button "New segmentation"
   void OnNewSegmentation();
 
   void OnManualTool2DSelected(int id);
 
   void OnShowMarkerNodes(bool);
 
   void OnCurrentLabelSelectionChanged(QmitkMultiLabelManager::LabelValueVectorType labels);
 
   void OnGoToLabel(mitk::LabelSetImage::LabelValueType label, const mitk::Point3D&);
   void OnLabelRenameRequested(mitk::Label* label, bool rename) const;
 
   void OnLabelAdded(mitk::LabelSetImage::LabelValueType labelValue);
   void OnLabelRemoved(mitk::LabelSetImage::LabelValueType labelValue);
   void OnGroupRemoved(mitk::LabelSetImage::GroupIndexType groupIndex);
 
 private:
 
   using Self = QmitkSegmentationView;
 
   mitk::LabelSetImage* GetWorkingImage();
   void AddObserversToWorkingImage();
   void RemoveObserversFromWorkingImage();
 
   void CreateQtPartControl(QWidget* parent) override;
 
   void SetFocus() override {}
   /**
   * @brief Enable or disable the SegmentationInteractor.
   *
   * The active tool is retrieved from the tool manager.
   * If the active tool is valid, the SegmentationInteractor is enabled
   * to listen to 'SegmentationInteractionEvent's.
   */
   void ActiveToolChanged();
 
   void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) override;
   void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) override;
   void RenderWindowPartInputChanged(mitk::IRenderWindowPart* renderWindowPart) override;
 
   void OnPreferencesChanged(const mitk::IPreferences* prefs) override;
 
   void NodeAdded(const mitk::DataNode* node) override;
 
   void NodeRemoved(const mitk::DataNode* node) override;
 
   void OnAnySelectionChanged();
 
   // make sure all images / segmentations look according to the user preference settings
   void ApplyDisplayOptions();
 
   // decorates a DataNode according to the user preference settings
   void ApplyDisplayOptions(mitk::DataNode* node);
 
   void ApplySelectionMode();
   void ApplySelectionModeOnReferenceNode();
   void ApplySelectionModeOnWorkingNode();
   void ApplySelectionMode(mitk::DataNode* node, mitk::NodePredicateBase* predicate);
 
   // If a contourmarker is selected, the plane in the related widget will be reoriented according to the marker`s geometry
   void OnContourMarkerSelected(const mitk::DataNode* node);
 
   void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer> &nodes) override;
 
   void ResetMouseCursor();
 
   void SetMouseCursor(const us::ModuleResource&, int hotspotX, int hotspotY);
 
   void UpdateGUI();
 
   void ValidateSelectionInput();
 
   void UpdateWarningLabel(QString text);
 
   std::string GetDefaultLabelSetPreset() const;
 
   mitk::LabelSetImage* GetCurrentSegmentation() const;
 
   QWidget* m_Parent;
 
   Ui::QmitkSegmentationViewControls* m_Controls;
 
   mitk::IRenderWindowPart* m_RenderWindowPart;
 
   mitk::ToolManager* m_ToolManager;
 
   mitk::DataNode::Pointer m_ReferenceNode;
   mitk::DataNode::Pointer m_WorkingNode;
 
   typedef std::map<mitk::DataNode*, unsigned long> NodeTagMapType;
   NodeTagMapType m_WorkingDataObserverTags;
   NodeTagMapType m_ReferenceDataObserverTags;
   unsigned int m_RenderingManagerObserverTag;
 
-  mitk::NodePredicateAnd::Pointer m_ReferencePredicate;
-  mitk::NodePredicateAnd::Pointer m_SegmentationPredicate;
+  mitk::NodePredicateBase::Pointer m_ReferencePredicate;
+  mitk::NodePredicateBase::Pointer m_SegmentationPredicate;
 
   bool m_DrawOutline;
   bool m_SelectionMode;
   bool m_MouseCursorSet;
 
   QString m_LabelSetPresetPreference;
   bool m_DefaultLabelNaming;
 
   bool m_SelectionChangeIsAlreadyBeingHandled;
 
   mitk::ITKEventObserverGuard m_LabelAddedObserver;
   mitk::ITKEventObserverGuard m_LabelRemovedObserver;
   mitk::ITKEventObserverGuard m_GroupRemovedObserver;
 };
 
 #endif