21 #ifndef otbStereoSensorModelToElevationMapFilter_hxx
22 #define otbStereoSensorModelToElevationMapFilter_hxx
25 #include "itkProgressReporter.h"
36 template <
class TInputImage,
class TOutputImage>
38 : m_ElevationOffset(50),
43 m_LeftToRightTransform(),
44 m_RightToLeftTransform(),
45 m_OutputOriginInLeftImage(),
46 m_MeanBaselineRatio(0),
51 this->SetNumberOfRequiredOutputs(2);
54 this->SetNthOutput(0, OutputImageType::New());
55 this->SetNthOutput(1, OutputImageType::New());
62 template <
class TInputImage,
class TOutputImage>
66 if (this->GetNumberOfOutputs() < 1)
70 return static_cast<const OutputImageType*
>(this->itk::ProcessObject::GetOutput(0));
73 template <
class TInputImage,
class TOutputImage>
77 if (this->GetNumberOfOutputs() < 1)
81 return static_cast<OutputImageType*
>(this->itk::ProcessObject::GetOutput(0));
84 template <
class TInputImage,
class TOutputImage>
88 if (this->GetNumberOfOutputs() < 2)
92 return static_cast<const OutputImageType*
>(this->itk::ProcessObject::GetOutput(1));
95 template <
class TInputImage,
class TOutputImage>
99 if (this->GetNumberOfOutputs() < 2)
103 return static_cast<OutputImageType*
>(this->itk::ProcessObject::GetOutput(1));
106 template <
class TInputImage,
class TOutputImage>
112 if (m_LeftImage.IsNull() || m_RightImage.IsNull())
114 itkExceptionMacro(<<
"Either left image or right image pointer is null, can not perform stereo-rectification.");
118 m_LeftImage->UpdateOutputInformation();
119 m_RightImage->UpdateOutputInformation();
126 RSTransform2DType::Pointer leftToGroundTransform = RSTransform2DType::New();
127 leftToGroundTransform->SetInputImageMetadata(&(m_LeftImage->GetImageMetadata()));
129 leftToGroundTransform->InstantiateTransform();
136 m_LeftToRightTransform->SetInputImageMetadata(&(m_LeftImage->GetImageMetadata()));
137 m_LeftToRightTransform->SetOutputImageMetadata(&(m_RightImage->GetImageMetadata()));
138 m_LeftToRightTransform->InstantiateTransform();
140 m_RightToLeftTransform->SetInputImageMetadata(&(m_RightImage->GetImageMetadata()));
141 m_RightToLeftTransform->SetOutputImageMetadata(&(m_LeftImage->GetImageMetadata()));
142 m_RightToLeftTransform->InstantiateTransform();
150 outputSpacing.Fill(m_Scale * m_GridStep);
151 double mean_spacing = 0.5 * (std::abs(m_LeftImage->GetSignedSpacing()[0]) + std::abs(m_LeftImage->GetSignedSpacing()[1]));
155 outputSpacing[0] *= mean_spacing;
156 outputSpacing[1] *= mean_spacing;
159 double localElevation = demHandler.GetDefaultHeightAboveEllipsoid();
163 RSTransform2DType::InputPointType tmpPoint;
164 localElevation = demHandler.GetHeightAboveEllipsoid(leftToGroundTransform->TransformPoint(m_LeftImage->GetOrigin()));
168 leftInputOrigin[0] = m_LeftImage->GetOrigin()[0];
169 leftInputOrigin[1] = m_LeftImage->GetOrigin()[1];
170 leftInputOrigin[2] = localElevation;
174 TDPointType rightEpiPoint, leftEpiLineStart, leftEpiLineEnd;
178 rightEpiPoint = m_LeftToRightTransform->TransformPoint(leftInputOrigin);
182 rightEpiPoint[2] = localElevation - m_ElevationOffset;
183 leftEpiLineStart = m_RightToLeftTransform->TransformPoint(rightEpiPoint);
187 rightEpiPoint[2] = localElevation + m_ElevationOffset;
188 leftEpiLineEnd = m_RightToLeftTransform->TransformPoint(rightEpiPoint);
193 if (leftEpiLineEnd[0] == leftEpiLineStart[0])
195 if (leftEpiLineEnd[1] > leftEpiLineStart[1])
206 double a = (leftEpiLineEnd[1] - leftEpiLineStart[1]) / (leftEpiLineEnd[0] - leftEpiLineStart[0]);
207 if (leftEpiLineEnd[0] > leftEpiLineStart[0])
209 alpha = std::atan(a);
220 double ux = std::cos(alpha);
221 double uy = std::sin(alpha);
222 double vx = -std::sin(alpha);
223 double vy = std::cos(alpha);
230 double urx = ux * m_LeftImage->GetLargestPossibleRegion().GetSize()[0] * m_LeftImage->GetSignedSpacing()[0];
231 double ury = vx * m_LeftImage->GetLargestPossibleRegion().GetSize()[0] * m_LeftImage->GetSignedSpacing()[0];
232 double llx = uy * m_LeftImage->GetLargestPossibleRegion().GetSize()[1] * m_LeftImage->GetSignedSpacing()[1];
233 double lly = vy * m_LeftImage->GetLargestPossibleRegion().GetSize()[1] * m_LeftImage->GetSignedSpacing()[1];
234 double lrx = ux * m_LeftImage->GetLargestPossibleRegion().GetSize()[0] * m_LeftImage->GetSignedSpacing()[0] +
235 uy * m_LeftImage->GetLargestPossibleRegion().GetSize()[1] * m_LeftImage->GetSignedSpacing()[1];
236 double lry = vx * m_LeftImage->GetLargestPossibleRegion().GetSize()[0] * m_LeftImage->GetSignedSpacing()[0] +
237 vy * m_LeftImage->GetLargestPossibleRegion().GetSize()[1] * m_LeftImage->GetSignedSpacing()[1];
240 double minx = std::min(std::min(std::min(urx, llx), lrx), 0.);
241 double miny = std::min(std::min(std::min(ury, lly), lry), 0.);
242 double maxx = std::max(std::max(std::max(urx, llx), lrx), 0.);
243 double maxy = std::max(std::max(std::max(ury, lly), lry), 0.);
247 m_RectifiedImageSize[0] =
static_cast<unsigned int>((maxx - minx) / (mean_spacing * m_Scale));
248 m_RectifiedImageSize[1] =
static_cast<unsigned int>((maxy - miny) / (mean_spacing * m_Scale));
252 m_OutputOriginInLeftImage[0] = leftInputOrigin[0] + (ux * minx + vx * miny);
253 m_OutputOriginInLeftImage[1] = leftInputOrigin[1] + (uy * minx + vy * miny);
254 m_OutputOriginInLeftImage[2] = localElevation;
258 outputSize[0] = (m_RectifiedImageSize[0] / m_GridStep + 2);
259 outputSize[1] = (m_RectifiedImageSize[1] / m_GridStep + 2);
263 outputLargestRegion.SetSize(outputSize);
266 leftDFPtr->SetLargestPossibleRegion(outputLargestRegion);
267 rightDFPtr->SetLargestPossibleRegion(outputLargestRegion);
269 leftDFPtr->SetSignedSpacing(outputSpacing);
270 rightDFPtr->SetSignedSpacing(outputSpacing);
272 leftDFPtr->SetNumberOfComponentsPerPixel(2);
273 rightDFPtr->SetNumberOfComponentsPerPixel(2);
276 template <
class TInputImage,
class TOutputImage>
280 Superclass::EnlargeOutputRequestedRegion(output);
287 leftDFPtr->SetRequestedRegionToLargestPossibleRegion();
288 rightDFPtr->SetRequestedRegionToLargestPossibleRegion();
291 template <
class TInputImage,
class TOutputImage>
295 this->AllocateOutputs();
299 auto const& threadDemHandler = demHandler.GetHandlerForCurrentThread();
303 RSTransform2DType::Pointer leftToGroundTransform = RSTransform2DType::New();
305 leftToGroundTransform->SetInputImageMetadata(&(m_LeftImage->GetImageMetadata()));
307 leftToGroundTransform->InstantiateTransform();
314 TDPointType currentPoint1, currentPoint2, nextLineStart1, nextLineStart2, startLine1, endLine1, startLine2, endLine2, epiPoint1, epiPoint2;
317 double localElevation = demHandler.GetDefaultHeightAboveEllipsoid();
320 double mean_spacing = 0.5 * (std::abs(m_LeftImage->GetSignedSpacing()[0]) + std::abs(m_LeftImage->GetSignedSpacing()[1]));
323 currentPoint1 = m_OutputOriginInLeftImage;
326 RSTransform2DType::InputPointType tmpPoint;
327 tmpPoint[0] = currentPoint1[0];
328 tmpPoint[1] = currentPoint1[1];
329 localElevation = demHandler.GetHeightAboveEllipsoid(leftToGroundTransform->TransformPoint(tmpPoint));
331 currentPoint1[2] = localElevation;
332 currentPoint2 = m_LeftToRightTransform->TransformPoint(currentPoint1);
333 currentPoint2[2] = currentPoint1[2];
336 nextLineStart1 = currentPoint1;
337 nextLineStart2 = currentPoint2;
340 typedef itk::ImageRegionIteratorWithIndex<OutputImageType> IteratorType;
342 IteratorType it1(leftDFPtr, leftDFPtr->GetLargestPossibleRegion());
343 IteratorType it2(rightDFPtr, rightDFPtr->GetLargestPossibleRegion());
349 m_MeanBaselineRatio = 0;
352 itk::ProgressReporter progress(
this, 0, leftDFPtr->GetLargestPossibleRegion().GetNumberOfPixels());
356 while (!it1.IsAtEnd() && !it2.IsAtEnd())
360 if (it1.GetIndex()[0] == 0 || it2.GetIndex()[0] == 0)
363 currentPoint1 = nextLineStart1;
364 currentPoint2 = nextLineStart2;
368 typename OutputImageType::PixelType dFValue1 = it1.Get();
369 typename OutputImageType::PixelType dFValue2 = it2.Get();
372 PointType currentDFPoint1, currentDFPoint2;
373 leftDFPtr->TransformIndexToPhysicalPoint(it1.GetIndex(), currentDFPoint1);
374 rightDFPtr->TransformIndexToPhysicalPoint(it2.GetIndex(), currentDFPoint2);
377 dFValue1[0] = currentPoint1[0] - currentDFPoint1[0];
378 dFValue1[1] = currentPoint1[1] - currentDFPoint1[1];
379 dFValue2[0] = currentPoint2[0] - currentDFPoint2[0];
380 dFValue2[1] = currentPoint2[1] - currentDFPoint2[1];
394 epiPoint2 = m_LeftToRightTransform->TransformPoint(currentPoint1);
398 epiPoint2[2] = localElevation - m_ElevationOffset;
399 startLine1 = m_RightToLeftTransform->TransformPoint(epiPoint2);
403 epiPoint2[2] = localElevation + m_ElevationOffset;
404 endLine1 = m_RightToLeftTransform->TransformPoint(epiPoint2);
407 double localBaselineRatio =
408 std::sqrt((endLine1[0] - startLine1[0]) * (endLine1[0] - startLine1[0]) + (endLine1[1] - startLine1[1]) * (endLine1[1] - startLine1[1])) /
409 (2 * m_ElevationOffset);
411 m_MeanBaselineRatio += localBaselineRatio;
416 if (endLine1[0] == startLine1[0])
418 if (endLine1[1] > startLine1[1])
429 a1 = (endLine1[1] - startLine1[1]) / (endLine1[0] - startLine1[0]);
430 if (endLine1[0] > startLine1[0])
432 alpha1 = std::atan(a1);
441 currentPoint2[2] = localElevation;
442 epiPoint1 = m_RightToLeftTransform->TransformPoint(currentPoint2);
444 epiPoint1[2] = localElevation - m_ElevationOffset;
445 startLine2 = m_LeftToRightTransform->TransformPoint(epiPoint1);
447 epiPoint1[2] = localElevation + m_ElevationOffset;
448 endLine2 = m_LeftToRightTransform->TransformPoint(epiPoint1);
456 double deltax1 = m_Scale * m_GridStep * mean_spacing * std::cos(alpha1);
457 double deltay1 = m_Scale * m_GridStep * mean_spacing * std::sin(alpha1);
460 currentPoint1[0] += deltax1;
461 currentPoint1[1] += deltay1;
464 RSTransform2DType::InputPointType tmpPoint;
465 tmpPoint[0] = currentPoint1[0];
466 tmpPoint[1] = currentPoint1[1];
469 currentPoint1[2] = localElevation;
472 currentPoint2 = m_LeftToRightTransform->TransformPoint(currentPoint1);
477 if (it1.GetIndex()[0] == 0 || it2.GetIndex()[0] == 0)
481 double nextdeltax1 = -m_Scale * mean_spacing * m_GridStep * std::sin(alpha1);
482 double nextdeltay1 = m_Scale * mean_spacing * m_GridStep * std::cos(alpha1);
485 nextLineStart1[0] = currentPoint1[0] - deltax1 + nextdeltax1;
486 nextLineStart1[1] = currentPoint1[1] - deltay1 + nextdeltay1;
487 nextLineStart1[2] = localElevation;
490 RSTransform2DType::InputPointType tmpPoint;
491 tmpPoint[0] = nextLineStart1[0];
492 tmpPoint[1] = nextLineStart1[1];
493 nextLineStart1[2] =
GetHeightAboveEllipsoid(threadDemHandler, leftToGroundTransform->TransformPoint(tmpPoint));
499 nextLineStart2 = m_LeftToRightTransform->TransformPoint(nextLineStart1);
507 progress.CompletedPixel();
511 m_MeanBaselineRatio /= leftDFPtr->GetBufferedRegion().GetNumberOfPixels();
514 template <
class TInputImage,
class TOutputImage>
518 Superclass::PrintSelf(os, indent);