Orfeo Toolbox  3.16
itkBSplineResampleImageFilterBase.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkBSplineResampleImageFilterBase.txx,v $
5  Language: C++
6  Date: $Date: 2009-05-11 21:42:52 $
7  Version: $Revision: 1.12 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  Portions of this code are covered under the VTK copyright.
13  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm 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 __itkBSplineResampleImageFilterBase_txx
22 #define __itkBSplineResampleImageFilterBase_txx
23 
25 #include "itkProgressReporter.h"
26 
27 namespace itk
28 {
29 
33 template <class TInputImage, class TOutputImage>
36 {
37  m_SplineOrder = -1;
38  int SplineOrder = 0;
39  // Because of inheritance the user must explicitly set this for m_SplineOrder != 0.
40  this->SetSplineOrder(SplineOrder);
41 }
42 
46 template <class TInputImage, class TOutputImage>
47 void
50  std::ostream& os,
51  Indent indent) const
52 {
53  Superclass::PrintSelf( os, indent );
54  os << indent << "Spline Order: " << m_SplineOrder << std::endl;
55 }
56 
60 template <class TInputImage, class TOutputImage>
63 {
64  switch (SplineOrder)
65  {
66 
67  case 0 :
68  m_GSize = 1;
69  m_HSize = 1;
70  break;
71 
72  case 1 :
73  m_GSize = 9;
74  m_HSize = 2;
75  m_G.resize(m_GSize);
76  m_H.resize(m_HSize);
77  m_G[0] = 0.707107;
78  m_G[1] = 0.292893;
79  m_G[2] = -0.12132;
80  m_G[3] = -0.0502525;
81  m_G[4] = 0.0208153;
82  m_G[5] = 0.00862197;
83  m_G[6] = -0.00357134;
84  m_G[7] = -0.0014793;
85  m_G[8] = 0.000612745;
86  m_H[0] = 1.;
87  m_H[1] = 0.5;
88  break;
89  case 2 :
90  m_GSize = 16;
91  m_HSize = 10;
92  m_G.resize(m_GSize);
93  m_H.resize(m_HSize);
94  m_G[0] = 0.617317;
95  m_G[1] = 0.310754;
96  m_G[2] = -0.0949641;
97  m_G[3] = -0.0858654;
98  m_G[4] = 0.0529153;
99  m_G[5] = 0.0362437;
100  m_G[6] = -0.0240408;
101  m_G[7] = -0.0160987;
102  m_G[8] = 0.0107498;
103  m_G[9] = 0.00718418;
104  m_G[10] = -0.00480004;
105  m_G[11] = -0.00320734;
106  m_G[12] = 0.00214306;
107  m_G[13] = 0.00143195;
108  m_G[14] = -0.0009568;
109  m_G[15] = -0.000639312;
110  m_H[0] = 1.;
111  m_H[1] = 0.585786;
112  m_H[2] = 0;
113  m_H[3] = -0.100505;
114  m_H[4] = 0;
115  m_H[5] = 0.0172439;
116  m_H[6] = 0;
117  m_H[7] = -0.00295859;
118  m_H[8] = 0;
119  m_H[9] = 0.000507614;
120  break;
121  case 3 :
122  m_GSize = 20;
123  m_HSize = 12;
124  m_G.resize(m_GSize);
125  m_H.resize(m_HSize);
126  m_G[0] = 0.596797;
127  m_G[1] = 0.313287;
128  m_G[2] = -0.0827691;
129  m_G[3] = -0.0921993;
130  m_G[4] = 0.0540288;
131  m_G[5] = 0.0436996;
132  m_G[6] = -0.0302508;
133  m_G[7] = -0.0225552;
134  m_G[8] = 0.0162251;
135  m_G[9] = 0.0118738;
136  m_G[10] = -0.00861788;
137  m_G[11] = -0.00627964;
138  m_G[12] = 0.00456713;
139  m_G[13] = 0.00332464;
140  m_G[14] = -0.00241916;
141  m_G[15] = -0.00176059;
142  m_G[16] = 0.00128128;
143  m_G[17] = 0.000932349;
144  m_G[18] = -0.000678643;
145  m_G[19] = -0.000493682;
146  m_H[0] = 1.;
147  m_H[1] = 0.600481;
148  m_H[2] = 0;
149  m_H[3] = -0.127405;
150  m_H[4] = 0;
151  m_H[5] = 0.034138;
152  m_H[6] = 0;
153  m_H[7] = -0.00914725;
154  m_H[8] = 0;
155  m_H[9] = 0.002451;
156  m_H[10] = 0;
157  m_H[11] = -0.000656743;
158  break;
159  default :
160  // Throw an exception
161  ExceptionObject err(__FILE__, __LINE__);
162  err.SetLocation( ITK_LOCATION );
163  err.SetDescription( "SplineOrder for l2 pyramid filter must be between 1 and 3. Requested spline order has not been implemented." );
164  throw err;
165  break;
166  }
167 }
168 
169 
170 template < class TInputImage, class TOutputImage>
172 ::SetSplineOrder(int splineOrder)
173 {
174  if (splineOrder == m_SplineOrder)
175  {
176  return;
177  }
178  m_SplineOrder = splineOrder;
179 
180  this->InitializePyramidSplineFilter(m_SplineOrder);
181  this->Modified();
182 
183 }
184 
189 template <class TInputImage, class TOutputImage>
191 ::Reduce1DImage( const std::vector<double> & in, OutputImageIterator & out,
192  unsigned int inTraverseSize, ProgressReporter &progress )
193 {
194 
195  int i1, i2;
196 
197  unsigned int outK, inK;
198  unsigned int outTraverseSize = inTraverseSize/2;
199  inTraverseSize = outTraverseSize*2; // ensures that an even number is used.
200  unsigned int inModK; // number for modulus math of in
201  inModK = inTraverseSize - 1;
202 
203 
204  double outVal;
205 
206 
207  //TODO: m_GSize < 2 has not been tested.
208  if (m_GSize < 2)
209  {
210  for (outK = 0; outK < outTraverseSize; outK++)
211  {
212  inK = 2 * outK;
213  i2 = inK + 1;
214  if (i2 > (int) inModK )
215  {
216  //Original was
217  //i2=inModK-i2;
218  //I don't think this is correct since this would be negative
219  i2 = inModK - (i2 % inModK); // Should I use this always instead of the if statement?
220  }
221  out.Set( static_cast<OutputImagePixelType> ( ( in[inK] + in[i2] ) / 2.0 ) );
222  ++out;
223  progress.CompletedPixel();
224  }
225  }
226 
227  else
228  {
229  for (outK = 0; outK < outTraverseSize; outK++)
230  {
231  inK = 2L * outK;
232 
233  outVal = in[inK] * m_G[0];
234 
235  for (int i = 1; i < m_GSize; i++)
236  {
237  // Calculate indicies for left and right of symmetrical filter.
238  i1 = inK - i;
239  i2 = inK + i;
240  // reflect at boundaries if necessary
241  if (i1 < 0)
242  {
243  i1 = (-i1) % inModK;
244  // Removed because i1 can never be greater than inModK, right?
245  //if (i1 > inModK)
246  //i1=inModK-i1; //TODO: I don't think this is correct.
247  }
248  if (i2 > (int) inModK)
249  {
250  i2 = i2 % inModK;
251  // Removed because i1 can never be greater than inModK, right?
252  //if (i2 > inModK)
253  //i2=inModK-i2; //TODO: I don't think this is correct.
254  }
255  outVal = outVal + m_G[i]*(in[i1] + in[i2]);
256  }
257  out.Set( static_cast<OutputImagePixelType> (outVal) );
258  ++out;
259  progress.CompletedPixel();
260  }
261  }
262 }
263 
268 template <class TInputImage, class TOutputImage>
270 ::Expand1DImage( const std::vector<double> & in, OutputImageIterator & out,
271  unsigned int inTraverseSize, ProgressReporter &progress )
272 {
273  int i1, i2;
274 
275  int outK;
276  unsigned int inK;
277  unsigned int outTraverseSize = inTraverseSize * 2;
278  //inTraverseSize = outTraverseSize/2; // ensures that an even number is used.
279  int inModK; // number for modulus math of in
280  inModK = inTraverseSize - 1;
281 
282 
283  double outVal;
284 
285 
286  //TODO: m_GSize < 2 has not been tested.
287  if (m_HSize < 2)
288  {
289  for (inK = 0; inK < inTraverseSize; inK++)
290  {
291  out.Set( static_cast<OutputImagePixelType> (in[inK]) );
292  ++out;
293  out.Set( static_cast<OutputImagePixelType> (in[inK]) );
294  ++out;
295  }
296  progress.CompletedPixel();
297  }
298 
299  else
300  {
301  for (outK = 0; outK < (int) outTraverseSize; outK++)
302  {
303  outVal = 0.0;
304  for (int k = (outK % 2); k < (int) m_HSize; k += 2)
305  {
306  i1 = ( outK - k ) / 2;
307  if ( i1 < 0 )
308  {
309  i1 = (-i1) % inModK;
310  // The following could never happen therefore removed.
311  //if (i1 > inModK)
312  //i1 - inModK - i1;
313  }
314  outVal = outVal + m_H[k] * in[i1];
315  }
316  for( int k = 2 - ( outK % 2); k < (int) m_HSize; k += 2 )
317  {
318  i2 = (outK + k)/ 2;
319  if ( i2 > inModK )
320  {
321  i2 = i2 % inModK;
322  i2 = inModK - i2;
323  // The following could never happen therefore removed.
324  //if (i2 > inModK)
325  //i2 - inModK - i2;
326  }
327  outVal += m_H[k] * in[i2];
328  }
329 
330  out.Set( static_cast<OutputImagePixelType> (outVal) );
331  ++out;
332  progress.CompletedPixel();
333  }
334  }
335 
336 }
337 
338 
341 template < class TInputImage, class TOutputImage>
344 {
345  // Set up variables for waking the image regions.
346  RegionType validRegion;
347  SizeType startSize;
348  SizeType currentSize;
349  // Does not support streaming
350  typename Superclass::InputImagePointer inputPtr = const_cast< TInputImage * > ( this->GetInput() );
351  startSize = inputPtr->GetBufferedRegion().GetSize();
352 
353  // Initilize scratchImage space and allocate memory
354  InitializeScratch(startSize);
355  typename TOutputImage::Pointer scratchImage;
356  scratchImage = TOutputImage::New();
357  scratchImage->CopyInformation( inputPtr );
358  RegionType scratchRegion;
359  scratchRegion = inputPtr->GetBufferedRegion();
360  currentSize = startSize;
361  // scratchImage only needs the 1/2 the space of the original
362  // image for the first dimension.
363  // TODO: Is dividing by 2 correct or do I need something more complicated for handling odd dimensioned
364  // images? i.e. is the rounding handled correctly?
365  currentSize[0] = currentSize[0]/2;
366  scratchRegion.SetSize( currentSize );
367  scratchImage->SetRegions( scratchRegion );
368  scratchImage->Allocate();
369 
370 
371  currentSize = startSize;
372  validRegion.SetSize( currentSize );
373  validRegion.SetIndex ( inputPtr->GetBufferedRegion().GetIndex() );
374 
385  // The first time through the loop our input image is inputPtr
386  typename TInputImage::ConstPointer workingImage;
387  workingImage = inputPtr;
388 
389  unsigned int count = scratchRegion.GetNumberOfPixels() * ImageDimension;
390  ProgressReporter progress(this,0,count,10);
391  for (unsigned int n=0; n < ImageDimension; n++)
392  {
393  // Setup iterators for input image.
394  ConstInputImageIterator inIterator1( workingImage, validRegion );
395  ConstOutputImageIterator inIterator2( scratchImage, scratchRegion );
396 
397  if (n==0)
398  {
399  // First time through the loop we use the InputImage
400  inIterator1.GoToBegin();
401  inIterator1.SetDirection( n);
402  }
403  else
404  {
405  // After first time through the loop we use the scratch image which is of
406  // the output type.
407  inIterator2.GoToBegin();
408  inIterator2.SetDirection( n);
409  }
410 
411 
412  // Setup iterators and bounds for output image.
413  currentSize[n] = currentSize[n]/2; // reduce by a factor of 2
414  validRegion.SetSize(currentSize);
415  // TODO: Is there a way to put this in the else statement below?
416  OutputImageIterator outIterator( scratchImage, validRegion );
417  if (n == ( ImageDimension - 1) )
418  {
419  // Last time through the loop write directly to the ouput
420  outIterator = outItr;
421  }
422 
423  outIterator.GoToBegin();
424  outIterator.SetDirection(n);
425 
426  if (n==0)
427  {
428  while (!inIterator1.IsAtEnd() )
429  {
430  // Copies one line of input to m_Scratch
431  this->CopyInputLineToScratch( inIterator1 );
432 
433  this->Reduce1DImage( m_Scratch, outIterator, startSize[n], progress );
434  inIterator1.NextLine();
435  outIterator.NextLine();
436  }
437  }
438  else
439  {
440  while (!inIterator2.IsAtEnd() )
441  {
442  // Copies one line of input to m_Scratch
443  this->CopyOutputLineToScratch( inIterator2 );
444 
445  this->Reduce1DImage( m_Scratch, outIterator, startSize[n], progress );
446  inIterator2.NextLine();
447  outIterator.NextLine();
448  }
449  }
450 
451  // After first loop the input image is scratchImage
452  //workingImage = scratchImage;
453 
454  }
455 
456 }
457 
460 template < class TInputImage, class TOutputImage>
463 {
464  // Set up variables for waking the image regions.
465  RegionType validRegion;
466  SizeType startSize;
467  SizeType currentSize;
468 
469  // Does not support streaming
470  typename Superclass::InputImagePointer inputPtr = const_cast< TInputImage * > ( this->GetInput() );
471  startSize = inputPtr->GetBufferedRegion().GetSize();
472 
473 
474  // Initilize scratchImage space and allocate memory
475  InitializeScratch(startSize);
476  typename TOutputImage::Pointer scratchImage;
477  scratchImage = TOutputImage::New();
478  scratchImage->CopyInformation( inputPtr );
479  RegionType scratchRegion;
480  scratchRegion = inputPtr->GetBufferedRegion();
481  currentSize = startSize;
482 
483  // scratchImage 2 times the space of the original image .
484 
485  for (unsigned int n = 0; n < ImageDimension; n++)
486  {
487  currentSize[n] = currentSize[n] * 2;
488  }
489  scratchRegion.SetSize( currentSize );
490  scratchImage->SetBufferedRegion( scratchRegion );
491  scratchImage->Allocate();
492 
493 
494  currentSize = startSize;
495  validRegion.SetSize( currentSize );
496  validRegion.SetIndex ( inputPtr->GetBufferedRegion().GetIndex() );
497 
508  // The first time through the loop our input image is m_Image
509  typename TInputImage::ConstPointer workingImage;
510  workingImage = inputPtr;
511 
512  RegionType workingRegion = validRegion;
513 
514  unsigned int count = scratchRegion.GetNumberOfPixels() * ImageDimension;
515  ProgressReporter progress(this,0,count,10);
516  for (unsigned int n=0; n < ImageDimension; n++)
517  {
518  // Setup iterators for input image.
519  ConstInputImageIterator inIterator1( workingImage, workingRegion);
520  ConstOutputImageIterator inIterator2( scratchImage, validRegion);
521  if (n==0)
522  {
523  // First time through the loop we use the InputImage
524  inIterator1.GoToBegin();
525  inIterator1.SetDirection( n);
526  }
527  else
528  {
529  // After first time through the loop we use the scratch image which is of
530  // the output type.
531  inIterator2.GoToBegin();
532  inIterator2.SetDirection( n);
533  }
534 
535  // Setup iterators and bounds for output image.
536  currentSize[n] = currentSize[n] * 2; // expand by a factor of 2
537  validRegion.SetSize(currentSize);
538 
539  OutputImageIterator outIterator( scratchImage, validRegion );
540  if (n == ( ImageDimension - 1) )
541  {
542  // Last time through the loop write directly to the ouput
543  outIterator = outItr;
544  }
545 
546 
547  outIterator.GoToBegin();
548  outIterator.SetDirection(n);
549 
550  if (n==0)
551  {
552  while (!inIterator1.IsAtEnd() )
553  {
554  // Copies one line of input to m_Scratch
555  this->CopyInputLineToScratch( inIterator1 );
556 
557  this->Expand1DImage( m_Scratch, outIterator, startSize[n], progress );
558  inIterator1.NextLine();
559  outIterator.NextLine();
560  }
561  }
562  else
563  {
564  while (!inIterator2.IsAtEnd() )
565  {
566  // Copies one line of input to m_Scratch
567  this->CopyOutputLineToScratch( inIterator2 );
568 
569  this->Expand1DImage( m_Scratch, outIterator, startSize[n], progress );
570  inIterator2.NextLine();
571  outIterator.NextLine();
572  }
573  }
574 
575 
576  }
577 }
578 
579 // Allocate scratch space
580 template <class TInputImage, class TOutputImage>
583 {
584  unsigned int maxLength = 0;
585  for ( unsigned int n = 0; n < ImageDimension; n++ )
586  {
587  if ( DataLength[n] > maxLength )
588  {
589  maxLength = DataLength[n];
590  }
591  }
592  m_Scratch.resize( maxLength );
593 }
594 
595 template <class TInputImage, class TOutputImage>
598 {
599  unsigned int j = 0;
600  while ( !Iter.IsAtEndOfLine() )
601  {
602  m_Scratch[j] = static_cast<double>( Iter.Get() );
603  ++Iter;
604  ++j;
605  }
606 }
607 
608 
609 template <class TInputImage, class TOutputImage>
612 {
613  unsigned int j = 0;
614  while ( !Iter.IsAtEndOfLine() )
615  {
616  m_Scratch[j] = static_cast<double>( Iter.Get() );
617  ++Iter;
618  ++j;
619  }
620 }
621 
622 template <class TInputImage, class TOutputImage>
625 {
626  unsigned int j = 0;
627  while ( !Iter.IsAtEndOfLine() )
628  {
629  m_Scratch[j] = static_cast<double>( Iter.Get() );
630  ++Iter;
631  ++j;
632  }
633 }
634 
635 
636 } // namespace itk
637 
638 #endif

Generated at Sat Feb 2 2013 23:31:02 for Orfeo Toolbox with doxygen 1.8.1.1