OTB  9.0.0
Orfeo Toolbox
otbPixelWiseBlockMatchingImageFilter.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 otbPixelWiseBlockMatchingImageFilter_hxx
22 #define otbPixelWiseBlockMatchingImageFilter_hxx
23 
25 #include "itkProgressReporter.h"
26 #include "itkConstantBoundaryCondition.h"
27 
28 namespace otb
29 {
30 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
31 PixelWiseBlockMatchingImageFilter<TInputImage, TOutputMetricImage, TOutputDisparityImage, TMaskImage,
32  TBlockMatchingFunctor>::PixelWiseBlockMatchingImageFilter()
33 {
34  // Set the number of inputs
35  this->SetNumberOfRequiredInputs(6);
36  this->SetNumberOfRequiredInputs(2);
37 
38  // Set the outputs
39  this->SetNumberOfRequiredOutputs(3);
40  this->SetNthOutput(0, TOutputMetricImage::New());
41  this->SetNthOutput(1, TOutputDisparityImage::New());
42  this->SetNthOutput(2, TOutputDisparityImage::New());
43 
44  // Default parameters
45  m_Radius.Fill(2);
46 
47  // Minimize by default
48  m_Minimize = true;
49 
50  // Default disparity range
51  m_MinimumHorizontalDisparity = -10;
52  m_MaximumHorizontalDisparity = 10;
53  m_MinimumVerticalDisparity = 0;
54  m_MaximumVerticalDisparity = 0;
55 
56  // Default initial disparity
57  m_InitHorizontalDisparity = 0;
58  m_InitVerticalDisparity = 0;
59 
60  // Default exploration radius : 0 (not used)
61  m_ExplorationRadius.Fill(0);
62 
63  // Default step
64  m_Step = 1;
65 
66  // Default grid index
67  m_GridIndex[0] = 0;
68  m_GridIndex[1] = 0;
69 }
70 
71 
72 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
73 PixelWiseBlockMatchingImageFilter<TInputImage, TOutputMetricImage, TOutputDisparityImage, TMaskImage,
74  TBlockMatchingFunctor>::~PixelWiseBlockMatchingImageFilter()
75 {
76 }
77 
78 
79 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
81  const TInputImage* image)
82 {
83  // Process object is not const-correct so the const casting is required.
84  this->SetNthInput(0, const_cast<TInputImage*>(image));
85 }
86 
87 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
89  const TInputImage* image)
90 {
91  // Process object is not const-correct so the const casting is required.
92  this->SetNthInput(1, const_cast<TInputImage*>(image));
93 }
94 
95 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
97  const TMaskImage* image)
98 {
99  // Process object is not const-correct so the const casting is required.
100  this->SetNthInput(2, const_cast<TMaskImage*>(image));
101 }
102 
103 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
105  const TMaskImage* image)
106 {
107  // Process object is not const-correct so the const casting is required.
108  this->SetNthInput(3, const_cast<TMaskImage*>(image));
109 }
110 
111 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
112 const TInputImage*
114 {
115  if (this->GetNumberOfInputs() < 1)
116  {
117  return nullptr;
118  }
119  return static_cast<const TInputImage*>(this->itk::ProcessObject::GetInput(0));
120 }
121 
122 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
123 const TInputImage*
125 {
126  if (this->GetNumberOfInputs() < 2)
127  {
128  return nullptr;
129  }
130  return static_cast<const TInputImage*>(this->itk::ProcessObject::GetInput(1));
131 }
132 
133 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
134 const TMaskImage*
136 {
137  if (this->GetNumberOfInputs() < 3)
138  {
139  return nullptr;
140  }
141  return static_cast<const TMaskImage*>(this->itk::ProcessObject::GetInput(2));
142 }
143 
144 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
145 const TMaskImage*
147 {
148  if (this->GetNumberOfInputs() < 4)
149  {
150  return nullptr;
151  }
152  return static_cast<const TMaskImage*>(this->itk::ProcessObject::GetInput(3));
153 }
154 
155 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
156 const TOutputMetricImage*
158 {
159  if (this->GetNumberOfOutputs() < 1)
160  {
161  return nullptr;
162  }
163  return static_cast<const TOutputMetricImage*>(this->itk::ProcessObject::GetOutput(0));
164 }
165 
166 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
167 TOutputMetricImage*
169 {
170  if (this->GetNumberOfOutputs() < 1)
171  {
172  return nullptr;
173  }
174  return static_cast<TOutputMetricImage*>(this->itk::ProcessObject::GetOutput(0));
175 }
176 
177 
178 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
179 const TOutputDisparityImage* PixelWiseBlockMatchingImageFilter<TInputImage, TOutputMetricImage, TOutputDisparityImage, TMaskImage,
180  TBlockMatchingFunctor>::GetHorizontalDisparityOutput() const
181 {
182  if (this->GetNumberOfOutputs() < 2)
183  {
184  return nullptr;
185  }
186  return static_cast<const TOutputDisparityImage*>(this->itk::ProcessObject::GetOutput(1));
187 }
188 
189 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
190 TOutputDisparityImage*
192 {
193  if (this->GetNumberOfOutputs() < 2)
194  {
195  return nullptr;
196  }
197  return static_cast<TOutputDisparityImage*>(this->itk::ProcessObject::GetOutput(1));
198 }
199 
200 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
201 const TOutputDisparityImage*
203 {
204  if (this->GetNumberOfOutputs() < 3)
205  {
206  return nullptr;
207  }
208  return static_cast<const TOutputDisparityImage*>(this->itk::ProcessObject::GetOutput(2));
209 }
210 
211 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
212 TOutputDisparityImage*
214 {
215  if (this->GetNumberOfOutputs() < 3)
216  {
217  return nullptr;
218  }
219  return static_cast<TOutputDisparityImage*>(this->itk::ProcessObject::GetOutput(2));
220 }
221 
222 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
224  const TOutputDisparityImage* hfield)
225 {
226  // Process object is not const-correct so the const casting is required.
227  this->SetNthInput(4, const_cast<TOutputDisparityImage*>(hfield));
228 }
229 
230 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
232  const TOutputDisparityImage* vfield)
233 {
234  // Process object is not const-correct so the const casting is required.
235  this->SetNthInput(5, const_cast<TOutputDisparityImage*>(vfield));
236 }
237 
238 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
239 const TOutputDisparityImage* PixelWiseBlockMatchingImageFilter<TInputImage, TOutputMetricImage, TOutputDisparityImage, TMaskImage,
240  TBlockMatchingFunctor>::GetHorizontalDisparityInput() const
241 {
242  if (this->GetNumberOfInputs() < 5)
243  {
244  return nullptr;
245  }
246  return static_cast<const TOutputDisparityImage*>(this->itk::ProcessObject::GetInput(4));
247 }
248 
249 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
250 const TOutputDisparityImage*
252 {
253  if (this->GetNumberOfInputs() < 6)
254  {
255  return nullptr;
256  }
257  return static_cast<const TOutputDisparityImage*>(this->itk::ProcessObject::GetInput(5));
258 }
259 
260 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
262 {
263  // Call superclass implementation
264  Superclass::GenerateOutputInformation();
265 
266  // Sanity check
267  if (this->m_Step == 0)
268  this->m_Step = 1;
269  this->m_GridIndex[0] = this->m_GridIndex[0] % this->m_Step;
270  this->m_GridIndex[1] = this->m_GridIndex[1] % this->m_Step;
271 
272  // Modify output size and index depending on the step
273  const TInputImage* inLeftPtr = this->GetLeftInput();
274 
275  RegionType outputLargest = this->ConvertFullToSubsampledRegion(inLeftPtr->GetLargestPossibleRegion(), this->m_Step, this->m_GridIndex);
276 
277  TOutputMetricImage* outMetricPtr = const_cast<TOutputMetricImage*>(this->GetMetricOutput());
278  TOutputDisparityImage* outHDispPtr = const_cast<TOutputDisparityImage*>(this->GetHorizontalDisparityOutput());
279  TOutputDisparityImage* outVDispPtr = const_cast<TOutputDisparityImage*>(this->GetVerticalDisparityOutput());
280 
281  outMetricPtr->SetLargestPossibleRegion(outputLargest);
282  outHDispPtr->SetLargestPossibleRegion(outputLargest);
283  outVDispPtr->SetLargestPossibleRegion(outputLargest);
284 
285  // Adapt spacing
286  SpacingType outSpacing = inLeftPtr->GetSignedSpacing();
287  outSpacing[0] *= static_cast<double>(this->m_Step);
288  outSpacing[1] *= static_cast<double>(this->m_Step);
289 
290  outMetricPtr->SetSignedSpacing(outSpacing);
291  outHDispPtr->SetSignedSpacing(outSpacing);
292  outVDispPtr->SetSignedSpacing(outSpacing);
293 
294  // Adapt origin
295  PointType outOrigin = inLeftPtr->GetOrigin();
296  SpacingType inSpacing = inLeftPtr->GetSignedSpacing();
297  outOrigin[0] += inSpacing[0] * static_cast<double>(this->m_GridIndex[0]);
298  outOrigin[1] += inSpacing[1] * static_cast<double>(this->m_GridIndex[1]);
299 
300  outMetricPtr->SetOrigin(outOrigin);
301  outHDispPtr->SetOrigin(outOrigin);
302  outVDispPtr->SetOrigin(outOrigin);
303 }
304 
305 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
306 void PixelWiseBlockMatchingImageFilter<TInputImage, TOutputMetricImage, TOutputDisparityImage, TMaskImage,
307  TBlockMatchingFunctor>::GenerateInputRequestedRegion()
308 {
309  // Call superclass implementation
310  Superclass::GenerateInputRequestedRegion();
311 
312  // Retrieve input pointers
313  TInputImage* inLeftPtr = const_cast<TInputImage*>(this->GetLeftInput());
314  TInputImage* inRightPtr = const_cast<TInputImage*>(this->GetRightInput());
315  TMaskImage* inLeftMaskPtr = const_cast<TMaskImage*>(this->GetLeftMaskInput());
316  TMaskImage* inRightMaskPtr = const_cast<TMaskImage*>(this->GetRightMaskInput());
317  TOutputDisparityImage* inHDispPtr = const_cast<TOutputDisparityImage*>(this->GetHorizontalDisparityInput());
318  TOutputDisparityImage* inVDispPtr = const_cast<TOutputDisparityImage*>(this->GetVerticalDisparityInput());
319 
320  TOutputMetricImage* outMetricPtr = this->GetMetricOutput();
321  TOutputDisparityImage* outHDispPtr = this->GetHorizontalDisparityOutput();
322  TOutputDisparityImage* outVDispPtr = this->GetVerticalDisparityOutput();
323 
324  // Check pointers before using them
325  if (!inLeftPtr || !inRightPtr || !outMetricPtr || !outHDispPtr || !outVDispPtr)
326  {
327  return;
328  }
329 
330  // Now, we impose that both inputs have the same size
331  if (inLeftPtr->GetLargestPossibleRegion() != inRightPtr->GetLargestPossibleRegion())
332  {
333  itkExceptionMacro(<< "Left and right images do not have the same size ! Left largest region: " << inLeftPtr->GetLargestPossibleRegion()
334  << ", right largest region: " << inRightPtr->GetLargestPossibleRegion());
335  }
336 
337  // We also check that left mask image has same size if present
338  if (inLeftMaskPtr && inLeftPtr->GetLargestPossibleRegion() != inLeftMaskPtr->GetLargestPossibleRegion())
339  {
340  itkExceptionMacro(<< "Left and mask images do not have the same size ! Left largest region: " << inLeftPtr->GetLargestPossibleRegion()
341  << ", mask largest region: " << inLeftMaskPtr->GetLargestPossibleRegion());
342  }
343 
344  // We also check that right mask image has same size if present
345  if (inRightMaskPtr && inRightPtr->GetLargestPossibleRegion() != inRightMaskPtr->GetLargestPossibleRegion())
346  {
347  itkExceptionMacro(<< "Right and mask images do not have the same size ! Right largest region: " << inRightPtr->GetLargestPossibleRegion()
348  << ", mask largest region: " << inRightMaskPtr->GetLargestPossibleRegion());
349  }
350 
351  // We check that the input initial disparity maps have the same size if present
352  if (inHDispPtr && inLeftPtr->GetLargestPossibleRegion() != inHDispPtr->GetLargestPossibleRegion())
353  {
354  itkExceptionMacro(<< "Left image and initial horizontal disparity map do not have the same size ! Left largest region: "
355  << inLeftPtr->GetLargestPossibleRegion() << ", horizontal disparity largest region: " << inHDispPtr->GetLargestPossibleRegion());
356  }
357  if (inVDispPtr && inLeftPtr->GetLargestPossibleRegion() != inVDispPtr->GetLargestPossibleRegion())
358  {
359  itkExceptionMacro(<< "Left image and initial vertical disparity map do not have the same size ! Left largest region: "
360  << inLeftPtr->GetLargestPossibleRegion() << ", vertical disparity largest region: " << inVDispPtr->GetLargestPossibleRegion());
361  }
362 
363  // Sanity check
364  if (this->m_Step == 0)
365  this->m_Step = 1;
366  this->m_GridIndex[0] = this->m_GridIndex[0] % this->m_Step;
367  this->m_GridIndex[1] = this->m_GridIndex[1] % this->m_Step;
368 
369  // Retrieve requested region (TODO: check if we need to handle
370  // region for outHDispPtr)
371  RegionType inputLeftRegion = this->ConvertSubsampledToFullRegion(outMetricPtr->GetRequestedRegion(), this->m_Step, this->m_GridIndex);
372 
373  // Pad by the appropriate radius
374  inputLeftRegion.PadByRadius(m_Radius);
375 
376  // Now, we must find the corresponding region in moving image
377  IndexType rightRequestedRegionIndex = inputLeftRegion.GetIndex();
378  rightRequestedRegionIndex[0] += m_MinimumHorizontalDisparity;
379  rightRequestedRegionIndex[1] += m_MinimumVerticalDisparity;
380 
381  SizeType rightRequestedRegionSize = inputLeftRegion.GetSize();
382  rightRequestedRegionSize[0] += m_MaximumHorizontalDisparity - m_MinimumHorizontalDisparity;
383  rightRequestedRegionSize[1] += m_MaximumVerticalDisparity - m_MinimumVerticalDisparity;
384 
385  RegionType inputRightRegion;
386  inputRightRegion.SetIndex(rightRequestedRegionIndex);
387  inputRightRegion.SetSize(rightRequestedRegionSize);
388 
389  // crop the left region at the left's largest possible region
390  if (inputLeftRegion.Crop(inLeftPtr->GetLargestPossibleRegion()))
391  {
392  inLeftPtr->SetRequestedRegion(inputLeftRegion);
393  }
394  else
395  {
396  // Couldn't crop the region (requested region is outside the largest
397  // possible region). Throw an exception.
398  // store what we tried to request (prior to trying to crop)
399  inLeftPtr->SetRequestedRegion(inputLeftRegion);
400 
401  // build an exception
402  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
403  std::ostringstream msg;
404  msg << this->GetNameOfClass() << "::GenerateInputRequestedRegion()";
405  e.SetLocation(msg.str());
406  e.SetDescription("Requested region is (at least partially) outside the largest possible region of left image.");
407  e.SetDataObject(inLeftPtr);
408  throw e;
409  }
410 
411 
412  // crop the right region at the right's largest possible region
413  if (inputRightRegion.Crop(inRightPtr->GetLargestPossibleRegion()))
414  {
415  inRightPtr->SetRequestedRegion(inputRightRegion);
416  }
417  else
418  {
419  // Couldn't crop the region (requested region is outside the largest
420  // possible region). Throw an exception.
421  // store what we tried to request (prior to trying to crop)
422  inRightPtr->SetRequestedRegion(inputRightRegion);
423 
424  // build an exception
425  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
426  std::ostringstream msg;
427  msg << this->GetNameOfClass() << "::GenerateInputRequestedRegion()";
428  e.SetLocation(msg.str());
429  e.SetDescription("Requested region is (at least partially) outside the largest possible region of right image.");
430  e.SetDataObject(inRightPtr);
431  throw e;
432  }
433 
434  if (inLeftMaskPtr)
435  {
436  // no need to crop the mask region : left mask and left image have same largest possible region
437  inLeftMaskPtr->SetRequestedRegion(inputLeftRegion);
438  }
439 
440  if (inRightMaskPtr)
441  {
442  // no need to crop the mask region : right mask and right image have same largest possible region
443  inRightMaskPtr->SetRequestedRegion(inputRightRegion);
444  }
445 
446  if (inHDispPtr && inVDispPtr)
447  {
448  inHDispPtr->SetRequestedRegion(inputLeftRegion);
449  inVDispPtr->SetRequestedRegion(inputLeftRegion);
450  }
451 }
452 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
454 {
455  TOutputMetricImage* outMetricPtr = this->GetMetricOutput();
456  TOutputDisparityImage* outHDispPtr = this->GetHorizontalDisparityOutput();
457  TOutputDisparityImage* outVDispPtr = this->GetVerticalDisparityOutput();
458 
459  // Sanity check
460  if (this->m_Step == 0)
461  this->m_Step = 1;
462  this->m_GridIndex[0] = this->m_GridIndex[0] % this->m_Step;
463  this->m_GridIndex[1] = this->m_GridIndex[1] % this->m_Step;
464 
465  // Fill buffers with default values
466  outMetricPtr->FillBuffer(0.);
467  outHDispPtr->FillBuffer(static_cast<DisparityPixelType>(m_MaximumHorizontalDisparity) / static_cast<DisparityPixelType>(m_Step));
468  outVDispPtr->FillBuffer(static_cast<DisparityPixelType>(m_MinimumVerticalDisparity) / static_cast<DisparityPixelType>(m_Step));
469 }
470 
471 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
473  const RegionType& outputRegionForThread, itk::ThreadIdType threadId)
474 {
475  // Retrieve pointers
476  const TInputImage* inLeftPtr = this->GetLeftInput();
477  const TInputImage* inRightPtr = this->GetRightInput();
478  const TMaskImage* inLeftMaskPtr = this->GetLeftMaskInput();
479  const TMaskImage* inRightMaskPtr = this->GetRightMaskInput();
480  const TOutputDisparityImage* inHDispPtr = this->GetHorizontalDisparityInput();
481  const TOutputDisparityImage* inVDispPtr = this->GetVerticalDisparityInput();
482  TOutputMetricImage* outMetricPtr = this->GetMetricOutput();
483  TOutputDisparityImage* outHDispPtr = this->GetHorizontalDisparityOutput();
484  TOutputDisparityImage* outVDispPtr = this->GetVerticalDisparityOutput();
485 
486  // Set-up progress reporting (this is not exact, since we do not
487  // account for pixels that are out of range for a given disparity
488  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels() * (m_MaximumHorizontalDisparity - m_MinimumHorizontalDisparity + 1) *
489  (m_MaximumVerticalDisparity - m_MinimumVerticalDisparity + 1),
490  100);
491 
492 
493  // Handle initialization properly
494  typename InputMaskImageType::Pointer initMaskPtr = InputMaskImageType::New();
495  initMaskPtr->SetRegions(outputRegionForThread);
496  initMaskPtr->Allocate();
497  initMaskPtr->FillBuffer(0);
498 
499  // Compute region for thread at full resolution
500  RegionType fullRegionForThread = this->ConvertSubsampledToFullRegion(outputRegionForThread, this->m_Step, this->m_GridIndex);
501 
502  // Check if we use initial disparities and exploration radius
503  bool useExplorationRadius = false;
504  bool useInitDispMaps = false;
505  if (m_ExplorationRadius[0] >= 1 || m_ExplorationRadius[1] >= 1)
506  {
507  useExplorationRadius = true;
508  if (inHDispPtr && inVDispPtr)
509  {
510  useInitDispMaps = true;
511  }
512  }
513 
514  // step value as disparityType
515  DisparityPixelType stepDisparityInv = 1. / static_cast<DisparityPixelType>(this->m_Step);
516 
517  // We loop on disparities
518  for (int vdisparity = m_MinimumVerticalDisparity; vdisparity <= m_MaximumVerticalDisparity; ++vdisparity)
519  {
520  for (int hdisparity = m_MinimumHorizontalDisparity; hdisparity <= m_MaximumHorizontalDisparity; ++hdisparity)
521  {
522  // First, we cast output region to the right image
523  IndexType rightRequestedRegionIndex = fullRegionForThread.GetIndex();
524  rightRequestedRegionIndex[0] += hdisparity;
525  rightRequestedRegionIndex[1] += vdisparity;
526 
527  // We crop
528  RegionType inputRightRegion;
529  inputRightRegion.SetIndex(rightRequestedRegionIndex);
530  inputRightRegion.SetSize(fullRegionForThread.GetSize());
531  inputRightRegion.Crop(inRightPtr->GetLargestPossibleRegion());
532 
533  // And then cast back
534  IndexType leftRequestedRegionIndex = inputRightRegion.GetIndex();
535  leftRequestedRegionIndex[0] -= hdisparity;
536  leftRequestedRegionIndex[1] -= vdisparity;
537 
538  RegionType inputLeftRegion;
539  inputLeftRegion.SetIndex(leftRequestedRegionIndex);
540  inputLeftRegion.SetSize(inputRightRegion.GetSize());
541 
542  // Compute the equivalent region in subsampled grid
543  RegionType outputRegion = this->ConvertFullToSubsampledRegion(inputLeftRegion, this->m_Step, this->m_GridIndex);
544 
545  // Define iterators
546  itk::ConstNeighborhoodIterator<TInputImage> leftIt(m_Radius, inLeftPtr, inputLeftRegion);
547  itk::ConstNeighborhoodIterator<TInputImage> rightIt(m_Radius, inRightPtr, inputRightRegion);
548  itk::ImageRegionIterator<TOutputMetricImage> outMetricIt(outMetricPtr, outputRegion);
549  itk::ImageRegionIterator<TOutputDisparityImage> outHDispIt(outHDispPtr, outputRegion);
550  itk::ImageRegionIterator<TOutputDisparityImage> outVDispIt(outVDispPtr, outputRegion);
551  itk::ImageRegionConstIterator<TMaskImage> inLeftMaskIt;
552  itk::ImageRegionConstIterator<TMaskImage> inRightMaskIt;
553  itk::ImageRegionConstIterator<TOutputDisparityImage> inHDispIt;
554  itk::ImageRegionConstIterator<TOutputDisparityImage> inVDispIt;
555  itk::ImageRegionIterator<TMaskImage> initIt(initMaskPtr, outputRegion);
556 
557  itk::ConstantBoundaryCondition<TInputImage> nbc1;
558  itk::ConstantBoundaryCondition<TInputImage> nbc2;
559 
560  leftIt.OverrideBoundaryCondition(&nbc1);
561  rightIt.OverrideBoundaryCondition(&nbc2);
562 
563  // If we have a mask, define the iterator
564  if (inLeftMaskPtr)
565  {
566  inLeftMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inLeftMaskPtr, inputLeftRegion);
567  inLeftMaskIt.GoToBegin();
568  }
569  if (inRightMaskPtr)
570  {
571  inRightMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inRightMaskPtr, inputRightRegion);
572  inRightMaskIt.GoToBegin();
573  }
574 
575  // If we use initial disparity maps, define the iterators
576  if (useInitDispMaps)
577  {
578  inHDispIt = itk::ImageRegionConstIterator<TOutputDisparityImage>(inHDispPtr, inputLeftRegion);
579  inVDispIt = itk::ImageRegionConstIterator<TOutputDisparityImage>(inVDispPtr, inputLeftRegion);
580  inHDispIt.GoToBegin();
581  inVDispIt.GoToBegin();
582  }
583 
584  // Initialize iterators
585  leftIt.GoToBegin();
586  rightIt.GoToBegin();
587  outMetricIt.GoToBegin();
588  outHDispIt.GoToBegin();
589  outVDispIt.GoToBegin();
590  initIt.GoToBegin();
591 
592  // Loop on pixels
593  while (!leftIt.IsAtEnd() || !rightIt.IsAtEnd() || !outMetricIt.IsAtEnd() || !outHDispIt.IsAtEnd() || !outVDispIt.IsAtEnd() || !initIt.IsAtEnd())
594  {
595  // If the pixel location is on the subsampled grid
596  IndexType tmpIndex = leftIt.GetIndex(leftIt.GetCenterNeighborhoodIndex());
597  if (((tmpIndex[0] - this->m_GridIndex[0] + this->m_Step) % this->m_Step == 0) &&
598  ((tmpIndex[1] - this->m_GridIndex[1] + this->m_Step) % this->m_Step == 0))
599  {
600  // If the mask is present and valid
601  if (!inLeftMaskPtr || (inLeftMaskIt.Get() > 0))
602  {
603  if (!inRightMaskPtr || (inRightMaskIt.Get() > 0))
604  {
605  int estimatedMinHDisp = m_MinimumHorizontalDisparity;
606  int estimatedMinVDisp = m_MinimumVerticalDisparity;
607  int estimatedMaxHDisp = m_MaximumHorizontalDisparity;
608  int estimatedMaxVDisp = m_MaximumVerticalDisparity;
609  if (useExplorationRadius)
610  {
611  // compute disparity bounds from initial position and exploration radius
612  if (useInitDispMaps)
613  {
614  estimatedMinHDisp = inHDispIt.Get() - m_ExplorationRadius[0];
615  estimatedMinVDisp = inVDispIt.Get() - m_ExplorationRadius[1];
616  estimatedMaxHDisp = inHDispIt.Get() + m_ExplorationRadius[0];
617  estimatedMaxVDisp = inVDispIt.Get() + m_ExplorationRadius[1];
618  }
619  else
620  {
621  estimatedMinHDisp = m_InitHorizontalDisparity - m_ExplorationRadius[0];
622  estimatedMinVDisp = m_InitVerticalDisparity - m_ExplorationRadius[1];
623  estimatedMaxHDisp = m_InitHorizontalDisparity + m_ExplorationRadius[0];
624  estimatedMaxVDisp = m_InitVerticalDisparity + m_ExplorationRadius[1];
625  }
626  // clamp to the minimum disparities
627  if (estimatedMinHDisp < m_MinimumHorizontalDisparity)
628  {
629  estimatedMinHDisp = m_MinimumHorizontalDisparity;
630  }
631  if (estimatedMinVDisp < m_MinimumVerticalDisparity)
632  {
633  estimatedMinVDisp = m_MinimumVerticalDisparity;
634  }
635  }
636 
637  if (vdisparity >= estimatedMinVDisp && vdisparity <= estimatedMaxVDisp && hdisparity >= estimatedMinHDisp && hdisparity <= estimatedMaxHDisp)
638  {
639  // Compute the block matching value
640  double metric = m_Functor(leftIt, rightIt);
641 
642  // If we are at first loop, fill both outputs
643  // We adapt the disparity value to keep consistent with disparity map index space
644  if (initIt.Get() == 0)
645  {
646  outHDispIt.Set(static_cast<DisparityPixelType>(hdisparity) * stepDisparityInv);
647  outVDispIt.Set(static_cast<DisparityPixelType>(vdisparity) * stepDisparityInv);
648  outMetricIt.Set(metric);
649  initIt.Set(1);
650  }
651  else if (m_Minimize && metric < outMetricIt.Get())
652  {
653  outHDispIt.Set(static_cast<DisparityPixelType>(hdisparity) * stepDisparityInv);
654  outVDispIt.Set(static_cast<DisparityPixelType>(vdisparity) * stepDisparityInv);
655  outMetricIt.Set(metric);
656  }
657  else if (!m_Minimize && metric > outMetricIt.Get())
658  {
659  outHDispIt.Set(static_cast<DisparityPixelType>(hdisparity) * stepDisparityInv);
660  outVDispIt.Set(static_cast<DisparityPixelType>(vdisparity) * stepDisparityInv);
661  outMetricIt.Set(metric);
662  }
663  }
664  }
665  }
666  ++outMetricIt;
667  ++outHDispIt;
668  ++outVDispIt;
669  ++initIt;
670  progress.CompletedPixel();
671  }
672  ++leftIt;
673  ++rightIt;
674 
675  if (inLeftMaskPtr)
676  {
677  ++inLeftMaskIt;
678  }
679 
680  if (inRightMaskPtr)
681  {
682  ++inRightMaskIt;
683  }
684 
685  if (useInitDispMaps)
686  {
687  ++inHDispIt;
688  ++inVDispIt;
689  }
690  }
691  }
692  }
693 }
694 
695 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
698  RegionType full, unsigned int step, IndexType index)
699 {
700  IndexType shiftedFull = full.GetIndex();
701  shiftedFull[0] -= index[0];
702  shiftedFull[1] -= index[1];
703 
704  IndexType subIndex;
705  subIndex[0] = (shiftedFull[0]) / step;
706  subIndex[1] = (shiftedFull[1]) / step;
707  if (shiftedFull[0] % step)
708  ++subIndex[0];
709  if (shiftedFull[1] % step)
710  ++subIndex[1];
711 
712  if (shiftedFull[0] < 0)
713  subIndex[0] = 0;
714  if (shiftedFull[1] < 0)
715  subIndex[1] = 0;
716 
717  SizeType subSize;
718  subSize[0] = (full.GetSize(0) - (subIndex[0] * step) + shiftedFull[0]) / step;
719  subSize[1] = (full.GetSize(1) - (subIndex[1] * step) + shiftedFull[1]) / step;
720 
721  if ((full.GetSize(0) - (subIndex[0] * step) + shiftedFull[0]) % step)
722  ++subSize[0];
723  if ((full.GetSize(1) - (subIndex[1] * step) + shiftedFull[1]) % step)
724  ++subSize[1];
725 
726  RegionType subRegion;
727  subRegion.SetIndex(subIndex);
728  subRegion.SetSize(subSize);
729  return subRegion;
730 }
731 
732 template <class TInputImage, class TOutputMetricImage, class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
735  RegionType sub, unsigned int step, IndexType index)
736 {
737  IndexType fullIndex;
738  fullIndex[0] = sub.GetIndex(0) * step + index[0];
739  fullIndex[1] = sub.GetIndex(1) * step + index[1];
740 
741  SizeType fullSize;
742  fullSize[0] = sub.GetSize(0) * step;
743  fullSize[1] = sub.GetSize(1) * step;
744  if (fullSize[0] > 0)
745  fullSize[0] -= (step - 1);
746  if (fullSize[1] > 0)
747  fullSize[1] -= (step - 1);
748 
749  RegionType fullRegion;
750  fullRegion.SetIndex(fullIndex);
751  fullRegion.SetSize(fullSize);
752  return fullRegion;
753 }
754 
755 } // End namespace otb
756 
757 #endif
otb::PixelWiseBlockMatchingImageFilter::ConvertSubsampledToFullRegion
static RegionType ConvertSubsampledToFullRegion(RegionType sub, unsigned int step, IndexType index)
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:734
otb::PixelWiseBlockMatchingImageFilter::ConvertFullToSubsampledRegion
static RegionType ConvertFullToSubsampledRegion(RegionType full, unsigned int step, IndexType index)
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:697
otb::PixelWiseBlockMatchingImageFilter::BeforeThreadedGenerateData
void BeforeThreadedGenerateData() override
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:453
otb::PixelWiseBlockMatchingImageFilter::GetRightMaskInput
const TMaskImage * GetRightMaskInput() const
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:146
otb::PixelWiseBlockMatchingImageFilter::PointType
InputImageType::PointType PointType
Definition: otbPixelWiseBlockMatchingImageFilter.h:324
otb::PixelWiseBlockMatchingImageFilter::SetRightMaskInput
void SetRightMaskInput(const TMaskImage *image)
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:104
otb::PixelWiseBlockMatchingImageFilter::SetRightInput
void SetRightInput(const TInputImage *image)
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:88
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::PixelWiseBlockMatchingImageFilter::GenerateOutputInformation
void GenerateOutputInformation() override
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:261
otb::PixelWiseBlockMatchingImageFilter::GetRightInput
const TInputImage * GetRightInput() const
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:124
otb::PixelWiseBlockMatchingImageFilter::DisparityPixelType
OutputDisparityImageType::PixelType DisparityPixelType
Definition: otbPixelWiseBlockMatchingImageFilter.h:328
otb::PixelWiseBlockMatchingImageFilter::SetHorizontalDisparityInput
void SetHorizontalDisparityInput(const TOutputDisparityImage *hfield)
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:223
otb::PixelWiseBlockMatchingImageFilter::IndexType
InputImageType::IndexType IndexType
Definition: otbPixelWiseBlockMatchingImageFilter.h:321
otb::PixelWiseBlockMatchingImageFilter::SetVerticalDisparityInput
void SetVerticalDisparityInput(const TOutputDisparityImage *vfield)
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:231
otb::PixelWiseBlockMatchingImageFilter::ThreadedGenerateData
void ThreadedGenerateData(const RegionType &outputRegionForThread, itk::ThreadIdType threadId) override
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:472
otb::PixelWiseBlockMatchingImageFilter::SetLeftMaskInput
void SetLeftMaskInput(const TMaskImage *image)
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:96
otbPixelWiseBlockMatchingImageFilter.h
otb::PixelWiseBlockMatchingImageFilter
Perform 2D block matching between two images.
Definition: otbPixelWiseBlockMatchingImageFilter.h:298
otb::PixelWiseBlockMatchingImageFilter::SizeType
InputImageType::SizeType SizeType
Definition: otbPixelWiseBlockMatchingImageFilter.h:320
otb::PixelWiseBlockMatchingImageFilter::RegionType
InputImageType::RegionType RegionType
Definition: otbPixelWiseBlockMatchingImageFilter.h:322
otb::PixelWiseBlockMatchingImageFilter::GetLeftMaskInput
const TMaskImage * GetLeftMaskInput() const
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:135
otb::PixelWiseBlockMatchingImageFilter::SpacingType
InputImageType::SpacingType SpacingType
Definition: otbPixelWiseBlockMatchingImageFilter.h:323
otb::PixelWiseBlockMatchingImageFilter::SetLeftInput
void SetLeftInput(const TInputImage *image)
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:80
otb::PixelWiseBlockMatchingImageFilter::GetMetricOutput
const TOutputMetricImage * GetMetricOutput() const
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:157
otb::PixelWiseBlockMatchingImageFilter::GetLeftInput
const TInputImage * GetLeftInput() const
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:113
otb::PixelWiseBlockMatchingImageFilter::GetVerticalDisparityInput
const TOutputDisparityImage * GetVerticalDisparityInput() const
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:251
otb::PixelWiseBlockMatchingImageFilter::GetHorizontalDisparityOutput
const TOutputDisparityImage * GetHorizontalDisparityOutput() const
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:180
otb::PixelWiseBlockMatchingImageFilter::GetVerticalDisparityOutput
const TOutputDisparityImage * GetVerticalDisparityOutput() const
Definition: otbPixelWiseBlockMatchingImageFilter.hxx:202