Orfeo Toolbox  3.16
itkBSplineDecompositionImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkBSplineDecompositionImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2010-03-19 07:06:01 $
7  Version: $Revision: 1.14 $
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 #ifndef __itkBSplineDecompositionImageFilter_txx
21 #define __itkBSplineDecompositionImageFilter_txx
24 #include "itkImageRegionIterator.h"
25 #include "itkProgressReporter.h"
26 #include "itkVector.h"
27 
28 namespace itk
29 {
30 
34 template <class TInputImage, class TOutputImage>
37 {
38  m_SplineOrder = 0;
39  int SplineOrder = 3;
40  m_Tolerance = 1e-10; // Need some guidance on this one...what is reasonable?
41  m_IteratorDirection = 0;
42  this->SetSplineOrder(SplineOrder);
43 }
44 
45 
49 template <class TInputImage, class TOutputImage>
50 void
53  std::ostream& os,
54  Indent indent) const
55 {
56  Superclass::PrintSelf( os, indent );
57  os << indent << "Spline Order: " << m_SplineOrder << std::endl;
58 
59 }
60 
61 
62 template <class TInputImage, class TOutputImage>
63 bool
66 {
67 
68  // See Unser, 1993, Part II, Equation 2.5,
69  // or Unser, 1999, Box 2. for an explaination.
70 
71  double c0 = 1.0;
72 
73  if (m_DataLength[m_IteratorDirection] == 1) //Required by mirror boundaries
74  {
75  return false;
76  }
77 
78  // Compute overall gain
79  for (int k = 0; k < m_NumberOfPoles; k++)
80  {
81  // Note for cubic splines lambda = 6
82  c0 = c0 * (1.0 - m_SplinePoles[k]) * (1.0 - 1.0 / m_SplinePoles[k]);
83  }
84 
85  // apply the gain
86  for (unsigned int n = 0; n < m_DataLength[m_IteratorDirection]; n++)
87  {
88  m_Scratch[n] *= c0;
89  }
90 
91  // loop over all poles
92  for (int k = 0; k < m_NumberOfPoles; k++)
93  {
94  // causal initialization
95  this->SetInitialCausalCoefficient(m_SplinePoles[k]);
96  // causal recursion
97  for (unsigned int n = 1; n < m_DataLength[m_IteratorDirection]; n++)
98  {
99  m_Scratch[n] += m_SplinePoles[k] * m_Scratch[n - 1];
100  }
101 
102  // anticausal initialization
103  this->SetInitialAntiCausalCoefficient(m_SplinePoles[k]);
104  // anticausal recursion
105  for ( int n = m_DataLength[m_IteratorDirection] - 2; 0 <= n; n--)
106  {
107  m_Scratch[n] = m_SplinePoles[k] * (m_Scratch[n + 1] - m_Scratch[n]);
108  }
109  }
110  return true;
111 
112 }
113 
114 
115 template <class TInputImage, class TOutputImage>
116 void
118 ::SetSplineOrder(unsigned int SplineOrder)
119 {
120  if (SplineOrder == m_SplineOrder)
121  {
122  return;
123  }
124  m_SplineOrder = SplineOrder;
125  this->SetPoles();
126  this->Modified();
127 
128 }
129 
130 
131 template <class TInputImage, class TOutputImage>
132 void
135 {
136  /* See Unser, 1997. Part II, Table I for Pole values */
137  // See also, Handbook of Medical Imaging, Processing and Analysis, Ed. Isaac N. Bankman,
138  // 2000, pg. 416.
139  switch (m_SplineOrder)
140  {
141  case 3:
142  m_NumberOfPoles = 1;
143  m_SplinePoles[0] = vcl_sqrt(3.0) - 2.0;
144  break;
145  case 0:
146  m_NumberOfPoles = 0;
147  break;
148  case 1:
149  m_NumberOfPoles = 0;
150  break;
151  case 2:
152  m_NumberOfPoles = 1;
153  m_SplinePoles[0] = vcl_sqrt(8.0) - 3.0;
154  break;
155  case 4:
156  m_NumberOfPoles = 2;
157  m_SplinePoles[0] = vcl_sqrt(664.0 - vcl_sqrt(438976.0)) + vcl_sqrt(304.0) - 19.0;
158  m_SplinePoles[1] = vcl_sqrt(664.0 + vcl_sqrt(438976.0)) - vcl_sqrt(304.0) - 19.0;
159  break;
160  case 5:
161  m_NumberOfPoles = 2;
162  m_SplinePoles[0] = vcl_sqrt(135.0 / 2.0 - vcl_sqrt(17745.0 / 4.0)) + vcl_sqrt(105.0 / 4.0)
163  - 13.0 / 2.0;
164  m_SplinePoles[1] = vcl_sqrt(135.0 / 2.0 + vcl_sqrt(17745.0 / 4.0)) - vcl_sqrt(105.0 / 4.0)
165  - 13.0 / 2.0;
166  break;
167  default:
168  // SplineOrder not implemented yet.
169  ExceptionObject err(__FILE__, __LINE__);
170  err.SetLocation( ITK_LOCATION);
171  err.SetDescription( "SplineOrder must be between 0 and 5. Requested spline order has not been implemented yet." );
172  throw err;
173  break;
174  }
175 }
176 
177 
178 template <class TInputImage, class TOutputImage>
179 void
182 {
183  /* begining InitialCausalCoefficient */
184  /* See Unser, 1999, Box 2 for explaination */
185  CoeffType sum;
186  double zn, z2n, iz;
187  unsigned long horizon;
188 
189  /* this initialization corresponds to mirror boundaries */
190  horizon = m_DataLength[m_IteratorDirection];
191  zn = z;
192  if (m_Tolerance > 0.0)
193  {
194  horizon = (long)vcl_ceil(vcl_log(m_Tolerance) / vcl_log(vcl_fabs(z)));
195  }
196  if (horizon < m_DataLength[m_IteratorDirection])
197  {
198  /* accelerated loop */
199  sum = m_Scratch[0]; // verify this
200  for (unsigned int n = 1; n < horizon; n++)
201  {
202  sum += zn * m_Scratch[n];
203  zn *= z;
204  }
205  m_Scratch[0] = sum;
206  }
207  else {
208  /* full loop */
209  iz = 1.0 / z;
210  z2n = vcl_pow(z, (double)(m_DataLength[m_IteratorDirection] - 1L));
211  sum = m_Scratch[0] + z2n * m_Scratch[m_DataLength[m_IteratorDirection] - 1L];
212  z2n *= z2n * iz;
213  for (unsigned int n = 1; n <= (m_DataLength[m_IteratorDirection] - 2); n++)
214  {
215  sum += (zn + z2n) * m_Scratch[n];
216  zn *= z;
217  z2n *= iz;
218  }
219  m_Scratch[0] = sum / (1.0 - zn * zn);
220  }
221 }
222 
223 
224 template <class TInputImage, class TOutputImage>
225 void
228 {
229  // this initialization corresponds to mirror boundaries
230  /* See Unser, 1999, Box 2 for explaination */
231  // Also see erratum at http://bigwww.epfl.ch/publications/unser9902.html
232  m_Scratch[m_DataLength[m_IteratorDirection] - 1] =
233  (z / (z * z - 1.0)) *
234  (z * m_Scratch[m_DataLength[m_IteratorDirection] - 2] + m_Scratch[m_DataLength[m_IteratorDirection] - 1]);
235 }
236 
237 
238 template <class TInputImage, class TOutputImage>
239 void
242 {
243  OutputImagePointer output = this->GetOutput();
244 
245  Size<ImageDimension> size = output->GetBufferedRegion().GetSize();
246 
247  unsigned int count = output->GetBufferedRegion().GetNumberOfPixels() / size[0] * ImageDimension;
248 
249  ProgressReporter progress(this, 0, count, 10);
250 
251  // Initialize coeffient array
252  this->CopyImageToImage(); // Coefficients are initialized to the input data
253 
254  for (unsigned int n=0; n < ImageDimension; n++)
255  {
256  m_IteratorDirection = n;
257  // Loop through each dimension
258 
259  // Initialize iterators
260  OutputLinearIterator CIterator( output, output->GetBufferedRegion() );
261  CIterator.SetDirection( m_IteratorDirection );
262  // For each data vector
263  while ( !CIterator.IsAtEnd() )
264  {
265  // Copy coefficients to scratch
266  this->CopyCoefficientsToScratch( CIterator );
267 
268 
269  // Perform 1D BSpline calculations
270  this->DataToCoefficients1D();
271 
272  // Copy scratch back to coefficients.
273  // Brings us back to the end of the line we were working on.
274  CIterator.GoToBeginOfLine();
275  this->CopyScratchToCoefficients( CIterator ); // m_Scratch = m_Image;
276  CIterator.NextLine();
277  progress.CompletedPixel();
278  }
279  }
280 }
281 
282 
286 template <class TInputImage, class TOutputImage>
287 void
290 {
291 
293  typedef ImageRegionIterator< TOutputImage > OutputIterator;
294  typedef typename TOutputImage::PixelType OutputPixelType;
295 
296  InputIterator inIt( this->GetInput(), this->GetInput()->GetBufferedRegion() );
297  OutputIterator outIt( this->GetOutput(), this->GetOutput()->GetBufferedRegion() );
298 
299  inIt = inIt.Begin();
300  outIt = outIt.Begin();
301 
302  while ( !outIt.IsAtEnd() )
303  {
304  outIt.Set( static_cast<OutputPixelType>( inIt.Get() ) );
305  ++inIt;
306  ++outIt;
307  }
308 
309 }
310 
311 
315 template <class TInputImage, class TOutputImage>
316 void
319 {
320  typedef typename TOutputImage::PixelType OutputPixelType;
321  unsigned long j = 0;
322  while ( !Iter.IsAtEndOfLine() )
323  {
324  Iter.Set( static_cast<OutputPixelType>( m_Scratch[j] ) );
325  ++Iter;
326  ++j;
327  }
328 
329 }
330 
331 
335 template <class TInputImage, class TOutputImage>
336 void
339 {
340  unsigned long j = 0;
341  while ( !Iter.IsAtEndOfLine() )
342  {
343  m_Scratch[j] = static_cast<CoeffType>( Iter.Get() );
344  ++Iter;
345  ++j;
346  }
347 }
348 
349 
353 template <class TInputImage, class TOutputImage>
354 void
357 {
358  // this filter requires the all of the input image to be in
359  // the buffer
360  InputImagePointer inputPtr = const_cast< TInputImage * > ( this->GetInput() );
361  if( inputPtr )
362  {
363  inputPtr->SetRequestedRegionToLargestPossibleRegion();
364  }
365 }
366 
367 
371 template <class TInputImage, class TOutputImage>
372 void
375  DataObject *output )
376 {
377 
378  // this filter requires the all of the output image to be in
379  // the buffer
380  TOutputImage *imgData;
381  imgData = dynamic_cast<TOutputImage*>( output );
382  if( imgData )
383  {
384  imgData->SetRequestedRegionToLargestPossibleRegion();
385  }
386 
387 }
388 
392 template <class TInputImage, class TOutputImage>
393 void
396 {
397 
398  // Allocate scratch memory
399  InputImageConstPointer inputPtr = this->GetInput();
400  m_DataLength = inputPtr->GetBufferedRegion().GetSize();
401 
402  unsigned long maxLength = 0;
403  for ( unsigned int n = 0; n < ImageDimension; n++ )
404  {
405  if ( m_DataLength[n] > maxLength )
406  {
407  maxLength = m_DataLength[n];
408  }
409  }
410  m_Scratch.resize( maxLength );
411 
412  // Allocate memory for output image
413  OutputImagePointer outputPtr = this->GetOutput();
414  outputPtr->SetBufferedRegion( outputPtr->GetRequestedRegion() );
415  outputPtr->Allocate();
416 
417  // Calculate actual output
418  this->DataToCoefficientsND();
419 
420  // Clean up
421  m_Scratch.clear();
422 
423 }
424 
425 
426 } // namespace itk
427 
428 #endif

Generated at Sat Feb 2 2013 23:30:37 for Orfeo Toolbox with doxygen 1.8.1.1