21 #ifndef otbOverlapSaveConvolutionImageFilter_hxx
22 #define otbOverlapSaveConvolutionImageFilter_hxx
24 #include "itkConfigure.h"
28 #include "itkConstNeighborhoodIterator.h"
29 #include "itkImageRegionIteratorWithIndex.h"
30 #include "itkNeighborhoodAlgorithm.h"
31 #include "itkOffset.h"
32 #include "itkProgressReporter.h"
35 #include "itkImageRegionIterator.h"
39 #include "itkFFTWCommon.h"
45 template <
class TInputImage,
class TOutputImage,
class TBoundaryCondition>
49 m_Filter.SetSize(3 * 3);
51 m_NormalizeFilter =
false;
54 template <
class TInputImage,
class TOutputImage,
class TBoundaryCondition>
57 #if defined ITK_USE_FFTWD
59 Superclass::GenerateInputRequestedRegion();
62 typename Superclass::InputImagePointer inputPtr =
const_cast<TInputImage*
>(this->GetInput());
63 typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
65 if (!inputPtr || !outputPtr)
72 typename TInputImage::RegionType inputRequestedRegion;
73 inputRequestedRegion = inputPtr->GetRequestedRegion();
76 inputRequestedRegion.PadByRadius(m_Radius);
79 if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
81 inputPtr->SetRequestedRegion(inputRequestedRegion);
90 inputPtr->SetRequestedRegion(inputRequestedRegion);
93 itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
94 e.SetLocation(ITK_LOCATION);
95 e.SetDescription(
"Requested region is (at least partially) outside the largest possible region.");
96 e.SetDataObject(inputPtr);
100 itkGenericExceptionMacro(<<
"The OverlapSaveConvolutionImageFilter can not operate without the FFTW library (double implementation). Please build ITK with "
101 "USE_FFTD set to ON, and rebuild OTB.");
105 template <
class TInputImage,
class TOutputImage,
class TBoundaryCondition>
111 #if defined ITK_USE_FFTWD
113 typename OutputImageType::Pointer output = this->GetOutput();
114 typename InputImageType::ConstPointer input = this->GetInput();
118 this->AllocateOutputs();
122 typename InputImageType::SizeType sizeOfFilter;
123 sizeOfFilter[0] = 2 * m_Radius[0] + 1;
124 sizeOfFilter[1] = 2 * m_Radius[1] + 1;
131 inputRegionForThread.PadByRadius(m_Radius);
135 typename InputImageType::RegionType pieceRegion = inputRegionForThread;
136 typename InputImageType::SizeType pieceSize = pieceRegion.GetSize();
137 typename InputImageType::IndexType pieceIndex = pieceRegion.GetIndex();
140 unsigned int pieceNbOfPixel = pieceRegion.GetNumberOfPixels();
141 unsigned int sizeFFT = (pieceSize[0] / 2 + 1) * pieceSize[1];
144 inputRegionForThread.Crop(input->GetLargestPossibleRegion());
145 typename InputImageType::IndexType inputIndex = inputRegionForThread.GetIndex();
146 typename InputImageType::SizeType inputSize = inputRegionForThread.GetSize();
149 itk::ConstNeighborhoodIterator<InputImageType, BoundaryConditionType> inputIt(m_Radius, input, inputRegionForThread);
153 itk::ImageRegionIteratorWithIndex<OutputImageType> outputIt;
154 outputIt = itk::ImageRegionIteratorWithIndex<OutputImageType>(output, outputRegionForThread);
157 unsigned int i, j, k, l;
160 typedef typename itk::fftw::Proxy<double> FFTWProxyType;
164 resampledFilterPiece =
static_cast<FFTWProxyType::PixelType*
>(fftw_malloc(pieceNbOfPixel *
sizeof(
InputPixelType)));
166 FFTWProxyType::ComplexType* filterPieceFFT;
167 filterPieceFFT =
static_cast<FFTWProxyType::ComplexType*
>(fftw_malloc(sizeFFT *
sizeof(FFTWProxyType::ComplexType)));
170 inputPiece =
static_cast<FFTWProxyType::PixelType*
>(fftw_malloc(pieceNbOfPixel *
sizeof(
InputPixelType)));
172 FFTWProxyType::ComplexType* inputPieceFFT;
173 inputPieceFFT =
static_cast<FFTWProxyType::ComplexType*
>(fftw_malloc(sizeFFT *
sizeof(FFTWProxyType::ComplexType)));
176 FFTWProxyType::PlanType inputPlan = FFTWProxyType::Plan_dft_r2c_2d(pieceSize[1], pieceSize[0], inputPiece, inputPieceFFT, FFTW_MEASURE);
179 unsigned int leftskip =
static_cast<unsigned int>(std::max((
typename InputImageType::IndexValueType)0, inputIndex[0] - pieceIndex[0]));
180 unsigned int topskip = pieceSize[0] *
static_cast<unsigned int>(std::max((
typename InputImageType::IndexValueType)0, inputIndex[1] - pieceIndex[1]));
186 for (l = 0; l < inputSize[1]; ++l)
188 for (k = 0; k < inputSize[0]; ++k)
190 inputPiece[topskip + pieceSize[0] * l + k + leftskip] = inputIt.GetCenterPixel();
195 FFTWProxyType::Execute(inputPlan);
198 FFTWProxyType::PlanType filterPlan = FFTWProxyType::Plan_dft_r2c_2d(pieceSize[1], pieceSize[0], resampledFilterPiece, filterPieceFFT, FFTW_MEASURE);
201 memset(resampledFilterPiece, 0, pieceNbOfPixel *
sizeof(
InputPixelType));
205 for (j = 0; j < sizeOfFilter[1]; ++j)
207 for (i = 0; i < sizeOfFilter[0]; ++i)
209 resampledFilterPiece[i + j * pieceSize[0]] = m_Filter.GetElement(k);
214 FFTWProxyType::Execute(filterPlan);
217 FFTWProxyType::ComplexType* multipliedFFTarray;
218 multipliedFFTarray =
static_cast<FFTWProxyType::ComplexType*
>(fftw_malloc(sizeFFT *
sizeof(FFTWProxyType::ComplexType)));
220 FFTWProxyType::PixelType* inverseFFTpiece;
221 inverseFFTpiece =
static_cast<FFTWProxyType::PixelType*
>(fftw_malloc(pieceNbOfPixel *
sizeof(FFTWProxyType::PixelType)));
224 FFTWProxyType::PlanType outputPlan = FFTWProxyType::Plan_dft_c2r_2d(pieceSize[1], pieceSize[0], multipliedFFTarray, inverseFFTpiece, FFTW_MEASURE);
227 for (k = 0; k < sizeFFT; ++k)
230 multipliedFFTarray[k][0] = inputPieceFFT[k][0] * filterPieceFFT[k][0] - inputPieceFFT[k][1] * filterPieceFFT[k][1];
231 multipliedFFTarray[k][1] = inputPieceFFT[k][0] * filterPieceFFT[k][1] + inputPieceFFT[k][1] * filterPieceFFT[k][0];
234 FFTWProxyType::Execute(outputPlan);
238 if (m_NormalizeFilter)
240 norm = itk::NumericTraits<InputRealType>::Zero;
241 for (i = 0; i < sizeOfFilter[0] * sizeOfFilter[1]; ++i)
260 outputIt.GoToBegin();
261 while (!outputIt.IsAtEnd())
263 typename InputImageType::IndexType index = outputIt.GetIndex();
264 unsigned int linearIndex = (index[1] + sizeOfFilter[1] - 1 - outputRegionForThread.GetIndex()[1]) * pieceSize[0] - 1 + index[0] + sizeOfFilter[0] -
265 outputRegionForThread.GetIndex()[0];
266 outputIt.Set(
static_cast<OutputPixelType>((inverseFFTpiece[linearIndex] / pieceNbOfPixel) *
static_cast<double>(norm)));
271 FFTWProxyType::DestroyPlan(inputPlan);
272 FFTWProxyType::DestroyPlan(filterPlan);
273 FFTWProxyType::DestroyPlan(outputPlan);
276 fftw_free(resampledFilterPiece);
277 fftw_free(inputPiece);
278 fftw_free(filterPieceFFT);
279 fftw_free(inputPieceFFT);
280 fftw_free(multipliedFFTarray);
281 fftw_free(inverseFFTpiece);
283 itkGenericExceptionMacro(<<
"The OverlapSaveConvolutionImageFilter can not operate without the FFTW library (double implementation). Please build ITK with "
284 "USE_FFTD set to ON, and rebuild OTB.");
289 template <
class TInputImage,
class TOutput,
class TBoundaryCondition>
292 Superclass::PrintSelf(os, indent);
293 os << indent <<
"Radius: " << m_Radius << std::endl;
294 os << indent <<
"Normalize filter: " << m_NormalizeFilter << std::endl;