diff --git a/Code/Algorithms/ITK/CMakeLists.txt b/Code/Algorithms/ITK/CMakeLists.txt index 9165df0..78c640e 100644 --- a/Code/Algorithms/ITK/CMakeLists.txt +++ b/Code/Algorithms/ITK/CMakeLists.txt @@ -1,28 +1,29 @@ MAP_CREATE_MODULE(MAPAlgorithmsITK DEPENDS MAPAlgorithms MAPITK MAPUtilities) MAP_CREATE_MODULE_TESTS(MAPAlgorithmsITK PACKAGE_DEPENDS Litmus HEADER_TESTS) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKEuler3DMattesMI PROFILE "deployed/ITKEuler3DMattesMI.profile" FILES "deployed/mapITKEuler3DMattesMI.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKEuler3DMattesMIMultiRes PROFILE "deployed/ITKEuler3DMattesMIMultiRes.profile" FILES "deployed/mapITKEuler3DMattesMIMultiRes.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKEuler3DMS PROFILE "deployed/ITKEuler3DMS.profile" FILES "deployed/mapITKEuler3DMS.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKRigid2DMattesMI PROFILE "deployed/ITKRigid2DMattesMI.profile" FILES "deployed/mapITKRigid2DMattesMI.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKRigid3DClosedForm PROFILE "deployed/ITKRigid3DClosedForm.profile" FILES "deployed/mapITKRigid3DClosedForm.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKPDEDemons3D PROFILE "deployed/ITKPDEDemons3D.profile" FILES "deployed/mapITKPDEDemons3D.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKLevelSetMotion3D PROFILE "deployed/ITKLevelSetMotion3D.profile" FILES "deployed/mapITKLevelSetMotion3D.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKSymmetricForcesDemons3D PROFILE "deployed/ITKSymmetricForcesDemons3D.profile" FILES "deployed/mapITKSymmetricForcesDemons3D.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKLevelSetMotion3DMultiRes PROFILE "deployed/ITKLevelSetMotion3DMultiRes.profile" FILES "deployed/mapITKLevelSetMotion3DMultiRes.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKTranslation3DMattesMIMultiRes PROFILE "deployed/ITKTranslation3DMattesMIMultiRes.profile" FILES "deployed/mapITKTranslation3DMattesMIMultiRes.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKAffine3DMattesMIMultiRes PROFILE "deployed/ITKAffine3DMattesMIMultiRes.profile" FILES "deployed/mapITKAffine3DMattesMIMultiRes.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKRigidHeadNeck PROFILE "deployed/ITKRigidHeadNeck.profile" FILES "deployed/mapITKRigidHeadNeck.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKRigidSlabbedHead PROFILE "deployed/ITKRigidSlabbedHead.profile" FILES "deployed/mapITKRigidSlabbedHead.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) +MAP_DEFINE_DEPLOYED_ALGORITHM(ITKRigid3DBoundingBox PROFILE "deployed/ITKRigid3DBoundingBox.profile" FILES "deployed/mapITKRigid3DBoundingBox.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) SET(_MAP_ITK_REVIEW_ACTIVE "OFF") MAP_CHECK_ITK_REVIEW_ACTIVE(_MAP_ITK_REVIEW_ACTIVE) IF (${_MAP_ITK_REVIEW_ACTIVE}) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKFastSymmetricForcesDemons3D PROFILE "deployed/ITKFastSymmetricForcesDemons3D.profile" FILES "deployed/mapITKFastSymmetricForcesDemons3D.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) MAP_DEFINE_DEPLOYED_ALGORITHM(ITKFastSymmetricForcesDemons3DMultiRes PROFILE "deployed/ITKFastSymmetricForcesDemons3DMultiRes.profile" FILES "deployed/mapITKFastSymmetricForcesDemons3DMultiRes.cpp" MODULE_DEPENDS MAPCore MAPAlgorithms MAPAlgorithmsITK MAPDeployment) ELSE (${_MAP_ITK_REVIEW_ACTIVE}) MESSAGE(WARNING "ITKReview Module is not activated. Following algorithms will not be deployed:\n - ITKFastSymmetricForcesDemons3D\n - ITKFastSymmetricForcesDemons3DMultiRes") ENDIF (${_MAP_ITK_REVIEW_ACTIVE}) \ No newline at end of file diff --git a/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h b/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.h similarity index 53% copy from Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h copy to Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.h index 70a73c2..e467f1e 100644 --- a/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h +++ b/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.h @@ -1,83 +1,98 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ -#ifndef __MAP_ITK_RIGID_MMI_HEADNECK_REGISTRATION_ALGORITHM_H -#define __MAP_ITK_RIGID_MMI_HEADNECK_REGISTRATION_ALGORITHM_H +#ifndef __MAP_ITK_RIGID_MMI_BOUNDINGBOX_REGISTRATION_ALGORITHM_H +#define __MAP_ITK_RIGID_MMI_BOUNDINGBOX_REGISTRATION_ALGORITHM_H #include "mapITKEuler3DMattesMIMultiResRegistrationAlgorithmTemplate.h" namespace map { namespace algorithm { namespace boxed { - /** \class MultiModalRigidHeadNeckRegistrationAlgorithm + /** \class ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm * \ingroup Data_image MetaProperty Model_rigid Det_comp_iterative Det_stochastic Det_res_multi Dim_3D_3D Mod_multi PreInit_Geo * Algorithm is used for special cases where a head image should be registered onto a head/neck image (target image). It skips the lower part of * the target image if a preinitialization (via geometric center or centroid) is used, to establish a better initialization. By default initializes via geometric centers. */ template >, class TPyramideInitializationPolicy = algorithm::itk::NoComponentInitializationPolicy> - class MultiModalRigidHeadNeckRegistrationAlgorithm : + class ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm : public map::algorithm::boxed::ITKEuler3DMattesMIMultiResRegistrationAlgorithm { public: - typedef MultiModalRigidHeadNeckRegistrationAlgorithm Self; + typedef ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm Self; - typedef ITKEuler3DMattesMIMultiResRegistrationAlgorithm - Superclass; + typedef ITKEuler3DMattesMIMultiResRegistrationAlgorithm Superclass; - typedef ::itk::SmartPointer Pointer; - typedef ::itk::SmartPointer ConstPointer; + typedef ::itk::SmartPointer Pointer; + typedef ::itk::SmartPointer ConstPointer; - itkTypeMacro(MultiModalRigidHeadNeckRegistrationAlgorithm, + itkTypeMacro(ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm, ITKEuler3DMattesMIMultiResRegistrationAlgorithm); mapNewAlgorithmMacro(Self); + mapSetMetaMacro(ActivateBoundingBox, bool); + mapSetMetaMacro(ActivateMargin, bool); + mapGetMetaMacro(ActivateBoundingBox, bool); + mapGetMetaMacro(ActivateMargin, bool); + protected: - MultiModalRigidHeadNeckRegistrationAlgorithm(); - virtual ~MultiModalRigidHeadNeckRegistrationAlgorithm(); + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm(); + virtual ~ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm(); + + void configureAlgorithm() override; + void doInterLevelSetup() override; + void prepPerpareInternalInputData() override; + void prepSetInternalInputData() override; + + void compileInfos(MetaPropertyVectorType& infos) const override; + MetaPropertyPointer doGetProperty(const MetaPropertyNameType& name) const override; + void doSetProperty(const MetaPropertyNameType& name, const MetaPropertyType* pProperty) override; - void configureAlgorithm(); - void doInterLevelSetup(); - void prepInitializeTransformation(); + bool _ActivateBoundingBox; + bool _ActivateMargin; + /**Margins that should be used to dilate masks/bounding boxes in mm (per side). E.G. 3 mm margin in 1st dimension will make the bounding box + bigger by 6 mm.*/ + ::itk::FixedArray _margins; private: - MultiModalRigidHeadNeckRegistrationAlgorithm(const Self& source); //purposely not implemented + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm(const Self& source); //purposely not implemented void operator=(const Self&); //purposely not implemented }; } } } #ifndef MatchPoint_MANUAL_TPP -#include "mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.tpp" +#include "mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.tpp" #endif #endif diff --git a/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.tpp b/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.tpp new file mode 100644 index 0000000..a37f5f7 --- /dev/null +++ b/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.tpp @@ -0,0 +1,352 @@ +// ----------------------------------------------------------------------- +// RAP - Registration Algoritm Portfolio +// +// Copyright (c) German Cancer Research Center (DKFZ), +// Software development for Integrated Diagnostics and Therapy (SIDT). +// ALL RIGHTS RESERVED. +// See rapCopyright.txt and/or notes within this file +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notices for more information. +// +//------------------------------------------------------------------------ +/*! +// @file +// @version $Revision: 4933 $ (last changed revision) +// @date $Date: 2013-09-05 17:19:45 +0200 (Do, 05 Sep 2013) $ (last change date) +// @author $Author: floca $ (last changed by) +// Subversion HeadURL: $HeadURL: http://sidt-hpc1/dkfz_repository/NotMeVisLab/SIDT/RAP/trunk/Algorithms/Diffusion/difRigid_MattesMI.cpp $ +*/ + + + +#include "mapDeploymentDLLHelper.h" +#include "mapDiscreteElements.h" +#include "mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.h" +#include "mapConfigure.h" + +#include "itkRegionOfInterestImageFilter.h" +#include "itkBinaryErodeImageFilter.h" +#include "itkFlatStructuringElement.h" +#include "itkImageMaskSpatialObject.h" + +namespace map +{ + namespace algorithm + { + namespace boxed + { + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm() : _ActivateBoundingBox(false), _ActivateMargin(false) + { + }; + + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + ~ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm() + { + }; + + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + void + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + configureAlgorithm() + { + Superclass::configureAlgorithm(); + + this->setResolutionLevels(3); + this->_preInitialize = true; + this->_useCenterOfGravity = false; + this->_ActivateBoundingBox = false; + this->_ActivateMargin = false; + this->_margins.Fill(0.0); + + //optimizer + ConcreteOptimizerType::ScalesType scales(6); + scales[0] = 10.0; + scales[1] = 10.0; + scales[2] = 10.0; + scales[3] = 1.0 / 10000; + scales[4] = 1.0 / 10000; + scales[5] = 1.0 / 10000; + + this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetMaximumStepLength(3.00); + this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetMinimumStepLength(0.5); + this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetNumberOfIterations(200); + this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetRelaxationFactor(0.8); + this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetGradientMagnitudeTolerance(1e-4); + + //metric + this->getConcreteMetricControl()->getConcreteMetric()->SetNumberOfHistogramBins(30); + this->getConcreteMetricControl()->getConcreteMetric()->SetUseAllPixels(true); + this->getConcreteMetricControl()->getConcreteMetric()->ReinitializeSeed(); + this->getConcreteMetricControl()->getConcreteMetric()->UseExplicitPDFDerivativesOn(); + } + + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + void + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + doInterLevelSetup() + { + Superclass::doInterLevelSetup(); + + if (this->getCurrentLevel() != 0) + { + getConcreteMetricControl()->getConcreteMetric()->SetUseAllPixels(false); + + OptimizerBaseType::SVNLOptimizerBaseType::ScalesType scales(6); + scales[0] = 1.0; + scales[1] = 1.0; + scales[2] = 1.0; + scales[3] = 1.0 / 1000; + scales[4] = 1.0 / 1000; + scales[5] = 1.0 / 1000; + + getConcreteOptimizerControl()->getConcreteOptimizer()->SetScales(scales); + + unsigned int nrOfSmpl = ::itk::Math::Round + (this->getMovingImage()->GetLargestPossibleRegion().GetNumberOfPixels() * 0.15); + + getConcreteMetricControl()->getConcreteMetric()->SetNumberOfSpatialSamples(nrOfSmpl); + } + }; + + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + void + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + prepPerpareInternalInputData() + { + ::map::core::OStringStream os; + ::map::core::OStringStream os2; + + if (this->_ActivateMargin) + { + using TargetImageSOType = ::itk::ImageSpatialObject; + + auto targetMask = this->getInternalTargetMask(); + auto targetImageMask = dynamic_cast(targetMask.GetPointer()); + + if (targetImageMask) + { + //we have a mask -> add margin + using TargetImageMaskImageType = typename TargetImageSOType::ImageType; + + auto spacing = this->getInternalTargetImage()->GetSpacing(); + + using StructuringElementType = ::itk::FlatStructuringElement; + StructuringElementType::RadiusType radius; + + for (unsigned int i = 0; i < spacing.Size(); ++i) + { + radius[i] = ::itk::Math::Round(_margins[i] / spacing[i]); + } + + StructuringElementType structuringElement = StructuringElementType::Ball(radius); + + //We don't know the mask lables, but we know that background is always 0. Therefore we erode + //the background. + using BinaryErodeImageFilterType = ::itk::BinaryErodeImageFilter; + + BinaryErodeImageFilterType::Pointer erodeFilter = BinaryErodeImageFilterType::New(); + erodeFilter->SetInput(targetImageMask->GetImage()); + erodeFilter->SetKernel(structuringElement); + erodeFilter->SetErodeValue(0); + erodeFilter->SetBackgroundValue(::itk::NumericTraits::max()); + erodeFilter->Update(); + + auto dilatedImage = erodeFilter->GetOutput(); + using TargetImageMaskSOType = ::itk::ImageMaskSpatialObject< TargetImageType::ImageDimension >; + TargetImageMaskSOType::Pointer newMask = TargetImageMaskSOType::New(); + newMask->SetImage(dilatedImage); + this->setInternalTargetMask(newMask); + os << "Target mask: add margin with size (in mm): " << _margins << " (pixels: "<< radius<<")"; + + } + else + { + os << "Target mask: is not image based. No margins added."; + } + + this->InvokeEvent(::map::events::AlgorithmEvent(this, os.str())); + + using MovingImageSOType = ::itk::ImageSpatialObject; + + auto movingMask = this->getInternalMovingMask(); + auto movingImageMask = dynamic_cast(movingMask.GetPointer()); + + if (movingImageMask) + { + //we have a mask -> add margin + using MovingImageMaskImageType = typename MovingImageSOType::ImageType; + + auto spacing = this->getInternalMovingImage()->GetSpacing(); + + using StructuringElementType = ::itk::FlatStructuringElement; + StructuringElementType::RadiusType radius; + + for (unsigned int i = 0; i < spacing.Size(); ++i) + { + radius[i] = ::itk::Math::Round(_margins[i] / spacing[i]); + } + + StructuringElementType structuringElement = StructuringElementType::Ball(radius); + + //We don't know the mask lables, but we know that background is always 0. Therefore we erode + //the background. + using BinaryErodeImageFilterType = ::itk::BinaryErodeImageFilter; + + BinaryErodeImageFilterType::Pointer erodeFilter = BinaryErodeImageFilterType::New(); + erodeFilter->SetInput(movingImageMask->GetImage()); + erodeFilter->SetKernel(structuringElement); + erodeFilter->SetErodeValue(0); + erodeFilter->SetBackgroundValue(::itk::NumericTraits::max()); + erodeFilter->Update(); + + auto dilatedImage = erodeFilter->GetOutput(); + using MovingImageMaskSOType = ::itk::ImageMaskSpatialObject< MovingImageType::ImageDimension >; + MovingImageMaskSOType::Pointer newMask = MovingImageMaskSOType::New(); + newMask->SetImage(dilatedImage); + this->setInternalMovingMask(newMask); + os << "Moving mask: add margin with size (in mm): " << _margins << " (pixels: " << radius << ")"; + + } + else + { + os << "Moving mask: is not image based. No margins added."; + } + + this->InvokeEvent(::map::events::AlgorithmEvent(this, os2.str())); + + } + + + if (this->_ActivateBoundingBox) + { + this->_ActivateBoundingBox = true; + } + Superclass::prepPerpareInternalInputData(); + } + + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + void + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + prepSetInternalInputData() + { + Superclass::prepSetInternalInputData(); + + if (this->_ActivateBoundingBox) + { + //the internal moving and target images have already cropped to the bpunding box. This we only + //have to deactivate the use of the mask. + this->InvokeEvent(events::AlgorithmEvent(this, "Deactivate masks -> use bounding box instead.")); + MovingMaskBaseType::Pointer nullMMask; + TargetMaskBaseType::Pointer nullTMask; + + this->getMetricInternal()->getImageToImageMetric()->SetMovingImageMask(nullMMask); + this->getMetricInternal()->getImageToImageMetric()->SetFixedImageMask(nullTMask); + } + } + + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + void + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + compileInfos(MetaPropertyVectorType& infos) const + { + Superclass::compileInfos(infos); +#ifndef MAP_SEAL_ALGORITHMS + infos.push_back(map::algorithm::MetaPropertyInfo::New("ActivateBoundingBox", typeid(bool), true, true)); + infos.push_back(map::algorithm::MetaPropertyInfo::New("ActivateMargins", typeid(bool), true, true)); + infos.push_back(map::algorithm::MetaPropertyInfo::New("Margin_X", typeid(double), true, true)); + infos.push_back(map::algorithm::MetaPropertyInfo::New("Margin_Y", typeid(double), true, true)); + infos.push_back(map::algorithm::MetaPropertyInfo::New("Margin_Z", typeid(double), true, true)); +#endif + } + + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + typename ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm::MetaPropertyPointer + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + doGetProperty(const MetaPropertyNameType& name) const + { + MetaPropertyPointer spResult; + + if (name == "ActivateBoundingBox") + { + spResult = map::core::MetaProperty::New(this->_ActivateBoundingBox); + } + else if (name == "ActivateMargins") + { + spResult = map::core::MetaProperty::New(this->_ActivateMargin); + } + else if (name == "Margin_X") + { + spResult = map::core::MetaProperty::New(this->_margins[0]); + } + else if (name == "Margin_Y") + { + spResult = map::core::MetaProperty::New(this->_margins[1]); + } + else if (name == "Margin_Z") + { + spResult = map::core::MetaProperty::New(this->_margins[2]); + } + else + { + spResult = Superclass::doGetProperty(name); + } + + return spResult; + + }; + + template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> + void + ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm:: + doSetProperty(const MetaPropertyNameType& name, const MetaPropertyType* pProperty) + { + if (name == "ActivateBoundingBox") + { + bool activate; + map::core::unwrapMetaProperty(pProperty, activate); + this->_ActivateBoundingBox = activate; + + if (activate) + { + this->_CropInputImagesByMask = true; + } + } + else if (name == "ActivateMargins") + { + bool activate; + map::core::unwrapMetaProperty(pProperty, activate); + this->_ActivateMargin = activate; + } + else if (name == "Margin_X") + { + double margin; + map::core::unwrapMetaProperty(pProperty, margin); + this->_margins[0] = margin; + } + else if (name == "Margin_Y") + { + double margin; + map::core::unwrapMetaProperty(pProperty, margin); + this->_margins[1] = margin; + } + else if (name == "Margin_Z") + { + double margin; + map::core::unwrapMetaProperty(pProperty, margin); + this->_margins[2] = margin; + } + else + { + Superclass::doSetProperty(name, pProperty); + } + + }; + + } + } +} \ No newline at end of file diff --git a/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h b/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h index 70a73c2..57ad0ec 100644 --- a/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h +++ b/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h @@ -1,83 +1,83 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ #ifndef __MAP_ITK_RIGID_MMI_HEADNECK_REGISTRATION_ALGORITHM_H #define __MAP_ITK_RIGID_MMI_HEADNECK_REGISTRATION_ALGORITHM_H #include "mapITKEuler3DMattesMIMultiResRegistrationAlgorithmTemplate.h" namespace map { namespace algorithm { namespace boxed { /** \class MultiModalRigidHeadNeckRegistrationAlgorithm * \ingroup Data_image MetaProperty Model_rigid Det_comp_iterative Det_stochastic Det_res_multi Dim_3D_3D Mod_multi PreInit_Geo * Algorithm is used for special cases where a head image should be registered onto a head/neck image (target image). It skips the lower part of * the target image if a preinitialization (via geometric center or centroid) is used, to establish a better initialization. By default initializes via geometric centers. */ template >, class TPyramideInitializationPolicy = algorithm::itk::NoComponentInitializationPolicy> class MultiModalRigidHeadNeckRegistrationAlgorithm : public map::algorithm::boxed::ITKEuler3DMattesMIMultiResRegistrationAlgorithm { public: typedef MultiModalRigidHeadNeckRegistrationAlgorithm Self; typedef ITKEuler3DMattesMIMultiResRegistrationAlgorithm Superclass; typedef ::itk::SmartPointer Pointer; typedef ::itk::SmartPointer ConstPointer; itkTypeMacro(MultiModalRigidHeadNeckRegistrationAlgorithm, ITKEuler3DMattesMIMultiResRegistrationAlgorithm); mapNewAlgorithmMacro(Self); protected: MultiModalRigidHeadNeckRegistrationAlgorithm(); virtual ~MultiModalRigidHeadNeckRegistrationAlgorithm(); - void configureAlgorithm(); - void doInterLevelSetup(); - void prepInitializeTransformation(); + void configureAlgorithm() override; + void doInterLevelSetup() override; + void prepInitializeTransformation() override; private: MultiModalRigidHeadNeckRegistrationAlgorithm(const Self& source); //purposely not implemented void operator=(const Self&); //purposely not implemented }; } } } #ifndef MatchPoint_MANUAL_TPP #include "mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.tpp" #endif #endif diff --git a/Code/Algorithms/ITK/deployed/ITKRigid3DBoundingBox.profile b/Code/Algorithms/ITK/deployed/ITKRigid3DBoundingBox.profile new file mode 100644 index 0000000..9b9ec19 --- /dev/null +++ b/Code/Algorithms/ITK/deployed/ITKRigid3DBoundingBox.profile @@ -0,0 +1,20 @@ +SET(ALGORITHM_PROFILE_UID_Namespace "de.dkfz.matchpoint.common") +SET(ALGORITHM_PROFILE_UID_Name "Rigid3DMattesMIAlgorithm.3D.BoundingBox") +SET(ALGORITHM_PROFILE_UID_Version "1.0.0") + +SET(ALGORITHM_PROFILE_Description "Algorithm is used for special cases where either the given mask should be dilated by a given margin (specified in mm) or instead of the mask itself just the bounding box (w/o margins) should be used instead of the mask itself..") +SET(ALGORITHM_PROFILE_Contact "Ralf Floca\; sbr@dkfz-heidelberg.de") + +SET(ALGORITHM_PROFILE_DataType "Image") +SET(ALGORITHM_PROFILE_ResolutionStyle "3 (multi res)") +SET(ALGORITHM_PROFILE_DimMoving "3") +SET(ALGORITHM_PROFILE_ModalityMoving "MR" "CT" "any") +SET(ALGORITHM_PROFILE_DimTarget "3") +SET(ALGORITHM_PROFILE_ModalityTarget "MR" "CT" "any") +SET(ALGORITHM_PROFILE_Subject "any") +SET(ALGORITHM_PROFILE_Object "any") +SET(ALGORITHM_PROFILE_TransformModel "rigid") +SET(ALGORITHM_PROFILE_Metric "Mattes mutual information") +SET(ALGORITHM_PROFILE_TransformDomain "global") +SET(ALGORITHM_PROFILE_Optimization "Regular Step Gradient Descent") +SET(ALGORITHM_PROFILE_Keywords "basic" "pre initialization" "Head/Neck" "HeadNeck" "multimodal" "rigid" "margin" "boundingbox") diff --git a/Code/Algorithms/ITK/deployed/mapITKRigid3DBoundingBox.cpp b/Code/Algorithms/ITK/deployed/mapITKRigid3DBoundingBox.cpp new file mode 100644 index 0000000..395fd54 --- /dev/null +++ b/Code/Algorithms/ITK/deployed/mapITKRigid3DBoundingBox.cpp @@ -0,0 +1,25 @@ +// ----------------------------------------------------------------------- +// MatchPoint - DKFZ translational registration framework +// +// Copyright (c) German Cancer Research Center (DKFZ), +// Software development for Integrated Diagnostics and Therapy (SIDT). +// ALL RIGHTS RESERVED. +// See mapCopyright.txt or +// http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notices for more information. +// +//------------------------------------------------------------------------ + +#include "mapDeploymentDLLHelper.h" +#include "mapDiscreteElements.h" +#include "mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.h" + +#include "ITKRigid3DBoundingBox_ProfileResource.h" + +typedef map::core::discrete::Elements<3>::InternalImageType ImageType; +typedef map::algorithm::boxed::ITKRigid3DMattesMIBoundingBoxRegistrationAlgorithm +AlgorithmType; +mapDeployAlgorithmMacro(AlgorithmType); diff --git a/Code/Algorithms/ITK/files.cmake b/Code/Algorithms/ITK/files.cmake index 9c824f5..4418060 100644 --- a/Code/Algorithms/ITK/files.cmake +++ b/Code/Algorithms/ITK/files.cmake @@ -1,245 +1,247 @@ SET(CPP_FILES source/mapITKOptimizerControlInterface.cpp source/mapITKSVNLOptimizerControlInterface.cpp source/mapArbitrarySVNLOptimizerPolicy.cpp source/mapITKMetricControlInterface.cpp source/mapITKSVMetricControlInterface.cpp source/mapITKMVNLOptimizerControlInterface.cpp source/mapITKMVMetricControlInterface.cpp source/mapArbitraryMVNLOptimizerPolicy.cpp ) SET(H_FILES include/mapArbitraryInterpolatorPolicy.h include/mapArbitrarySVNLOptimizerPolicy.h include/mapFixedInterpolatorPolicy.h include/mapFixedSVNLOptimizerPolicy.h include/mapITKImageRegistrationAlgorithm.h include/mapITKImageRegistrationAlgorithmInterface.h include/mapITKInterpolatorSetterInterface.h include/mapITKImageToImageMetricSetterInterface.h include/mapITKSVNLOptimizerControlBase.h include/mapDefaultITKOptimizerControls.h include/mapITKOptimizerControlInterface.h include/mapITKSVNLOptimizerControlInterface.h include/mapITKSVNLOptimizerSetterInterface.h include/mapITKTransformSetterInterface.h include/mapArbitraryImageToImageMetricPolicy.h include/mapArbitraryTransformPolicy.h include/mapFixedImageToImageMetricPolicy.h include/mapFixedTransformPolicy.h include/mapITKMetricControlInterface.h include/mapITKSVMetricControlInterface.h include/mapITKImageToImageMetricControlInterface.h include/mapITKMetricControl.h include/mapITKImageToImageMetricControlBase.h include/mapITKMeanSquaresImageToImageMetric.h include/mapITKMattesMutualInformationImageToImageMetric.h include/mapITKCompareHistogramImageToImageMetric.h include/mapITKCorrelationCoefficientHistogramImageToImageMetric.h include/mapITKKappaStatisticImageToImageMetric.h include/mapITKGradientDifferenceImageToImageMetric.h include/mapITKMatchCardinalityImageToImageMetric.h include/mapITKMeanSquaresHistogramImageToImageMetric.h include/mapITKMutualInformationHistogramImageToImageMetric.h include/mapITKMutualInformationImageToImageMetric.h include/mapITKNormalizedCorrelationImageToImageMetric.h include/mapITKNormalizedMutualInformationHistogramImageToImageMetric.h include/mapITKAmoebaOptimizer.h include/mapITKPowellOptimizer.h include/mapITKRegularStepGradientDescentOptimizer.h include/mapITKConjugateGradientOptimizer.h include/mapITKFRPROptimizer.h include/mapITKGradientDescentOptimizer.h include/mapITKLBFGSBOptimizer.h include/mapITKLBFGSOptimizer.h include/mapITKOnePlusOneEvolutionaryOptimizer.h include/mapITKQuaternionRgidTransformGradientDescentOptimizer.h include/mapITKSPSAOptimizer.h include/mapITKVersorRigid3DTransformOptimizer.h include/mapITKVersorTransformOptimizer.h include/mapSealedInterpolatorPolicy.h include/mapSealedOptimizerPolicy.h include/mapSealedImageToImageMetricPolicy.h include/mapSealedTransformPolicy.h include/mapITKSVNLOptimizerGetterInterface.h include/mapITKInterpolatorGetterInterface.h include/mapITKImageToImageMetricGetterInterface.h include/mapITKTransformGetterInterface.h include/mapITKExhaustiveOptimizer.h include/mapITKLinearInterpolateImageFunction.h include/mapITKNearestNeighborInterpolateImageFunction.h include/mapITKBSplineInterpolateImageFunction.h include/mapITKWindowedSincInterpolateImageFunction.h include/mapITKMVNLOptimizerControlInterface.h include/mapITKPointSetToPointSetMetricControlBase.h include/mapITKPointSetToPointSetMetricControlInterface.h include/mapITKMVMetricControlInterface.h include/mapITKPointSetToPointSetMetricSetterInterface.h include/mapITKPointSetToPointSetMetricGetterInterface.h include/mapITKMVNLOptimizerSetterInterface.h include/mapITKMVNLOptimizerGetterInterface.h include/mapITKMVNLOptimizerControlBase.h include/mapArbitraryMVNLOptimizerPolicy.h include/mapFixedMVNLOptimizerPolicy.h include/mapArbitraryPointSetToPointSetMetricPolicy.h include/mapFixedPointSetToPointSetMetricPolicy.h include/mapSealedPointSetToPointSetMetricPolicy.h include/mapITKEuclideanDistancePointMetric.h include/mapITKEuclideanPairDistancePointMetric.h include/mapITKLevenbergMarquardtOptimizer.h include/mapITKMultiResImageRegistrationAlgorithm.h include/mapITKClosedFormRegistrationAlgorithm.h include/mapITKLandmarkKernelRegistrationAlgorithm.h include/mapITKPointSetRegistrationAlgorithm.h include/mapITKPDEDeformableRegistrationAlgorithmBase.h include/mapITKPDEDeformableRegistrationAlgorithm.h include/mapITKMultiResPDEDeformableRegistrationAlgorithm.h include/mapITKTranslationTransform.h include/mapITKScaleTransform.h include/mapITKAffineTransform.h include/mapITKAzimuthElevationToCartesianTransform.h include/mapITKCenteredAffineTransform.h include/mapITKElasticBodyReciprocalSplineKernelTransform.h include/mapITKElasticBodySplineKernelTransform.h include/mapITKFixedCenterOfRotationAffineTransform.h include/mapITKIdentityTransform.h include/mapITKKernelTransform.h include/mapITKScalableAffineTransform.h include/mapITKScaleLogarithmicTransform.h include/mapITKThinPlateR2LogRSplineKernelTransform.h include/mapITKThinPlateSplineKernelTransform.h include/mapITKVolumeSplineKernelTransform.h include/mapITKCenteredEuler3DTransform.h include/mapITKCenteredRigid2DTransform.h include/mapITKCenteredSimilarity2DTransform.h include/mapITKEuler2DTransform.h include/mapITKEuler3DTransform.h include/mapITKQuaternionRigidTransform.h include/mapITKRigid2DTransform.h include/mapITKRigid3DTransform.h include/mapITKRigid3DPerspectiveTransform.h include/mapITKScaleVersor3DTransform.h include/mapITKSimilarity2DTransform.h include/mapITKSimilarity3DTransform.h include/mapITKVersorRigid3DTransform.h include/mapITKVersorTransform.h include/mapITKBSplineDeformableTransform.h boxed/mapITKAffineMattesMIMultiResRegistrationAlgorithmTemplate.h boxed/mapITKDemonsRegistrationAlgorithm.h boxed/mapITKEuler3DICPRegistrationAlgorithmTemplate.h boxed/mapITKEuler3DMattesMIMultiResRegistrationAlgorithmTemplate.h boxed/mapITKEuler3DMattesMIRegistrationAlgorithmTemplate.h boxed/mapITKEuler3DMSRegistrationAlgorithmTemplate.h boxed/mapITKInitializedImageRegistrationAlgorithm.h boxed/mapITKInitializedMultiResImageRegistrationAlgorithm.h boxed/mapITKRigid2DClosedFormRegistrationAlgorithmTemplate.h boxed/mapITKRigid2DICPRegistrationAlgorithmTemplate.h boxed/mapITKRigid3DICPRegistrationAlgorithmTemplate.h boxed/mapITKRigid2DMattesMIRegistrationAlgorithmTemplate.h boxed/mapITKRigid3DClosedFormRegistrationAlgorithmTemplate.h boxed/mapTransMSRegistrationAlgorithmTemplate.h boxed/mapTransMattesMIRegistrationAlgorithmTemplate.h boxed/mapITKTransMattesMIMultiResRegistrationAlgorithm.h boxed/mapITKPDEDemonsRegistrationAlgorithm.h boxed/mapITKLevelSetMotionRegistrationAlgorithm.h boxed/mapITKSymmetricForcesDemonsRegistrationAlgorithm.h boxed/mapITKLevelSetMotionMultiResRegistrationAlgorithm.h boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.h boxed/mapITKRigid3DMattesMISlabbedHeadRegistrationAlgorithmTemplate.h +boxed/mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.h ) SET(TPP_FILES include/mapITKImageRegistrationAlgorithm.tpp include/mapITKImageRegistrationAlgorithmInterface.tpp include/mapITKSVNLOptimizerControlBase.tpp include/mapITKMVNLOptimizerControlBase.tpp include/mapArbitraryInterpolatorPolicy.tpp include/mapArbitraryImageToImageMetricPolicy.tpp include/mapArbitraryTransformPolicy.tpp include/mapFixedInterpolatorPolicy.tpp include/mapFixedImageToImageMetricPolicy.tpp include/mapFixedSVNLOptimizerPolicy.tpp include/mapFixedTransformPolicy.tpp include/mapITKImageToImageMetricControlBase.tpp include/mapSealedInterpolatorPolicy.tpp include/mapSealedOptimizerPolicy.tpp include/mapSealedImageToImageMetricPolicy.tpp include/mapSealedTransformPolicy.tpp include/mapITKPointSetToPointSetMetricControlBase.tpp include/mapFixedMVNLOptimizerPolicy.tpp include/mapArbitraryPointSetToPointSetMetricPolicy.tpp include/mapFixedPointSetToPointSetMetricPolicy.tpp include/mapSealedPointSetToPointSetMetricPolicy.tpp include/mapITKPointSetRegistrationAlgorithm.tpp include/mapITKPointSetRegistrationAlgorithmInterface.tpp include/mapITKMultiResImageRegistrationAlgorithm.tpp include/mapITKClosedFormRegistrationAlgorithm.tpp include/mapITKLandmarkKernelRegistrationAlgorithm.tpp include/mapITKPointSetRegistrationAlgorithm.tpp include/mapITKPDEDeformableRegistrationAlgorithmBase.tpp include/mapITKPDEDeformableRegistrationAlgorithm.tpp include/mapITKMultiResPDEDeformableRegistrationAlgorithm.tpp boxed/mapITKAffineMattesMIMultiResRegistrationAlgorithmTemplate.tpp boxed/mapITKDemonsRegistrationAlgorithm.tpp boxed/mapITKEuler3DMattesMIMultiResRegistrationAlgorithmTemplate.tpp boxed/mapITKEuler3DMattesMIRegistrationAlgorithmTemplate.tpp boxed/mapITKEuler3DMSRegistrationAlgorithmTemplate.tpp boxed/mapITKTransMattesMIMultiResRegistrationAlgorithm.tpp boxed/mapITKInitializedImageRegistrationAlgorithm.tpp boxed/mapITKInitializedMultiResImageRegistrationAlgorithm.tpp boxed/mapITKRigid2DMattesMIRegistrationAlgorithmTemplate.tpp boxed/mapITKPDEDemonsRegistrationAlgorithm.tpp boxed/mapITKLevelSetMotionRegistrationAlgorithm.tpp boxed/mapITKSymmetricForcesDemonsRegistrationAlgorithm.tpp boxed/mapITKLevelSetMotionMultiResRegistrationAlgorithm.tpp boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.tpp boxed/mapITKRigid3DMattesMISlabbedHeadRegistrationAlgorithmTemplate.tpp +boxed/mapITKRigid3DMattesMIBoundingBoxRegistrationAlgorithmTemplate.tpp ) SET(TEST_CPP_FILES test/mapAlgorithmsITKTests.cpp test/mapITKOptimizerControlInterfaceTest.cpp test/mapITKOptimizerControlTest.cpp test/mapFixedSVNLOptimizerPolicyTest.cpp test/mapArbitrarySVNLOptimizerPolicyTest.cpp test/mapFixedInterpolatorPolicyTest.cpp test/mapArbitraryInterpolatorPolicyTest.cpp test/mapFixedImageToImageMetricPolicyTest.cpp test/mapArbitraryImageToImageMetricPolicyTest.cpp test/mapFixedTransformPolicyTest.cpp test/mapArbitraryTransformPolicyTest.cpp test/mapITKImageRegistrationAlgorithmTest.cpp test/mapFixedITKImageRegistrationAlgorithmTest.cpp test/mapArbitraryMVNLOptimizerPolicyTest.cpp test/mapFixedMVNLOptimizerPolicyTest.cpp test/mapArbitraryPointSetToPointSetMetricPolicyTest.cpp test/mapFixedPointSetToPointSetMetricPolicyTest.cpp test/mapITKPointSetRegistrationAlgorithmTest.cpp test/mapITKRigid2DICPRegistrationAlgorithmTemplateTest.cpp test/mapITKEuler3DICPRegistrationAlgorithmTemplateTest.cpp test/mapITKRigid2DClosedFormRegistrationAlgorithmTemplateTest.cpp test/mapITKRigid3DClosedFormRegistrationAlgorithmTemplateTest.cpp test/mapITKLandmarkKernelRegistrationAlgorithmTest.cpp test/mapITKEuler3DMattesMIRegistrationAlgorithmTemplateTest.cpp test/mapITKTransMattesMIMultiResRegistrationAlgorithmTest.cpp ) SET(_MAP_ITK_REVIEW_ACTIVE "OFF") MAP_CHECK_ITK_REVIEW_ACTIVE(_MAP_ITK_REVIEW_ACTIVE) IF (${_MAP_ITK_REVIEW_ACTIVE}) SET(H_FILES ${H_FILES} include/mapITKComplexBSplineInterpolateImageFunction.h boxed/mapITKFastSymmetricForcesDemonsRegistrationAlgorithm.h boxed/mapITKFastSymmetricForcesDemonsMultiResRegistrationAlgorithm.h) SET(TPP_FILES ${TPP_FILES} boxed/mapITKFastSymmetricForcesDemonsMultiResRegistrationAlgorithm.tpp boxed/mapITKFastSymmetricForcesDemonsRegistrationAlgorithm.tpp) ELSE (${_MAP_ITK_REVIEW_ACTIVE}) MESSAGE(WARNING "ITKReview Module is not activated. Dependend resources will be deactivated:\n - mapITKComplexBSplineInterpolateImageFunction.h\n - mapITKFastSymmetricForcesDemonsRegistrationAlgorithm\n - mapITKFastSymmetricForcesDemonsMultiResRegistrationAlgorithm") ENDIF (${_MAP_ITK_REVIEW_ACTIVE}) \ No newline at end of file diff --git a/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.h b/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.h index e586391..8ad02b6 100644 --- a/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.h +++ b/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.h @@ -1,436 +1,466 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ #ifndef __MAP_ITK_IMAGE_REGISTRATION_ALGORITHM_H #define __MAP_ITK_IMAGE_REGISTRATION_ALGORITHM_H #include "mapContinuous.h" #include "mapClassMacros.h" #include "mapArbitraryTransformPolicy.h" #include "mapIterativeRegistrationAlgorithm.h" #include "mapImageRegistrationAlgorithmBase.h" #include "mapMetaPropertyAlgorithmBase.h" #include "mapMaskedRegistrationAlgorithmBase.h" #include "mapITKImageRegistrationAlgorithmInterface.h" #include "mapArbitraryInterpolatorPolicy.h" #include "mapArbitraryImageToImageMetricPolicy.h" #include "mapArbitrarySVNLOptimizerPolicy.h" #include "mapArbitraryTransformPolicy.h" #include "mapObserverSentinel.h" #include "mapModificationTimeValidator.h" #include "itkImageRegistrationMethod.h" #include "itkSimpleFastMutexLock.h" /*! @namespace map The namespace map is used throughout the MatchPoint project to mark code as components of this project */ namespace map { namespace algorithm { namespace itk { /*! @class ITKImageRegistrationAlgorithm @brief The class for an image registration algorithm based on ITK @ingroup Algorithms @ingroup ITK */ template < class TMovingImage, class TTargetImage, class TIdentificationPolicy, class TInterpolatorPolicy = ArbitraryInterpolatorPolicy, class TMetricPolicy = ArbitraryImageToImageMetricPolicy, class TOptimizerPolicy = ArbitrarySVNLOptimizerPolicy, class TTransformPolicy = ArbitraryTransformPolicy< ::map::core::continuous::ScalarType, TMovingImage::ImageDimension, TTargetImage::ImageDimension>, class TInternalRegistrationMethod = ::itk::ImageRegistrationMethod > class ITKImageRegistrationAlgorithm : public IterativeRegistrationAlgorithm, public ImageRegistrationAlgorithmBase, public MaskedRegistrationAlgorithmBase, public MetaPropertyAlgorithmBase, public ITKImageRegistrationAlgorithmInterface, public TIdentificationPolicy, public TInterpolatorPolicy, public TMetricPolicy, public TOptimizerPolicy, public TTransformPolicy { public: typedef ITKImageRegistrationAlgorithm < TMovingImage, TTargetImage, TIdentificationPolicy, TInterpolatorPolicy, TMetricPolicy, TOptimizerPolicy, TTransformPolicy, TInternalRegistrationMethod > Self; typedef IterativeRegistrationAlgorithm Superclass; typedef ITKImageRegistrationAlgorithmInterface ITKRegistrationType; using Pointer = ::itk::SmartPointer; using ConstPointer = ::itk::SmartPointer; itkTypeMacro(ITKImageRegistrationAlgorithm, IterativeRegistrationAlgorithm); mapNewAlgorithmMacro(Self); using UIDType = typename Superclass::UIDType; using UIDPointer = typename Superclass::UIDPointer; using InterpolatorPolicyType = TInterpolatorPolicy; using MetricPolicyType = TMetricPolicy; using OptimizerPolicyType = TOptimizerPolicy; using TransformPolicyType = TTransformPolicy; using IdentificationPolicyType = TIdentificationPolicy; using OptimizerBaseType = typename ITKRegistrationType::OptimizerBaseType; using MetricBaseType = typename ITKRegistrationType::MetricBaseType; using TransformBaseType = typename ITKRegistrationType::TransformBaseType; using InterpolatorBaseType = typename ITKRegistrationType::InterpolatorBaseType; typedef typename IterativeRegistrationAlgorithm::OptimizerMeasureType OptimizerMeasureType; typedef ImageRegistrationAlgorithmBase ImageRegistrationAlgorithmBaseType; + using MaskRegistrationAlgorithmBaseType = MaskedRegistrationAlgorithmBase; using TargetImageType = typename ImageRegistrationAlgorithmBaseType::TargetImageType; using MovingImageType = typename ImageRegistrationAlgorithmBaseType::MovingImageType; using MovingImageConstPointer = typename ImageRegistrationAlgorithmBaseType::MovingImageConstPointer; using TargetImageConstPointer = typename ImageRegistrationAlgorithmBaseType::TargetImageConstPointer; + using MovingMaskBaseType = typename MaskRegistrationAlgorithmBaseType::MovingMaskBaseType; + using TargetMaskBaseType = typename MaskRegistrationAlgorithmBaseType::TargetMaskBaseType; + using MovingMaskBaseConstPointer = typename MaskRegistrationAlgorithmBaseType::MovingMaskBaseConstPointer; + using TargetMaskBaseConstPointer = typename MaskRegistrationAlgorithmBaseType::TargetMaskBaseConstPointer; + using MovingRepresentationDescriptorType = typename Superclass::MovingRepresentationDescriptorType; using TargetRepresentationDescriptorType = typename Superclass::TargetRepresentationDescriptorType; using RegistrationPointer = typename Superclass::RegistrationPointer; using RegistrationType = typename Superclass::RegistrationType; using FieldRepRequirement = typename Superclass::FieldRepRequirement; using IterationCountType = typename Superclass::IterationCountType; using MetaPropertyPointer = typename MetaPropertyAlgorithmBase::MetaPropertyPointer; using MetaPropertyNameType = typename MetaPropertyAlgorithmBase::MetaPropertyNameType; using MetaPropertyVectorType = typename MetaPropertyAlgorithmBase::MetaPropertyVectorType; // IterativeRegistrationAlgorithm /*! @eguarantee strong*/ virtual bool isStoppable() const; /*! has the algorithm an iteration count? @eguarantee no fail @return Indicates if the algorithm can determin its current iteration count */ virtual bool hasIterationCount() const; /*! has the algorithm an maximum iteration count? @eguarantee no fail @return Indicates if the algorithm can determin its maximum iteration count */ virtual bool hasMaxIterationCount() const; /*! This function indicates of the optimizer of the iterative registration algorithm is * able to return its current metric/optimizer value(s)? @eguarantee no fail @return Indicates if the algorithm can determin its curent value. */ virtual bool hasCurrentOptimizerValue() const; mapDefineAlgorithmIdentificationByPolicyMacro; virtual typename FieldRepRequirement::Type isMovingRepresentationRequired() const; virtual typename FieldRepRequirement::Type isTargetRepresentationRequired() const; virtual bool isReusable() const; mapSetMacro(CropInputImagesByMask, bool); mapGetMacro(CropInputImagesByMask, bool); protected: ITKImageRegistrationAlgorithm(); ~ITKImageRegistrationAlgorithm() override; using InternalRegistrationMethodType = TInternalRegistrationMethod; using InterimRegistrationType = typename Superclass::InterimRegistrationType; using InterimRegistrationPointer = typename Superclass::InterimRegistrationPointer; /*! @overwrite * This default implementation does nothing.*/ virtual void configureAlgorithm(); // MetaPropertyAlgorithmBase /*! @reimplemented*/ void compileInfos(MetaPropertyVectorType& infos) const override; /*! @reimplemented*/ MetaPropertyPointer doGetProperty(const MetaPropertyNameType& name) const override; /*! @reimplemented*/ void doSetProperty(const MetaPropertyNameType& name, const MetaPropertyType* pProperty) override; // IterativeRegistrationAlgorithmInterface /*! @brief gets the registration result that has been computed in the last iteration. This result is limited by a region @pre pMovingRepresentation and pTargetRepresentation must not be null. @param [in] pMovingRepresentation Pointer to @eguarantee strong @return the interim registration result as smart pointer @retval a Registration object @sa Registration */ virtual InterimRegistrationPointer determineInterimRegistration(const MovingRepresentationDescriptorType* pMovingRepresentation, const TargetRepresentationDescriptorType* pTargetRepresentation) const; /*! * Returns the final registration @eguarantee strong */ virtual RegistrationPointer doGetRegistration() const; /*! Returns if the registration should be computed. The registration is outdated if doGetRegistration returns null * or the modification times of at least one policy is newer then the modification time of the registration. @eguarantee strong @return true if the registration should be (re)computed. False if the registration is uptodate. */ virtual bool registrationIsOutdated() const; virtual bool doStopAlgorithm(); /*! This method should do all preparation tasks right before the algorithms execution. At the and of this method * the algorithm should be set up and ready to use.\n * The method delegates the main work of initialization to several sub methods. This sub methods serves as slots * that can be rewritten by a algorithm developer to alter certain aspects and keep the rest untouched.\n * The sequence of slot calls is: \n * - prepCheckValidity * - prepPrepareSubComponents * - prepAssembleSubComponents * - prepPerpareInternalInputData * - prepSetInternalInputData * - prepInitializeTransformation * - prepFinalizePreparation * @remark If you want to change the execution style, then overwrite runAlgorithm(). @remark If you want to alter settings of optimzer, metric or interpolator depending on the resolution level use the method doInterLevelSetup() @remark configureAlgorithmByMetaProperties is called after preCheckValidity and before prepPerpareSubComponent. @eguarantee strong */ virtual void prepareAlgorithm(); /*! This method is the slot to check if all internal components and input data are properly set. * @remark The default implementation checks transform, interpolator, optimizer, metric, pyramides, moving and target image. * overload this method to alter the validity check. * @remark It is assumed that the implementation of this method throws an exception if the algorithm is not be configured * correctly.*/ virtual void prepCheckValidity(); /*! This method is the slot where sub components can be configured before(!) they are set to the * internal registration method. * @remark The default implementation just calls the preparation methods of the component policies.*/ virtual void prepPrepareSubComponents(); /*! This method is the slot where sub components are set to the internal registration method. * @remark The default implementation just calls the preparation methods of the component policies.*/ virtual void prepAssembleSubComponents(); /*! This method is the slot for internal preprocessing of input data. This method should * be reimplemented if you want to prepare the input data before they go into the internal * registration method. E.g. blurring or normalizing the moving and target image before registration. * @remark The default implementation does nothing. Thus the public input data will be the data used by the * internal algorithm. * @remark Implementations of this method should work with getInternalTargetImage()/getInternalMovingImage() and * set there results via setInternalTargetImage()/setInternalMovingImage() to allow the correct handling. @eguarantee strong */ virtual void prepPerpareInternalInputData(); /*! This method is the slot for passing relevant input data to the internal algorithm or its components. * @remark The default implementation passes getInternalTargetImage and getInternalMovingImage, sets the schedules, the fixed image region of the registration and the metric masks. * @remark If you need to access the images use getInternalTargetImage()/getInternalMovingImage(). @eguarantee strong */ virtual void prepSetInternalInputData(); /*! This method is a slot that is used for the initialization of the transformation model used * by the internal registration algorithm. * @remark By default it just sets the initial transformation parameter for the internal registration methods to the current values of the transform. * @remark If you need to access the images use getInternalTargetImage()/getInternalMovingImage(). @eguarantee strong */ virtual void prepInitializeTransformation(); /*! This method is the slot for final steps in the preparation process * @remark The default implementation calls the prepareAfterAssembly methods of the sub component policies. * @remark If you need to access the images use getInternalTargetImage()/getInternalMovingImage(). @eguarantee strong */ virtual void prepFinalizePreparation(); /*! This method should just execute the iteration loop. * @remark If you want to change the initialization or the finalization, then overwrite prepareAlgorithm() or finalizeAlgorithm(). * @return Indicates of the registration was successfully determined (e.g. could be * false if an iterative algorithm was stopped prematurely by the user). * @eguarantee strong */ virtual bool runAlgorithm(); /*! This method should do all the finalization work (e.g. generating the registration based on the iteration results). * @remark If you want to change the initialization or the iteration, then overwrite prepareAlgorithm() or runAlgorithm(). @eguarantee strong */ virtual void finalizeAlgorithm(); using TransformParametersType = typename TransformPolicyType::TransformType::ParametersType; /*! Gets the member variable _currentTransformParameters secured via _currentIterationLock. @return Copy of the current transform parameters. */ TransformParametersType getCurrentTransformParameters() const; /*! Sets the member variable _currentTransformParameters secured via _currentIterationLock. @param [in] Reference to the new current parameters. */ void setCurrentTransformParameters(const TransformParametersType& param); /*! return the optimizer value(s) of the current iteration step. Will be called by getCurrentOptimizerValue() if hasCurrentValue() returns true. @eguarantee strong @return current measure */ virtual OptimizerMeasureType doGetCurrentOptimizerValue() const; /*! Methods invoked by derivated classes. */ virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; /*! @eguarantee strong*/ virtual IterationCountType doGetCurrentIteration() const; /*! @brief gets the maximum number of the algorithm's iterations @eguarantee strong @return returns the algorithm's maximum iterations count */ virtual IterationCountType doGetMaxIterations() const; /*! Offers access to the internal registration method */ InternalRegistrationMethodType& getInternalRegistrationMethod(); /*! The count if the iterations, since starting the registration algorithm the last time. * 0 indicates that no iteration has been processed yet.*/ IterationCountType _currentIterationCount; /*! The lock is used to manage the access to the member variable _currentIterationCount.*/ mutable ::itk::SimpleFastMutexLock _currentIterationLock; /*! The current parameters of the registration transform. Will be set in every iteration step*/ TransformParametersType _currentTransformParameters; /*! The parameters of the registration transform of the last successfull registration determiniation. Will be set by finalizeAlgorithm()*/ TransformParametersType _finalizedTransformParameters; /*! Smartpointer to the finalized registration. Will be set by finalizeAlgorithm()*/ typename RegistrationType::Pointer _spFinalizedRegistration; /*! Method returns pointer to the moving image used by the algorithm internally. This is used to allow the algorithm * or its derived classes to modify the moving image with out changing the public moving image pointer. * It returns _spMovingImage if setInternalMovingImage was never called (thus no special internal image was defined). * Otherwise it will return _spInternalMovingImage. * (e.g.: An algorithm always normalizes an image before registration. Then the algorithm can use the prepPerpareInternalInputData() * function to manipulate the internal moving image before it is used by prepareAlgorithm() to set the internal algorithm)*/ MovingImageConstPointer getInternalMovingImage() const; /*! Method returns pointer to the target image used by the algorithm internally. This is used to allow the algorithm * or its derived classes to modify the target image with out changing the public target image pointer. * It returns _spTargetImage if setInternalTargetImage was never called (thus no special internal image was defined). * Otherwise it will return _spInternalTargetImage. * (e.g.: An algorithm always normalizes an image before registration. Then the algorithm can use the prepPerpareInternalInputData() * function to manipulate the internal target image before it is used by prepareAlgorithm() to set the internal algorithm)*/ TargetImageConstPointer getInternalTargetImage() const; /*!Method sets _spInternalMovingImage to the passed image and therefore overrides the target which is internally used by the algorithm.*/ void setInternalMovingImage(MovingImageType* image); /*!Method sets _spInternalTargetImage to the passed image and therefore overrides the target which is internally used by the algorithm.*/ void setInternalTargetImage(TargetImageType* image); + /*! Method returns pointer to the moving mask used by the algorithm internally. This is used to allow the algorithm + * or its derived classes to modify the moving mask with out changing the public moving mask pointer. + * It returns _spMovingMask if setInternalMovingMask was never called (thus no special internal mask was defined). + * Otherwise it will return _spInternalMovingMask.*/ + MovingMaskBaseConstPointer getInternalMovingMask() const; + /*! Method returns pointer to the target mask used by the algorithm internally. This is used to allow the algorithm + * or its derived classes to modify the target mask with out changing the public target mask pointer. + * It returns _spTargetMask if setInternalTargetMask was never called (thus no special internal mask was defined). + * Otherwise it will return _spInternalTargetMask.*/ + TargetMaskBaseConstPointer getInternalTargetMask() const; + + /*!Method sets _spInternalMovingMask to the passed mask and therefore overrides the target which is internally used by the algorithm.*/ + void setInternalMovingMask(MovingMaskBaseType* mask); + /*!Method sets _spInternalTargetMask to the passed mask and therefore overrides the target which is internally used by the algorithm.*/ + void setInternalTargetMask(TargetMaskBaseType* mask); + + bool _CropInputImagesByMask; + private: typename InternalRegistrationMethodType::Pointer _internalRegistrationMethod; /*!Pointer to the moving image used by the algorithm internally if it was changed by setInternalMovingImage(). * This is used to allow the algorithm or its derived classes to modify the moving image with out changing the public moving image pointer. * (e.g.: An algorithm always normalizes an image before registration. Then the algorithm can use the prepPerpareInternalInputData() * function to manipulate _spInternalMovingImage before it is used by prepareAlgorithm() to set the internal algorithm)*/ typename MovingImageType::Pointer _spInternalMovingImage; /*!Pointer to the target image used by the algorithm internally if it was changed by setInternalTargetImage(). * This is used to allow the algorithm or its derived classes to modify the target image with out changing the public target image pointer. * (e.g.: An algorithm always normalizes an image before registration. Then the algorithm can use the prepPerpareInternalInputData() * function to manipulate _spInternalTargetImage before it is used by prepareAlgorithm() to set the internal algorithm)*/ typename TargetImageType::Pointer _spInternalTargetImage; - bool _CropInputImagesByMask; + /*!Pointer to the moving mask used by the algorithm internally if it was changed by setInternalMovingMask(). + * This is used to allow the algorithm or its derived classes to modify the moving mask with out changing the public moving mask pointer.*/ + typename MovingMaskBaseType::Pointer _spInternalMovingMask; + + /*!Pointer to the target mask used by the algorithm internally if it was changed by setInternaltargetMask(). + * This is used to allow the algorithm or its derived classes to modify the target mask with out changing the public target mask pointer.*/ + typename TargetMaskBaseType::Pointer _spInternalTargetMask; mutable core::ObserverSentinel::Pointer _onIterationObserver; mutable core::ObserverSentinel::Pointer _onGeneralOptimizerObserver; mutable core::ObserverSentinel::Pointer _onGeneralMetricObserver; mutable core::ObserverSentinel::Pointer _onGeneralInterpolatorObserver; mutable core::ObserverSentinel::Pointer _onGeneralTransformObserver; /*! This member function is called by the observer of the optimizer, when ever a IterationEvent is invoked.*/ void onIterationEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); /*! This member function is called by the observer of the optimizer for all kind of events. It serves as a pass through.*/ void onGeneralOptimizerEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); /*! This member function is called by the observer of the metric for all kind of events. It serves as a pass through.*/ void onGeneralMetricEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); /*! This member function is called by the observer of the interpolator for all kind of events. It serves as a pass through.*/ void onGeneralInterpolatorEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); /*! This member function is called by the observer of the transform for all kind of events. It serves as a pass through.*/ void onGeneralTransformEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); /*! This member function is called by the observer of the transform for all kind of events. It serves as a pass through.*/ void onGeneralRegistrationMethodEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); /*! This member function is called by the optimizer policy if the optimizer instance changes.*/ void onOptimizerChange(const ::itk::EventObject& eventObject); /*! This member function is called by the metric policy if the metric instance changes.*/ void onMetricChange(const ::itk::EventObject& eventObject); /*! This member function is called by the interpolator policy if the interpolator instance changes.*/ void onInterpolatorChange(const ::itk::EventObject& eventObject); /*! This member function is called by the transform policy if the transform model instance changes.*/ void onTransformChange(const ::itk::EventObject& eventObject); ITKImageRegistrationAlgorithm(const Self& source); void operator=(const Self&); //purposely not implemented }; } // namespace itk } // namespace algorithm } // namespace map #ifndef MatchPoint_MANUAL_TPP #include "mapITKImageRegistrationAlgorithm.tpp" #endif #endif diff --git a/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.tpp b/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.tpp index dbbfaae..6e8a1d4 100644 --- a/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.tpp +++ b/Code/Algorithms/ITK/include/mapITKImageRegistrationAlgorithm.tpp @@ -1,1070 +1,1116 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) // Subversion HeadURL: $HeadURL$ */ #ifndef __MAP_ITK_IMAGE_REGISTRATION_ALGORITHM_TPP #define __MAP_ITK_IMAGE_REGISTRATION_ALGORITHM_TPP #include "itkMutexLockHolder.h" #include "itkExtractImageFilter.h" #include "mapAlgorithmException.h" #include "mapPreCachedRegistrationKernel.h" #include "mapInverseRegistrationKernelGenerator.h" #include "mapRegistrationManipulator.h" #include "mapAlgorithmWrapperEvent.h" #include "mapITKMVNLOptimizerControlInterface.h" #include "mapITKSVNLOptimizerControlInterface.h" #include "mapMaskBoundingBoxHelper.h" namespace map { namespace algorithm { namespace itk { template typename ITKImageRegistrationAlgorithm::FieldRepRequirement::Type ITKImageRegistrationAlgorithm:: isMovingRepresentationRequired() const { return FieldRepRequirement::No; }; template typename ITKImageRegistrationAlgorithm::FieldRepRequirement::Type ITKImageRegistrationAlgorithm:: isTargetRepresentationRequired() const { return FieldRepRequirement::No; }; template bool ITKImageRegistrationAlgorithm:: isStoppable() const { bool result = false; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->isStoppable(); } return result; }; template typename ITKImageRegistrationAlgorithm::IterationCountType ITKImageRegistrationAlgorithm:: doGetCurrentIteration() const { return this->_currentIterationCount; }; template typename ITKImageRegistrationAlgorithm::IterationCountType ITKImageRegistrationAlgorithm:: doGetMaxIterations() const { IterationCountType result = 0; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->getMaxIterations(); } return result; }; template bool ITKImageRegistrationAlgorithm:: hasIterationCount() const { return true; }; template bool ITKImageRegistrationAlgorithm:: hasMaxIterationCount() const { bool result = false; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->hasMaxIterationCount(); } return result; }; template bool ITKImageRegistrationAlgorithm:: hasCurrentOptimizerValue() const { bool result = false; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->hasCurrentValue(); } return result; }; template bool ITKImageRegistrationAlgorithm:: isReusable() const { return true; } template ITKImageRegistrationAlgorithm:: ITKImageRegistrationAlgorithm() { _finalizedTransformParameters.clear(); _currentTransformParameters.clear(); _currentIterationCount = 0; _spInternalMovingImage = NULL; _spInternalTargetImage = NULL; _CropInputImagesByMask = true; //now set the policy event slots typedef ::itk::ReceptorMemberCommand AlgorithmCommandType; typename AlgorithmCommandType::Pointer spInterpolatorCmd = AlgorithmCommandType::New(); spInterpolatorCmd->SetCallbackFunction(this, &Self::onInterpolatorChange); InterpolatorPolicyType::_spOnChange = spInterpolatorCmd; typename AlgorithmCommandType::Pointer spOptimizerCmd = AlgorithmCommandType::New(); spOptimizerCmd->SetCallbackFunction(this, &Self::onOptimizerChange); OptimizerPolicyType::_spOnChange = spOptimizerCmd; typename AlgorithmCommandType::Pointer spMetricCmd = AlgorithmCommandType::New(); spMetricCmd->SetCallbackFunction(this, &Self::onMetricChange); MetricPolicyType::_spOnChange = spMetricCmd; typename AlgorithmCommandType::Pointer spTransformCmd = AlgorithmCommandType::New(); spTransformCmd->SetCallbackFunction(this, &Self::onTransformChange); TransformPolicyType::_spOnChange = spTransformCmd; }; template ITKImageRegistrationAlgorithm:: ~ITKImageRegistrationAlgorithm() { }; template void ITKImageRegistrationAlgorithm:: configureAlgorithm() { //default implementation does nothing; } template typename ITKImageRegistrationAlgorithm::TransformParametersType ITKImageRegistrationAlgorithm:: getCurrentTransformParameters() const { typedef ::itk::MutexLockHolder< ::itk::SimpleFastMutexLock> LockHolderType; LockHolderType holder(this->_currentIterationLock); return this->_currentTransformParameters; }; template void ITKImageRegistrationAlgorithm:: setCurrentTransformParameters(const TransformParametersType& param) { typedef ::itk::MutexLockHolder< ::itk::SimpleFastMutexLock> LockHolderType; LockHolderType holder(this->_currentIterationLock); this->_currentTransformParameters = param; }; template typename ITKImageRegistrationAlgorithm::InterimRegistrationPointer ITKImageRegistrationAlgorithm:: determineInterimRegistration(const MovingRepresentationDescriptorType* pMovingRepresentation, const TargetRepresentationDescriptorType* pTargetRepresentation) const { InterimRegistrationPointer spResult = NULL; if (this->_currentIterationCount > 0) { //the algorithm has iterated at least once so we can determin an interim registration const TransformBaseType* pTransformModel = this->getTransformInternal(); if (!pTransformModel) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine interim registration. No transform model present on internal level (getTransformInternal(). Pleas ensure proper setup of algorithm."); } //clone the transform model typename TransformBaseType::Pointer spInterimTransformModel = pTransformModel->Clone(); if (spInterimTransformModel.IsNull()) { std::ostringstream modelStrm; pTransformModel->Print(modelStrm); mapExceptionMacro(AlgorithmException, << "Error. Cannot determine interim registration. Unable to clone transform model. Current model: "); //<< modelStrm); } //set the parameter of the interim transform model to the current transform parameters of the algorithm //We set the parameter by Value and not by using SetParameter() because otherwise //it could cause errors with itk transforms that only keep a pointer to their parameters (e.g. itk::BSplineDeformableTransform). //This transforms would be invalid as soon as we leave this method. spInterimTransformModel->SetParametersByValue( this->getCurrentTransformParameters()); //now build the inverse kernel (main kernel of a image based registration algorithm) typedef core::PreCachedRegistrationKernel InverseKernelType; typename InverseKernelType::Pointer spIKernel = InverseKernelType::New(); spIKernel->setTransformModel(spInterimTransformModel); //now build the direct kernel via inversion of the inverse kernel typedef core::InverseRegistrationKernelGenerator GeneratorType; typename GeneratorType::Pointer spGenerator = GeneratorType::New(); typedef typename GeneratorType::InverseKernelBaseType DirectKernelType; typename DirectKernelType::Pointer spDKernel = spGenerator->generateInverse(* (spIKernel.GetPointer()), pMovingRepresentation); if (spDKernel.IsNull()) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine direct mapping kernel of interim registration. Current inverse kernel: " << spIKernel); } //now create the registration an set the kernels spResult = InterimRegistrationType::New(); ::map::core::RegistrationManipulator manipulator(spResult); manipulator.setDirectMapping(spDKernel); manipulator.setInverseMapping(spIKernel); manipulator.getTagValues()[tags::AlgorithmUID] = this->getUID()->toStr(); } return spResult; }; template bool ITKImageRegistrationAlgorithm:: doStopAlgorithm() { bool result = false; OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { result = pOptimizer->stop(); } return result; }; template void ITKImageRegistrationAlgorithm:: prepCheckValidity() { if (!this->getTransformInternal()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no transformation model available."); } if (!this->getInterpolatorInternal()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no interpolator available."); } if (!this->getOptimizerInternal()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no optimizer available."); } if (!this->getMetricInternal()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no metric available."); } if (!this->getMovingImage()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no moving image."); } if (!this->getTargetImage()) { mapExceptionMacro(AlgorithmException, << "Cannot start algorithm; no target image."); } } template void ITKImageRegistrationAlgorithm:: prepPrepareSubComponents() { this->prepareTransform(); this->prepareInterpolator(); this->prepareMetric(); this->prepareOptimizer(); } template void ITKImageRegistrationAlgorithm:: prepAssembleSubComponents() { this->_internalRegistrationMethod->SetMetric(this->getMetricInternal()->getImageToImageMetric()); this->_internalRegistrationMethod->SetOptimizer(this->getOptimizerInternal()->getSVNLOptimizer()); this->_internalRegistrationMethod->SetTransform(this->getTransformInternal()); this->_internalRegistrationMethod->SetInterpolator(this->getInterpolatorInternal()); } template void ITKImageRegistrationAlgorithm:: prepPerpareInternalInputData() { typedef ::itk::ExtractImageFilter MovingExtractFilterType; typedef ::itk::ExtractImageFilter TargetExtractFilterType; typename MovingExtractFilterType::Pointer movingFilter = MovingExtractFilterType::New(); ::map::core::OStringStream os; ::map::core::OStringStream os2; if (this->getCropInputImagesByMask()) { - if (this->getTargetMask().IsNotNull()) + if (this->getInternalTargetMask().IsNotNull()) { //we have a mask -> so construct the image region typename TargetImageType::RegionType boundedRegion; if (::map::algorithm::MaskBoundingBoxHelper::computeBoundingImageRegion( - this->getTargetMask(), this->getInternalTargetImage(), boundedRegion)) + this->getInternalTargetMask(), this->getInternalTargetImage(), boundedRegion)) { if (boundedRegion.Crop(this->getInternalTargetImage()->GetLargestPossibleRegion())) { os << "Target mask: set -> target image space region is set to: " << ::std::endl << boundedRegion; typename TargetExtractFilterType::Pointer targetFilter = TargetExtractFilterType::New(); targetFilter->SetExtractionRegion(boundedRegion); targetFilter->SetInput(this->getInternalTargetImage()); targetFilter->Update(); typename TargetImageType::Pointer newTarget = targetFilter->GetOutput(); newTarget->DisconnectPipeline(); this->setInternalTargetImage(newTarget); } else { os << "Target mask: set, but invalid (not within the bufferd target image) -> use complete target image."; } } else { os << "Target mask: set, but invalid (cannot compute bounding box) -> use complete target image."; } } else { os << "Target mask: none -> use complete target image."; } this->InvokeEvent(::map::events::AlgorithmEvent(this, os.str())); - if (this->getMovingMask().IsNotNull()) + if (this->getInternalMovingMask().IsNotNull()) { //we have a mask -> so construct the image region typename MovingImageType::RegionType boundedRegion; if (::map::algorithm::MaskBoundingBoxHelper::computeBoundingImageRegion( - this->getMovingMask(), this->getInternalMovingImage(), boundedRegion)) + this->getInternalMovingMask(), this->getInternalMovingImage(), boundedRegion)) { if (boundedRegion.Crop(this->getInternalMovingImage()->GetLargestPossibleRegion())) { os2 << "Moving mask: set -> moving image space region is set to: " << ::std::endl << boundedRegion; typename MovingExtractFilterType::Pointer movingFilter = MovingExtractFilterType::New(); movingFilter->SetExtractionRegion(boundedRegion); movingFilter->SetInput(this->getInternalMovingImage()); movingFilter->Update(); typename MovingImageType::Pointer newMoving = movingFilter->GetOutput(); newMoving->DisconnectPipeline(); this->setInternalMovingImage(newMoving); } else { os2 << "Moving mask: set, but invalid (not within the bufferd moving image) -> use complete moving image."; } } else { os2 << "Moving mask: set, but invalid (cannot compute bounding box) -> use complete moving image."; } } else { os2 << "Moving mask: none -> use complete moving image."; } this->InvokeEvent(::map::events::AlgorithmEvent(this, os2.str())); } } template void ITKImageRegistrationAlgorithm:: prepSetInternalInputData() { //Connect images this->InvokeEvent(::map::events::AlgorithmEvent(this, "Connect images to itk registration method.")); this->_internalRegistrationMethod->SetFixedImage(this->getInternalTargetImage()); this->_internalRegistrationMethod->SetMovingImage(this->getInternalMovingImage()); //Connect masks if present this->InvokeEvent(::map::events::AlgorithmEvent(this, "Connect masks to registration metric.")); - if (this->getMovingMask().IsNotNull()) + if (this->getInternalMovingMask().IsNotNull()) { //add moving mask - this->getMetricInternal()->getImageToImageMetric()->SetMovingImageMask(this->getMovingMask()); + this->getMetricInternal()->getImageToImageMetric()->SetMovingImageMask(this->getInternalMovingMask()); } - if (this->getTargetMask().IsNotNull()) + if (this->getInternalTargetMask().IsNotNull()) { //add target mask - this->getMetricInternal()->getImageToImageMetric()->SetFixedImageMask(this->getTargetMask()); + this->getMetricInternal()->getImageToImageMetric()->SetFixedImageMask(this->getInternalTargetMask()); } this->_internalRegistrationMethod->SetFixedImageRegion( this->getInternalTargetImage()->GetLargestPossibleRegion()); } template void ITKImageRegistrationAlgorithm:: prepInitializeTransformation() { const TransformBaseType* pTransformModel = this->getTransformInternal(); if (!pTransformModel) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine interim registration. No transform model present on internal level (getTransformInternal(). Pleas ensure proper setup of algorithm."); } ::map::core::OStringStream os; os << "Set start transformation parameters to: " << pTransformModel->GetParameters(); //set the parameter of the transform model to the current transform parameters of the algorithm this->setCurrentTransformParameters(pTransformModel->GetParameters()); this->_internalRegistrationMethod->SetInitialTransformParameters( pTransformModel->GetParameters()); this->InvokeEvent(::map::events::AlgorithmEvent(this, os.str())); }; template void ITKImageRegistrationAlgorithm:: prepFinalizePreparation() { //initialize registration components after assembly this->prepareTransformAfterAssembly(); this->prepareInterpolatorAfterAssembly(); this->prepareMetricAfterAssembly(); this->prepareOptimizerAfterAssembly(this->getMetricInternal()->getMinimizeToOptimize()); }; template void ITKImageRegistrationAlgorithm:: prepareAlgorithm() { this->prepCheckValidity(); this->_currentIterationCount = 0; this->_spFinalizedRegistration = NULL; this->_spInternalMovingImage = NULL; this->_spInternalTargetImage = NULL; this->_finalizedTransformParameters.Fill(0); //create method this->_internalRegistrationMethod = InternalRegistrationMethodType::New(); //initialize registration components this->InvokeEvent(::map::events::AlgorithmEvent(this, "Transfer cached MetaProperties.")); this->configureAlgorithmByMetaProperties(); //initialize registration components this->InvokeEvent(::map::events::AlgorithmEvent(this, "Initializing registration components.")); this->prepPrepareSubComponents(); //assemble registration components this->InvokeEvent(::map::events::AlgorithmEvent(this, "Initializing itk multi resolution registration method.")); this->prepAssembleSubComponents(); this->InvokeEvent(::map::events::AlgorithmEvent(this, "Initializing/Preparing input data.")); this->prepPerpareInternalInputData(); this->InvokeEvent(::map::events::AlgorithmEvent(this, "Passing input data to internal algorithm.")); this->prepSetInternalInputData(); //possibility to initialize internal registration method after assembly this->prepInitializeTransformation(); //initialize registration components after assembly this->InvokeEvent(::map::events::AlgorithmEvent(this, "Finalizing initialization...")); this->prepFinalizePreparation(); //Register observers if (_onIterationObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onIterationEvent); _onIterationObserver = core::ObserverSentinel::New(this->getOptimizerInternal()->getSVNLOptimizer(), ::itk::IterationEvent(), spCommand); } if (_onGeneralOptimizerObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralOptimizerEvent); _onGeneralOptimizerObserver = core::ObserverSentinel::New( this->getOptimizerInternal()->getSVNLOptimizer(), ::itk::AnyEvent(), spCommand); } if (_onGeneralMetricObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralMetricEvent); _onGeneralMetricObserver = core::ObserverSentinel::New( this->getMetricInternal()->getImageToImageMetric(), ::itk::AnyEvent(), spCommand); } if (_onGeneralInterpolatorObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralInterpolatorEvent); _onGeneralInterpolatorObserver = core::ObserverSentinel::New(this->getInterpolatorInternal(), ::itk::AnyEvent(), spCommand); } if (_onGeneralTransformObserver.IsNull()) { typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralTransformEvent); _onGeneralTransformObserver = core::ObserverSentinel::New( this->getTransformInternal(), ::itk::AnyEvent(), spCommand); } typename ::itk::MemberCommand::Pointer spCommand = ::itk::MemberCommand::New(); spCommand->SetCallbackFunction(this, &Self::onGeneralRegistrationMethodEvent); this->_internalRegistrationMethod->AddObserver(::itk::AnyEvent(), spCommand); }; template bool ITKImageRegistrationAlgorithm:: runAlgorithm() { this->_internalRegistrationMethod->Update(); this->_stopConditionDescription = this->getOptimizerInternal()->getStopConditionDescription(); return true; }; template void ITKImageRegistrationAlgorithm:: finalizeAlgorithm() { RegistrationPointer spResult = NULL; //touch the sub component to ensure an actualzed modification time, //this is needed because in case of arbitrary policies and dll deployment //the components could come out of another context. So a //ModificationTimeValidator is needed in it could produce //false positives in this constellation. OptimizerPolicyType::GetMTime(); MetricPolicyType::GetMTime(); TransformPolicyType::GetMTime(); TransformBaseType* pTransformModel = this->getTransformInternal(); if (!pTransformModel) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine final registration. No transform model present on internal level (getTransformInternal()). Please ensure proper setup of algorithm."); } //clone the transform model typename TransformBaseType::Pointer spFinalTransformModel = pTransformModel->Clone(); if (spFinalTransformModel.IsNull()) { std::ostringstream modelStrm; pTransformModel->Print(modelStrm); mapExceptionMacro(AlgorithmException, << "Error. Cannot determine final registration. Unable to clone transform model. Current model: " << modelStrm.str()); } TransformParametersType lastTransformParameters = this->_internalRegistrationMethod->GetLastTransformParameters(); //set the parameter of the final transform model to the final transform parameters of the algorithm spFinalTransformModel->SetParametersByValue( lastTransformParameters); //this line is need to ensure correct cloning for //itk transforms that only keep a pointer to their parameters (e.g. itk::BSplineDeformableTransform). //Thoose transforms can cause problems with optimizers that only keep the parameters localy (e.g. itk::LBFGSOptimizer). //Excplicit resetting the parameters is a work arround to this problem. //now build the inverse kernel (main kernel of a image based registration algorithm) typedef core::PreCachedRegistrationKernel InverseKernelType; typename InverseKernelType::Pointer spIKernel = InverseKernelType::New(); spIKernel->setTransformModel(spFinalTransformModel); //now build the direct kernel via inversion of the inverse kernel typedef core::InverseRegistrationKernelGenerator GeneratorType; typename GeneratorType::Pointer spGenerator = GeneratorType::New(); typedef typename GeneratorType::InverseKernelBaseType DirectKernelType; typename DirectKernelType::Pointer spDKernel = spGenerator->generateInverse(* (spIKernel.GetPointer()), this->getMovingRepresentation()); if (spDKernel.IsNull()) { mapExceptionMacro(AlgorithmException, << "Error. Cannot determine direct mapping kernel of final registration. Current inverse kernel: " << spIKernel); } //ensure that settings changed to the registration determination process are reseted to default this->configureAlgorithm(); //now create the registration an set the kernels spResult = RegistrationType::New(); ::map::core::RegistrationManipulator manipulator(spResult); manipulator.setDirectMapping(spDKernel); manipulator.setInverseMapping(spIKernel); manipulator.getTagValues()[tags::AlgorithmUID] = this->getUID()->toStr(); //store the final results _spFinalizedRegistration = spResult; _finalizedTransformParameters = lastTransformParameters; }; template typename ITKImageRegistrationAlgorithm::RegistrationPointer ITKImageRegistrationAlgorithm:: doGetRegistration() const { return _spFinalizedRegistration; }; template void ITKImageRegistrationAlgorithm:: onIterationEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::core::OStringStream os; TransformParametersType currentParams = this->getTransformInternal()->GetParameters(); bool hasCurrentPosition = this->getOptimizerInternal()->hasCurrentPosition(); typename OptimizerBaseType::OptimizerPositionType currentPosition = this->getOptimizerInternal()->getCurrentPosition(); bool hasCurrentValue = this->getOptimizerInternal()->hasCurrentValue(); typename OptimizerBaseType::SVNLMeasureType currentValue = this->getOptimizerInternal()->getCurrentMeasure(); this->_currentIterationLock.Lock(); ++_currentIterationCount; _currentTransformParameters = currentParams; os << "Iteration #" << _currentIterationCount << "; params: "; os << currentParams << "; optimizer position: "; if (hasCurrentPosition) { os << currentPosition; } else { os << "unkown"; } os << "; metric value: "; if (hasCurrentValue) { os << currentValue; } else { os << "unkown"; } this->_currentIterationLock.Unlock(); this->InvokeEvent(::map::events::AlgorithmIterationEvent(this, os.str())); }; template void ITKImageRegistrationAlgorithm:: onGeneralOptimizerEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal optimizer event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onGeneralMetricEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal metric event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onGeneralInterpolatorEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal interpolator event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onGeneralTransformEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal transform event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onGeneralRegistrationMethodEvent(::itk::Object* caller, const ::itk::EventObject& eventObject) { ::map::events::AlgorithmWrapperEvent wrappedEvent(eventObject, caller, "internal registration method event"); this->InvokeEvent(wrappedEvent); }; template void ITKImageRegistrationAlgorithm:: onOptimizerChange(const ::itk::EventObject& eventObject) { map::events::UnregisterAlgorithmComponentEvent unregEvent; if (unregEvent.CheckEvent(&eventObject)) { // we can directly reset the observer sentinel befor the optimizer will be unregistered this->_onGeneralOptimizerObserver = NULL; } }; template void ITKImageRegistrationAlgorithm:: onMetricChange(const ::itk::EventObject& eventObject) { map::events::UnregisterAlgorithmComponentEvent unregEvent; if (unregEvent.CheckEvent(&eventObject)) { //we can directly reset the observer sentinel befor the metric will be unregistered this->_onGeneralMetricObserver = NULL; } }; template void ITKImageRegistrationAlgorithm:: onInterpolatorChange(const ::itk::EventObject& eventObject) { map::events::UnregisterAlgorithmComponentEvent unregEvent; if (unregEvent.CheckEvent(&eventObject)) { //we can directly reset the observer sentinel befor the interpolator will be unregistered this->_onGeneralInterpolatorObserver = NULL; } }; template void ITKImageRegistrationAlgorithm:: onTransformChange(const ::itk::EventObject& eventObject) { map::events::UnregisterAlgorithmComponentEvent unregEvent; if (unregEvent.CheckEvent(&eventObject)) { //we can directly reset the observer sentinel befor the transform will be unregistered this->_onGeneralTransformObserver = NULL; } }; template bool ITKImageRegistrationAlgorithm:: registrationIsOutdated() const { bool outdated = _spFinalizedRegistration.IsNull(); if (_spFinalizedRegistration.IsNotNull()) { if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < MetaPropertyAlgorithmBase::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < InterpolatorPolicyType::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < OptimizerPolicyType::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < MetricPolicyType::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < TransformPolicyType::GetMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < this->getMovingImageMTime(); } if (!outdated) { outdated = _spFinalizedRegistration->GetMTime() < this->getTargetImageMTime(); } if (!outdated) { //check if the target mask has been changed outdated = _spFinalizedRegistration->GetMTime() < this->getTargetMaskMTime(); } if (!outdated) { //check if the moving mask has been changed outdated = _spFinalizedRegistration->GetMTime() < this->getMovingMaskMTime(); } } return outdated; }; template typename ITKImageRegistrationAlgorithm::OptimizerMeasureType ITKImageRegistrationAlgorithm:: doGetCurrentOptimizerValue() const { OptimizerMeasureType result; const OptimizerBaseType* pOptimizer = this->getOptimizerInternal(); if (pOptimizer) { if (pOptimizer->hasCurrentValue()) { result = pOptimizer->getCurrentValue(); } } return result; }; template typename ITKImageRegistrationAlgorithm::InternalRegistrationMethodType& ITKImageRegistrationAlgorithm:: getInternalRegistrationMethod() { return *(this->_internalRegistrationMethod.GetPointer()); }; template void ITKImageRegistrationAlgorithm:: PrintSelf(std::ostream& os, ::itk::Indent indent) const { Superclass::PrintSelf(os, indent); ImageRegistrationAlgorithmBase::PrintSelf(os, indent); MaskedRegistrationAlgorithmBase::PrintSelf( os, indent); os << indent << "Current itertation count: " << _currentIterationCount << std::endl; os << indent << "Current transform parameters: " << _currentTransformParameters << std::endl; os << indent << "Finalized transform parameters: " << _finalizedTransformParameters << std::endl; os << indent << "Finalized registration: " << _spFinalizedRegistration << std::endl; }; template void ITKImageRegistrationAlgorithm:: compileInfos(MetaPropertyVectorType& infos) const { #ifndef MAP_SEAL_ALGORITHMS infos.push_back(::map::algorithm::MetaPropertyInfo::New("CropInputImagesByMasks", typeid(bool), true, true)); #endif }; template typename ITKImageRegistrationAlgorithm::MetaPropertyPointer ITKImageRegistrationAlgorithm:: doGetProperty(const MetaPropertyNameType& name) const { MetaPropertyPointer spResult; if (name == "CropInputImagesByMasks") { spResult = ::map::core::MetaProperty::New(this->_CropInputImagesByMask); } return spResult; }; template void ITKImageRegistrationAlgorithm:: doSetProperty(const MetaPropertyNameType& name, const MetaPropertyType* pProperty) { if (name == "CropInputImagesByMasks") { bool crop; ::map::core::unwrapMetaProperty(pProperty, crop); this->_CropInputImagesByMask = crop; } else { assert(false); //any other property name should have been excluded or allready handled by the calling function. } }; template typename ITKImageRegistrationAlgorithm::MovingImageConstPointer ITKImageRegistrationAlgorithm:: getInternalMovingImage() const { MovingImageConstPointer result = this->getMovingImage(); if (this->_spInternalMovingImage.IsNotNull()) { result = _spInternalMovingImage; } return result; }; template typename ITKImageRegistrationAlgorithm::TargetImageConstPointer ITKImageRegistrationAlgorithm:: getInternalTargetImage() const { TargetImageConstPointer result = this->getTargetImage(); if (this->_spInternalTargetImage.IsNotNull()) { result = _spInternalTargetImage; } return result; }; template void ITKImageRegistrationAlgorithm:: setInternalMovingImage(MovingImageType* image) { _spInternalMovingImage = image; }; template void ITKImageRegistrationAlgorithm:: setInternalTargetImage(TargetImageType* image) { _spInternalTargetImage = image; }; + template + typename ITKImageRegistrationAlgorithm::MovingMaskBaseConstPointer + ITKImageRegistrationAlgorithm:: + getInternalMovingMask() const + { + MovingMaskBaseConstPointer result = this->getMovingMask(); + + if (this->_spInternalMovingMask.IsNotNull()) + { + result = _spInternalMovingMask; + } + + return result; + } + + template + typename ITKImageRegistrationAlgorithm::TargetMaskBaseConstPointer + ITKImageRegistrationAlgorithm:: + getInternalTargetMask() const + { + TargetMaskBaseConstPointer result = this->getTargetMask(); + + if (this->_spInternalTargetMask.IsNotNull()) + { + result = _spInternalTargetMask; + } + + return result; + } + + template + void + ITKImageRegistrationAlgorithm:: + setInternalMovingMask(MovingMaskBaseType* mask) + { + _spInternalMovingMask = mask; + } + + template + void + ITKImageRegistrationAlgorithm:: + setInternalTargetMask(TargetMaskBaseType* mask) + { + _spInternalTargetMask = mask; + } + } // end namespace itk } // end namespace algorithm } // end namespace map #endif