OTB  9.0.0
Orfeo Toolbox
otbMultiDisparityMapTo3DFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbMultiDisparityMapTo3DFilter_hxx
22 #define otbMultiDisparityMapTo3DFilter_hxx
23 
25 #include "itkImageRegionConstIteratorWithIndex.h"
26 #include "itkImageRegionIterator.h"
27 
28 namespace otb
29 {
30 
31 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
33 {
34  // Set the number of inputs (1 moving image by default -> 3 inputs)
35  this->SetNumberOfRequiredInputs(3);
36  this->SetNumberOfRequiredInputs(1);
37  this->m_MovingImageMetadatas.resize(1);
38 
39  // Set the outputs
40  this->SetNumberOfRequiredOutputs(2);
41  this->SetNthOutput(0, TOutputImage::New());
42  this->SetNthOutput(1, TResidueImage::New());
43 }
44 
45 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
47 {
48 }
49 
50 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
52 {
53  if (nb > 0)
54  {
55  this->SetNumberOfRequiredInputs(3 * nb);
56  this->m_MovingImageMetadatas.resize(nb);
57  }
58 }
59 
60 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
62 {
63  return this->m_MovingImageMetadatas.size();
64 }
65 
66 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
68  const TDisparityImage* hmap)
69 {
70  if ((3 * (index + 1)) > this->GetNumberOfRequiredInputs())
71  {
72  itkExceptionMacro(<< "Index is greater than the number of moving images");
73  }
74  // Process object is not const-correct so the const casting is required.
75  this->SetNthInput(3 * index, const_cast<TDisparityImage*>(hmap));
76 }
77 
78 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
80  const TDisparityImage* vmap)
81 {
82  if ((3 * (index + 1)) > this->GetNumberOfRequiredInputs())
83  {
84  itkExceptionMacro(<< "Index is greater than the number of moving images");
85  }
86  // Process object is not const-correct so the const casting is required.
87  this->SetNthInput(3 * index + 1, const_cast<TDisparityImage*>(vmap));
88 }
89 
90 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
92 {
93  if ((3 * (index + 1)) > this->GetNumberOfRequiredInputs())
94  {
95  itkExceptionMacro(<< "Index is greater than the number of moving images");
96  }
97  // Process object is not const-correct so the const casting is required.
98  this->SetNthInput(3 * index + 2, const_cast<TMaskImage*>(mask));
99 }
100 
101 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
102 const TDisparityImage*
104 {
105  if ((3 * (index + 1)) > this->GetNumberOfRequiredInputs())
106  {
107  return nullptr;
108  }
109  return static_cast<const TDisparityImage*>(this->itk::ProcessObject::GetInput(3 * index));
110 }
111 
112 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
113 const TDisparityImage*
115 {
116  if ((3 * (index + 1)) > this->GetNumberOfRequiredInputs())
117  {
118  return nullptr;
119  }
120  return static_cast<const TDisparityImage*>(this->itk::ProcessObject::GetInput(3 * index + 1));
121 }
122 
123 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
125 {
126  if ((3 * (index + 1)) > this->GetNumberOfRequiredInputs())
127  {
128  return nullptr;
129  }
130  return static_cast<const TMaskImage*>(this->itk::ProcessObject::GetInput(3 * index + 2));
131 }
132 
133 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
135 {
136  return static_cast<const TResidueImage*>(this->itk::ProcessObject::GetOutput(1));
137 }
138 
139 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
141 {
142  return static_cast<TResidueImage*>(this->itk::ProcessObject::GetOutput(1));
143 }
144 
145 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
147  const ImageMetadata* imd)
148 {
149  if (this->m_MovingImageMetadatas.size() > index)
150  {
151  this->m_MovingImageMetadatas[index] = imd;
152  }
153 }
154 
155 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
156 const ImageMetadata*
158 {
159  if (this->m_MovingImageMetadatas.size() <= index)
160  {
161  itkExceptionMacro(<< "ImageMetadata index is outside the container");
162  }
163  return this->m_MovingImageMetadatas[index];
164 }
165 
166 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
168 {
169  const TDisparityImage* horizDisp = this->GetHorizontalDisparityMapInput(0);
170  TOutputImage* outputPtr = this->GetOutput();
171  TResidueImage* residuePtr = this->GetResidueOutput();
172 
173  if (horizDisp)
174  {
175  outputPtr->SetLargestPossibleRegion(horizDisp->GetLargestPossibleRegion());
176  outputPtr->SetNumberOfComponentsPerPixel(3);
177 
178  residuePtr->SetLargestPossibleRegion(horizDisp->GetLargestPossibleRegion());
179  residuePtr->SetNumberOfComponentsPerPixel(1);
180 
181  // copy also origin and spacing
182  outputPtr->SetOrigin(horizDisp->GetOrigin());
183  outputPtr->SetSignedSpacing(horizDisp->GetSignedSpacing());
184 
185  residuePtr->SetOrigin(horizDisp->GetOrigin());
186  residuePtr->SetSignedSpacing(horizDisp->GetSignedSpacing());
187 
188  if (this->m_ReferenceImageMetadata)
189  {
190  auto outputmetadata = *m_ReferenceImageMetadata;
191  // Don't copy band metadata, as output bands are not related to input bands.
192  outputmetadata.Bands.clear();
193  outputPtr->SetImageMetadata(outputmetadata);
194  residuePtr->SetImageMetadata(outputmetadata);
195  }
196  else
197  {
198  itkExceptionMacro(<< "Reference ImageMetadata is missing");
199  }
200  }
201  else
202  {
203  itkExceptionMacro(<< "First horizontal disparity map is missing");
204  }
205 }
206 
207 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
209 {
210  RegionType requested = this->GetOutput()->GetRequestedRegion();
211  RegionType largest = this->GetHorizontalDisparityMapInput(0)->GetLargestPossibleRegion();
212 
213  for (unsigned int i = 0; i < this->GetNumberOfRequiredInputs(); ++i)
214  {
215  unsigned int index = i % 3;
216  unsigned int pos = i / 3;
217  switch (index)
218  {
219  case 0:
220  {
221  // check horizontal disparity maps
222  TDisparityImage* horizDisp = const_cast<TDisparityImage*>(this->GetHorizontalDisparityMapInput(pos));
223  if (horizDisp)
224  {
225  if (horizDisp->GetLargestPossibleRegion() != largest)
226  {
227  itkExceptionMacro(<< "Horizontal disparity map at position " << pos << " has a different largest region");
228  }
229  horizDisp->SetRequestedRegion(requested);
230  }
231  else
232  {
233  itkExceptionMacro(<< "Horizontal disparity map at position " << pos << " is missing");
234  }
235  }
236  break;
237  case 1:
238  {
239  // check vertical disparity maps
240  TDisparityImage* vertiDisp = const_cast<TDisparityImage*>(this->GetVerticalDisparityMapInput(pos));
241  if (vertiDisp)
242  {
243  if (vertiDisp->GetLargestPossibleRegion() != largest)
244  {
245  itkExceptionMacro(<< "Vertical disparity map at position " << pos << " has a different largest region");
246  }
247  vertiDisp->SetRequestedRegion(requested);
248  }
249  }
250  break;
251  case 2:
252  {
253  // check disparity masks
254  TMaskImage* maskDisp = const_cast<TMaskImage*>(this->GetDisparityMaskInput(pos));
255  if (maskDisp)
256  {
257  if (maskDisp->GetLargestPossibleRegion() != largest)
258  {
259  itkExceptionMacro(<< "Disparity mask at position " << pos << " has a different largest region");
260  }
261  maskDisp->SetRequestedRegion(requested);
262  }
263  }
264  break;
265  default:
266  itkExceptionMacro(<< "Unexpected value for (i%3) ");
267  }
268  }
269 
270  // Check moving ImageMetadata
271  for (unsigned int k = 0; k < this->m_MovingImageMetadatas.size(); ++k)
272  {
273  if (!this->m_MovingImageMetadatas[k])
274  {
275  itkExceptionMacro(<< "ImageMetadata of moving image at position " << k << " is empty");
276  }
277  }
278 }
279 
280 template <class TDisparityImage, class TOutputImage, class TMaskImage, class TResidueImage>
282  itk::ThreadIdType itkNotUsed(threadId))
283 { // Instantiate all transforms
284  auto referenceToGroundTransform = RSTransformType::New();
285 
286  referenceToGroundTransform->SetInputImageMetadata(this->m_ReferenceImageMetadata);
287  referenceToGroundTransform->InstantiateTransform();
288 
290  std::vector<RSTransformType::Pointer> movingToGroundTransform;
291 
292  for (unsigned int k = 0; k < this->m_MovingImageMetadatas.size(); ++k)
293  {
294  RSTransformType::Pointer transfo = RSTransformType::New();
295  transfo->SetInputImageMetadata(this->m_MovingImageMetadatas[k]);
296  transfo->InstantiateTransform();
297  movingToGroundTransform.push_back(transfo);
298  }
299 
300 
301  TOutputImage* outputPtr = this->GetOutput();
302  TResidueImage* residuePtr = this->GetResidueOutput();
303 
304  itk::ImageRegionIteratorWithIndex<OutputImageType> outIt(outputPtr, outputRegionForThread);
305  itk::ImageRegionIterator<ResidueImageType> resIt(residuePtr, outputRegionForThread);
306 
307  typename OptimizerType::Pointer optimizer = OptimizerType::New();
308 
309  DispMapIteratorList hDispIts;
310  DispMapIteratorList vDispIts;
311  MaskIteratorList maskIts;
312 
313  for (unsigned int k = 0; k < this->m_MovingImageMetadatas.size(); ++k)
314  {
315  // Iterators over horizontal disparity maps
316  hDispIts[k] = itk::ImageRegionConstIterator<DisparityMapType>(this->GetHorizontalDisparityMapInput(k), outputRegionForThread);
317  hDispIts[k].GoToBegin();
318  // Iterators over vertical disparity maps
319  if (this->GetVerticalDisparityMapInput(k))
320  {
321  vDispIts[k] = itk::ImageRegionConstIterator<DisparityMapType>(this->GetVerticalDisparityMapInput(k), outputRegionForThread);
322  vDispIts[k].GoToBegin();
323  }
324  // Iterators over disparity masks
325  if (this->GetDisparityMaskInput(k))
326  {
327  maskIts[k] = itk::ImageRegionConstIterator<MaskImageType>(this->GetDisparityMaskInput(k), outputRegionForThread);
328  maskIts[k].GoToBegin();
329  }
330  }
331 
332  outIt.GoToBegin();
333  resIt.GoToBegin();
334 
335  PrecisionType altiMin = 0;
336  PrecisionType altiMax = 500;
337 
338  typename OutputImageType::PointType pointRef;
339  TDPointType currentPoint;
340 
341  typename OutputImageType::PixelType outPixel(3);
342  PrecisionType globalResidue;
343 
344  typename PointSetType::Pointer pointSetA = PointSetType::New();
345  typename PointSetType::Pointer pointSetB = PointSetType::New();
346 
347  while (!outIt.IsAtEnd())
348  {
349  pointSetA->Initialize();
350  pointSetB->Initialize();
351 
352  // Compute reference line of sight
353  TDPointType pointA, pointB;
354 
355  outputPtr->TransformIndexToPhysicalPoint(outIt.GetIndex(), pointRef);
356 
357  currentPoint[0] = pointRef[0];
358  currentPoint[1] = pointRef[1];
359  currentPoint[2] = altiMax;
360 
361  pointA = referenceToGroundTransform->TransformPoint(currentPoint);
362 
363  currentPoint[2] = altiMin;
364  pointB = referenceToGroundTransform->TransformPoint(currentPoint);
365 
366  pointSetA->SetPoint(0, pointA);
367  pointSetB->SetPoint(0, pointB);
368  pointSetA->SetPointData(0, 0);
369  pointSetB->SetPointData(0, 0);
370 
371  unsigned int nbPoints = 1;
372 
373  for (unsigned int k = 0; k < this->m_MovingImageMetadatas.size(); ++k)
374  {
375  // Compute the N moving lines of sight
376  TDPointType pointAi, pointBi;
377 
378  if (maskIts.count(k) && !(maskIts[k].Get() > 0))
379  {
380  continue;
381  }
382 
383  currentPoint[0] = pointRef[0] + hDispIts[k].Get();
384  currentPoint[1] = pointRef[1];
385  if (vDispIts.count(k))
386  {
387  currentPoint[1] += vDispIts[k].Get();
388  }
389 
390  currentPoint[2] = altiMax;
391  pointAi = movingToGroundTransform[k]->TransformPoint(currentPoint);
392  currentPoint[2] = altiMin;
393  pointBi = movingToGroundTransform[k]->TransformPoint(currentPoint);
394  pointSetA->SetPoint(nbPoints, pointAi);
395  pointSetB->SetPoint(nbPoints, pointBi);
396  pointSetA->SetPointData(nbPoints, k + 1);
397  pointSetB->SetPointData(nbPoints, k + 1);
398  ++nbPoints;
399  }
400 
401  // Check if there are at least 2 lines of sight, then compute intersection
402  if (nbPoints >= 2)
403  {
404  TDPointType intersection = optimizer->Compute(pointSetA, pointSetB);
405  outPixel[0] = intersection[0];
406  outPixel[1] = intersection[1];
407  outPixel[2] = intersection[2];
408  globalResidue = optimizer->GetGlobalResidue();
409  }
410  else
411  {
412  outPixel.Fill(0);
413  globalResidue = 0;
414  }
415 
416  outIt.Set(outPixel);
417  resIt.Set(globalResidue);
418 
419  // Increment all iterators
420  for (typename DispMapIteratorList::iterator hIt = hDispIts.begin(); hIt != hDispIts.end(); ++hIt)
421  {
422  ++hIt->second;
423  }
424  for (typename DispMapIteratorList::iterator vIt = vDispIts.begin(); vIt != vDispIts.end(); ++vIt)
425  {
426  ++vIt->second;
427  }
428  for (typename MaskIteratorList::iterator mIt = maskIts.begin(); mIt != maskIts.end(); ++mIt)
429  {
430  ++mIt->second;
431  }
432 
433  ++outIt;
434  ++resIt;
435  }
436 }
437 }
438 
439 #endif
otb::MultiDisparityMapTo3DFilter::SetVerticalDisparityMapInput
void SetVerticalDisparityMapInput(unsigned int index, const TDisparityImage *vmap)
Definition: otbMultiDisparityMapTo3DFilter.hxx:79
otb::GenericRSTransform::Pointer
itk::SmartPointer< Self > Pointer
Definition: otbGenericRSTransform.h:66
otb::MultiDisparityMapTo3DFilter::SetMovingImageMetadata
void SetMovingImageMetadata(unsigned int index, const ImageMetadata *imd)
Definition: otbMultiDisparityMapTo3DFilter.hxx:146
otb::LineOfSightOptimizer::Pointer
itk::SmartPointer< Self > Pointer
Definition: otbLineOfSightOptimizer.h:48
otb::MultiDisparityMapTo3DFilter::GenerateInputRequestedRegion
void GenerateInputRequestedRegion() override
Definition: otbMultiDisparityMapTo3DFilter.hxx:208
otb::MultiDisparityMapTo3DFilter::SetNumberOfMovingImages
void SetNumberOfMovingImages(unsigned int nb)
Definition: otbMultiDisparityMapTo3DFilter.hxx:51
otb::MultiDisparityMapTo3DFilter::GetHorizontalDisparityMapInput
const TDisparityImage * GetHorizontalDisparityMapInput(unsigned int index) const
Definition: otbMultiDisparityMapTo3DFilter.hxx:103
otb::MultiDisparityMapTo3DFilter::GetResidueOutput
const TResidueImage * GetResidueOutput() const
Definition: otbMultiDisparityMapTo3DFilter.hxx:134
otb::MultiDisparityMapTo3DFilter::GetDisparityMaskInput
const TMaskImage * GetDisparityMaskInput(unsigned int index) const
Definition: otbMultiDisparityMapTo3DFilter.hxx:124
otbMultiDisparityMapTo3DFilter.h
otb::MultiDisparityMapTo3DFilter::SetHorizontalDisparityMapInput
void SetHorizontalDisparityMapInput(unsigned int index, const TDisparityImage *hmap)
Definition: otbMultiDisparityMapTo3DFilter.hxx:67
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::MultiDisparityMapTo3DFilter::DispMapIteratorList
std::map< unsigned int, itk::ImageRegionConstIterator< DisparityMapType > > DispMapIteratorList
Definition: otbMultiDisparityMapTo3DFilter.h:97
otb::MultiDisparityMapTo3DFilter::MaskIteratorList
std::map< unsigned int, itk::ImageRegionConstIterator< MaskImageType > > MaskIteratorList
Definition: otbMultiDisparityMapTo3DFilter.h:99
otb::MultiDisparityMapTo3DFilter::PrecisionType
double PrecisionType
Definition: otbMultiDisparityMapTo3DFilter.h:86
otb::MultiDisparityMapTo3DFilter::SetDisparityMaskInput
void SetDisparityMaskInput(unsigned int index, const TMaskImage *mask)
Definition: otbMultiDisparityMapTo3DFilter.hxx:91
otb::MultiDisparityMapTo3DFilter::GetNumberOfMovingImages
unsigned int GetNumberOfMovingImages()
Definition: otbMultiDisparityMapTo3DFilter.hxx:61
otb::MultiDisparityMapTo3DFilter::~MultiDisparityMapTo3DFilter
~MultiDisparityMapTo3DFilter() override
Definition: otbMultiDisparityMapTo3DFilter.hxx:46
otb::MultiDisparityMapTo3DFilter::RegionType
OutputImageType::RegionType RegionType
Definition: otbMultiDisparityMapTo3DFilter.h:81
otb::MultiDisparityMapTo3DFilter::GetVerticalDisparityMapInput
const TDisparityImage * GetVerticalDisparityMapInput(unsigned int index) const
Definition: otbMultiDisparityMapTo3DFilter.hxx:114
otb::ImageMetadata
Generic class containing image metadata used in OTB.
Definition: otbImageMetadata.h:270
otb::MultiDisparityMapTo3DFilter::GenerateOutputInformation
void GenerateOutputInformation() override
Definition: otbMultiDisparityMapTo3DFilter.hxx:167
otb::MultiDisparityMapTo3DFilter::MultiDisparityMapTo3DFilter
MultiDisparityMapTo3DFilter()
Definition: otbMultiDisparityMapTo3DFilter.hxx:32
otb::MultiDisparityMapTo3DFilter::GetMovingImageMetadata
const ImageMetadata * GetMovingImageMetadata(unsigned int index) const
Definition: otbMultiDisparityMapTo3DFilter.hxx:157
otb::MultiDisparityMapTo3DFilter::ThreadedGenerateData
void ThreadedGenerateData(const RegionType &outputRegionForThread, itk::ThreadIdType threadId) override
Definition: otbMultiDisparityMapTo3DFilter.hxx:281
otb::MultiDisparityMapTo3DFilter::TDPointType
RSTransformType::InputPointType TDPointType
Definition: otbMultiDisparityMapTo3DFilter.h:90