21 #ifndef otbStereoSensorModelToElevationMapFilter_hxx
22 #define otbStereoSensorModelToElevationMapFilter_hxx
26 #include "itkImageRegionIteratorWithIndex.h"
27 #include "itkProgressReporter.h"
28 #include "itkLinearInterpolateImageFunction.h"
30 #include "itkConstNeighborhoodIterator.h"
35 template <
class TInputImage,
class TOutputHeight>
39 this->SetNumberOfRequiredInputs(2);
40 this->SetNumberOfRequiredOutputs(2);
41 this->SetNthOutput(1, OutputImageType::New());
44 m_Interpolator = itk::LinearInterpolateImageFunction<TInputImage>::New();
50 m_LowerElevation = -20;
51 m_HigherElevation = 20;
53 m_CorrelationThreshold = 0.7;
54 m_VarianceThreshold = 4;
55 m_SubtractInitialElevation =
false;
58 template <
class TInputImage,
class TOutputHeight>
63 template <
class TInputImage,
class TOutputHeight>
66 this->SetNthInput(0,
const_cast<TInputImage*
>(image));
69 template <
class TInputImage,
class TOutputHeight>
72 this->SetNthInput(1,
const_cast<TInputImage*
>(image));
75 template <
class TInputImage,
class TOutputHeight>
78 if (this->GetNumberOfInputs() < 1)
82 return static_cast<const TInputImage*
>(this->itk::ProcessObject::GetInput(0));
85 template <
class TInputImage,
class TOutputHeight>
88 if (this->GetNumberOfInputs() < 2)
92 return static_cast<const TInputImage*
>(this->itk::ProcessObject::GetInput(1));
95 template <
class TInputImage,
class TOutputHeight>
98 if (this->GetNumberOfOutputs() < 2)
102 return static_cast<TOutputHeight*
>(this->itk::ProcessObject::GetOutput(1));
105 template <
class TInputImage,
class TOutputHeight>
109 Superclass::GenerateInputRequestedRegion();
116 if (!masterPtr || !slavePtr || !outputPtr)
123 typename InputImageType::RegionType masterRequestedRegion, slaveRequestedRegion;
124 masterRequestedRegion = outputPtr->GetRequestedRegion();
127 masterRequestedRegion.PadByRadius(m_Radius);
130 typename InputImageType::IndexType mul, mur, mll, mlr;
131 mul = masterRequestedRegion.GetIndex();
132 mur = masterRequestedRegion.GetIndex();
133 mur[0] += masterRequestedRegion.GetSize()[0] - 1;
134 mll = masterRequestedRegion.GetIndex();
135 mll[1] += masterRequestedRegion.GetSize()[1] - 1;
136 mlr = masterRequestedRegion.GetIndex();
137 mlr[0] += masterRequestedRegion.GetSize()[0] - 1;
138 mlr[1] += masterRequestedRegion.GetSize()[1] - 1;
141 typename InputImageType::PointType mpul, mpur, mpll, mplr;
142 masterPtr->TransformIndexToPhysicalPoint(mul, mpul);
143 masterPtr->TransformIndexToPhysicalPoint(mur, mpur);
144 masterPtr->TransformIndexToPhysicalPoint(mll, mpll);
145 masterPtr->TransformIndexToPhysicalPoint(mlr, mplr);
149 transform->SetInputImageMetadata(&(masterPtr->GetImageMetadata()));
150 transform->SetOutputImageMetadata(&(slavePtr->GetImageMetadata()));
152 transform->InstantiateTransform();
158 typename InputImageType::PointType sMinPul, sMinPur, sMinPll, sMinPlr, sMaxPul, sMaxPur, sMaxPll, sMaxPlr;
161 params[0] = m_LowerElevation;
162 transform->SetParameters(params);
164 sMinPul = transform->TransformPoint(mpul);
165 sMinPur = transform->TransformPoint(mpur);
166 sMinPll = transform->TransformPoint(mpll);
167 sMinPlr = transform->TransformPoint(mplr);
170 params[0] = m_HigherElevation;
171 transform->SetParameters(params);
173 sMaxPul = transform->TransformPoint(mpul);
174 sMaxPur = transform->TransformPoint(mpur);
175 sMaxPll = transform->TransformPoint(mpll);
176 sMaxPlr = transform->TransformPoint(mplr);
179 typename InputImageType::IndexType sMinul, sMinur, sMinll, sMinlr, sMaxul, sMaxur, sMaxll, sMaxlr;
181 slavePtr->TransformPhysicalPointToIndex(sMinPul, sMinul);
182 slavePtr->TransformPhysicalPointToIndex(sMaxPul, sMaxul);
183 slavePtr->TransformPhysicalPointToIndex(sMinPur, sMinur);
184 slavePtr->TransformPhysicalPointToIndex(sMaxPur, sMaxur);
185 slavePtr->TransformPhysicalPointToIndex(sMinPll, sMinll);
186 slavePtr->TransformPhysicalPointToIndex(sMaxPll, sMaxll);
187 slavePtr->TransformPhysicalPointToIndex(sMinPlr, sMinlr);
188 slavePtr->TransformPhysicalPointToIndex(sMaxPlr, sMaxlr);
191 typename InputImageType::IndexType sul, slr;
193 sul[0] = std::min(std::min(std::min(sMinul[0], sMaxul[0]), std::min(sMinur[0], sMaxur[0])),
194 std::min(std::min(sMinll[0], sMaxll[0]), std::min(sMinlr[0], sMaxlr[0])));
195 sul[1] = std::min(std::min(std::min(sMinul[1], sMaxul[1]), std::min(sMinur[1], sMaxur[1])),
196 std::min(std::min(sMinll[1], sMaxll[1]), std::min(sMinlr[1], sMaxlr[1])));
197 slr[0] = std::max(std::max(std::max(sMinul[0], sMaxul[0]), std::max(sMinur[0], sMaxur[0])),
198 std::max(std::max(sMinll[0], sMaxll[0]), std::max(sMinlr[0], sMaxlr[0])));
199 slr[1] = std::max(std::max(std::max(sMinul[1], sMaxul[1]), std::max(sMinur[1], sMaxur[1])),
200 std::max(std::max(sMinll[1], sMaxll[1]), std::max(sMinlr[1], sMaxlr[1])));
203 slaveRequestedRegion.SetIndex(sul);
204 typename InputImageType::SizeType ssize;
205 ssize[0] = slr[0] - sul[0] + 1;
206 ssize[1] = slr[1] - sul[1] + 1;
207 slaveRequestedRegion.SetSize(ssize);
210 if (masterRequestedRegion.Crop(masterPtr->GetLargestPossibleRegion()))
212 masterPtr->SetRequestedRegion(masterRequestedRegion);
219 masterPtr->SetRequestedRegion(masterRequestedRegion);
222 itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
223 std::ostringstream msg;
224 msg << this->GetNameOfClass() <<
"::GenerateInputRequestedRegion()";
225 e.SetLocation(msg.str());
226 e.SetDescription(
"Requested region is (at least partially) outside the largest possible region of image 1.");
227 e.SetDataObject(masterPtr);
232 if (slaveRequestedRegion.Crop(slavePtr->GetLargestPossibleRegion()))
234 slavePtr->SetRequestedRegion(slaveRequestedRegion);
241 typename InputImageType::SizeType slaveSize;
243 slaveRequestedRegion.SetSize(slaveSize);
244 typename InputImageType::IndexType slaveIndex;
246 slaveRequestedRegion.SetIndex(slaveIndex);
249 slavePtr->SetRequestedRegion(slaveRequestedRegion);
254 template <
class TInputImage,
class TOutputHeight>
258 m_Interpolator->SetInputImage(this->GetSlaveInput());
259 this->GetCorrelationOutput()->FillBuffer(0.);
269 rsTransform->SetInputImageMetadata(&(outputPtr->GetImageMetadata()));
270 rsTransform->InstantiateTransform();
273 itk::ImageRegionIteratorWithIndex<OutputImageType> outputIt(outputPtr, outputPtr->GetBufferedRegion());
275 for (outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt)
279 outputPtr->TransformIndexToPhysicalPoint(outputIt.GetIndex(), outputPoint);
282 geoPoint = rsTransform->TransformPoint(outputPoint);
290 m_MasterToSlave = GenericRSTransform3DType::New();
291 m_MasterToSlave->SetInputImageMetadata(&(masterPtr->GetImageMetadata()));
292 m_MasterToSlave->SetOutputImageMetadata(&(slavePtr->GetImageMetadata()));
293 m_MasterToSlave->InstantiateTransform();
296 template <
class TInputImage,
class TOutputHeight>
355 itk::ConstNeighborhoodIterator<InputImageType> inputIt(m_Radius, masterPtr, outputRegionForThread);
356 itk::ImageRegionIterator<OutputImageType> outputIt(outputPtr, outputRegionForThread);
357 itk::ImageRegionIteratorWithIndex<OutputImageType> correlIt(correlPtr, outputRegionForThread);
360 outputIt.GoToBegin();
361 correlIt.GoToBegin();
366 std::vector<double> master;
367 master.reserve(inputIt.Size());
368 master = std::vector<double>(inputIt.Size(), 0);
371 std::vector<double> slave;
372 slave.reserve(inputIt.Size());
373 slave = std::vector<double>(inputIt.Size(), 0);
377 while (!outputIt.IsAtEnd() && !inputIt.IsAtEnd())
380 typename InputImageType::PointType inPoint, outPoint, currentPoint, optimalPoint;
382 typename InputImageType::IndexType index;
385 double initHeight = outputIt.Get();
386 double optimalHeight = initHeight;
387 double optimalCorrelation = 0;
390 if (initHeight != -32768)
393 double masterSum = 0;
394 double masterVariance = 0;
397 for (
unsigned int i = 0; i < inputIt.Size(); ++i)
400 double value = inputIt.GetPixel(i);
408 masterSum /= inputIt.Size();
411 for (
unsigned int i = 0; i < inputIt.Size(); ++i)
413 masterVariance += (master[i] - masterSum) * (master[i] - masterSum);
415 masterVariance /= (inputIt.Size() - 1);
418 if (masterVariance > m_VarianceThreshold)
421 for (
double height = initHeight + m_LowerElevation; height < initHeight + m_HigherElevation; height += m_ElevationStep)
425 for (
unsigned int i = 0; i < inputIt.Size(); ++i)
428 index = inputIt.GetIndex(i);
431 masterPtr->TransformIndexToPhysicalPoint(index, inPoint);
432 in3DPoint[0] = inPoint[0];
433 in3DPoint[1] = inPoint[1];
434 in3DPoint[2] = height;
437 out3DPoint = m_MasterToSlave->TransformPoint(in3DPoint);
438 outPoint[0] = out3DPoint[0];
439 outPoint[1] = out3DPoint[1];
442 if (m_Interpolator->IsInsideBuffer(outPoint))
445 slave[i] = m_Interpolator->Evaluate(outPoint);
456 double correlationValue = this->Correlation(master, slave);
459 if (correlationValue > optimalCorrelation)
462 optimalCorrelation = correlationValue;
463 optimalHeight = height;
471 double finalOffset = 0.;
474 if (m_SubtractInitialElevation)
476 finalOffset = initHeight;
479 if (optimalCorrelation > m_CorrelationThreshold)
481 outputIt.Set(optimalHeight - finalOffset);
482 correlIt.Set(optimalCorrelation);
486 outputIt.Set(initHeight - finalOffset);
497 template <
class TInputImage,
class TOutputHeight>
500 double meanSlave = 0;
501 double meanMaster = 0;
502 double correlationValue = 0;
505 for (
unsigned int i = 0; i < master.size(); ++i)
507 meanSlave += slave[i];
508 meanMaster += master[i];
510 meanSlave /= slave.size();
511 meanMaster /= master.size();
513 double crossProd = 0.;
514 double squareSumMaster = 0.;
515 double squareSumSlave = 0.;
519 for (
unsigned int i = 0; i < master.size(); ++i)
521 crossProd += (slave[i] - meanSlave) * (master[i] - meanMaster);
522 squareSumSlave += (slave[i] - meanSlave) * (slave[i] - meanSlave);
523 squareSumMaster += (master[i] - meanMaster) * (master[i] - meanMaster);
526 correlationValue = std::abs(crossProd / (std::sqrt(squareSumSlave) * std::sqrt(squareSumMaster)));
528 return correlationValue;
static DEMHandler & GetInstance()
TOutputHeight OutputImageType
void GenerateInputRequestedRegion(void) override
OutputImageType::RegionType OutputRegionType
StereoSensorModelToElevationFilter()
~StereoSensorModelToElevationFilter() override
TOutputHeight * GetCorrelationOutput()
const TInputImage * GetSlaveInput() const
double Correlation(const std::vector< double > &master, const std::vector< double > &slave) const
OutputImageType::PointType OutputPointType
const TInputImage * GetMasterInput() const
TInputImage InputImageType
void DynamicThreadedGenerateData(const OutputRegionType &outputRegionForThread) override
void SetMasterInput(const TInputImage *image)
void BeforeThreadedGenerateData() override
void SetSlaveInput(const TInputImage *image)
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
double GetHeightAboveEllipsoid(DEMHandlerTLS const &, double lon, double lat)