22 #ifndef otbStreamingWarpImageFilter_hxx
23 #define otbStreamingWarpImageFilter_hxx
26 #include "itkImageRegionIteratorWithIndex.h"
27 #include "itkDefaultConvertPixelTraits.h"
28 #include "itkMetaDataObject.h"
35 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
39 m_MaximumDisplacement.Fill(1);
40 m_OutputSignedSpacing = this->Superclass::GetOutputSpacing();
44 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
47 m_OutputSignedSpacing = outputSpacing;
49 typename TInputImage::DirectionType direction = this->GetOutput()->GetDirection();
50 for (
unsigned int i = 0; i < TInputImage::ImageDimension; ++i)
54 if (direction[i][i] > 0)
56 for (
unsigned int j = 0; j < TInputImage::ImageDimension; ++j)
58 direction[j][i] = -direction[j][i];
61 spacing[i] = -spacing[i];
64 this->Superclass::SetOutputSpacing(spacing);
65 this->Superclass::SetOutputDirection(direction);
69 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
73 for (
unsigned int i = 0; i < TInputImage::ImageDimension; ++i)
75 s[i] =
static_cast<typename SpacingType::ValueType
>(values[i]);
77 this->SetOutputSpacing(s);
80 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
83 Superclass::GenerateInputRequestedRegion();
90 if (!inputPtr || !displacementPtr || !outputPtr)
100 typename OutputImageType::RegionType outputRequestedRegion = outputPtr->GetRequestedRegion();
101 typename OutputImageType::IndexType outIndexStart = outputRequestedRegion.GetIndex();
102 typename OutputImageType::IndexType outIndexEnd;
103 for (
unsigned int dim = 0; dim < OutputImageType::ImageDimension; ++dim)
104 outIndexEnd[dim] = outIndexStart[dim] + outputRequestedRegion.GetSize()[dim] - 1;
105 typename OutputImageType::PointType outPointStart, outPointEnd;
106 outputPtr->TransformIndexToPhysicalPoint(outIndexStart, outPointStart);
107 outputPtr->TransformIndexToPhysicalPoint(outIndexEnd, outPointEnd);
109 typename DisplacementFieldType::IndexType defIndexStart, defIndexEnd;
110 displacementPtr->TransformPhysicalPointToIndex(outPointStart, defIndexStart);
111 displacementPtr->TransformPhysicalPointToIndex(outPointEnd, defIndexEnd);
113 typename DisplacementFieldType::SizeType defRequestedSize;
114 typename DisplacementFieldType::IndexType defRequestedIndex;
116 for (
unsigned int dim = 0; dim < OutputImageType::ImageDimension; ++dim)
118 defRequestedIndex[dim] = std::min(defIndexStart[dim], defIndexEnd[dim]);
119 defRequestedSize[dim] = std::max(defIndexStart[dim], defIndexEnd[dim]) - defRequestedIndex[dim] + 1;
123 typename DisplacementFieldType::RegionType displacementRequestedRegion;
124 displacementRequestedRegion.SetIndex(defRequestedIndex);
125 displacementRequestedRegion.SetSize(defRequestedSize);
128 displacementRequestedRegion.PadByRadius(1);
131 if (displacementRequestedRegion.Crop(displacementPtr->GetLargestPossibleRegion()))
133 displacementPtr->SetRequestedRegion(displacementRequestedRegion);
141 displacementPtr->SetRequestedRegion(displacementRequestedRegion);
144 itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
145 e.SetLocation(ITK_LOCATION);
146 e.SetDescription(
"Requested region is (at least partially) outside the largest possible region of the displacement field.");
147 e.SetDataObject(inputPtr);
157 displacementPtr->PropagateRequestedRegion();
158 displacementPtr->UpdateOutputData();
161 itk::ImageRegionIteratorWithIndex<DisplacementFieldType> defIt(displacementPtr, displacementRequestedRegion);
164 typename InputImageType::PointType currentPoint;
165 typename InputImageType::PointType inputStartPoint, inputEndPoint;
168 displacementPtr->TransformIndexToPhysicalPoint(defIt.GetIndex(), currentPoint);
169 for (
unsigned int dim = 0; dim < DisplacementFieldType::ImageDimension; ++dim)
171 currentPoint[dim] += defIt.Get()[dim];
173 inputStartPoint = currentPoint;
174 inputEndPoint = currentPoint;
179 while (!defIt.IsAtEnd())
181 displacementPtr->TransformIndexToPhysicalPoint(defIt.GetIndex(), currentPoint);
182 for (
unsigned int dim = 0; dim < DisplacementFieldType::ImageDimension; ++dim)
184 currentPoint[dim] += defIt.Get()[dim];
185 if (inputStartPoint[dim] > currentPoint[dim])
186 inputStartPoint[dim] = currentPoint[dim];
187 if (inputEndPoint[dim] < currentPoint[dim])
188 inputEndPoint[dim] = currentPoint[dim];
194 typename InputImageType::IndexType inputStartIndex, inputEndIndex;
195 inputPtr->TransformPhysicalPointToIndex(inputStartPoint, inputStartIndex);
196 inputPtr->TransformPhysicalPointToIndex(inputEndPoint, inputEndIndex);
198 typename InputImageType::SizeType inputFinalSize;
199 typename InputImageType::IndexType inputFinalIndex;
201 for (
unsigned int dim = 0; dim < DisplacementFieldType::ImageDimension; ++dim)
203 inputFinalIndex[dim] = std::min(inputStartIndex[dim], inputEndIndex[dim]);
204 inputFinalSize[dim] = std::max(inputStartIndex[dim], inputEndIndex[dim]) - inputFinalIndex[dim] + 1;
207 typename InputImageType::RegionType inputRequestedRegion;
208 inputRequestedRegion.SetIndex(inputFinalIndex);
209 inputRequestedRegion.SetSize(inputFinalSize);
215 inputRequestedRegion.PadByRadius(interpolatorRadius);
218 if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
220 inputPtr->SetRequestedRegion(inputRequestedRegion);
228 for (
auto dim = 0U; dim < InputImageType::ImageDimension; ++dim)
230 auto largestInputRegion = inputPtr->GetLargestPossibleRegion();
232 if (largestInputRegion.GetSize()[dim] > 1)
234 inputFinalIndex[dim] = largestInputRegion.GetIndex()[dim] + 1;
235 inputFinalSize[dim] = 0;
239 inputFinalIndex[dim] = largestInputRegion.GetIndex()[dim];
240 inputFinalSize[dim] = largestInputRegion.GetSize()[dim];
244 inputRequestedRegion.SetSize(inputFinalSize);
245 inputRequestedRegion.SetIndex(inputFinalIndex);
246 inputPtr->SetRequestedRegion(inputRequestedRegion);
251 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
254 Superclass::GenerateOutputInformation();
257 std::vector<bool> noDataValueAvailable;
258 std::vector<double> noDataValue;
260 auto res =
ReadNoDataFlags(this->GetOutput()->GetImageMetadata(), noDataValueAvailable, noDataValue);
264 noDataValueAvailable.resize(this->GetOutput()->GetNumberOfComponentsPerPixel(),
false);
265 noDataValue.resize(this->GetOutput()->GetNumberOfComponentsPerPixel(), 0.0);
268 PixelType edgePadding = this->GetEdgePaddingValue();
269 if (itk::NumericTraits<PixelType>::GetLength(edgePadding) != this->GetOutput()->GetNumberOfComponentsPerPixel())
271 itk::NumericTraits<PixelType>::SetLength(edgePadding, this->GetOutput()->GetNumberOfComponentsPerPixel());
272 this->SetEdgePaddingValue(edgePadding);
274 for (
unsigned int i = 0; i < noDataValueAvailable.size(); ++i)
276 if (!noDataValueAvailable[i])
278 noDataValueAvailable[i] =
true;
279 noDataValue[i] = itk::DefaultConvertPixelTraits<PixelType>::GetNthComponent(i, edgePadding);
283 WriteNoDataFlags(noDataValueAvailable, noDataValue, this->GetOutput()->GetImageMetadata());
286 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
288 itk::ThreadIdType threadId)
291 Superclass::ThreadedGenerateData(outputRegionForThread, threadId);
294 const PixelType paddingValue = this->GetEdgePaddingValue();
306 itk::ImageRegionIteratorWithIndex<OutputImageType> outputIt(outputPtr, outputRegionForThread);
309 itk::ContinuousIndex<double, DisplacementFieldType::ImageDimension> contiIndex;
311 while (!outputIt.IsAtEnd())
314 currentIndex = outputIt.GetIndex();
315 outputPtr->TransformIndexToPhysicalPoint(currentIndex, currentPoint);
316 fieldPtr->TransformPhysicalPointToContinuousIndex(currentPoint, contiIndex);
318 for (
unsigned int dim = 0; dim < DisplacementFieldType::ImageDimension; ++dim)
320 if (contiIndex[dim] <
static_cast<double>(defRegion.GetIndex(dim)) ||
321 contiIndex[dim] >
static_cast<double>(defRegion.GetIndex(dim) + defRegion.GetSize(dim) - 1))
323 outputIt.Set(paddingValue);
331 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
334 Superclass::PrintSelf(os, indent);
335 os << indent <<
"Maximum displacement: " << m_MaximumDisplacement << std::endl;