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