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

Generated at Sun Feb 3 2013 00:55:35 for Orfeo Toolbox with doxygen 1.8.1.1