X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=itk%2FclitkResampleImageWithOptionsFilter.txx;h=a3f88beb3db8443f08fa376da1480433f24e4051;hb=02f230e65dbfde06e84da374bb085643e29b5090;hp=aee15f5d397670e4f90a30c5b8ac497116bc2c20;hpb=8e4f61d01c82ffcf2e9180d7fd4e3aedac83f6f7;p=clitk.git diff --git a/itk/clitkResampleImageWithOptionsFilter.txx b/itk/clitkResampleImageWithOptionsFilter.txx index aee15f5..a3f88be 100644 --- a/itk/clitkResampleImageWithOptionsFilter.txx +++ b/itk/clitkResampleImageWithOptionsFilter.txx @@ -1,9 +1,9 @@ /*========================================================================= Program: vv http://www.creatis.insa-lyon.fr/rio/vv - Authors belong to: + Authors belong to: - University of LYON http://www.universite-lyon.fr/ - - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr + - Léon Bérard cancer center http://www.centreleonberard.fr - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr This software is distributed WITHOUT ANY WARRANTY; without even @@ -14,10 +14,10 @@ - BSD See included LICENSE.txt file - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html - ======================================================================-====*/ + ===========================================================================**/ // clitk -#include "clitkCommon.h" +#include "clitkDD.h" // itk include #include "itkImage.h" @@ -28,270 +28,307 @@ #include "itkResampleImageFilter.h" #include "itkAffineTransform.h" #include "itkNearestNeighborInterpolateImageFunction.h" +#include "itkWindowedSincInterpolateImageFunction.h" #include "itkLinearInterpolateImageFunction.h" #include "itkBSplineInterpolateImageFunction.h" #include "itkBSplineInterpolateImageFunctionWithLUT.h" #include "itkCommand.h" -namespace clitk { - - //-------------------------------------------------------------------- - template - ResampleImageWithOptionsFilter:: - ResampleImageWithOptionsFilter():itk::ImageToImageFilter() { - static const unsigned int dim = InputImageType::ImageDimension; - this->SetNumberOfRequiredInputs(1); - m_OutputIsoSpacing = -1; - m_InterpolationType = NearestNeighbor; - m_GaussianFilteringEnabled = true; - m_BSplineOrder = 3; - m_BLUTSamplingFactor = 20; - m_LastDimensionIsTime = false; - m_Transform = TransformType::New(); - if (dim == 4) m_LastDimensionIsTime = true; // by default 4D is 3D+t - for(unsigned int i=0; i +clitk::ResampleImageWithOptionsFilter:: +ResampleImageWithOptionsFilter():itk::ImageToImageFilter() +{ + static const unsigned int dim = InputImageType::ImageDimension; + this->SetNumberOfRequiredInputs(1); + m_OutputIsoSpacing = -1; + m_InterpolationType = NearestNeighbor; + m_GaussianFilteringEnabled = true; + m_BSplineOrder = 3; + m_BLUTSamplingFactor = 20; + m_LastDimensionIsTime = false; + m_Transform = TransformType::New(); + if (dim == 4) m_LastDimensionIsTime = true; // by default 4D is 3D+t + for(unsigned int i=0; i - void - ResampleImageWithOptionsFilter:: - SetInput(const InputImageType * image) { - // Process object is not const-correct so the const casting is required. - this->SetNthInput(0, const_cast(image)); - } - //-------------------------------------------------------------------- - - - //-------------------------------------------------------------------- - template - void - ResampleImageWithOptionsFilter:: - GenerateInputRequestedRegion() { - // call the superclass's implementation of this method - Superclass::GenerateInputRequestedRegion(); - - // get pointers to the input and output - InputImagePointer inputPtr = - const_cast< TInputImage *>( this->GetInput() ); - - // Request the entire input image - InputImageRegionType inputRegion; - inputRegion = inputPtr->GetLargestPossibleRegion(); - inputPtr->SetRequestedRegion(inputRegion); - } - //-------------------------------------------------------------------- - - - //-------------------------------------------------------------------- - template - void - ResampleImageWithOptionsFilter:: - GenerateOutputInformation() { - static const unsigned int dim = InputImageType::ImageDimension; - - // Warning - if (!std::numeric_limits::is_signed) { - if ((m_InterpolationType == BSpline) || - (m_InterpolationType == B_LUT)) { - std::cerr << "Warning : input pixel type is not signed, use bspline interpolation at your own risk ..." << std::endl; - } +//-------------------------------------------------------------------- +template +void +clitk::ResampleImageWithOptionsFilter:: +SetInput(const InputImageType * image) +{ + // Process object is not const-correct so the const casting is required. + this->SetNthInput(0, const_cast(image)); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ResampleImageWithOptionsFilter:: +GenerateInputRequestedRegion() +{ + // call the superclass's implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // get pointers to the input and output + InputImagePointer inputPtr = + const_cast< InputImageType *>( this->GetInput() ); + + // Request the entire input image + InputImageRegionType inputRegion; + inputRegion = inputPtr->GetLargestPossibleRegion(); + inputPtr->SetRequestedRegion(inputRegion); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +void +clitk::ResampleImageWithOptionsFilter:: +GenerateOutputInformation() +{ + static const unsigned int dim = InputImageType::ImageDimension; + + // Warning + if (!std::numeric_limits::is_signed) { + if ((m_InterpolationType == BSpline) || + (m_InterpolationType == B_LUT)) { + std::cerr << "Warning : input pixel type is not signed, use bspline interpolation at your own risk ..." << std::endl; } + } + + // Get input pointer + InputImagePointer input = dynamic_cast(itk::ProcessObject::GetInput(0)); - // Get input pointer - InputImagePointer input = dynamic_cast(itk::ProcessObject::GetInput(0)); - - // Perform default implementation - Superclass::GenerateOutputInformation(); + // Perform default implementation + Superclass::GenerateOutputInformation(); - // Compute sizes - InputImageSpacingType inputSpacing = input->GetSpacing(); - InputImageSizeType inputSize = input->GetLargestPossibleRegion().GetSize(); + // Compute sizes + InputImageSpacingType inputSpacing = input->GetSpacing(); + InputImageSizeType inputSize = input->GetLargestPossibleRegion().GetSize(); - if (m_OutputIsoSpacing != -1) { // apply isoSpacing + if (m_OutputIsoSpacing != -1) { // apply isoSpacing + for(unsigned int i=0; iGetOutput(0); - OutputImageRegionType region; - region.SetSize(m_OutputSize); - region.SetIndex(input->GetLargestPossibleRegion().GetIndex()); - DD(input->GetLargestPossibleRegion().GetIndex()); - outputImage->SetLargestPossibleRegion(region); - outputImage->SetSpacing(m_OutputSpacing); - - // Init Gaussian sigma - if (m_GaussianSigma[0] != -1) { // Gaussian filter set by user - m_GaussianFilteringEnabled = true; - } - else { - if (m_GaussianFilteringEnabled) { // Automated sigma when downsample - for(unsigned int i=0; i inputSpacing[i]) { // downsample - m_GaussianSigma[i] = 0.5*m_OutputSpacing[i];// / inputSpacing[i]); - } - else m_GaussianSigma[i] = 0; // will be ignore after + // Special case for temporal image 2D+t or 3D+t + if (m_LastDimensionIsTime) { + int l = dim-1; + m_OutputSize[l] = inputSize[l]; + m_OutputSpacing[l] = inputSpacing[l]; + } + + // Set Size/Spacing + OutputImagePointer outputImage = this->GetOutput(0); + // OutputImageRegionType region; + m_OutputRegion.SetSize(m_OutputSize); + m_OutputRegion.SetIndex(input->GetLargestPossibleRegion().GetIndex()); + outputImage->CopyInformation(input); + outputImage->SetLargestPossibleRegion(m_OutputRegion); + outputImage->SetSpacing(m_OutputSpacing); + + // Init Gaussian sigma + if (m_GaussianSigma[0] != -1) { // Gaussian filter set by user + m_GaussianFilteringEnabled = true; + } + else { + if (m_GaussianFilteringEnabled) { // Automated sigma when downsample + for(unsigned int i=0; i inputSpacing[i]) { // downsample + m_GaussianSigma[i] = 0.5*m_OutputSpacing[i];// / inputSpacing[i]); } + else m_GaussianSigma[i] = 0; // will be ignore after } } - if (m_GaussianFilteringEnabled && m_LastDimensionIsTime) { - m_GaussianSigma[dim-1] = 0; - } } - //-------------------------------------------------------------------- + if (m_GaussianFilteringEnabled && m_LastDimensionIsTime) { + m_GaussianSigma[dim-1] = 0; + } +} +//-------------------------------------------------------------------- - //-------------------------------------------------------------------- - template - void - ResampleImageWithOptionsFilter:: - GenerateData() { +//-------------------------------------------------------------------- +template +void +clitk::ResampleImageWithOptionsFilter:: +GenerateData() +{ - // Get input pointer - InputImagePointer input = dynamic_cast(itk::ProcessObject::GetInput(0)); - static const unsigned int dim = InputImageType::ImageDimension; - - // Create main Resample Image Filter - typedef itk::ResampleImageFilter FilterType; - typename FilterType::Pointer filter = FilterType::New(); - filter->GraftOutput(this->GetOutput()); -// this->GetOutput()->Print(std::cout); -// this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetLargestPossibleRegion()); -// this->GetOutput()->Print(std::cout); - - // Print options if needed - if (m_VerboseOptions) { - std::cout << "Output Spacing = " << m_OutputSpacing << std::endl - << "Output Size = " << m_OutputSize << std::endl - << "Gaussian = " << m_GaussianFilteringEnabled << std::endl; - if (m_GaussianFilteringEnabled) - std::cout << "Sigma = " << m_GaussianSigma << std::endl; - std::cout << "Interpol = "; - switch (m_InterpolationType) { - case NearestNeighbor: std::cout << "NearestNeighbor" << std::endl; break; - case Linear: std::cout << "Linear" << std::endl; break; - case BSpline: std::cout << "BSpline " << m_BSplineOrder << std::endl; break; - case B_LUT: std::cout << "B-LUT " << m_BSplineOrder << " " << m_BLUTSamplingFactor << std::endl; break; - } - std::cout << "Threads = " << this->GetNumberOfThreads() << std::endl; - std::cout << "LastDimIsTime = " << m_LastDimensionIsTime << std::endl; - } + // Get input pointer + InputImagePointer input = dynamic_cast(itk::ProcessObject::GetInput(0)); + static const unsigned int dim = InputImageType::ImageDimension; - // Instance of the transform object to be passed to the resample - // filter. By default, identity transform is applied - filter->SetTransform(m_Transform); - filter->SetSize(m_OutputSize); - filter->SetOutputSpacing(m_OutputSpacing); - filter->SetOutputOrigin(input->GetOrigin()); - filter->SetDefaultPixelValue(m_DefaultPixelValue); - filter->SetNumberOfThreads(this->GetNumberOfThreads()); + // Create main Resample Image Filter + typedef itk::ResampleImageFilter FilterType; + typename FilterType::Pointer filter = FilterType::New(); + filter->GraftOutput(this->GetOutput()); + this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetLargestPossibleRegion()); - // Select interpolator + // Print options if needed + if (m_VerboseOptions) { + std::cout << "Output Spacing = " << m_OutputSpacing << std::endl + << "Output Size = " << m_OutputSize << std::endl + << "Gaussian = " << m_GaussianFilteringEnabled << std::endl; + if (m_GaussianFilteringEnabled) + std::cout << "Sigma = " << m_GaussianSigma << std::endl; + std::cout << "Interpol = "; switch (m_InterpolationType) { - case NearestNeighbor: - { - typedef itk::NearestNeighborInterpolateImageFunction InterpolatorType; - typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); - filter->SetInterpolator(interpolator); - break; - } - case Linear: - { - typedef itk::LinearInterpolateImageFunction InterpolatorType; - typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); - filter->SetInterpolator(interpolator); - break; - } - case BSpline: - { - typedef itk::BSplineInterpolateImageFunction InterpolatorType; - typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); - interpolator->SetSplineOrder(m_BSplineOrder); - filter->SetInterpolator(interpolator); - break; - } - case B_LUT: - { - typedef itk::BSplineInterpolateImageFunctionWithLUT InterpolatorType; - typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); - interpolator->SetSplineOrder(m_BSplineOrder); - interpolator->SetLUTSamplingFactor(m_BLUTSamplingFactor); - filter->SetInterpolator(interpolator); - break; - } + case NearestNeighbor: std::cout << "NearestNeighbor" << std::endl; break; + case Linear: std::cout << "Linear" << std::endl; break; + case BSpline: std::cout << "BSpline " << m_BSplineOrder << std::endl; break; + case B_LUT: std::cout << "B-LUT " << m_BSplineOrder << " " << m_BLUTSamplingFactor << std::endl; break; + case WSINC: std::cout << "Windowed Sinc" << std::endl; break; } - - // Initial Gaussian blurring if needed - typedef itk::RecursiveGaussianImageFilter GaussianFilterType; - std::vector gaussianFilters; - if (m_GaussianFilteringEnabled) { - for(unsigned int i=0; iSetDirection(i); - gaussianFilters[i]->SetOrder(GaussianFilterType::ZeroOrder); - gaussianFilters[i]->SetNormalizeAcrossScale(false); - gaussianFilters[i]->SetSigma(m_GaussianSigma[i]); // in millimeter ! - if (gaussianFilters.size() == 1) { // first - gaussianFilters[0]->SetInput(input); - } - else { - gaussianFilters[i]->SetInput(gaussianFilters[i-1]->GetOutput()); - } + std::cout << "Threads = " << this->GetNumberOfThreads() << std::endl; + std::cout << "LastDimIsTime = " << m_LastDimensionIsTime << std::endl; + } + + // Instance of the transform object to be passed to the resample + // filter. By default, identity transform is applied + filter->SetTransform(m_Transform); + filter->SetSize(m_OutputSize); + filter->SetOutputSpacing(m_OutputSpacing); + filter->SetOutputOrigin(input->GetOrigin()); + filter->SetDefaultPixelValue(m_DefaultPixelValue); + filter->SetNumberOfThreads(this->GetNumberOfThreads()); + filter->SetOutputDirection(input->GetDirection()); // <-- NEEDED if we want to keep orientation (in case of PermutAxes for example) + + // Select interpolator + switch (m_InterpolationType) { + case NearestNeighbor: { + typedef itk::NearestNeighborInterpolateImageFunction InterpolatorType; + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); + filter->SetInterpolator(interpolator); + break; + } + case Linear: { + typedef itk::LinearInterpolateImageFunction InterpolatorType; + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); + filter->SetInterpolator(interpolator); + break; + } + case BSpline: { + typedef itk::BSplineInterpolateImageFunction InterpolatorType; + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); + interpolator->SetSplineOrder(m_BSplineOrder); + filter->SetInterpolator(interpolator); + break; + } + case B_LUT: { + typedef itk::BSplineInterpolateImageFunctionWithLUT InterpolatorType; + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); + interpolator->SetSplineOrder(m_BSplineOrder); + interpolator->SetLUTSamplingFactor(m_BLUTSamplingFactor); + filter->SetInterpolator(interpolator); + break; + } + case WSINC: { + typedef itk::WindowedSincInterpolateImageFunction InterpolatorType; + typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); + filter->SetInterpolator(interpolator); + break; + } + } + + // Initial Gaussian blurring if needed + // TODO : replace by itk::DiscreteGaussianImageFilter for small sigma + typedef itk::RecursiveGaussianImageFilter GaussianFilterType; + std::vector gaussianFilters; + if (m_GaussianFilteringEnabled) { + for(unsigned int i=0; iSetDirection(i); + gaussianFilters[i]->SetOrder(GaussianFilterType::ZeroOrder); + gaussianFilters[i]->SetNormalizeAcrossScale(false); + gaussianFilters[i]->SetSigma(m_GaussianSigma[i]); // in millimeter ! + if (gaussianFilters.size() == 1) { // first + gaussianFilters[0]->SetInput(input); + } else { + gaussianFilters[i]->SetInput(gaussianFilters[i-1]->GetOutput()); } } - if (gaussianFilters.size() > 0) { - filter->SetInput(gaussianFilters[gaussianFilters.size()-1]->GetOutput()); - } - else filter->SetInput(input); } - else filter->SetInput(input); - - // Go ! - filter->Update(); - - // Set output - // DD("before Graft"); - this->GraftOutput(filter->GetOutput()); - // DD("after Graft"); + if (gaussianFilters.size() > 0) { + filter->SetInput(gaussianFilters[gaussianFilters.size()-1]->GetOutput()); + } else filter->SetInput(input); + } else filter->SetInput(input); + + // Go ! + filter->Update(); + + // Set output + // DD("before Graft"); + + //this->GraftOutput(filter->GetOutput()); + this->SetNthOutput(0, filter->GetOutput()); + + // DD("after Graft"); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +template +typename InputImageType::Pointer +clitk::ResampleImageSpacing(typename InputImageType::Pointer input, + typename InputImageType::SpacingType spacing, + int interpolationType) +{ + typedef clitk::ResampleImageWithOptionsFilter ResampleFilterType; + typename ResampleFilterType::Pointer resampler = ResampleFilterType::New(); + resampler->SetInput(input); + resampler->SetOutputSpacing(spacing); + typename ResampleFilterType::InterpolationTypeEnumeration inter=ResampleFilterType::NearestNeighbor; + switch(interpolationType) { + case 0: inter = ResampleFilterType::NearestNeighbor; break; + case 1: inter = ResampleFilterType::Linear; break; + case 2: inter = ResampleFilterType::BSpline; break; + case 3: inter = ResampleFilterType::B_LUT; break; + case 4: inter = ResampleFilterType::WSINC; break; } - //-------------------------------------------------------------------- - -}//end clitk - + resampler->SetInterpolationType(inter); + resampler->SetGaussianFilteringEnabled(true); + resampler->Update(); + return resampler->GetOutput(); +} +//--------------------------------------------------------------------