OTB  10.0.0
Orfeo Toolbox
otbBijectionCoherencyFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2024 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 otbBijectionCoherencyFilter_hxx
22 #define otbBijectionCoherencyFilter_hxx
23 
25 
26 #include "itkImageRegionConstIteratorWithIndex.h"
27 #include "itkImageRegionIterator.h"
28 
29 namespace otb
30 {
31 
32 template <class TDisparityImage, class TOutputImage>
34 {
35  // Set the number of inputs (1 moving image by default -> 3 inputs)
36  this->SetNumberOfRequiredInputs(4);
37  this->SetNumberOfRequiredInputs(1);
38  this->m_Tolerance = 1.;
39  this->m_MinHDisp = -5;
40  this->m_MaxHDisp = 5;
41  this->m_MinVDisp = -5;
42  this->m_MaxVDisp = 5;
43 
44  // Set the outputs
45  this->SetNumberOfRequiredOutputs(1);
46  this->SetNthOutput(0, TOutputImage::New());
47 }
48 
49 template <class TDisparityImage, class TOutputImage>
51 {
52  // Process object is not const-correct so the const casting is required.
53  this->SetNthInput(0, const_cast<TDisparityImage*>(hmap));
54 }
55 
56 template <class TDisparityImage, class TOutputImage>
58 {
59  // Process object is not const-correct so the const casting is required.
60  this->SetNthInput(1, const_cast<TDisparityImage*>(vmap));
61 }
62 
63 template <class TDisparityImage, class TOutputImage>
65 {
66  // Process object is not const-correct so the const casting is required.
67  this->SetNthInput(2, const_cast<TDisparityImage*>(hmap));
68 }
69 
70 template <class TDisparityImage, class TOutputImage>
72 {
73  // Process object is not const-correct so the const casting is required.
74  this->SetNthInput(3, const_cast<TDisparityImage*>(vmap));
75 }
76 
77 template <class TDisparityImage, class TOutputImage>
79 {
80  if (this->GetNumberOfInputs() < 1)
81  {
82  return nullptr;
83  }
84  return static_cast<const TDisparityImage*>(this->itk::ProcessObject::GetInput(0));
85 }
86 
87 template <class TDisparityImage, class TOutputImage>
89 {
90  if (this->GetNumberOfInputs() < 2)
91  {
92  return nullptr;
93  }
94  return static_cast<const TDisparityImage*>(this->itk::ProcessObject::GetInput(1));
95 }
96 
97 template <class TDisparityImage, class TOutputImage>
99 {
100  if (this->GetNumberOfInputs() < 3)
101  {
102  return nullptr;
103  }
104  return static_cast<const TDisparityImage*>(this->itk::ProcessObject::GetInput(2));
105 }
106 
107 template <class TDisparityImage, class TOutputImage>
109 {
110  if (this->GetNumberOfInputs() < 4)
111  {
112  return nullptr;
113  }
114  return static_cast<const TDisparityImage*>(this->itk::ProcessObject::GetInput(3));
115 }
116 
117 template <class TDisparityImage, class TOutputImage>
119 {
120  this->Superclass::GenerateOutputInformation();
121 
122  // check that both direct and reverse disparity maps are present
123  const TDisparityImage* directHmap = this->GetDirectHorizontalDisparityMapInput();
124  const TDisparityImage* reverseHmap = this->GetReverseHorizontalDisparityMapInput();
125 
126  const TDisparityImage* directVmap = this->GetDirectVerticalDisparityMapInput();
127  const TDisparityImage* reverseVmap = this->GetReverseVerticalDisparityMapInput();
128 
129  if (!directHmap)
130  {
131  itkExceptionMacro(<< "Direct horizontal disparity map is missing");
132  }
133 
134  if (!reverseHmap)
135  {
136  itkExceptionMacro(<< "Reverse horizontal disparity map is missing");
137  }
138 
139  if (directVmap && directVmap->GetLargestPossibleRegion() != directHmap->GetLargestPossibleRegion())
140  {
141  itkExceptionMacro(<< "Horizontal and vertical direct disparity maps have different sizes.");
142  }
143 
144  if (reverseVmap && reverseVmap->GetLargestPossibleRegion() != reverseHmap->GetLargestPossibleRegion())
145  {
146  itkExceptionMacro(<< "Horizontal and vertical reverse disparity maps have different sizes.");
147  }
148 
149  if (this->m_MinHDisp > this->m_MaxHDisp)
150  {
151  itkExceptionMacro(<< "Wrong horizontal exploration values");
152  }
153  if (this->m_MinVDisp > this->m_MaxVDisp)
154  {
155  itkExceptionMacro(<< "Wrong horizontal exploration values");
156  }
157 }
158 
159 template <class TDisparityImage, class TOutputImage>
161 {
162  this->Superclass::GenerateInputRequestedRegion();
163 
164  OutputRegionType requested = this->GetOutput()->GetRequestedRegion();
165  InputRegionType directLargest = this->GetDirectHorizontalDisparityMapInput()->GetLargestPossibleRegion();
166  InputRegionType directRequested;
167  InputRegionType reverseLargest = this->GetReverseHorizontalDisparityMapInput()->GetLargestPossibleRegion();
168  InputRegionType reverseRequested;
169 
170  this->CallCopyOutputRegionToInputRegion(directRequested, requested);
171 
172  reverseRequested.SetIndex(0, requested.GetIndex(0) + this->m_MinHDisp);
173  reverseRequested.SetIndex(1, requested.GetIndex(1) + this->m_MinVDisp);
174  reverseRequested.SetSize(0, requested.GetSize(0) + this->m_MaxHDisp - this->m_MinHDisp);
175  reverseRequested.SetSize(1, requested.GetSize(1) + this->m_MaxVDisp - this->m_MinVDisp);
176 
177  if (!reverseRequested.Crop(reverseLargest))
178  {
179  reverseRequested.SetIndex(0, reverseLargest.GetIndex(0));
180  reverseRequested.SetIndex(1, reverseLargest.GetIndex(1));
181  reverseRequested.SetSize(0, 0);
182  reverseRequested.SetSize(1, 0);
183  }
184 
185  TDisparityImage* directHmap = const_cast<TDisparityImage*>(this->GetDirectHorizontalDisparityMapInput());
186  TDisparityImage* directVmap = const_cast<TDisparityImage*>(this->GetDirectVerticalDisparityMapInput());
187  TDisparityImage* reverseHmap = const_cast<TDisparityImage*>(this->GetReverseHorizontalDisparityMapInput());
188  TDisparityImage* reverseVmap = const_cast<TDisparityImage*>(this->GetReverseVerticalDisparityMapInput());
189 
190  directHmap->SetRequestedRegion(directRequested);
191  if (directVmap)
192  directVmap->SetRequestedRegion(directRequested);
193 
194  reverseHmap->SetRequestedRegion(reverseRequested);
195  if (reverseVmap)
196  reverseVmap->SetRequestedRegion(reverseRequested);
197 }
198 
199 template <class TDisparityImage, class TOutputImage>
201 {
202  const TDisparityImage* directHmap = this->GetDirectHorizontalDisparityMapInput();
203  const TDisparityImage* directVmap = this->GetDirectVerticalDisparityMapInput();
204  const TDisparityImage* reverseHmap = this->GetReverseHorizontalDisparityMapInput();
205  const TDisparityImage* reverseVmap = this->GetReverseVerticalDisparityMapInput();
206 
207  TOutputImage* output = this->GetOutput();
208 
209  InputRegionType buffered = reverseHmap->GetBufferedRegion();
210 
211  typedef itk::ImageRegionIterator<TOutputImage> MaskIteratorType;
212  MaskIteratorType outIter = MaskIteratorType(output, outputRegionForThread);
213 
214  typedef itk::ImageRegionConstIteratorWithIndex<TDisparityImage> DispIteratorType;
215  DispIteratorType directHorizIter = DispIteratorType(directHmap, outputRegionForThread);
216 
217  DispIteratorType directVertiIter;
218  if (directVmap)
219  {
220  directVertiIter = DispIteratorType(directVmap, outputRegionForThread);
221  directVertiIter.GoToBegin();
222  }
223 
224  outIter.GoToBegin();
225  directHorizIter.GoToBegin();
226 
227  while (!outIter.IsAtEnd())
228  {
229  IndexType startIndex = directHorizIter.GetIndex();
230  itk::ContinuousIndex<double, 2> tmpIndex(startIndex);
231 
232  tmpIndex[0] += directHorizIter.Get();
233  if (directVmap)
234  tmpIndex[1] += directVertiIter.Get();
235 
236  // Interpolate in reverse disparity map
237  typedef typename IndexType::IndexValueType IndexValueType;
238  IndexType ul, ur, ll, lr;
239  ul[0] = static_cast<long>(std::floor(tmpIndex[0]));
240  ul[1] = static_cast<long>(std::floor(tmpIndex[1]));
241  if (ul[0] < buffered.GetIndex()[0])
242  ul[0] = buffered.GetIndex()[0];
243  if (ul[1] < buffered.GetIndex()[1])
244  ul[1] = buffered.GetIndex()[1];
245  if (ul[0] > static_cast<IndexValueType>(buffered.GetIndex()[0] + buffered.GetSize()[0] - 1))
246  ul[0] = (buffered.GetIndex()[0] + buffered.GetSize()[0] - 1);
247  if (ul[1] > static_cast<IndexValueType>(buffered.GetIndex()[1] + buffered.GetSize()[1] - 1))
248  ul[1] = (buffered.GetIndex()[1] + buffered.GetSize()[1] - 1);
249 
250  ur = ul;
251  ll = ul;
252  lr = ul;
253  if (ul[0] < static_cast<IndexValueType>(buffered.GetIndex()[0] + buffered.GetSize()[0] - 1))
254  {
255  ur[0] += 1;
256  lr[0] += 1;
257  }
258  if (ul[1] < static_cast<IndexValueType>(buffered.GetIndex()[1] + buffered.GetSize()[1] - 1))
259  {
260  ll[1] += 1;
261  lr[1] += 1;
262  }
263 
264  double rx = tmpIndex[0] - static_cast<double>(ul[0]);
265  double ry = tmpIndex[1] - static_cast<double>(ul[1]);
266 
267  itk::ContinuousIndex<double, 2> backIndex(tmpIndex);
268  backIndex[0] += (1. - ry) * ((1. - rx) * reverseHmap->GetPixel(ul) + rx * reverseHmap->GetPixel(ur)) +
269  ry * ((1. - rx) * reverseHmap->GetPixel(ll) + rx * reverseHmap->GetPixel(lr));
270  if (reverseVmap)
271  {
272  backIndex[1] += (1. - ry) * ((1. - rx) * reverseVmap->GetPixel(ul) + rx * reverseVmap->GetPixel(ur)) +
273  ry * ((1. - rx) * reverseVmap->GetPixel(ll) + rx * reverseVmap->GetPixel(lr));
274  }
275 
276  if (std::abs(backIndex[0] - static_cast<double>(startIndex[0])) < this->m_Tolerance &&
277  std::abs(backIndex[1] - static_cast<double>(startIndex[1])) < this->m_Tolerance)
278  {
279  outIter.Set(255);
280  }
281  else
282  {
283  outIter.Set(0);
284  }
285 
286  ++outIter;
287  ++directHorizIter;
288  if (directVmap)
289  ++directVertiIter;
290  }
291 }
292 }
293 
294 #endif
void SetReverseHorizontalDisparityMapInput(const TDisparityImage *hmap)
void SetDirectHorizontalDisparityMapInput(const TDisparityImage *hmap)
void SetDirectVerticalDisparityMapInput(const TDisparityImage *vmap)
const TDisparityImage * GetDirectHorizontalDisparityMapInput() const
void DynamicThreadedGenerateData(const OutputRegionType &outputRegionForThread) override
const TDisparityImage * GetReverseVerticalDisparityMapInput() const
const TDisparityImage * GetDirectVerticalDisparityMapInput() const
void SetReverseVerticalDisparityMapInput(const TDisparityImage *vmap)
const TDisparityImage * GetReverseHorizontalDisparityMapInput() const
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.