OTB  5.9.0
Orfeo Toolbox
otbWaveletFilterBank.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12  Copyright (c) Institut Mines-Telecom. All rights reserved.
13  See IMTCopyright.txt for details.
14 
15  This software is distributed WITHOUT ANY WARRANTY; without even
16  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17  PURPOSE. See the above copyright notices for more information.
18 
19 =========================================================================*/
20 
21 #ifndef otbWaveletFilterBank_txx
22 #define otbWaveletFilterBank_txx
23 #include "otbWaveletFilterBank.h"
24 
27 
29 
30 // FIXME
31 #define __myDebug__ 0
32 
33 namespace otb {
34 
39 template <class TInputImage, class TOutputImage, class TWaveletOperator>
42 {
43  this->SetNumberOfRequiredInputs(1);
44  this->SetNumberOfRequiredInputs(1);
45 
46  unsigned int numOfOutputs = 1 << InputImageDimension;
47 
48  this->SetNumberOfRequiredOutputs(numOfOutputs);
49  for (unsigned int i = 0; i < numOfOutputs; ++i)
50  {
51  this->SetNthOutput(i, OutputImageType::New());
52  }
53 
54  m_UpSampleFilterFactor = 0;
55  m_SubsampleImageFactor = 1;
56 
57  //this->SetNumberOfThreads(1);
58 }
59 
60 template <class TInputImage, class TOutputImage, class TWaveletOperator>
61 void
64 {
65  Superclass::GenerateOutputInformation();
66 
67  if (GetSubsampleImageFactor() == 1) return;
68 
69 #if __myDebug__
70  otbGenericMsgDebugMacro(<< " down sampling output regions by a factor of " << GetSubsampleImageFactor());
71  otbGenericMsgDebugMacro(<< "initial region " << this->GetInput()->GetLargestPossibleRegion().GetSize()[0]
72  << "," << this->GetInput()->GetLargestPossibleRegion().GetSize()[1]);
73 #endif
74 
75  OutputImageRegionType newRegion;
76  this->CallCopyInputRegionToOutputRegion(newRegion, this->GetInput()->GetLargestPossibleRegion());
77 
78  for (unsigned int i = 0; i < this->GetNumberOfOutputs(); ++i)
79  {
80  this->GetOutput(i)->SetRegions(newRegion);
81  }
82 
83 #if __myDebug__
84  otbGenericMsgDebugMacro(<< "new region output " << newRegion.GetSize()[0] << "," << newRegion.GetSize()[1]);
85 #endif
86 }
87 
88 template <class TInputImage, class TOutputImage, class TWaveletOperator>
89 void
92 throw (itk::InvalidRequestedRegionError)
93  {
94  Superclass::GenerateInputRequestedRegion();
95 
96  // Filter length calculation
97  LowPassOperatorType lowPassOperator;
98  lowPassOperator.SetDirection(0);
99  lowPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
100  lowPassOperator.CreateDirectional();
101 
102  unsigned int radius = lowPassOperator.GetRadius()[0];
103 
104  HighPassOperatorType highPassOperator;
105  highPassOperator.SetDirection(0);
106  highPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
107  highPassOperator.CreateDirectional();
108 
109  if (radius < highPassOperator.GetRadius()[0]) radius = highPassOperator.GetRadius()[0];
110 
111  // Get the requested region and pad it
112  InputImagePointerType input = const_cast<InputImageType*>(this->GetInput());
113  InputImageRegionType inputRegion = input->GetRequestedRegion();
114  inputRegion.PadByRadius(radius);
115 
116  if (inputRegion.Crop(input->GetLargestPossibleRegion()))
117  {
118  input->SetRequestedRegion(inputRegion);
119  }
120  else
121  {
122  input->SetRequestedRegion(inputRegion);
123  itk::InvalidRequestedRegionError err(__FILE__, __LINE__);
124  err.SetLocation(ITK_LOCATION);
125  err.SetDescription("Requested region is (at least partially) outside the largest possible region.");
126  err.SetDataObject(input);
127  throw err;
128  }
129  }
130 
131 template <class TInputImage, class TOutputImage, class TWaveletOperator>
132 void
135 {
136 
137  unsigned int one = 1;
138  if (m_SubsampleImageFactor > 1)
139  {
140  // Check the dimension
141  for (unsigned int i = 0; i < InputImageDimension; ++i)
142  {
143  if ((m_SubsampleImageFactor
144  * (this->GetInput()->GetRequestedRegion().GetSize()[i] / m_SubsampleImageFactor))
145  != this->GetInput()->GetRequestedRegion().GetSize()[i])
146  {
147  itk::InvalidRequestedRegionError err(__FILE__, __LINE__);
148  err.SetLocation(ITK_LOCATION);
149  err.SetDescription("Requested region dimension cannot be used in multiresolution analysis (crop it).");
150  err.SetDataObject(const_cast<InputImageType*>(this->GetInput()));
151  throw err;
152  }
153  }
154 
155  if (InputImageDimension > 1)
156  {
157  // Internal images will be used only if m_SubsampledInputImages != 1
158  m_InternalImages.resize(InputImageDimension - 1);
159  for (unsigned int i = 0; i < m_InternalImages.size(); ++i)
160  {
161  // the size is linked to the SubsampleImageFactor that is assume to be 2!!!
162  m_InternalImages[InputImageDimension - 2 - i].resize( one << (i + 1));
163  }
164 
165  OutputImageRegionType intermediateRegion;
166  this->Superclass::CallCopyInputRegionToOutputRegion(intermediateRegion,
167  this->GetInput()->GetLargestPossibleRegion());
168 
169  AllocateInternalData(intermediateRegion);
170  }
171  }
172 }
173 
174 template <class TInputImage, class TOutputImage, class TWaveletOperator>
175 void
178  (const OutputImageRegionType& outputRegion)
179 {
180  OutputImageRegionType smallerRegion;
181  OutputImageRegionType largerRegion = outputRegion;
182 
183  for (unsigned int direction = 0; direction < InputImageDimension - 1; direction++)
184  {
185  this->CallCopyInputRegionToOutputRegion(InputImageDimension - 1 - direction,
186  smallerRegion, largerRegion);
187 
188  for (unsigned int i = 0; i < m_InternalImages[direction].size(); ++i)
189  {
190  m_InternalImages[InputImageDimension - 2 - direction][i] = OutputImageType::New();
191  m_InternalImages[InputImageDimension - 2 - direction][i]->SetRegions(smallerRegion);
192  m_InternalImages[InputImageDimension - 2 - direction][i]->Allocate();
193  m_InternalImages[InputImageDimension - 2 - direction][i]->FillBuffer(0);
194  }
195 
196  largerRegion = smallerRegion;
197  }
198 }
199 
200 template <class TInputImage, class TOutputImage, class TWaveletOperator>
201 void
204 {
205  if (m_SubsampleImageFactor > 1 && InputImageDimension > 1)
206  {
207  m_InternalImages.clear();
208  }
209 }
210 
211 template <class TInputImage, class TOutputImage, class TWaveletOperator>
212 void
215  (InputImageRegionType& destRegion, const OutputImageRegionType& srcRegion)
216 {
217  Superclass::CallCopyOutputRegionToInputRegion(destRegion, srcRegion);
218 
219  if (GetSubsampleImageFactor() > 1)
220  {
221  OutputIndexType srcIndex = srcRegion.GetIndex();
222  OutputSizeType srcSize = srcRegion.GetSize();
223 
224  InputIndexType destIndex;
225  InputSizeType destSize;
226 
227  for (unsigned int i = 0; i < InputImageDimension; ++i)
228  {
229  destIndex[i] = srcIndex[i] * GetSubsampleImageFactor();
230  destSize[i] = srcSize[i] * GetSubsampleImageFactor();
231  }
232 
233  destRegion.SetIndex(destIndex);
234  destRegion.SetSize(destSize);
235 
236 #if 0
237  // Contrairement a Wavelet::INVERSE, ici ca ne sera a rien apparemment...
238 
239  // Region Padding
240  LowPassOperatorType lowPassOperator;
241  lowPassOperator.SetDirection(0);
242  lowPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
243  lowPassOperator.CreateDirectional();
244 
245  unsigned long radius[InputImageDimension];
246  radius[0] = lowPassOperator.GetRadius()[0];
247 
248  HighPassOperatorType highPassOperator;
249  highPassOperator.SetDirection(0);
250  highPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
251  highPassOperator.CreateDirectional();
252 
253  if (radius[0] < highPassOperator.GetRadius()[0]) radius[0] = highPassOperator.GetRadius()[0];
254 
255  for (unsigned int i = 1; i < InputImageDimension; ++i)
256  radius[i] = 0;
257 
258  InputImageRegionType paddedRegion = destRegion;
259  paddedRegion.PadByRadius(radius);
260 
261  if (paddedRegion.Crop(this->GetInput()->GetLargestPossibleRegion()))
262  {
263  destRegion = paddedRegion;
264  }
265 #endif
266 
267  }
268 }
269 
270 template <class TInputImage, class TOutputImage, class TWaveletOperator>
271 void
274  (unsigned int direction,
275  InputImageRegionType& destRegion, const OutputImageRegionType& srcRegion)
276 {
277  Superclass::CallCopyOutputRegionToInputRegion(destRegion, srcRegion);
278 
279  if (GetSubsampleImageFactor() > 1)
280  {
281  OutputIndexType srcIndex = srcRegion.GetIndex();
282  OutputSizeType srcSize = srcRegion.GetSize();
283 
284  InputIndexType destIndex;
285  InputSizeType destSize;
286 
287  for (unsigned int i = 0; i < InputImageDimension; ++i)
288  {
289  if (i == direction)
290  {
291  destIndex[i] = srcIndex[i] * GetSubsampleImageFactor();
292  destSize[i] = srcSize[i] * GetSubsampleImageFactor();
293  }
294  else
295  {
296  destIndex[i] = srcIndex[i];
297  destSize[i] = srcSize[i];
298  }
299  }
300 
301  destRegion.SetIndex(destIndex);
302  destRegion.SetSize(destSize);
303  }
304 }
305 
306 template <class TInputImage, class TOutputImage, class TWaveletOperator>
307 void
310  (OutputImageRegionType& destRegion, const InputImageRegionType& srcRegion)
311 {
312  Superclass::CallCopyInputRegionToOutputRegion(destRegion, srcRegion);
313 
314  if (GetSubsampleImageFactor() > 1)
315  {
316  typename InputImageRegionType::IndexType srcIndex = srcRegion.GetIndex();
317  typename InputImageRegionType::SizeType srcSize = srcRegion.GetSize();
318 
319  typename OutputImageRegionType::IndexType destIndex;
320  typename OutputImageRegionType::SizeType destSize;
321 
322  for (unsigned int i = 0; i < InputImageDimension; ++i)
323  {
324  // TODO: This seems not right in odd index cases
325  destIndex[i] = srcIndex[i] / GetSubsampleImageFactor();
326  destSize[i] = srcSize[i] / GetSubsampleImageFactor();
327  }
328 
329  destRegion.SetIndex(destIndex);
330  destRegion.SetSize(destSize);
331  }
332 }
333 
334 template <class TInputImage, class TOutputImage, class TWaveletOperator>
335 void
338  (unsigned int direction,
339  OutputImageRegionType& destRegion, const InputImageRegionType& srcRegion)
340 {
341  Superclass::CallCopyInputRegionToOutputRegion(destRegion, srcRegion);
342 
343  if (GetSubsampleImageFactor() > 1)
344  {
345  typename InputImageRegionType::IndexType srcIndex = srcRegion.GetIndex();
346  typename InputImageRegionType::SizeType srcSize = srcRegion.GetSize();
347 
348  typename OutputImageRegionType::IndexType destIndex;
349  typename OutputImageRegionType::SizeType destSize;
350 
351  for (unsigned int i = 0; i < InputImageDimension; ++i)
352  {
353  if (i == direction)
354  {
355  // TODO: This seems not right in odd index cases
356  destIndex[i] = srcIndex[i] / GetSubsampleImageFactor();
357  destSize[i] = srcSize[i] / GetSubsampleImageFactor();
358  }
359  else
360  {
361  destIndex[i] = srcIndex[i];
362  destSize[i] = srcSize[i];
363  }
364  }
365 
366  destRegion.SetIndex(destIndex);
367  destRegion.SetSize(destSize);
368  }
369 }
370 
371 template <class TInputImage, class TOutputImage, class TWaveletOperator>
372 void
375  (const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
376 {
377  unsigned int dir = InputImageDimension - 1;
378 
379  if ((1 << dir) >= static_cast<int>(this->GetNumberOfOutputs()))
380  {
381  std::ostringstream msg;
382  msg << "Output number 1<<" << dir << " = " << (1 << dir) << " not allocated\n";
383  msg << "Number of expected outputs " << this->GetNumberOfOutputs() << "\n";
384  throw itk::ExceptionObject(__FILE__, __LINE__, msg.str().c_str(), ITK_LOCATION);
385  }
386 
387  itk::ProgressReporter reporter(this, threadId,
388  outputRegionForThread.GetNumberOfPixels() * this->GetNumberOfOutputs() * 2);
389 
390  const InputImageType * input = this->GetInput();
391  InputImageRegionType inputRegionForThread;
392  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
393 
394  OutputImagePointerType outputLowPass = this->GetOutput(0);
395  OutputImagePointerType outputHighPass = this->GetOutput(1 << dir);
396 
397  // On multidimensional case, if m_SubsampleImageFactor != 1, we need internal images of different size
398  if (dir != 0 && m_SubsampleImageFactor > 1)
399  {
400  outputLowPass = m_InternalImages[dir - 1][0];
401  outputHighPass = m_InternalImages[dir - 1][1];
402  }
403 
404  // typedef for the iterations over the input image
405  typedef itk::ConstNeighborhoodIterator<InputImageType> NeighborhoodIteratorType;
406  typedef itk::NeighborhoodInnerProduct<InputImageType> InnerProductType;
407  typedef itk::ImageRegionIterator<OutputImageType> IteratorType;
408 
409  // Prepare the subsampling image factor, if any.
410  typedef SubsampledImageRegionConstIterator<InputImageType> SubsampleIteratorType;
411  typename SubsampleIteratorType::IndexType subsampling;
412  subsampling.Fill(1);
413  subsampling[dir] = GetSubsampleImageFactor();
414 
415  // Inner product
416  InnerProductType innerProduct;
417 
418  // High pass part calculation
419  HighPassOperatorType highPassOperator;
420  highPassOperator.SetDirection(dir);
421  highPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
422  highPassOperator.CreateDirectional();
423 
424  SubsampleIteratorType subItHighPass(input, inputRegionForThread);
425  subItHighPass.SetSubsampleFactor(subsampling);
426  subItHighPass.GoToBegin();
427 
428  NeighborhoodIteratorType itHighPass(highPassOperator.GetRadius(), input, inputRegionForThread);
430  itHighPass.OverrideBoundaryCondition(&boundaryCondition);
431 
432  IteratorType outHighPass(outputHighPass, subItHighPass.GenerateOutputInformation());
433  outHighPass.GoToBegin();
434 
435  while (!subItHighPass.IsAtEnd() && !outHighPass.IsAtEnd())
436  {
437  itHighPass.SetLocation(subItHighPass.GetIndex());
438  outHighPass.Set(innerProduct(itHighPass, highPassOperator));
439 
440  ++subItHighPass;
441  ++outHighPass;
442 
443  reporter.CompletedPixel();
444  }
445 
446  // Low pass part calculation
447  LowPassOperatorType lowPassOperator;
448  lowPassOperator.SetDirection(dir);
449  lowPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
450  lowPassOperator.CreateDirectional();
451 
452  SubsampleIteratorType subItLowPass(input, inputRegionForThread);
453  subItLowPass.SetSubsampleFactor(subsampling);
454  subItLowPass.GoToBegin();
455 
456  NeighborhoodIteratorType itLowPass(lowPassOperator.GetRadius(), input, inputRegionForThread);
457  itLowPass.OverrideBoundaryCondition(&boundaryCondition);
458 
459  IteratorType outLowPass(outputLowPass, subItLowPass.GenerateOutputInformation());
460  outLowPass.GoToBegin();
461 
462  while (!subItLowPass.IsAtEnd() && !outLowPass.IsAtEnd())
463  {
464  itLowPass.SetLocation(subItLowPass.GetIndex());
465  outLowPass.Set(innerProduct(itLowPass, lowPassOperator));
466 
467  ++subItLowPass;
468  ++outLowPass;
469 
470  reporter.CompletedPixel();
471  }
472 
473  if (dir > 0)
474  {
475  // Note that outputImageRegion correspond to the actual region of (local) input !
476  OutputImageRegionType outputImageRegion;
477  this->CallCopyInputRegionToOutputRegion(dir, outputImageRegion, inputRegionForThread);
478 
479  ThreadedGenerateDataAtDimensionN(0, dir - 1, reporter, outputImageRegion, threadId);
480  ThreadedGenerateDataAtDimensionN(1 << dir, dir - 1, reporter, outputImageRegion, threadId);
481  }
482 }
483 
484 template <class TInputImage, class TOutputImage, class TWaveletOperator>
485 void
488  (unsigned int idx, unsigned int direction, itk::ProgressReporter& reporter,
489  const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
490 {
491  // Note that outputRegionForThread correspond to the actual region of input !
492  OutputImagePointerType input = this->GetOutput(idx);
493  OutputImagePointerType outputHighPass = this->GetOutput(idx + (1 << direction));
494  OutputImagePointerType outputLowPass = OutputImageType::New();
495 
496  OutputImageRegionType outputImageRegion;
497  this->CallCopyInputRegionToOutputRegion(direction, outputImageRegion, outputRegionForThread);
498 
499  if (m_SubsampleImageFactor > 1)
500  {
501  input = m_InternalImages[direction][idx / (1 << (direction + 1))];
502 
503  if (direction != 0)
504  {
505  outputLowPass = m_InternalImages[direction - 1][idx / (1 << direction)];
506  outputHighPass = m_InternalImages[direction - 1][idx / (1 << direction) + 1];
507  }
508  }
509 
510  if (direction == 0)
511  {
512  // The output image has to be allocated
513  // May be not valid on multithreaded process ???
514  outputLowPass->SetRegions(outputImageRegion);
515  outputLowPass->Allocate(); // FIXME Check this line...
516  outputLowPass->FillBuffer(0);
517  }
518 
520  typedef itk::ConstNeighborhoodIterator<OutputImageType> NeighborhoodIteratorType;
521  typedef itk::NeighborhoodInnerProduct<OutputImageType> InnerProductType;
522  typedef itk::ImageRegionIterator<OutputImageType> IteratorType;
523 
524  // Prepare the subsampling image factor, if any.
525  typedef SubsampledImageRegionConstIterator<InputImageType> SubsampleIteratorType;
526  typename SubsampleIteratorType::IndexType subsampling;
527  subsampling.Fill(1);
528  subsampling[direction] = GetSubsampleImageFactor();
529 
530  // Inner products
531  InnerProductType innerProduct;
532 
533  // High pass part calculation
534  HighPassOperatorType highPassOperator;
535  highPassOperator.SetDirection(direction);
536  highPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
537  highPassOperator.CreateDirectional();
538 
539  SubsampleIteratorType subItHighPass(input, outputRegionForThread);
540  subItHighPass.SetSubsampleFactor(subsampling);
541  subItHighPass.GoToBegin();
542 
543  NeighborhoodIteratorType itHighPass(highPassOperator.GetRadius(), input, outputRegionForThread);
545  itHighPass.OverrideBoundaryCondition(&boundaryCondition);
546 
547  IteratorType outHighPass(outputHighPass, subItHighPass.GenerateOutputInformation());
548  outHighPass.GoToBegin();
549 
550  while (!subItHighPass.IsAtEnd() && !outHighPass.IsAtEnd())
551  {
552  itHighPass.SetLocation(subItHighPass.GetIndex());
553  outHighPass.Set(innerProduct(itHighPass, highPassOperator));
554 
555  ++subItHighPass;
556  ++outHighPass;
557 
558  reporter.CompletedPixel();
559  }
560 
561  // Low pass part calculation
562  LowPassOperatorType lowPassOperator;
563  lowPassOperator.SetDirection(direction);
564  lowPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
565  lowPassOperator.CreateDirectional();
566 
567  SubsampleIteratorType subItLowPass(input, outputRegionForThread);
568  subItLowPass.SetSubsampleFactor(subsampling);
569  subItLowPass.GoToBegin();
570 
571  NeighborhoodIteratorType itLowPass(lowPassOperator.GetRadius(), input, outputRegionForThread);
572  itLowPass.OverrideBoundaryCondition(&boundaryCondition);
573 
574  IteratorType outLowPass(outputLowPass, subItLowPass.GenerateOutputInformation());
575  outLowPass.GoToBegin();
576 
577  while (!subItLowPass.IsAtEnd() && !outLowPass.IsAtEnd())
578  {
579  itLowPass.SetLocation(subItLowPass.GetIndex());
580  outLowPass.Set(innerProduct(itLowPass, lowPassOperator));
581 
582  ++subItLowPass;
583  ++outLowPass;
584 
585  reporter.CompletedPixel();
586  }
587 
588  // Swap input and lowPassOutput
589  itk::ImageRegionConstIterator<OutputImageType> inIt(outputLowPass, outputImageRegion);
590  IteratorType outIt((direction != 0 && m_SubsampleImageFactor > 1) ?
591  static_cast<OutputImageType*>(m_InternalImages[direction - 2][idx / (1 << (direction - 1))])
592  : this->GetOutput(idx),
593  outputImageRegion);
594 
595  for (inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd(); ++inIt, ++outIt)
596  {
597  outIt.Set(inIt.Get());
598  }
599 
600  if (direction != 0)
601  {
602  ThreadedGenerateDataAtDimensionN(idx, direction - 1, reporter, outputImageRegion, threadId);
603  ThreadedGenerateDataAtDimensionN(idx + (1 << direction), direction - 1, reporter, outputImageRegion, threadId);
604  }
605 }
606 
611 template <class TInputImage, class TOutputImage, class TWaveletOperator>
614 {
615  this->SetNumberOfRequiredInputs(1 << InputImageDimension);
616 
617  m_UpSampleFilterFactor = 0;
618  m_SubsampleImageFactor = 1;
619 
620  // TODO: For now, we force the number threads to 1 because there is a bug with multithreading in INVERSE transform
621  // Resulting in discontinuities in the reconstructed images
622  this->SetNumberOfThreads(1);
623 }
624 
625 template <class TInputImage, class TOutputImage, class TWaveletOperator>
626 void
629 {
630  Superclass::GenerateOutputInformation();
631 
632  for (unsigned int i = 1; i < this->GetNumberOfInputs(); ++i)
633  {
634  for (unsigned int dim = 0; dim < InputImageDimension; dim++)
635  {
636  if (this->GetInput(0)->GetLargestPossibleRegion().GetSize()[dim]
637  != this->GetInput(i)->GetLargestPossibleRegion().GetSize()[dim])
638  {
639  throw itk::ExceptionObject(__FILE__, __LINE__,
640  "Input images are not of the same dimension", ITK_LOCATION);
641  }
642  }
643  }
644 
645 #if __myDebug__
646  otbGenericMsgDebugMacro(<< " up sampling output regions by a factor of " << GetSubsampleImageFactor());
647 
648  otbGenericMsgDebugMacro(<< "initial region "
649  << this->GetInput(0)->GetLargestPossibleRegion().GetSize()[0]
650  << "," << this->GetInput(0)->GetLargestPossibleRegion().GetSize()[1]);
651 #endif
652 
653  OutputImageRegionType newRegion;
654  this->CallCopyInputRegionToOutputRegion(newRegion, this->GetInput(0)->GetLargestPossibleRegion());
655  this->GetOutput()->SetRegions(newRegion);
656 
657 #if __myDebug__
658  otbGenericMsgDebugMacro(<< "new region output " << newRegion.GetSize()[0] << "," << newRegion.GetSize()[1]);
659 #endif
660 }
661 
662 template <class TInputImage, class TOutputImage, class TWaveletOperator>
663 void
666 throw (itk::InvalidRequestedRegionError)
667  {
668  Superclass::GenerateInputRequestedRegion();
669 
670  // Filter length calculation
671  LowPassOperatorType lowPassOperator;
672  lowPassOperator.SetDirection(0);
673  lowPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
674  lowPassOperator.CreateDirectional();
675 
676  unsigned int radius = lowPassOperator.GetRadius()[0];
677 
678  HighPassOperatorType highPassOperator;
679  highPassOperator.SetDirection(0);
680  highPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
681  highPassOperator.CreateDirectional();
682 
683  if (radius < highPassOperator.GetRadius()[0]) radius = highPassOperator.GetRadius()[0];
684 
685  // Get the requested regionand pad it
686  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
687  {
688  InputImagePointerType input = const_cast<InputImageType*>(this->GetInput(idx));
689  InputImageRegionType inputRegion = input->GetRequestedRegion();
690  inputRegion.PadByRadius(radius);
691 
692  if (inputRegion.Crop(input->GetLargestPossibleRegion()))
693  {
694  input->SetRequestedRegion(inputRegion);
695  }
696  else
697  {
698  input->SetRequestedRegion(inputRegion);
699  itk::InvalidRequestedRegionError err(__FILE__, __LINE__);
700  err.SetLocation(ITK_LOCATION);
701  err.SetDescription("Requested region is (at least partially) outside the largest possible region.");
702  err.SetDataObject(input);
703  throw err;
704  }
705  }
706  }
707 
708 template <class TInputImage, class TOutputImage, class TWaveletOperator>
709 void
712 {
713  unsigned int one = 1;
714  if (InputImageDimension > 1)
715  {
716  // Internal images will be used only if m_SubsampleImageFactor != 1
717  m_InternalImages.resize(InputImageDimension - 1);
718  for (unsigned int i = 0; i < m_InternalImages.size(); ++i)
719  {
720  // the size is linked to the SubsampleImageFactor that is assume to be 2!!!
721  m_InternalImages[i].resize( one << (i + 1));
722  }
723 
724  OutputImageRegionType intermediateRegion;
725  Superclass::CallCopyInputRegionToOutputRegion(intermediateRegion,
726  this->GetInput(0)->GetLargestPossibleRegion());
727 
728  AllocateInternalData(intermediateRegion);
729  }
730 }
731 
732 template <class TInputImage, class TOutputImage, class TWaveletOperator>
733 void
736  (const OutputImageRegionType& outputRegion)
737 {
738  OutputImageRegionType largerRegion;
739  OutputImageRegionType smallerRegion = outputRegion;
740 
741  for (unsigned int direction = 0; direction < InputImageDimension - 1; direction++)
742  {
743  this->CallCopyInputRegionToOutputRegion(direction,
744  largerRegion, smallerRegion);
745 
746  for (unsigned int i = 0; i < m_InternalImages[direction].size(); ++i)
747  {
748  m_InternalImages[direction][i] = OutputImageType::New();
749  m_InternalImages[direction][i]->SetRegions(largerRegion);
750  m_InternalImages[direction][i]->Allocate();
751  m_InternalImages[direction][i]->FillBuffer(0);
752  }
753 
754  smallerRegion = largerRegion;
755  }
756 }
757 
758 template <class TInputImage, class TOutputImage, class TWaveletOperator>
759 void
762 {
763  if (m_SubsampleImageFactor > 1 && InputImageDimension > 1)
764  {
765  m_InternalImages.clear();
766  }
767 }
768 
769 template <class TInputImage, class TOutputImage, class TWaveletOperator>
770 void
773  (InputImageRegionType& destRegion, const OutputImageRegionType& srcRegion)
774 {
775  Superclass::CallCopyOutputRegionToInputRegion(destRegion, srcRegion);
776 
777  if (GetSubsampleImageFactor() > 1)
778  {
779  OutputIndexType srcIndex = srcRegion.GetIndex();
780  OutputSizeType srcSize = srcRegion.GetSize();
781 
782  InputIndexType destIndex;
783  InputSizeType destSize;
784 
785  for (unsigned int i = 0; i < InputImageDimension; ++i)
786  {
787  // TODO: This seems not right in odd index cases
788  destIndex[i] = srcIndex[i] / GetSubsampleImageFactor();
789  destSize[i] = srcSize[i] / GetSubsampleImageFactor();
790  }
791 
792  destRegion.SetIndex(destIndex);
793  destRegion.SetSize(destSize);
794 
795 #if 1
796  // Region Padding
797  LowPassOperatorType lowPassOperator;
798  lowPassOperator.SetDirection(0);
799  lowPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
800  lowPassOperator.CreateDirectional();
801 
802  typename InputImageRegionType::SizeType radius;
803  radius[0] = lowPassOperator.GetRadius()[0];
804 
805  HighPassOperatorType highPassOperator;
806  highPassOperator.SetDirection(0);
807  highPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
808  highPassOperator.CreateDirectional();
809 
810  if (radius[0] < highPassOperator.GetRadius()[0]) radius[0] = highPassOperator.GetRadius()[0];
811 
812  for (unsigned int i = 1; i < InputImageDimension; ++i)
813  radius[i] = 0;
814 
815 // for ( unsigned int i = 0; i < InputImageDimension; ++i )
816 // {
817 // radius[i] = lowPassOperator.GetRadius()[i];
818 // if ( radius[i] < highPassOperator.GetRadius()[i] )
819 // radius[i] = highPassOperator.GetRadius()[i];
820 // }
821 
822  InputImageRegionType paddedRegion = destRegion;
823  paddedRegion.PadByRadius(radius);
824 
825  if (paddedRegion.Crop(this->GetInput(0)->GetLargestPossibleRegion()))
826  {
827  destRegion = paddedRegion;
828  }
829 #endif
830  }
831 }
832 
833 template <class TInputImage, class TOutputImage, class TWaveletOperator>
834 void
837  (OutputImageRegionType& destRegion, const InputImageRegionType& srcRegion)
838 {
839  Superclass::CallCopyInputRegionToOutputRegion(destRegion, srcRegion);
840 
841  if (GetSubsampleImageFactor() > 1)
842  {
843  OutputIndexType srcIndex = srcRegion.GetIndex();
844  OutputSizeType srcSize = srcRegion.GetSize();
845 
846  InputIndexType destIndex;
847  InputSizeType destSize;
848 
849  for (unsigned int i = 0; i < InputImageDimension; ++i)
850  {
851  destIndex[i] = srcIndex[i] * GetSubsampleImageFactor();
852  destSize[i] = srcSize[i] * GetSubsampleImageFactor();
853  }
854 
855  destRegion.SetIndex(destIndex);
856  destRegion.SetSize(destSize);
857  }
858 }
859 
860 template <class TInputImage, class TOutputImage, class TWaveletOperator>
861 void
864  (unsigned int direction,
865  InputImageRegionType& destRegion, const OutputImageRegionType& srcRegion)
866 {
867  Superclass::CallCopyOutputRegionToInputRegion(destRegion, srcRegion);
868 
869  if (GetSubsampleImageFactor() > 1)
870  {
871  OutputIndexType srcIndex = srcRegion.GetIndex();
872  OutputSizeType srcSize = srcRegion.GetSize();
873 
874  InputIndexType destIndex;
875  InputSizeType destSize;
876 
877  for (unsigned int i = 0; i < InputImageDimension; ++i)
878  {
879  if (i == direction)
880  {
881  // TODO: This seems not right in odd index cases
882  destIndex[i] = srcIndex[i] / GetSubsampleImageFactor();
883  destSize[i] = srcSize[i] / GetSubsampleImageFactor();
884  }
885  else
886  {
887  destIndex[i] = srcIndex[i];
888  destSize[i] = srcSize[i];
889  }
890  }
891 
892  destRegion.SetIndex(destIndex);
893  destRegion.SetSize(destSize);
894  }
895 }
896 
897 template <class TInputImage, class TOutputImage, class TWaveletOperator>
898 void
901  (unsigned int direction,
902  OutputImageRegionType& destRegion, const InputImageRegionType& srcRegion)
903 {
904  Superclass::CallCopyInputRegionToOutputRegion(destRegion, srcRegion);
905 
906  if (GetSubsampleImageFactor() > 1)
907  {
908  typename InputImageRegionType::IndexType srcIndex = srcRegion.GetIndex();
909  typename InputImageRegionType::SizeType srcSize = srcRegion.GetSize();
910 
911  typename OutputImageRegionType::IndexType destIndex;
912  typename OutputImageRegionType::SizeType destSize;
913 
914  for (unsigned int i = 0; i < InputImageDimension; ++i)
915  {
916  if (i == direction)
917  {
918  destIndex[i] = srcIndex[i] * GetSubsampleImageFactor();
919  destSize[i] = srcSize[i] * GetSubsampleImageFactor();
920  }
921  else
922  {
923  destIndex[i] = srcIndex[i];
924  destSize[i] = srcSize[i];
925  }
926  }
927 
928  destRegion.SetIndex(destIndex);
929  destRegion.SetSize(destSize);
930  }
931 }
932 
933 template <class TInputImage, class TOutputImage, class TWaveletOperator>
934 void
937  (const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
938 {
939  itk::ProgressReporter reporter(this, threadId,
940  outputRegionForThread.GetNumberOfPixels() * this->GetNumberOfInputs());
941 
942  InputImageRegionType inputRegionForThread;
943  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
944 
945  unsigned int dir = 0;
946 
947  // Low pass part calculation
948  LowPassOperatorType lowPassOperator;
949  lowPassOperator.SetDirection(dir);
950  lowPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
951  lowPassOperator.CreateDirectional();
952 
953  // High pass part calculation
954  HighPassOperatorType highPassOperator;
955  highPassOperator.SetDirection(dir);
956  highPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
957  highPassOperator.CreateDirectional();
958 
959  // typedef for the iterations over the input image
960  typedef itk::ConstNeighborhoodIterator<OutputImageType> NeighborhoodIteratorType;
961  typedef itk::NeighborhoodInnerProduct<OutputImageType> InnerProductType;
962 
963  // Faces iterations
964  typename NeighborhoodIteratorType::RadiusType radiusMax;
965  for (unsigned int idx = 0; idx < OutputImageDimension; ++idx)
966  {
967  radiusMax[idx] = lowPassOperator.GetRadius(idx);
968  if (radiusMax[idx] < highPassOperator.GetRadius(idx)) radiusMax[idx] = highPassOperator.GetRadius(idx);
969  }
970 
971  // The multiresolution case requires a SubsampleImageFilter step
972  if (m_SubsampleImageFactor > 1)
973  {
974  for (unsigned int i = 0; i < this->GetNumberOfInputs(); i += 2)
975  {
976  InputImagePointerType imgLowPass = const_cast<InputImageType*>(this->GetInput(i));
977  InputImagePointerType imgHighPass = const_cast<InputImageType*>(this->GetInput(i + 1));
978 
979  OutputImagePointerType outputImage = this->GetOutput();
980  if (dir != InputImageDimension - 1)
981  {
982  outputImage = m_InternalImages[0][i / 2];
983  }
984 
986  typename FilterType::InputImageIndexType delta;
987  delta.Fill(1);
988  delta[dir] = this->GetSubsampleImageFactor();
989 
990  InputImagePointerType cropedLowPass = InputImageType::New();
991  cropedLowPass->SetRegions(inputRegionForThread);
992  cropedLowPass->Allocate();
993  cropedLowPass->FillBuffer(0.);
994  itk::ImageRegionIterator<InputImageType> cropedLowPassIt(cropedLowPass, inputRegionForThread);
995  itk::ImageRegionIterator<InputImageType> imgLowPassIt(imgLowPass, inputRegionForThread);
996  for (cropedLowPassIt.GoToBegin(), imgLowPassIt.GoToBegin();
997  !cropedLowPassIt.IsAtEnd() && !imgLowPassIt.IsAtEnd();
998  ++cropedLowPassIt, ++imgLowPassIt)
999  {
1000  cropedLowPassIt.Set(imgLowPassIt.Get());
1001  }
1002 
1003  typename FilterType::Pointer overSampledLowPass = FilterType::New();
1004  overSampledLowPass->SetInput(cropedLowPass);
1005  overSampledLowPass->SetSubsampleFactor(delta);
1006  overSampledLowPass->Update();
1007 
1008  InputImagePointerType cropedHighPass = InputImageType::New();
1009  cropedHighPass->SetRegions(inputRegionForThread);
1010  cropedHighPass->Allocate();
1011  cropedHighPass->FillBuffer(0.);
1012  itk::ImageRegionIterator<InputImageType> cropedHighPassIt(cropedHighPass, inputRegionForThread);
1013  itk::ImageRegionIterator<InputImageType> imgHighPassIt(imgHighPass, inputRegionForThread);
1014  for (cropedHighPassIt.GoToBegin(), imgHighPassIt.GoToBegin();
1015  !cropedHighPassIt.IsAtEnd() && !imgHighPassIt.IsAtEnd();
1016  ++cropedHighPassIt, ++imgHighPassIt)
1017  {
1018  cropedHighPassIt.Set(imgHighPassIt.Get());
1019  }
1020 
1021  typename FilterType::Pointer overSampledHighPass = FilterType::New();
1022  overSampledHighPass->SetInput(cropedHighPass);
1023  overSampledHighPass->SetSubsampleFactor(delta);
1024  overSampledHighPass->Update();
1025 
1026  InnerProductType innerProduct;
1027 
1029  (outputImage, overSampledLowPass->GetOutput()->GetRequestedRegion());
1030 
1031  NeighborhoodIteratorType lowIter(lowPassOperator.GetRadius(),
1032  overSampledLowPass->GetOutput(),
1033  overSampledLowPass->GetOutput()->GetRequestedRegion());
1035  lowIter.OverrideBoundaryCondition(&boundaryCondition);
1036 
1037  NeighborhoodIteratorType highIter(highPassOperator.GetRadius(),
1038  overSampledHighPass->GetOutput(),
1039  overSampledHighPass->GetOutput()->GetRequestedRegion());
1040  highIter.OverrideBoundaryCondition(&boundaryCondition);
1041 
1042  lowIter.GoToBegin();
1043  highIter.GoToBegin();
1044  out.GoToBegin();
1045 
1046  while (!out.IsAtEnd())
1047  {
1048  out.Set(innerProduct(lowIter, lowPassOperator)
1049  + innerProduct(highIter, highPassOperator));
1050 
1051  ++lowIter;
1052  ++highIter;
1053  ++out;
1054 
1055  reporter.CompletedPixel();
1056  }
1057  } // end for each overSampledLowPass/overSampledhighPass pair of entry
1058  }
1059  else // multiscale case
1060  {
1061  for (unsigned int i = 0; i < this->GetNumberOfInputs(); i += 2)
1062  {
1063  InputImagePointerType imgLowPass = const_cast<InputImageType*>(this->GetInput(i));
1064  InputImagePointerType imgHighPass = const_cast<InputImageType*>(this->GetInput(i + 1));
1065 
1066  OutputImagePointerType outputImage = this->GetOutput();
1067  if (dir != InputImageDimension - 1)
1068  {
1069  outputImage = m_InternalImages[0][i / 2];
1070  }
1071 
1072  InnerProductType innerProduct;
1073 
1074  itk::ImageRegionIterator<OutputImageType> out(outputImage, imgLowPass->GetRequestedRegion());
1075 
1076  NeighborhoodIteratorType lowIter(lowPassOperator.GetRadius(), imgLowPass, imgLowPass->GetRequestedRegion());
1078  lowIter.OverrideBoundaryCondition(&boundaryCondition);
1079 
1080  NeighborhoodIteratorType highIter(highPassOperator.GetRadius(), imgHighPass, imgLowPass->GetRequestedRegion());
1081  highIter.OverrideBoundaryCondition(&boundaryCondition);
1082 
1083  lowIter.GoToBegin();
1084  highIter.GoToBegin();
1085  out.GoToBegin();
1086 
1087  while (!out.IsAtEnd())
1088  {
1089  out.Set((innerProduct(lowIter, lowPassOperator)
1090  + innerProduct(highIter, highPassOperator)) / 2.);
1091 
1092  ++lowIter;
1093  ++highIter;
1094  ++out;
1095 
1096  reporter.CompletedPixel();
1097  }
1098  } // end for each imgLowPass/imghighPass pair of entry
1099  } // end multiscale case
1100 
1101  if (dir != InputImageDimension - 1)
1102  {
1103  // Note that outputImageRegion correspond to the actual region of (local) input !
1104  OutputImageRegionType outputImageRegion;
1105  this->CallCopyInputRegionToOutputRegion(dir, outputImageRegion, inputRegionForThread);
1106 
1107  ThreadedGenerateDataAtDimensionN(dir + 1, reporter, outputImageRegion, threadId);
1108  }
1109 
1110 }
1111 
1112 template <class TInputImage, class TOutputImage, class TWaveletOperator>
1113 void
1116  (unsigned int direction,
1117  itk::ProgressReporter& reporter,
1118  const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
1119 {
1120  OutputImageRegionType outputImageRegion;
1121  this->CallCopyInputRegionToOutputRegion(direction, outputImageRegion, outputRegionForThread);
1122 
1123  // Low pass part calculation
1124  LowPassOperatorType lowPassOperator;
1125  lowPassOperator.SetDirection(direction);
1126  lowPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
1127  lowPassOperator.CreateDirectional();
1128 
1129  // High pass part calculation
1130  HighPassOperatorType highPassOperator;
1131  highPassOperator.SetDirection(direction);
1132  highPassOperator.SetUpSampleFactor(this->GetUpSampleFilterFactor());
1133  highPassOperator.CreateDirectional();
1134 
1135  // typedef for the iterations over the input image
1136  typedef itk::ConstNeighborhoodIterator<OutputImageType> NeighborhoodIteratorType;
1137  typedef itk::NeighborhoodInnerProduct<OutputImageType> InnerProductType;
1138  // Faces iterations
1139  typename NeighborhoodIteratorType::RadiusType radiusMax;
1140  for (unsigned int i = 0; i < InputImageDimension; ++i)
1141  {
1142  radiusMax[i] = lowPassOperator.GetRadius(i);
1143  if (radiusMax[i] < highPassOperator.GetRadius(i)) radiusMax[i] = highPassOperator.GetRadius(i);
1144  }
1145 
1146  // The multiresolution case requires a SubsampleImageFilter step
1147  if (m_SubsampleImageFactor > 1)
1148  {
1149  for (unsigned int i = 0; i < m_InternalImages[direction - 1].size(); i += 2)
1150  {
1151  InputImagePointerType imgLowPass = m_InternalImages[direction - 1][i];
1152  InputImagePointerType imgHighPass = m_InternalImages[direction - 1][i + 1];
1153 
1154  OutputImagePointerType outputImage = this->GetOutput();
1155  if (direction < InputImageDimension - 1)
1156  {
1157  outputImage = m_InternalImages[direction][i / 2];
1158  }
1159 
1161  typename FilterType::InputImageIndexType delta;
1162  delta.Fill(1);
1163  delta[direction] = this->GetSubsampleImageFactor();
1164 
1165  InputImagePointerType cropedLowPass = InputImageType::New();
1166  cropedLowPass->SetRegions(outputRegionForThread);
1167  cropedLowPass->Allocate();
1168  cropedLowPass->FillBuffer(0.);
1169  itk::ImageRegionIterator<InputImageType> cropedLowPassIt(cropedLowPass, outputRegionForThread);
1170  itk::ImageRegionIterator<InputImageType> imgLowPassIt(imgLowPass, outputRegionForThread);
1171  for (cropedLowPassIt.GoToBegin(), imgLowPassIt.GoToBegin();
1172  !cropedLowPassIt.IsAtEnd() && !imgLowPassIt.IsAtEnd();
1173  ++cropedLowPassIt, ++imgLowPassIt)
1174  {
1175  cropedLowPassIt.Set(imgLowPassIt.Get());
1176  }
1177 
1178  typename FilterType::Pointer overSampledLowPass = FilterType::New();
1179  overSampledLowPass->SetInput(cropedLowPass);
1180  overSampledLowPass->SetSubsampleFactor(delta);
1181  overSampledLowPass->Update();
1182 
1183  InputImagePointerType cropedHighPass = InputImageType::New();
1184  cropedHighPass->SetRegions(outputRegionForThread);
1185  cropedHighPass->Allocate();
1186  cropedHighPass->FillBuffer(0.);
1187  itk::ImageRegionIterator<InputImageType> cropedHighPassIt(cropedHighPass, outputRegionForThread);
1188  itk::ImageRegionIterator<InputImageType> imgHighPassIt(imgHighPass, outputRegionForThread);
1189  for (cropedHighPassIt.GoToBegin(), imgHighPassIt.GoToBegin();
1190  !cropedHighPassIt.IsAtEnd() && !imgHighPassIt.IsAtEnd();
1191  ++cropedHighPassIt, ++imgHighPassIt)
1192  {
1193  cropedHighPassIt.Set(imgHighPassIt.Get());
1194  }
1195 
1196  typename FilterType::Pointer overSampledHighPass = FilterType::New();
1197  overSampledHighPass->SetInput(cropedHighPass);
1198  overSampledHighPass->SetSubsampleFactor(delta);
1199  overSampledHighPass->Update();
1200 
1201  InnerProductType innerProduct;
1202 
1204  overSampledLowPass->GetOutput()->GetRequestedRegion());
1205 
1206  // TODO: This might be the cause of the multithreading bug : we use a neighborhood iterator on cropped data
1207  // Are we sure that we have cropped enough data to access the neighborhood ?
1208  NeighborhoodIteratorType lowIter(lowPassOperator.GetRadius(),
1209  overSampledLowPass->GetOutput(),
1210  overSampledLowPass->GetOutput()->GetRequestedRegion());
1212  lowIter.OverrideBoundaryCondition(&boundaryCondition);
1213 
1214  NeighborhoodIteratorType highIter(highPassOperator.GetRadius(),
1215  overSampledHighPass->GetOutput(),
1216  overSampledHighPass->GetOutput()->GetRequestedRegion());
1217  highIter.OverrideBoundaryCondition(&boundaryCondition);
1218 
1219  lowIter.GoToBegin();
1220  highIter.GoToBegin();
1221  out.GoToBegin();
1222 
1223  while (!out.IsAtEnd())
1224  {
1225  out.Set(innerProduct(lowIter, lowPassOperator)
1226  + innerProduct(highIter, highPassOperator));
1227 
1228  ++lowIter;
1229  ++highIter;
1230  ++out;
1231 
1232  reporter.CompletedPixel();
1233  }
1234  } // end for each overSampledLowPass/overSampledhighPass pair of entry
1235  }
1236  else // multiscale case
1237  {
1238  for (unsigned int i = 0; i < m_InternalImages[direction - 1].size(); i += 2)
1239  {
1240  InputImagePointerType imgLowPass = m_InternalImages[direction - 1][i];
1241  InputImagePointerType imgHighPass = m_InternalImages[direction - 1][i + 1];
1242 
1243  OutputImagePointerType outputImage = this->GetOutput();
1244  if (direction < InputImageDimension - 1)
1245  {
1246  outputImage = m_InternalImages[direction][i / 2];
1247  }
1248 
1249  InnerProductType innerProduct;
1250 
1251  itk::ImageRegionIterator<OutputImageType> out(outputImage, imgLowPass->GetRequestedRegion());
1252 
1253  NeighborhoodIteratorType lowIter(lowPassOperator.GetRadius(), imgLowPass, imgLowPass->GetRequestedRegion());
1255  lowIter.OverrideBoundaryCondition(&boundaryCondition);
1256 
1257  NeighborhoodIteratorType highIter(highPassOperator.GetRadius(), imgHighPass, imgLowPass->GetRequestedRegion());
1258  highIter.OverrideBoundaryCondition(&boundaryCondition);
1259 
1260  lowIter.GoToBegin();
1261  highIter.GoToBegin();
1262  out.GoToBegin();
1263 
1264  while (!out.IsAtEnd())
1265  {
1266  out.Set((innerProduct(lowIter, lowPassOperator)
1267  + innerProduct(highIter, highPassOperator)) / 2.);
1268 
1269  ++lowIter;
1270  ++highIter;
1271  ++out;
1272 
1273  reporter.CompletedPixel();
1274  }
1275  } // end for each imgLowPass/imghighPass pair of entry
1276  }
1277 
1278  if (direction < InputImageDimension - 1)
1279  {
1280  ThreadedGenerateDataAtDimensionN(direction + 1, reporter, outputImageRegion, threadId);
1281  }
1282 }
1283 
1284 } // end of namespace
1285 
1286 #endif
itk::Size< Monteverdi_DIMENSION > SizeType
Definition: mvdTypes.h:144
void SetDataObject(DataObject *dobj)
virtual void SetDescription(const std::string &s)
virtual void SetLocation(const std::string &s)
void Set(const PixelType &value) const
virtual void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId)
Performs a down sampling of an image.
virtual void CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion, const OutputImageRegionType &srcRegion)
virtual void BeforeThreadedGenerateData()
#define otbGenericMsgDebugMacro(x)
Definition: otbMacro.h:67
Regular subsample iterator over an image.
itk::Index< Monteverdi_DIMENSION > IndexType
Definition: mvdTypes.h:140
InputImageType::RegionType InputImageRegionType
TInputImage InputImageType
virtual void GenerateInputRequestedRegion() override
unsigned int ThreadIdType
virtual void GenerateOutputInformation()
virtual void AfterThreadedGenerateData()
OutputImageType::RegionType OutputImageRegionType
virtual void CallCopyInputRegionToOutputRegion(OutputImageRegionType &destRegion, const InputImageRegionType &srcRegion)
bool IsAtEnd(void) const
PixelType Get(void) const
const SizeValueType * GetSize() const
One level stationary wavelet transform.