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 + 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 #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 +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 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((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 PadFilterType; - PadFilterType::Pointer padFilter = PadFilterType::New(); - padFilter->SetInput(itkImage); + typedef itk::ConstantPadImageFilter 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 BinaryImageType; - typedef itk::BinaryThresholdImageFilter BinaryFilterType; - BinaryFilterType::Pointer binaryFilter = BinaryFilterType::New(); + typedef itk::BinaryThresholdImageFilter 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 #include namespace mitk { template class WeakPointer final { public: using DeleteEventCallbackType = std::function; 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 Lock() const { return m_RawPointer; } void SetDeleteEventCallback(const DeleteEventCallbackType &callback) { m_DeleteEventCallback = callback; } private: void AddDeleteEventObserver() { if (nullptr != m_RawPointer) { auto command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &WeakPointer::OnDeleteEvent); - using TWithoutConst = typename std::remove_const::type; + using TWithoutConst = typename std::remove_const_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(m_RawPointer); m_ObserverTag = nonConstPointer->AddObserver(itk::DeleteEvent(), command); } } void RemoveDeleteEventObserver() { if (nullptr != m_RawPointer) { - using TWithoutConst = typename std::remove_const::type; + using TWithoutConst = typename std::remove_const_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(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()(left.m_RawPointer, right.m_RawPointer); } friend bool operator <(const WeakPointer &left, std::nullptr_t right) noexcept { return std::less()(left.m_RawPointer, right); } friend bool operator <(std::nullptr_t left, const WeakPointer &right) noexcept { return std::less()(left, right.m_RawPointer); } friend bool operator <(const WeakPointer &left, const T *right) noexcept { return std::less()(left.m_RawPointer, right); } friend bool operator <(const T *left, const WeakPointer &right) noexcept { return std::less()(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 bool operator !=(const mitk::WeakPointer &left, const mitk::WeakPointer &right) noexcept { return !(left == right); } template bool operator <=(const mitk::WeakPointer &left, const mitk::WeakPointer &right) noexcept { return !(right < left); } template bool operator >(const mitk::WeakPointer &left, const mitk::WeakPointer &right) noexcept { return right < left; } template bool operator >=(const mitk::WeakPointer &left, const mitk::WeakPointer &right) noexcept { return !(left < right); } template bool operator ==(const mitk::WeakPointer &left, std::nullptr_t) noexcept { return !left; } template bool operator !=(const mitk::WeakPointer &left, std::nullptr_t right) noexcept { return !(left == right); } template bool operator ==(std::nullptr_t, const mitk::WeakPointer &right) noexcept { return !right; } template bool operator !=(std::nullptr_t left, const mitk::WeakPointer &right) noexcept { return !(left == right); } template bool operator <=(const mitk::WeakPointer &left, std::nullptr_t right) noexcept { return !(right < left); } template bool operator >(const mitk::WeakPointer &left, std::nullptr_t right) noexcept { return right < left; } template bool operator >=(const mitk::WeakPointer &left, std::nullptr_t right) noexcept { return !(left < right); } template bool operator <=(std::nullptr_t left, const mitk::WeakPointer &right) noexcept { return !(right < left); } template bool operator >(std::nullptr_t left, const mitk::WeakPointer &right) noexcept { return right < left; } template bool operator >=(std::nullptr_t left, const mitk::WeakPointer &right) noexcept { return !(left < right); } template bool operator !=(const mitk::WeakPointer &left, const T *right) noexcept { return !(left == right); } template bool operator <=(const mitk::WeakPointer &left, const T *right) noexcept { return !(right < left); } template bool operator >(const mitk::WeakPointer &left, const T *right) noexcept { return right < left; } template bool operator >=(const mitk::WeakPointer &left, const T *right) noexcept { return !(left < right); } template bool operator ==(const T *left, const mitk::WeakPointer &right) noexcept { return right == left; } template bool operator !=(const T *left, const mitk::WeakPointer &right) noexcept { return !(right == left); } template bool operator <=(const T *left, const mitk::WeakPointer &right) noexcept { return !(right < left); } template bool operator >(const T *left, const mitk::WeakPointer &right) noexcept { return right < left; } template bool operator >=(const T *left, const mitk::WeakPointer &right) noexcept { return !(left < right); } template bool operator !=(const mitk::WeakPointer &left, itk::SmartPointer right) noexcept { return !(left == right); } template bool operator <=(const mitk::WeakPointer &left, itk::SmartPointer right) noexcept { return !(right < left); } template bool operator >(const mitk::WeakPointer &left, itk::SmartPointer right) noexcept { return right < left; } template bool operator >=(const mitk::WeakPointer &left, itk::SmartPointer right) noexcept { return !(left < right); } template bool operator ==(itk::SmartPointer left, const mitk::WeakPointer &right) noexcept { return right == left; } template bool operator !=(itk::SmartPointer left, const mitk::WeakPointer &right) noexcept { return !(right == left); } template bool operator <=(itk::SmartPointer left, const mitk::WeakPointer &right) noexcept { return !(right < left); } template bool operator >(itk::SmartPointer left, const mitk::WeakPointer &right) noexcept { return right < left; } template bool operator >=(itk::SmartPointer left, const mitk::WeakPointer &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 #include #include +#include #include #include #include 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& strings) { std::ostringstream stream; stream << "["; for (std::vector::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(), 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::Image::Pointer regularImage = mitk::Image::New(); unsigned int dimensions[3] = { 96, 128, 52 }; regularImage->Initialize(mitk::MakeScalarPixelType(), 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(m_LabelSetImage.GetPointer())->GetActiveLabel()->GetValue() == value2); } void TestInitializeByLabeledImage() { mitk::Image::Pointer image = mitk::IOUtil::Load(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({ "Label1", "Label2", "Label3"}), names); names = m_LabelSetImage->GetLabelClassNamesByGroup(0); CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong names retrieved for group 0", std::vector({ "Label1"}), names); names = m_LabelSetImage->GetLabelClassNamesByGroup(1); CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong names retrieved for group 1", std::vector({"Label2", "Label3" }), names); names = m_LabelSetImage->GetLabelClassNamesByGroup(2); CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong names retrieved for group 2", std::vector(), 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(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 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(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 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(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 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(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 #include #include #include const mitk::Label::PixelType mitk::Label::MAX_LABEL_VALUE = std::numeric_limits::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