From 1e974f55220b2334d719ab91aa6dfd828707ea04 Mon Sep 17 00:00:00 2001 From: Julien Michel Date: Mon, 26 Oct 2015 17:54:45 +0100 Subject: [PATCH 1/2] ENH: Support of VectorImage as template parameters for WarpImageFilter This patch relates to issue #2895 ( https://issues.itk.org/jira/browse/ITK-2895#comment-27056 ) It is a straigthforward port of OTB patch provided by Julien Malik on his github page (see first comment) Patch summary: - In itkWarpImageFilter.h: - Replace HasNumericTraits concept checking on TInputImage::PixelType by checking on TInputImage::InternalPixelType, since HasNumericTraits will fail with VariableLengthVector as PixelType - In itkWarpImageFilter.txx: - Changed instanciation of m_EdgePaddingValue member to avoid calling NumericTraits< PixelType >::Zero, which does not exist for VariableLengthVector - Add further initialization of m_EdgePaddingValue in BeforeThreadedGenerateData, so that it will generate a VariableLenghtVector of appropriate length if needed - Avoid calling DisplacementType::Dimension and use the GetLength method from NumericTraits instead, which will support both static and dynamic (VariableLengthVector) length - In itkWarpImageFilterTest.cxx: - Added a simple test for template instanciation of WarpImageFilter using VectorImage for all three template parameters Change-Id: I44fb183dd6a684a23312446b2bc2d62e7f8eff7b --- .../ImageGrid/include/itkWarpImageFilter.h | 2 +- .../ImageGrid/include/itkWarpImageFilter.hxx | 14 ++++++++++++-- .../ImageGrid/test/itkWarpImageFilterTest.cxx | 11 +++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.h b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.h index 44558f581e7..86c626b8bb5 100644 --- a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.h +++ b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.h @@ -240,7 +240,7 @@ class WarpImageFilter: itkConceptMacro( SameDimensionCheck2, ( Concept::SameDimension< ImageDimension, DisplacementFieldDimension > ) ); itkConceptMacro( InputHasNumericTraitsCheck, - ( Concept::HasNumericTraits< typename TInputImage::PixelType > ) ); + ( Concept::HasNumericTraits< typename TInputImage::InternalPixelType > ) ); itkConceptMacro( DisplacementFieldHasNumericTraitsCheck, ( Concept::HasNumericTraits< typename TDisplacementField::PixelType::ValueType > ) ); // End concept checking diff --git a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx index a9a72a258b9..cae18eb0d4c 100644 --- a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx +++ b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx @@ -43,7 +43,7 @@ WarpImageFilter< TInputImage, TOutputImage, TDisplacementField > m_OutputOrigin.Fill(0.0); m_OutputDirection.SetIdentity(); m_OutputSize.Fill(0); - m_EdgePaddingValue = NumericTraits< PixelType >::ZeroValue(); + m_EdgePaddingValue = NumericTraits< typename OutputImageType::InternalPixelType >::ZeroValue(); m_OutputStartIndex.Fill(0); // Setup default interpolator typename DefaultInterpolatorType::Pointer interp = @@ -179,6 +179,16 @@ WarpImageFilter< TInputImage, TOutputImage, TDisplacementField > } DisplacementFieldPointer fieldPtr = this->GetDisplacementField(); + + if (NumericTraits::GetLength(m_EdgePaddingValue) + != this->GetInput()->GetNumberOfComponentsPerPixel() ) + { + // Assume EdgePaddingValue has not been set externally + // initialize it here with ZeroValue, when we know the number of components + const PixelType& pixel = this->GetInput()->GetPixel( this->GetInput()->GetBufferedRegion().GetIndex() ); + m_EdgePaddingValue = NumericTraits::ZeroValue( pixel ); + } + // Connect input image to interpolator m_Interpolator->SetInputImage( this->GetInput() ); @@ -292,7 +302,7 @@ WarpImageFilter< TInputImage, TOutputImage, TDisplacementField > { const DisplacementType input = fieldPtr->GetPixel(neighIndex); - for ( unsigned int k = 0; k < ImageDimension; k++ ) + for ( unsigned int k = 0; k < NumericTraits::GetLength(input); k++ ) { output[k] += overlap * static_cast< double >( input[k] ); } diff --git a/Modules/Filtering/ImageGrid/test/itkWarpImageFilterTest.cxx b/Modules/Filtering/ImageGrid/test/itkWarpImageFilterTest.cxx index 117cb8a1df0..d7f91c26334 100644 --- a/Modules/Filtering/ImageGrid/test/itkWarpImageFilterTest.cxx +++ b/Modules/Filtering/ImageGrid/test/itkWarpImageFilterTest.cxx @@ -22,6 +22,7 @@ #include "itkWarpImageFilter.h" #include "itkVectorCastImageFilter.h" #include "itkStreamingImageFilter.h" +#include "itkVectorImage.h" #include "itkMath.h" // class to produce a linear image pattern @@ -97,8 +98,8 @@ int itkWarpImageFilterTest(int, char* [] ) typedef float PixelType; enum { ImageDimension = 2 }; typedef itk::Image ImageType; - - typedef itk::Vector VectorType; + typedef itk::VectorImage VectorImageType; + typedef itk::Vector VectorType; typedef itk::Image FieldType; bool testPassed = true; @@ -169,7 +170,13 @@ int itkWarpImageFilterTest(int, char* [] ) } //============================================================= + std::cout << "Instanciate WarpImageFilter with VectorImage."; + std::cout << std::endl; + typedef itk::WarpImageFilter WarpVectorImageFilterType; + WarpVectorImageFilterType::Pointer warpVectorImageFilter = WarpVectorImageFilterType::New(); + + //============================================================= std::cout << "Run WarpImageFilter in standalone mode with progress."; std::cout << std::endl; typedef itk::WarpImageFilter WarperType; From 091a58e1343397b9bb1493ff9e7715092d308ff5 Mon Sep 17 00:00:00 2001 From: Julien Michel Date: Fri, 30 Oct 2015 09:34:14 +0100 Subject: [PATCH 2/2] ENH: Modifying initialization of m_EdgePaddingValue to follow the same behaviour as in itk::ResampleImageFilter --- .../ImageGrid/include/itkWarpImageFilter.h | 1 + .../ImageGrid/include/itkWarpImageFilter.hxx | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.h b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.h index 86c626b8bb5..4cf044747cb 100644 --- a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.h +++ b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.h @@ -114,6 +114,7 @@ class WarpImageFilter: typedef typename OutputImageType::IndexValueType IndexValueType; typedef typename OutputImageType::SizeType SizeType; typedef typename OutputImageType::PixelType PixelType; + typedef typename OutputImageType::InternalPixelType PixelComponentType; typedef typename OutputImageType::SpacingType SpacingType; /** Determine the image dimension. */ diff --git a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx index cae18eb0d4c..a03be3c16d9 100644 --- a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx +++ b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx @@ -23,6 +23,7 @@ #include "itkImageRegionIteratorWithIndex.h" #include "itkImageAlgorithm.h" #include "itkNumericTraits.h" +#include "itkDefaultConvertPixelTraits.h" #include "itkProgressReporter.h" #include "itkContinuousIndex.h" #include "vnl/vnl_math.h" @@ -43,7 +44,7 @@ WarpImageFilter< TInputImage, TOutputImage, TDisplacementField > m_OutputOrigin.Fill(0.0); m_OutputDirection.SetIdentity(); m_OutputSize.Fill(0); - m_EdgePaddingValue = NumericTraits< typename OutputImageType::InternalPixelType >::ZeroValue(); + m_EdgePaddingValue = NumericTraits< PixelType >::ZeroValue(m_EdgePaddingValue); m_OutputStartIndex.Fill(0); // Setup default interpolator typename DefaultInterpolatorType::Pointer interp = @@ -179,6 +180,19 @@ WarpImageFilter< TInputImage, TOutputImage, TDisplacementField > } DisplacementFieldPointer fieldPtr = this->GetDisplacementField(); + unsigned int nbComponents = DefaultConvertPixelTraits::GetNumberOfComponents(m_EdgePaddingValue); + + if(nbComponents!= this->GetInput()->GetNumberOfComponentsPerPixel()) + { + PixelComponentType zeroComponent = NumericTraits::ZeroValue(zeroComponent); + nbComponents = this->GetInput()->GetNumberOfComponentsPerPixel(); + NumericTraits::SetLength(m_EdgePaddingValue,nbComponents); + + for(unsigned int n = 0; n < nbComponents;++n) + { + DefaultConvertPixelTraits::SetNthComponent(n,m_EdgePaddingValue,zeroComponent); + } + } if (NumericTraits::GetLength(m_EdgePaddingValue) != this->GetInput()->GetNumberOfComponentsPerPixel() )