diff --git a/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.tpp b/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.tpp index f448b2e..cd1e39d 100644 --- a/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.tpp +++ b/Code/Algorithms/ITK/boxed/mapITKRigid3DMattesMIHeadNeckRegistrationAlgorithmTemplate.tpp @@ -1,174 +1,207 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #ifndef __ITK_RIGID_3D_MATTESMI_HEADNECK_REGISTRATION_ALGORITHM_TPP #define __ITK_RIGID_3D_MATTESMI_HEADNECK_REGISTRATION_ALGORITHM_TPP #include "itkRegionOfInterestImageFilter.h" namespace map { namespace algorithm { namespace boxed { template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> MultiModalRigidHeadNeckRegistrationAlgorithm:: MultiModalRigidHeadNeckRegistrationAlgorithm() { }; template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> MultiModalRigidHeadNeckRegistrationAlgorithm:: ~MultiModalRigidHeadNeckRegistrationAlgorithm() { }; template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> void MultiModalRigidHeadNeckRegistrationAlgorithm:: configureAlgorithm() { Superclass::configureAlgorithm(); this->setResolutionLevels(3); this->_preInitialize = true; this->_useCenterOfGravity = false; //optimizer typename Superclass::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()->SetScales(scales); 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 MultiModalRigidHeadNeckRegistrationAlgorithm:: doInterLevelSetup(){ Superclass::doInterLevelSetup(); if (this->getCurrentLevel() != 0) { this->getConcreteMetricControl()->getConcreteMetric()->SetUseAllPixels(false); typename Superclass::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; this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetScales(scales); unsigned int nrOfSmpl = ::itk::Math::Round (this->getMovingImage()->GetLargestPossibleRegion().GetNumberOfPixels() * 0.15); this->getConcreteMetricControl()->getConcreteMetric()->SetNumberOfSpatialSamples(nrOfSmpl); //optimizer adjustment this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetMaximumStepLength( this->getConcreteOptimizerControl()->getConcreteOptimizer()->GetCurrentStepLength() * 2.0); this->getConcreteOptimizerControl()->getConcreteOptimizer()->SetMinimumStepLength( this->getConcreteOptimizerControl()->getConcreteOptimizer()->GetMinimumStepLength() * 0.5); } } template < class TImageType, class TIdentificationPolicy, class TInterpolatorPolicy, class TPyramideInitializationPolicy> void MultiModalRigidHeadNeckRegistrationAlgorithm:: prepInitializeTransformation(){ Superclass::Superclass::prepInitializeTransformation(); if (this->_preInitialize) { this->InvokeEvent(events::AlgorithmEvent(this, "Preinitialize transform.")); typedef ::itk::CenteredTransformInitializer InitializerType; typedef ::itk::RegionOfInterestImageFilter ROIFilterType; typename InitializerType::Pointer spInitializer = InitializerType::New(); - typename ROIFilterType::Pointer spROIFilter = ROIFilterType::New(); - spROIFilter->SetInput(this->getInternalTargetImage()); - typename ROIFilterType::RegionType region = this->getInternalTargetImage()->GetLargestPossibleRegion(); - typename ROIFilterType::RegionType::SizeValueType zSize = region.GetSize(2); - region.SetIndex(2, zSize / 3); - region.SetSize(2, 2 * zSize / 3); - spROIFilter->SetRegionOfInterest(region); + + const auto movingRegion = this->getInternalMovingImage()->GetLargestPossibleRegion(); + const auto targetRegion = this->getInternalTargetImage()->GetLargestPossibleRegion(); + const auto movingZSize = movingRegion.GetSize(2); + const auto targetZSize = targetRegion.GetSize(2); + + bool targetIsHeadNeck = targetZSize >= movingZSize; + + typename ROIFilterType::RegionType usedRegion = targetRegion; + auto usedSize = targetZSize; + + typename ROIFilterType::Pointer spROIFilter = ROIFilterType::New(); + if (targetIsHeadNeck) + { + spROIFilter->SetInput(this->getInternalTargetImage()); + this->InvokeEvent(events::AlgorithmEvent(this, + "Target image dedected as HeadNeck image.")); + } + else + { + spROIFilter->SetInput(this->getInternalMovingImage()); + usedRegion = movingRegion; + usedSize = movingZSize; + this->InvokeEvent(events::AlgorithmEvent(this, + "Moving image dedected as HeadNeck image.")); + } + + usedRegion.SetIndex(2, usedSize / 3); + usedRegion.SetSize(2, 2 * usedSize / 3); + spROIFilter->SetRegionOfInterest(usedRegion); core::OStringStream stream; - stream << region; + stream << usedRegion; + this->InvokeEvent(events::AlgorithmEvent(this, - "Prepare target region of interest. region: " + stream.str())); + "Prepare region of interest for HeadNeck. region: " + stream.str())); spROIFilter->Update(); - spInitializer->SetMovingImage(this->getInternalMovingImage()); - spInitializer->SetFixedImage(spROIFilter->GetOutput()); + if (targetIsHeadNeck) + { + spInitializer->SetMovingImage(this->getInternalMovingImage()); + spInitializer->SetFixedImage(spROIFilter->GetOutput()); + } + else + { + spInitializer->SetMovingImage(spROIFilter->GetOutput()); + spInitializer->SetFixedImage(this->getInternalTargetImage()); + } + spInitializer->SetTransform(this->getConcreteTransformModel()); if (this->_useCenterOfGravity) { this->InvokeEvent(events::AlgorithmEvent(this, "Preinitialize by moments.")); spInitializer->MomentsOn(); } else { this->InvokeEvent(events::AlgorithmEvent(this, "Preinitialize by image geometry.")); spInitializer->GeometryOn(); } spInitializer->InitializeTransform(); } core::OStringStream os; os << "Preinitialized transform to: " << this->getConcreteTransformModel()->GetParameters(); //set the parameter of the transform model to the current transform parameters of the algorithm this->setCurrentTransformParameters( this->getConcreteTransformModel()->GetParameters()); this->getInternalRegistrationMethod().SetInitialTransformParameters( this->getConcreteTransformModel()->GetParameters()); this->InvokeEvent(events::AlgorithmEvent(this, os.str())); } } // end namespace itk } // end namespace algorithm } // end namespace map #endif diff --git a/Code/Algorithms/ITK/deployed/ITKRigidHeadNeck.profile b/Code/Algorithms/ITK/deployed/ITKRigidHeadNeck.profile index 15d15dd..6cee64d 100644 --- a/Code/Algorithms/ITK/deployed/ITKRigidHeadNeck.profile +++ b/Code/Algorithms/ITK/deployed/ITKRigidHeadNeck.profile @@ -1,20 +1,20 @@ SET(ALGORITHM_PROFILE_UID_Namespace "de.dkfz.matchpoint.common") SET(ALGORITHM_PROFILE_UID_Name "Rigid3DMattesMIAlgorithm.3D.Head2HeadNeck") -SET(ALGORITHM_PROFILE_UID_Version "1.0.2") +SET(ALGORITHM_PROFILE_UID_Version "1.1.0") -SET(ALGORITHM_PROFILE_Description "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.") +SET(ALGORITHM_PROFILE_Description "Algorithm is used for special cases where a head image and a head neck image (assumed to be the larger image in z direction) should be registered. It skips the lower part of the head neck image if a preinitialization (via geometric center or centroid) is used, to establish a better initialization. By default initializes via geometric centers.") 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" "any") SET(ALGORITHM_PROFILE_DimTarget "3") SET(ALGORITHM_PROFILE_ModalityTarget "MR" "any") SET(ALGORITHM_PROFILE_Subject "any") SET(ALGORITHM_PROFILE_Object "Head" "Head/Neck") 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")