From 849966f8ca3a76f25eb85aed016ae9018e9140f8 Mon Sep 17 00:00:00 2001 From: Pablo Hernandez-Cerdan Date: Mon, 14 Jan 2019 15:09:00 -0500 Subject: [PATCH] BUG: Fix origin of itkFFTPadPositiveIndexImageFilter See https://github.com/InsightSoftwareConsortium/ITK/issues/400 for more context on the origin in ITK. It corresponds to the index{0}, not to the first index. Some tests related with boundary condition are removed, as they are not needed. --- include/itkFFTPadPositiveIndexImageFilter.h | 18 ++++++++++++++++- include/itkFFTPadPositiveIndexImageFilter.hxx | 9 +++++++++ test/CMakeLists.txt | 13 +----------- .../itkFFTPadPositiveIndexImageFilterTest.cxx | 20 +++++++++++++++++++ .../itkFFTPadPositiveIndexImageFilter.wrap | 6 +----- 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/include/itkFFTPadPositiveIndexImageFilter.h b/include/itkFFTPadPositiveIndexImageFilter.h index 35da3b7..6c81876 100644 --- a/include/itkFFTPadPositiveIndexImageFilter.h +++ b/include/itkFFTPadPositiveIndexImageFilter.h @@ -21,6 +21,8 @@ #include "itkFFTPadImageFilter.h" #include "itkImageBoundaryCondition.h" +#include "itkConstantBoundaryCondition.h" +#include "itkPeriodicBoundaryCondition.h" #include "itkChangeInformationImageFilter.h" namespace itk @@ -101,7 +103,20 @@ class FFTPadPositiveIndexImageFilter: this->Modified(); } } - + itkGetConstMacro(HalfPadSize, SizeType); + void SetBoundaryConditionToConstant(const OutputImagePixelType & boundaryValue) + { + using BoundaryCondition = itk::ConstantBoundaryCondition< InputImageType, OutputImageType >; + static BoundaryCondition boundaryCondition; + boundaryCondition.SetConstant(boundaryValue); + this->SetBoundaryCondition(&boundaryCondition); + } + void SetBoundaryConditionToPeriodic() + { + using BoundaryCondition = itk::PeriodicBoundaryCondition< InputImageType, OutputImageType >; + static BoundaryCondition boundaryCondition; + this->SetBoundaryCondition(&boundaryCondition); + } protected: FFTPadPositiveIndexImageFilter(); ~FFTPadPositiveIndexImageFilter() override {}; @@ -118,6 +133,7 @@ class FFTPadPositiveIndexImageFilter: typename ChangeInfoFilterType::Pointer m_ChangeInfoFilter; SizeValueType m_SizeGreatestPrimeFactor; BoundaryConditionPointerType m_BoundaryCondition; + SizeType m_HalfPadSize; }; // end of class } // end namespace itk diff --git a/include/itkFFTPadPositiveIndexImageFilter.hxx b/include/itkFFTPadPositiveIndexImageFilter.hxx index 18875ff..0a21e26 100644 --- a/include/itkFFTPadPositiveIndexImageFilter.hxx +++ b/include/itkFFTPadPositiveIndexImageFilter.hxx @@ -37,6 +37,7 @@ FFTPadPositiveIndexImageFilter< TInputImage, TOutputImage > m_BoundaryCondition = m_FFTPadFilter->GetBoundaryCondition(); m_ChangeInfoFilter = ChangeInfoFilterType::New(); m_ChangeInfoFilter->ChangeRegionOn(); + m_ChangeInfoFilter->ChangeOriginOn(); } template< class TInputImage, class TOutputImage > @@ -106,11 +107,14 @@ FFTPadPositiveIndexImageFilter< TInputImage, TOutputImage > // make sure the total size is even padSize += ( inputRegion.GetSize()[i] + padSize ) % 2; } + m_HalfPadSize[i] = padSize/2; index[i] = inputRegion.GetIndex()[i]; size[i] = inputRegion.GetSize()[i] + padSize; } RegionType region( index, size ); outputPtr->SetLargestPossibleRegion( region ); + // In GenerateData the output will be grafted from a ChangeInformationFilter. + // That will set the correct Origin. } template< class TInputImage, class TOutputImage > @@ -148,8 +152,13 @@ FFTPadPositiveIndexImageFilter< TInputImage, TOutputImage > typename OutputImageType::IndexType negativeIndex = m_FFTPadFilter->GetOutput()->GetLargestPossibleRegion().GetIndex(); + auto outputNewOrigin = this->GetInput()->GetOrigin(); + auto fakeOriginIndex = this->GetInput()->GetLargestPossibleRegion().GetIndex() - m_HalfPadSize; + this->GetInput()->TransformIndexToPhysicalPoint(fakeOriginIndex, outputNewOrigin); + m_ChangeInfoFilter->SetOutputOffset( outputIndex - negativeIndex); itkDebugMacro(<< "Offset difference: " << outputIndex - negativeIndex); + m_ChangeInfoFilter->SetOutputOrigin( outputNewOrigin ); m_ChangeInfoFilter->SetInput(m_FFTPadFilter->GetOutput()); m_ChangeInfoFilter->GraftOutput(output); m_ChangeInfoFilter->Update(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bd384c0..008ef09 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -345,24 +345,13 @@ itk_add_test(NAME itkFrequencyShrinkEvenTest 2 ) ##FFTPad -itk_add_test(NAME itkFFTPadPositiveIndexImageFilterTestZeroFluxNeumann - COMMAND IsotropicWaveletsTestDriver - itkFFTPadPositiveIndexImageFilterTest - DATA{Input/checkershadow_Lch_512x512.tiff} - ${ITK_TEST_OUTPUT_DIR}/itkFFTPadPositiveIndexImageFilterTestZeroFluxNeumann.tiff 2 ZEROFLUXNEUMANN - ) +# TODO: Add 2D Odd Data, current 512x512 input does not cover the class well. Other boundary conditions have been removed. itk_add_test(NAME itkFFTPadPositiveIndexImageFilterTestConstant COMMAND IsotropicWaveletsTestDriver itkFFTPadPositiveIndexImageFilterTest DATA{Input/checkershadow_Lch_512x512.tiff} ${ITK_TEST_OUTPUT_DIR}/itkFFTPadPositiveIndexImageFilterTestConstant.tiff 2 CONSTANT ) - itk_add_test(NAME itkFFTPadPositiveIndexImageFilterTestPeriodic - COMMAND IsotropicWaveletsTestDriver - itkFFTPadPositiveIndexImageFilterTest - DATA{Input/checkershadow_Lch_512x512.tiff} - ${ITK_TEST_OUTPUT_DIR}/itkFFTPadPositiveIndexImageFilterTestPeriodic.tiff 2 PERIODIC - ) ## ZeroDC itk_add_test(NAME itkZeroDCImageFilterTest COMMAND IsotropicWaveletsTestDriver diff --git a/test/itkFFTPadPositiveIndexImageFilterTest.cxx b/test/itkFFTPadPositiveIndexImageFilterTest.cxx index 1545be3..865f60d 100644 --- a/test/itkFFTPadPositiveIndexImageFilterTest.cxx +++ b/test/itkFFTPadPositiveIndexImageFilterTest.cxx @@ -67,6 +67,7 @@ int itkFFTPadPositiveIndexImageFilterTest( int argc, char * argv[] ) { fftpad->SetBoundaryCondition( &constantBoundaryCondition ); TEST_SET_GET_VALUE( &constantBoundaryCondition, fftpad->GetBoundaryCondition() ); + fftpad->SetBoundaryConditionToConstant(0); } else if ( boundaryCondition == "PERIODIC" ) { @@ -102,6 +103,25 @@ int itkFFTPadPositiveIndexImageFilterTest( int argc, char * argv[] ) return EXIT_FAILURE; } } + auto inOrigin = reader->GetOutput()->GetOrigin(); + auto outOrigin = fftpad->GetOutput()->GetOrigin(); + std::cout << "InputOrigin: " << inOrigin << ". OutputOrigin: " << outOrigin << std::endl; + + auto expectedOrigin = reader->GetOutput()->GetOrigin(); + auto computedIndex = + reader->GetOutput()->GetLargestPossibleRegion().GetIndex() - fftpad->GetHalfPadSize(); + reader->GetOutput()->TransformIndexToPhysicalPoint( computedIndex, expectedOrigin); + for ( unsigned int i = 0; i < Dimension; ++i ) + { + if ( expectedOrigin[i] != outOrigin[i] ) + { + std::cerr << "Test failed!" << std::endl; + std::cerr << "Origin is not updated." << std::endl; + std::cerr << "Dim: " << i << ". Expected: " << expectedOrigin[i] << + ". Output: " << outOrigin[i] << std::endl; + return EXIT_FAILURE; + } + } auto writer = WriterType::New(); writer->SetInput( fftpad->GetOutput() ); diff --git a/wrapping/itkFFTPadPositiveIndexImageFilter.wrap b/wrapping/itkFFTPadPositiveIndexImageFilter.wrap index 90044c4..e83687e 100644 --- a/wrapping/itkFFTPadPositiveIndexImageFilter.wrap +++ b/wrapping/itkFFTPadPositiveIndexImageFilter.wrap @@ -1,7 +1,3 @@ itk_wrap_class("itk::FFTPadPositiveIndexImageFilter" POINTER) - foreach(d ${ITK_WRAP_IMAGE_DIMS}) - foreach(t ${WRAP_ITK_REAL}) - itk_wrap_template("${ITKM_I${t}${d}}" "${ITKT_I${t}${d}}") - endforeach() - endforeach() + itk_wrap_image_filter("${WRAP_ITK_ALL_TYPES}" 1) itk_end_wrap_class()