diff --git a/Modules/Segmentation/SegmentationUtilities/BooleanOperations/mitkBooleanOperation.cpp b/Modules/Segmentation/SegmentationUtilities/BooleanOperations/mitkBooleanOperation.cpp
index 2808f95126..f85d05554e 100644
--- a/Modules/Segmentation/SegmentationUtilities/BooleanOperations/mitkBooleanOperation.cpp
+++ b/Modules/Segmentation/SegmentationUtilities/BooleanOperations/mitkBooleanOperation.cpp
@@ -1,185 +1,182 @@
 /*============================================================================
 
 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 "mitkBooleanOperation.h"
-#include <itkAndImageFilter.h>
-#include <itkNotImageFilter.h>
-#include <itkOrImageFilter.h>
+#include <itkNaryFunctorImageFilter.h>
 #include <mitkExceptionMacro.h>
 #include <mitkImageCast.h>
 #include <mitkImageTimeSelector.h>
+#include <mitkITKEventObserverGuard.h>
 
-typedef itk::Image<mitk::Label::PixelType, 3> ImageType;
+using ITKGroupImageType = itk::Image<mitk::Label::PixelType, 3>;
+using BoolOpsFunctionType = mitk::Label::PixelType(const std::vector<mitk::Label::PixelType>& inputArray);
 
-static mitk::Image::Pointer Get3DSegmentation(mitk::Image::Pointer segmentation, mitk::TimePointType time)
+/** 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 TPixelType>
+class BoolOpsFunctor
 {
-  if (segmentation->GetDimension() != 4)
-    return segmentation;
 
-  auto imageTimeSelector = mitk::ImageTimeSelector::New();
-  imageTimeSelector->SetInput(segmentation);
-  imageTimeSelector->SetTimeNr(segmentation->GetTimeGeometry()->TimePointToTimeStep(time));
+public:
+  BoolOpsFunctor() {};
 
-  imageTimeSelector->UpdateLargestPossibleRegion();
-
-  return imageTimeSelector->GetOutput();
-}
-
-static ImageType::Pointer CastTo3DItkImage(mitk::Image::Pointer segmentation, mitk::TimePointType time)
-{
-  ImageType::Pointer result;
-  mitk::CastToItkImage(Get3DSegmentation(segmentation, time), result);
-  return result;
-}
-
-mitk::BooleanOperation::BooleanOperation(Type type,
-                                         mitk::Image::Pointer segmentationA,
-                                         mitk::Image::Pointer segmentationB,
-                                         TimePointType time)
-  : m_Type(type), m_SegmentationA(segmentationA), m_SegmentationB(segmentationB), m_TimePoint(time)
-{
-  this->ValidateSegmentations();
-}
+  BoolOpsFunctor(std::function<BoolOpsFunctionType> opsFunction) : m_Function(opsFunction)
+  {
+  };
 
-mitk::BooleanOperation::~BooleanOperation()
-{
-}
+  ~BoolOpsFunctor() {};
 
-mitk::LabelSetImage::Pointer mitk::BooleanOperation::GetResult() const
-{
-  switch (m_Type)
+  bool operator!=(const BoolOpsFunctor& other)const
   {
-    case Difference:
-      return this->GetDifference();
+    return !(*this == other);
+  }
 
-    case Intersection:
-      return this->GetIntersection();
+  bool operator==(const BoolOpsFunctor& other) const
+  {
+    if ((this->m_Function.target_type() == other.m_Function.target_type())
+      && (this->m_Function.target<int(*)(int)>() && other.m_Function.target<int(*)(int)>())
+      // If both std::function objects hold function pointers of the same signature,
+      // we can compare the pointers to check if they point to the same function.
+      && (*this->m_Function.target<int(*)(int)>() == *other.m_Function.target<int(*)(int)>()))
+    {
+      return true;
+    }
+    return false;
+  }
 
-    case Union:
-      return this->GetUnion();
+  BoolOpsFunctor& operator=(const BoolOpsFunctor& other)
+  {
+    this->m_Function = other.m_Function;
 
-    default:
-      mitkThrow() << "Unknown boolean operation type '" << m_Type << "'!";
+    return *this;
   }
-}
 
-mitk::LabelSetImage::Pointer mitk::BooleanOperation::GetDifference() const
-{
-  auto input1 = CastTo3DItkImage(m_SegmentationA, m_TimePoint);
-  auto input2 = CastTo3DItkImage(m_SegmentationB, m_TimePoint);
-
-  auto notFilter = itk::NotImageFilter<ImageType, ImageType>::New();
-  notFilter->SetInput(input2);
+  inline TPixelType operator()(const std::vector<TPixelType>& inputArray)
+  {
+    return m_Function(inputArray);
+  }
 
-  auto andFilter = itk::AndImageFilter<ImageType, ImageType>::New();
-  andFilter->SetInput1(input1);
-  andFilter->SetInput2(notFilter->GetOutput());
+private:
+  std::function<BoolOpsFunctionType> m_Function;
+};
 
-  andFilter->UpdateLargestPossibleRegion();
 
-  auto tempResult = Image::New();
-  CastToMitkImage<ImageType>(andFilter->GetOutput(), tempResult);
+mitk::Image::Pointer GenerateInternal(const mitk::LabelSetImage* segmentation, mitk::LabelSetImage::LabelValueVectorType labeValues, std::function<BoolOpsFunctionType> opsFunction,
+  std::function<void(float progress)> progressCallback = [](float) {})
+{
+  if (nullptr == segmentation) mitkThrow() << "Cannot perform boolean operation. Passed segmentation is not valid";
 
-  tempResult->DisconnectPipeline();
+  mitk::Image::Pointer result = mitk::Image::New();
+  result->Initialize(mitk::MakeScalarPixelType<mitk::LabelSetImage::LabelValueType>(), *(segmentation->GetTimeGeometry()));
 
-  auto result = mitk::LabelSetImage::New();
-  result->InitializeByLabeledImage(tempResult);
+  const auto timeStepCount = segmentation->GetTimeGeometry()->CountTimeSteps();
 
-  return result;
-}
+  for (mitk::TimeStepType i = 0; i < timeStepCount; ++i)
+  {
+    using OpsFilterType = itk::NaryFunctorImageFilter<ITKGroupImageType, ITKGroupImageType, BoolOpsFunctor<mitk::LabelSetImage::LabelValueType> >;
+    auto opsFilter = OpsFilterType::New();
 
-mitk::LabelSetImage::Pointer mitk::BooleanOperation::GetIntersection() const
-{
-  auto input1 = CastTo3DItkImage(m_SegmentationA, m_TimePoint);
-  auto input2 = CastTo3DItkImage(m_SegmentationB, m_TimePoint);
+    mitk::ITKEventObserverGuard eventGuard(opsFilter, itk::ProgressEvent(), [&opsFilter, progressCallback, timeStepCount](const itk::EventObject& event)
+      { progressCallback(opsFilter->GetProgress() / static_cast<float>(timeStepCount)); });
 
-  auto andFilter = itk::AndImageFilter<ImageType, ImageType>::New();
-  andFilter->SetInput1(input1);
-  andFilter->SetInput2(input2);
+    BoolOpsFunctor<mitk::LabelSetImage::LabelValueType> functor(opsFunction);
+    opsFilter->SetFunctor(functor);
+    std::vector < ITKGroupImageType::ConstPointer > inputImages;
 
-  andFilter->UpdateLargestPossibleRegion();
+    unsigned int inputIndex = 0;
+    for (auto value : labeValues)
+    {
+      auto groupImage = segmentation->GetGroupImage(segmentation->GetGroupIndexOfLabel(value));
+      auto groupImageAtTS = mitk::SelectImageByTimeStep(groupImage, i);
 
-  auto tempResult = Image::New();
-  CastToMitkImage<ImageType>(andFilter->GetOutput(), tempResult);
+      ITKGroupImageType::Pointer itkImage;
+      mitk::CastToItkImage(groupImageAtTS, itkImage);
+      inputImages.push_back(itkImage);
+      opsFilter->SetInput(inputIndex, itkImage);
+      ++inputIndex;
+    }
 
-  tempResult->DisconnectPipeline();
+    opsFilter->Update();
+    auto resultTS = opsFilter->GetOutput();
 
-  auto result = mitk::LabelSetImage::New();
-  result->InitializeByLabeledImage(tempResult);
+    result->SetVolume(resultTS->GetBufferPointer(), i);
+  }
 
   return result;
 }
 
-mitk::LabelSetImage::Pointer mitk::BooleanOperation::GetUnion() const
-{
-  auto input1 = CastTo3DItkImage(m_SegmentationA, m_TimePoint);
-  auto input2 = CastTo3DItkImage(m_SegmentationB, m_TimePoint);
-
-  auto orFilter = itk::OrImageFilter<ImageType, ImageType>::New();
-  orFilter->SetInput1(input1);
-  orFilter->SetInput2(input2);
 
-  orFilter->UpdateLargestPossibleRegion();
-
-  auto tempResult = Image::New();
-  CastToMitkImage<ImageType>(orFilter->GetOutput(), tempResult);
-
-  tempResult->DisconnectPipeline();
-
-  auto result = mitk::LabelSetImage::New();
-  result->InitializeByLabeledImage(tempResult);
-
-  return result;
+mitk::Image::Pointer mitk::BooleanOperation::GenerateUnion(const LabelSetImage* segmentation, LabelSetImage::LabelValueVectorType labelValues,
+  std::function<void(float progress)> progressCallback)
+{
+  auto unionOps = [labelValues](const std::vector<mitk::Label::PixelType>& inputArray)
+    {
+      mitk::Label::PixelType result = 0;
+      for (auto inIt = inputArray.cbegin(), refIt = labelValues.cbegin(); inIt != inputArray.cend(); ++inIt, ++refIt)
+      {
+        if (*inIt == *refIt)
+        {
+          result = 1;
+          break;
+        }
+      }
+      return result;
+    };
+
+  return GenerateInternal(segmentation, labelValues, unionOps, progressCallback);
 }
 
-void mitk::BooleanOperation::ValidateSegmentation(mitk::Image::Pointer segmentation) const
+mitk::Image::Pointer mitk::BooleanOperation::GenerateIntersection(const LabelSetImage* segmentation, LabelSetImage::LabelValueVectorType labelValues,
+  std::function<void(float progress)> progressCallback)
 {
-  if (segmentation.IsNull())
-    mitkThrow() << "Segmentation is nullptr!";
-
-  if (segmentation->GetImageDescriptor()->GetNumberOfChannels() != 1)
-    mitkThrow() << "Segmentation has more than one channel!";
-
-  auto pixelType = segmentation->GetImageDescriptor()->GetChannelDescriptor().GetPixelType();
-
-  if (pixelType.GetPixelType() != itk::IOPixelEnum::SCALAR ||
-      (pixelType.GetComponentType() != itk::IOComponentEnum::UCHAR &&
-       pixelType.GetComponentType() != itk::IOComponentEnum::USHORT))
-    mitkThrow() << "Segmentation is neither of type 'unsigned char' nor type 'unsigned short'!";
-
-  auto dimension = segmentation->GetDimension();
-
-  if (dimension > 4)
-    mitkThrow() << "Segmentation has more than four dimensions!";
-
-  if (dimension < 3)
-    mitkThrow() << "Segmentation has less than three dimensions!";
-
-  if (!segmentation->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
-    mitkThrow() << "Segmentation is not defined for specified time point. Time point: " << m_TimePoint;
+  auto intersectOps = [labelValues](const std::vector<mitk::Label::PixelType>& inputArray)
+    {
+      mitk::Label::PixelType result = 1;
+      for (auto inIt = inputArray.cbegin(), refIt = labelValues.cbegin(); inIt != inputArray.cend(); ++inIt, ++refIt)
+      {
+        if (*inIt != *refIt)
+        {
+          result = 0;
+          break;
+        }
+      }
+      return result;
+    };
+
+  return GenerateInternal(segmentation, labelValues, intersectOps, progressCallback);
 }
 
-void mitk::BooleanOperation::ValidateSegmentations() const
+mitk::Image::Pointer mitk::BooleanOperation::GenerateDifference(const LabelSetImage* segmentation, LabelSetImage::LabelValueType minuendLabelValue,
+  LabelSetImage::LabelValueVectorType subtrahendLabelValues, std::function<void(float progress)> progressCallback)
 {
-  this->ValidateSegmentation(m_SegmentationA);
-  this->ValidateSegmentation(m_SegmentationB);
-
-  if (m_SegmentationA->GetDimension() != m_SegmentationB->GetDimension())
-    mitkThrow() << "Segmentations have different dimensions!";
-
-  const auto geometryA = m_SegmentationA->GetTimeGeometry()->GetGeometryForTimePoint(m_TimePoint);
-  const auto geometryB = m_SegmentationB->GetTimeGeometry()->GetGeometryForTimePoint(m_TimePoint);
-  if (!mitk::Equal(*(geometryA.GetPointer()), *(geometryB.GetPointer()),eps,false))
-  {
-    mitkThrow() << "Segmentations have different geometries and cannot be used for boolean operations!";
-  }
+  auto intersectOps = [minuendLabelValue, subtrahendLabelValues](const std::vector<mitk::Label::PixelType>& inputArray)
+    {
+      if (minuendLabelValue != inputArray.front())
+        return mitk::Label::PixelType(0);
+
+      mitk::Label::PixelType result = 1;
+      for (auto inIt = inputArray.cbegin()+1, refIt = subtrahendLabelValues.cbegin(); inIt != inputArray.cend(); ++inIt, ++refIt)
+      {
+        if (*inIt == *refIt)
+        {
+          result = 0;
+          break;
+        }
+      }
+      return result;
+    };
+
+  auto labelValues = subtrahendLabelValues;
+  labelValues.insert(labelValues.begin(), minuendLabelValue);
+  return GenerateInternal(segmentation, labelValues, intersectOps, progressCallback);
 }
diff --git a/Modules/Segmentation/SegmentationUtilities/BooleanOperations/mitkBooleanOperation.h b/Modules/Segmentation/SegmentationUtilities/BooleanOperations/mitkBooleanOperation.h
index 8822957cd2..613e8d21bf 100644
--- a/Modules/Segmentation/SegmentationUtilities/BooleanOperations/mitkBooleanOperation.h
+++ b/Modules/Segmentation/SegmentationUtilities/BooleanOperations/mitkBooleanOperation.h
@@ -1,73 +1,38 @@
 /*============================================================================
 
 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 mitkBooleanOperation_h
 #define mitkBooleanOperation_h
 
 #include <MitkSegmentationExports.h>
 #include <mitkLabelSetImage.h>
 
 namespace mitk
 {
   /** \brief Executes a boolean operation on two different segmentations.
-   *
    * All parameters of the boolean operations must be specified during construction.
    * The actual operation is executed when calling GetResult().
    */
-  class MITKSEGMENTATION_EXPORT BooleanOperation
+  namespace BooleanOperation
   {
-  public:
-    enum Type
-    {
-      None,
-      Difference,
-      Intersection,
-      Union
-    };
 
-    /* \brief Construct a boolean operation.
-     *
-     * Throws an mitk::Exception when segmentations are somehow invalid.
-     *
-     * \param[in] type The type of the boolean operation.
-     * \param[in] segmentationA The first operand of the boolean operation.
-     * \param[in] segmentationB The second operand of the boolean operation.
-     * \param[in] The time point at which the operation will be executed.
-     */
-    BooleanOperation(Type type, Image::Pointer segmentationA, Image::Pointer segmentationB, TimePointType time = 0.);
-    ~BooleanOperation();
+    Image::Pointer MITKSEGMENTATION_EXPORT GenerateUnion(const LabelSetImage*, LabelSetImage::LabelValueVectorType labeValues,
+      std::function<void(float progress)> progressCallback = [](float) {});
+    Image::Pointer MITKSEGMENTATION_EXPORT GenerateIntersection(const LabelSetImage*, LabelSetImage::LabelValueVectorType labelValues,
+      std::function<void(float progress)> progressCallback = [](float) {});
+    Image::Pointer MITKSEGMENTATION_EXPORT GenerateDifference(const LabelSetImage*, LabelSetImage::LabelValueType minuendLabelValue,
+      LabelSetImage::LabelValueVectorType subtrahendLabelValues, std::function<void(float progress)> progressCallback = [](float) {});
 
-    /* \brief Execute boolean operation and return resulting segmentation.
-     *
-     * \return The resulting segmentation.
-     */
-    LabelSetImage::Pointer GetResult() const;
-
-  private:
-    BooleanOperation(const BooleanOperation &);
-    BooleanOperation &operator=(const BooleanOperation &);
-
-    LabelSetImage::Pointer GetDifference() const;
-    LabelSetImage::Pointer GetIntersection() const;
-    LabelSetImage::Pointer GetUnion() const;
-
-    void ValidateSegmentation(Image::Pointer segmentation) const;
-    void ValidateSegmentations() const;
-
-    Type m_Type;
-    Image::Pointer m_SegmentationA;
-    Image::Pointer m_SegmentationB;
-    TimePointType m_TimePoint;
   };
 }
 
 #endif