From 60f345e91ebb8764e30207069b0a3ea49b4e76ec Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Thu, 21 Apr 2016 15:52:27 -0400 Subject: [PATCH 1/6] ENH: adding methods and tests for Virtual image Adding test which utilizes the FixedInitialTransform with setting the VirtualDomain. The Fixed InitialTransfrom maps from the zero origin virutal domain to the offset-ed FixedImage, the same as the origin. Change-Id: Ib7ab091225b7e5148de15408812fed870d035987 --- .../include/sitkImageRegistrationMethod.h | 17 +++++ .../src/sitkImageRegistrationMethod.cxx | 41 ++++++++++++ .../Unit/sitkImageRegistrationMethodTests.cxx | 65 ++++++++++++++++++- 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/Code/Registration/include/sitkImageRegistrationMethod.h b/Code/Registration/include/sitkImageRegistrationMethod.h index ba56f96e8..33193d7f9 100644 --- a/Code/Registration/include/sitkImageRegistrationMethod.h +++ b/Code/Registration/include/sitkImageRegistrationMethod.h @@ -177,6 +177,18 @@ namespace simple { return this->m_FixedInitialTransform; } /**@}*/ + + /** \brief Set the virtual domain used for sampling + * + * @{ + */ + SITK_RETURN_SELF_TYPE_HEADER SetVirtualDomain( const std::vector &virtualSize, + const std::vector &virtualOrigin, + const std::vector &virtualSpacing, + const std::vector &virtualDirection ); + SITK_RETURN_SELF_TYPE_HEADER SetVirtualDomainFromImage( const Image &virtualImage ); + /**@}*/ + /** \brief Use normalized cross correlation using a small * neighborhood for each voxel between two images, with speed * optimizations for dense registration. @@ -598,6 +610,11 @@ namespace simple Transform m_MovingInitialTransform; Transform m_FixedInitialTransform; + std::vector m_VirtualDomainSize; + std::vector m_VirtualDomainOrigin; + std::vector m_VirtualDomainSpacing; + std::vector m_VirtualDomainDirection; + // optimizer enum OptimizerType { ConjugateGradientLineSearch, RegularStepGradientDescent, diff --git a/Code/Registration/src/sitkImageRegistrationMethod.cxx b/Code/Registration/src/sitkImageRegistrationMethod.cxx index 2f2a77f10..80c1e8678 100644 --- a/Code/Registration/src/sitkImageRegistrationMethod.cxx +++ b/Code/Registration/src/sitkImageRegistrationMethod.cxx @@ -131,6 +131,34 @@ ImageRegistrationMethod::SetInitialTransform ( Transform &transform, bool inPlac return *this; } +ImageRegistrationMethod::Self& +ImageRegistrationMethod::SetVirtualDomain( const std::vector &virtualSize, + const std::vector &virtualOrigin, + const std::vector &virtualSpacing, + const std::vector &virtualDirection ) +{ + const size_t dim = virtualSize.size(); + + // todo check size of vectors + + this->m_VirtualDomainSize = virtualSize; + this->m_VirtualDomainOrigin = virtualOrigin; + this->m_VirtualDomainSpacing = virtualSpacing; + this->m_VirtualDomainDirection = virtualDirection; + return *this; +} + +ImageRegistrationMethod::Self& +ImageRegistrationMethod::SetVirtualDomainFromImage( const Image &virtualImage ) +{ + this->m_VirtualDomainSize = virtualImage.GetSize(); + this->m_VirtualDomainOrigin = virtualImage.GetOrigin(); + this->m_VirtualDomainSpacing = virtualImage.GetSpacing(); + this->m_VirtualDomainDirection = virtualImage.GetDirection(); + + return *this; +} + ImageRegistrationMethod::Self& ImageRegistrationMethod::SetMetricAsANTSNeighborhoodCorrelation( unsigned int radius ) { @@ -665,6 +693,7 @@ Transform ImageRegistrationMethod::ExecuteInternal ( const Image &inFixed, const { sitkExceptionMacro( "Unexpected error converting initial moving transform! Possible miss matching dimensions!" ); } + std::cout << "--------> Setting MovingInitalTransform\n"; registration->SetMovingInitialTransform(itkTx); } @@ -676,6 +705,7 @@ Transform ImageRegistrationMethod::ExecuteInternal ( const Image &inFixed, const { sitkExceptionMacro( "Unexpected error converting initial moving transform! Possible miss matching dimensions!" ); } + std::cout << "--------> Setting FixedInitalTransform\n"; registration->SetFixedInitialTransform(itkTx); } @@ -967,6 +997,17 @@ ImageRegistrationMethod::SetupMetric( metric->SetUseFixedImageGradientFilter( m_MetricUseFixedImageGradientFilter ); metric->SetUseMovingImageGradientFilter( m_MetricUseMovingImageGradientFilter ); + if ( this->m_VirtualDomainSize.size() != 0 ) + { + typename FixedImageType::SpacingType itkSpacing = sitkSTLVectorToITK(this->m_VirtualDomainSpacing); + typename FixedImageType::PointType itkOrigin = sitkSTLVectorToITK(this->m_VirtualDomainOrigin); + typename FixedImageType::DirectionType itkDirection = sitkSTLToITKDirection(this->m_VirtualDomainDirection); + + typename FixedImageType::RegionType itkRegion; + itkRegion.SetSize( sitkSTLVectorToITK( this->m_VirtualDomainSize ) ); + + metric->SetVirtualDomain( itkSpacing, itkOrigin, itkDirection, itkRegion ); + } typedef itk::InterpolateImageFunction< FixedImageType, double > FixedInterpolatorType; typename FixedInterpolatorType::Pointer fixedInterpolator = CreateInterpolator(fixed, m_Interpolator); diff --git a/Testing/Unit/sitkImageRegistrationMethodTests.cxx b/Testing/Unit/sitkImageRegistrationMethodTests.cxx index de534cf4e..b637655a0 100644 --- a/Testing/Unit/sitkImageRegistrationMethodTests.cxx +++ b/Testing/Unit/sitkImageRegistrationMethodTests.cxx @@ -118,7 +118,7 @@ class sitkRegistrationMethodTest const std::vector &pt1, const std::vector &size) { - sitk::GaussianImageSource source1; + sitk::GaussianImageSource source1; source1.SetMean(pt0); source1.SetScale(1.0); @@ -162,7 +162,6 @@ TEST_F(sitkRegistrationMethodTest, Metric_Evaluate) sitk::Image fixed = fixedBlobs; sitk::Image moving = fixedBlobs; - sitk::ImageRegistrationMethod R; R.SetInitialTransform(sitk::Transform(fixed.GetDimension(),sitk::sitkIdentity)); @@ -441,6 +440,68 @@ TEST_F(sitkRegistrationMethodTest, Mask_Test2) } +TEST_F(sitkRegistrationMethodTest, VirtualDomain_Test) +{ + // Test usage of setting virtual domain + + sitk::ImageRegistrationMethod R; + R.SetInterpolator(sitk::sitkLinear); + //R.DebugOn(); + sitk::Image virtualImage = MakeGaussianBlob( v2(32,32), std::vector(2,64) ); + + R.SetVirtualDomainFromImage(virtualImage); + + // transform to optimize + sitk::TranslationTransform tx(virtualImage.GetDimension()); + tx.SetOffset(v2(3.2,-1.2)); + R.SetInitialTransform(tx, false); + + sitk::Image fixedImage = virtualImage; + fixedImage.SetOrigin(v2(100, 0)); + + // virtual image to fixed image + sitk::TranslationTransform fixedTransform(fixedImage.GetDimension()); + fixedTransform.SetOffset(v2(100, 0)); + R.SetFixedInitialTransform(fixedTransform); + + sitk::Image movingImage = virtualImage; + movingImage.SetOrigin(v2(0, 200)); + + // transform from virtual domain to moving image with "optimizing" transform + sitk::TranslationTransform movingTransform(movingImage.GetDimension()); + movingTransform.SetOffset(v2(0, 200)); + R.SetMovingInitialTransform(movingTransform); + + R.SetMetricAsCorrelation(); + + double minStep=1e-5; + unsigned int numberOfIterations=100; + double relaxationFactor=0.75; + double gradientMagnitudeTolerance = 1e-20; + R.SetOptimizerAsRegularStepGradientDescent(.1, + minStep, + numberOfIterations, + relaxationFactor, + gradientMagnitudeTolerance); + + + IterationUpdate cmd(R); + R.AddCommand(sitk::sitkIterationEvent, cmd); + + sitk::Transform outTx = R.Execute(fixedImage, movingImage); + + + std::cout << "-------" << std::endl; + std::cout << outTx.ToString() << std::endl; + std::cout << "Optimizer stop condition: " << R.GetOptimizerStopConditionDescription() << std::endl; + std::cout << " Iteration: " << R.GetOptimizerIteration() << std::endl; + std::cout << " Metric value: " << R.GetMetricValue() << std::endl; + + EXPECT_VECTOR_DOUBLE_NEAR(v2(0.0,0.0), outTx.GetParameters(), 1e-3); + EXPECT_GT( R.GetOptimizerIteration(), 1 ); + +} + TEST_F(sitkRegistrationMethodTest, OptimizerWeights_Test) { // Test the usage of optimizer weights From e5e4b3b8386d848d744474c4002ed882adf741d0 Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Thu, 17 Nov 2016 15:35:11 -0500 Subject: [PATCH 2/6] Remove extraneous print statements. Change-Id: Ic6251b4b06da1aa28f44483ba0b34444c03a5a05 --- Code/Registration/src/sitkImageRegistrationMethod.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/Code/Registration/src/sitkImageRegistrationMethod.cxx b/Code/Registration/src/sitkImageRegistrationMethod.cxx index 80c1e8678..bd5e8a1ce 100644 --- a/Code/Registration/src/sitkImageRegistrationMethod.cxx +++ b/Code/Registration/src/sitkImageRegistrationMethod.cxx @@ -693,7 +693,6 @@ Transform ImageRegistrationMethod::ExecuteInternal ( const Image &inFixed, const { sitkExceptionMacro( "Unexpected error converting initial moving transform! Possible miss matching dimensions!" ); } - std::cout << "--------> Setting MovingInitalTransform\n"; registration->SetMovingInitialTransform(itkTx); } @@ -705,7 +704,6 @@ Transform ImageRegistrationMethod::ExecuteInternal ( const Image &inFixed, const { sitkExceptionMacro( "Unexpected error converting initial moving transform! Possible miss matching dimensions!" ); } - std::cout << "--------> Setting FixedInitalTransform\n"; registration->SetFixedInitialTransform(itkTx); } From cdfbaf0d283e8f437351c9e681f581d37b108953 Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Thu, 17 Nov 2016 15:35:30 -0500 Subject: [PATCH 3/6] Adding registration test with multi-levels and virtual image Change-Id: I93febb6e28d907638b437b956d4d5733e4cf0c90 --- .../Unit/sitkImageRegistrationMethodTests.cxx | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/Testing/Unit/sitkImageRegistrationMethodTests.cxx b/Testing/Unit/sitkImageRegistrationMethodTests.cxx index b637655a0..de93b5944 100644 --- a/Testing/Unit/sitkImageRegistrationMethodTests.cxx +++ b/Testing/Unit/sitkImageRegistrationMethodTests.cxx @@ -502,6 +502,78 @@ TEST_F(sitkRegistrationMethodTest, VirtualDomain_Test) } +TEST_F(sitkRegistrationMethodTest, VirtualDomain_MultiRes_Test) +{ + // Test usage of setting virtual domain + + sitk::ImageRegistrationMethod R; + R.SetInterpolator(sitk::sitkLinear); + //R.DebugOn(); + sitk::Image virtualImage = MakeGaussianBlob( v3(32,32,32), std::vector(3,64) ); + + R.SetVirtualDomainFromImage(virtualImage); + + // transform to optimize + sitk::TranslationTransform tx(virtualImage.GetDimension()); + tx.SetOffset(v3(5.21231, 3.2,-1.2)); + R.SetInitialTransform(tx, false); + + sitk::Image fixedImage = virtualImage; + fixedImage.SetOrigin(v3(1000, 100, 0)); + + // virtual image to fixed image + sitk::TranslationTransform fixedTransform(fixedImage.GetDimension()); + fixedTransform.SetOffset(v3(1000, 100, 0)); + R.SetFixedInitialTransform(fixedTransform); + + sitk::Image movingImage = virtualImage; + movingImage.SetOrigin(v3(0, 200, 512)); + + // transform from virtual domain to moving image with "optimizing" transform + sitk::TranslationTransform movingTransform(movingImage.GetDimension()); + movingTransform.SetOffset(v3(0, 200, 512)); + R.SetMovingInitialTransform(movingTransform); + + R.SetMetricAsMeanSquares(); + + double minStep=1e-3; + unsigned int numberOfIterations=10; + double relaxationFactor=0.6; + double gradientMagnitudeTolerance = 1e-10; + sitk::ImageRegistrationMethod::EstimateLearningRateType estimateLearningRate = sitk::ImageRegistrationMethod::Never; + R.SetOptimizerAsRegularStepGradientDescent(2, + minStep, + numberOfIterations, + relaxationFactor, + gradientMagnitudeTolerance, + estimateLearningRate); + + std::vector shrinkFactors(2); + shrinkFactors[0] = 8; + shrinkFactors[1] = 1; + R.SetShrinkFactorsPerLevel( shrinkFactors ); + R.SetSmoothingSigmasPerLevel( v2(0.0, 0.0) ); + + R.SetOptimizerScalesFromJacobian(); + + IterationUpdate cmd(R); + R.AddCommand(sitk::sitkIterationEvent, cmd); + + sitk::Transform outTx = R.Execute(fixedImage, movingImage); + + + std::cout << "-------" << std::endl; + std::cout << outTx.ToString() << std::endl; + std::cout << "Optimizer stop condition: " << R.GetOptimizerStopConditionDescription() << std::endl; + std::cout << " Iteration: " << R.GetOptimizerIteration() << std::endl; + std::cout << " Metric value: " << R.GetMetricValue() << std::endl; + + EXPECT_VECTOR_DOUBLE_NEAR(v3(0.0,0.0,0.0), outTx.GetParameters(), 1e-1); + EXPECT_GT( R.GetOptimizerIteration(), 1 ); + +} + + TEST_F(sitkRegistrationMethodTest, OptimizerWeights_Test) { // Test the usage of optimizer weights From 60f8efc3d4569192db3bd277f17869e86f0ed695 Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Fri, 18 Nov 2016 10:28:21 -0500 Subject: [PATCH 4/6] Adding check for virtual domain parameters Verify that all parameters to describe the virtual domain are a compatible length. Change-Id: Ic65017988ef6df0b916ddcbb753ce3fa6b862927 --- .../src/sitkImageRegistrationMethod.cxx | 15 +++++- .../Unit/sitkImageRegistrationMethodTests.cxx | 46 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/Code/Registration/src/sitkImageRegistrationMethod.cxx b/Code/Registration/src/sitkImageRegistrationMethod.cxx index bd5e8a1ce..d84c7a6fa 100644 --- a/Code/Registration/src/sitkImageRegistrationMethod.cxx +++ b/Code/Registration/src/sitkImageRegistrationMethod.cxx @@ -139,7 +139,20 @@ ImageRegistrationMethod::SetVirtualDomain( const std::vector &virtualS { const size_t dim = virtualSize.size(); - // todo check size of vectors + if ( virtualOrigin.size() != dim ) + { + sitkExceptionMacro("Expected virtualOrigin to be of length " << dim << "!" ); + } + + if ( virtualSpacing.size() != dim ) + { + sitkExceptionMacro("Expected virtualSpacing to be of length " << dim << "!" ); + } + + if ( virtualDirection.size() != dim*dim ) + { + sitkExceptionMacro("Expected virtualDirection to be of length " << dim*dim << "!" ); + } this->m_VirtualDomainSize = virtualSize; this->m_VirtualDomainOrigin = virtualOrigin; diff --git a/Testing/Unit/sitkImageRegistrationMethodTests.cxx b/Testing/Unit/sitkImageRegistrationMethodTests.cxx index de93b5944..644321206 100644 --- a/Testing/Unit/sitkImageRegistrationMethodTests.cxx +++ b/Testing/Unit/sitkImageRegistrationMethodTests.cxx @@ -574,6 +574,52 @@ TEST_F(sitkRegistrationMethodTest, VirtualDomain_MultiRes_Test) } + +TEST_F(sitkRegistrationMethodTest, VirtualDomain_Parameters) +{ + + sitk::ImageRegistrationMethod R; + R.SetInterpolator(sitk::sitkLinear); + + sitk::Image virtualImage = MakeGaussianBlob( v3(32,32,32), std::vector(3,64) ); + + std::vector size(3, 64); + + EXPECT_NO_THROW( + R.SetVirtualDomain(size, + v3(0.0,0.0,0.0), + v3(1.0,1.0,1.0), + v9(1.0,0.0,0.0, + 0.0,1.0,0.0, + 0.0,0.0,1.0)) ); + + EXPECT_THROW( + R.SetVirtualDomain(size, + v2(0.0,0.0), + v3(1.0,1.0,1.0), + v9(1.0,0.0,0.0, + 0.0,1.0,0.0, + 0.0,0.0,1.0)), + sitk::GenericException); + + + EXPECT_THROW( + R.SetVirtualDomain(size, + v3(0.0,0.0,0.0), + v2(1.0,1.0), + v9(1.0,0.0,0.0, + 0.0,1.0,0.0, + 0.0,0.0,1.0)), + sitk::GenericException ); + + EXPECT_THROW( + R.SetVirtualDomain(size, + v3(0.0,0.0,0.0), + v3(1.0,1.0,1.0), + v3(1.0,0.0,0.0)), + sitk::GenericException ); +} + TEST_F(sitkRegistrationMethodTest, OptimizerWeights_Test) { // Test the usage of optimizer weights From 26b9b88b20e2f0c6699412341c5dd52f52fd63b0 Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Fri, 25 Nov 2016 10:36:37 -0500 Subject: [PATCH 5/6] address signed to unsigned integer comparison warning --- Testing/Unit/sitkImageRegistrationMethodTests.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Testing/Unit/sitkImageRegistrationMethodTests.cxx b/Testing/Unit/sitkImageRegistrationMethodTests.cxx index 644321206..bfb1548fc 100644 --- a/Testing/Unit/sitkImageRegistrationMethodTests.cxx +++ b/Testing/Unit/sitkImageRegistrationMethodTests.cxx @@ -498,7 +498,7 @@ TEST_F(sitkRegistrationMethodTest, VirtualDomain_Test) std::cout << " Metric value: " << R.GetMetricValue() << std::endl; EXPECT_VECTOR_DOUBLE_NEAR(v2(0.0,0.0), outTx.GetParameters(), 1e-3); - EXPECT_GT( R.GetOptimizerIteration(), 1 ); + EXPECT_GT( R.GetOptimizerIteration(), 1u ); } From 6cd05a7d4a04cf60db56ba73b979c76f3df400cf Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Mon, 5 Dec 2016 15:09:48 -0500 Subject: [PATCH 6/6] Fix another signed to unsigned comparison warning Change-Id: I7778bcea4e8b295376634fe2bf5b7a27a73df2a6 --- Testing/Unit/sitkImageRegistrationMethodTests.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Testing/Unit/sitkImageRegistrationMethodTests.cxx b/Testing/Unit/sitkImageRegistrationMethodTests.cxx index bfb1548fc..6f63405a4 100644 --- a/Testing/Unit/sitkImageRegistrationMethodTests.cxx +++ b/Testing/Unit/sitkImageRegistrationMethodTests.cxx @@ -569,7 +569,7 @@ TEST_F(sitkRegistrationMethodTest, VirtualDomain_MultiRes_Test) std::cout << " Metric value: " << R.GetMetricValue() << std::endl; EXPECT_VECTOR_DOUBLE_NEAR(v3(0.0,0.0,0.0), outTx.GetParameters(), 1e-1); - EXPECT_GT( R.GetOptimizerIteration(), 1 ); + EXPECT_GT( R.GetOptimizerIteration(), 1u ); }