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>
38 this->DynamicMultiThreadingOn();
40 m_MaximumDisplacement.Fill(1);
41 m_OutputSignedSpacing = this->Superclass::GetOutputSpacing();
45 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
48 m_OutputSignedSpacing = outputSpacing;
50 typename TInputImage::DirectionType direction = this->GetOutput()->GetDirection();
51 for (
unsigned int i = 0; i < TInputImage::ImageDimension; ++i)
55 if (direction[i][i] > 0)
57 for (
unsigned int j = 0; j < TInputImage::ImageDimension; ++j)
59 direction[j][i] = -direction[j][i];
62 spacing[i] = -spacing[i];
65 this->Superclass::SetOutputSpacing(spacing);
66 this->Superclass::SetOutputDirection(direction);
70 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
74 for (
unsigned int i = 0; i < TInputImage::ImageDimension; ++i)
76 s[i] =
static_cast<typename SpacingType::ValueType
>(values[i]);
78 this->SetOutputSpacing(s);
81 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
84 Superclass::GenerateInputRequestedRegion();
91 if (!inputPtr || !displacementPtr || !outputPtr)
101 typename OutputImageType::RegionType outputRequestedRegion = outputPtr->GetRequestedRegion();
102 typename OutputImageType::IndexType outIndexStart = outputRequestedRegion.GetIndex();
103 typename OutputImageType::IndexType outIndexEnd;
104 for (
unsigned int dim = 0; dim < OutputImageType::ImageDimension; ++dim)
105 outIndexEnd[dim] = outIndexStart[dim] + outputRequestedRegion.GetSize()[dim] - 1;
106 typename OutputImageType::PointType outPointStart, outPointEnd;
107 outputPtr->TransformIndexToPhysicalPoint(outIndexStart, outPointStart);
108 outputPtr->TransformIndexToPhysicalPoint(outIndexEnd, outPointEnd);
110 typename DisplacementFieldType::IndexType defIndexStart, defIndexEnd;
111 displacementPtr->TransformPhysicalPointToIndex(outPointStart, defIndexStart);
112 displacementPtr->TransformPhysicalPointToIndex(outPointEnd, defIndexEnd);
114 typename DisplacementFieldType::SizeType defRequestedSize;
115 typename DisplacementFieldType::IndexType defRequestedIndex;
117 for (
unsigned int dim = 0; dim < OutputImageType::ImageDimension; ++dim)
119 defRequestedIndex[dim] = std::min(defIndexStart[dim], defIndexEnd[dim]);
120 defRequestedSize[dim] = std::max(defIndexStart[dim], defIndexEnd[dim]) - defRequestedIndex[dim] + 1;
124 typename DisplacementFieldType::RegionType displacementRequestedRegion;
125 displacementRequestedRegion.SetIndex(defRequestedIndex);
126 displacementRequestedRegion.SetSize(defRequestedSize);
129 displacementRequestedRegion.PadByRadius(1);
132 if (displacementRequestedRegion.Crop(displacementPtr->GetLargestPossibleRegion()))
134 displacementPtr->SetRequestedRegion(displacementRequestedRegion);
142 displacementPtr->SetRequestedRegion(displacementRequestedRegion);
145 itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
146 e.SetLocation(ITK_LOCATION);
147 e.SetDescription(
"Requested region is (at least partially) outside the largest possible region of the displacement field.");
148 e.SetDataObject(inputPtr);
158 displacementPtr->PropagateRequestedRegion();
159 displacementPtr->UpdateOutputData();
162 itk::ImageRegionIteratorWithIndex<DisplacementFieldType> defIt(displacementPtr, displacementRequestedRegion);
165 typename InputImageType::PointType currentPoint;
166 typename InputImageType::PointType inputStartPoint, inputEndPoint;
169 displacementPtr->TransformIndexToPhysicalPoint(defIt.GetIndex(), currentPoint);
170 for (
unsigned int dim = 0; dim < DisplacementFieldType::ImageDimension; ++dim)
172 currentPoint[dim] += defIt.Get()[dim];
174 inputStartPoint = currentPoint;
175 inputEndPoint = currentPoint;
180 while (!defIt.IsAtEnd())
182 displacementPtr->TransformIndexToPhysicalPoint(defIt.GetIndex(), currentPoint);
183 for (
unsigned int dim = 0; dim < DisplacementFieldType::ImageDimension; ++dim)
185 currentPoint[dim] += defIt.Get()[dim];
186 if (inputStartPoint[dim] > currentPoint[dim])
187 inputStartPoint[dim] = currentPoint[dim];
188 if (inputEndPoint[dim] < currentPoint[dim])
189 inputEndPoint[dim] = currentPoint[dim];
195 typename InputImageType::IndexType inputStartIndex, inputEndIndex;
196 inputPtr->TransformPhysicalPointToIndex(inputStartPoint, inputStartIndex);
197 inputPtr->TransformPhysicalPointToIndex(inputEndPoint, inputEndIndex);
199 typename InputImageType::SizeType inputFinalSize;
200 typename InputImageType::IndexType inputFinalIndex;
202 for (
unsigned int dim = 0; dim < DisplacementFieldType::ImageDimension; ++dim)
204 inputFinalIndex[dim] = std::min(inputStartIndex[dim], inputEndIndex[dim]);
205 inputFinalSize[dim] = std::max(inputStartIndex[dim], inputEndIndex[dim]) - inputFinalIndex[dim] + 1;
208 typename InputImageType::RegionType inputRequestedRegion;
209 inputRequestedRegion.SetIndex(inputFinalIndex);
210 inputRequestedRegion.SetSize(inputFinalSize);
216 inputRequestedRegion.PadByRadius(interpolatorRadius);
219 if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
221 inputPtr->SetRequestedRegion(inputRequestedRegion);
229 for (
auto dim = 0U; dim < InputImageType::ImageDimension; ++dim)
231 auto largestInputRegion = inputPtr->GetLargestPossibleRegion();
233 if (largestInputRegion.GetSize()[dim] > 1)
235 inputFinalIndex[dim] = largestInputRegion.GetIndex()[dim] + 1;
236 inputFinalSize[dim] = 0;
240 inputFinalIndex[dim] = largestInputRegion.GetIndex()[dim];
241 inputFinalSize[dim] = largestInputRegion.GetSize()[dim];
245 inputRequestedRegion.SetSize(inputFinalSize);
246 inputRequestedRegion.SetIndex(inputFinalIndex);
247 inputPtr->SetRequestedRegion(inputRequestedRegion);
252 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
255 Superclass::GenerateOutputInformation();
258 std::vector<bool> noDataValueAvailable;
259 std::vector<double> noDataValue;
261 auto res =
ReadNoDataFlags(this->GetOutput()->GetImageMetadata(), noDataValueAvailable, noDataValue);
265 noDataValueAvailable.resize(this->GetOutput()->GetNumberOfComponentsPerPixel(),
false);
266 noDataValue.resize(this->GetOutput()->GetNumberOfComponentsPerPixel(), 0.0);
269 PixelType edgePadding = this->GetEdgePaddingValue();
270 if (itk::NumericTraits<PixelType>::GetLength(edgePadding) != this->GetOutput()->GetNumberOfComponentsPerPixel())
272 itk::NumericTraits<PixelType>::SetLength(edgePadding, this->GetOutput()->GetNumberOfComponentsPerPixel());
273 this->SetEdgePaddingValue(edgePadding);
275 for (
unsigned int i = 0; i < noDataValueAvailable.size(); ++i)
277 if (!noDataValueAvailable[i])
279 noDataValueAvailable[i] =
true;
280 noDataValue[i] = itk::DefaultConvertPixelTraits<PixelType>::GetNthComponent(i, edgePadding);
284 WriteNoDataFlags(noDataValueAvailable, noDataValue, this->GetOutput()->GetImageMetadata());
287 template <
class TInputImage,
class TOutputImage,
class TDisplacementField>
291 Superclass::DynamicThreadedGenerateData(outputRegionForThread);
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;
static unsigned int CalculateNeededRadiusForInterpolator(const InterpolationType *interpolator)
OutputImageType::SpacingType SpacingType
TOutputImage OutputImageType
OutputImageType::PixelType PixelType
OutputImageType::IndexType IndexType
OutputImageType::PointType PointType
void SetOutputSpacing(const SpacingType OutputSpacing) override
void GenerateInputRequestedRegion() override
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) override
TInputImage InputImageType
void GenerateOutputInformation() override
StreamingWarpImageFilter()
OutputImageType::Pointer OutputImagePointerType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
OutputImageType::RegionType OutputImageRegionType
DisplacementFieldType::RegionType DisplacementFieldRegionType
TDisplacementField DisplacementFieldType
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
bool OTBMetadata_EXPORT ReadNoDataFlags(const ImageMetadata &imd, std::vector< bool > &flags, std::vector< double > &values)
void OTBMetadata_EXPORT WriteNoDataFlags(const std::vector< bool > &flags, const std::vector< double > &values, ImageMetadata &imd)