Orfeo Toolbox  3.16
itkResampleImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkResampleImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2009-03-25 21:10:39 $
7  Version: $Revision: 1.66 $
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  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 #ifndef __itkResampleImageFilter_txx
18 #define __itkResampleImageFilter_txx
19 
20 // First make sure that the configuration is available.
21 // This line can be removed once the optimized versions
22 // gets integrated into the main directories.
23 #include "itkConfigure.h"
24 
25 #ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
27 #else
28 
29 
30 #include "itkResampleImageFilter.h"
31 #include "itkObjectFactory.h"
32 #include "itkIdentityTransform.h"
34 #include "itkProgressReporter.h"
38 
39 namespace itk
40 {
41 
45 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
48 {
49  m_OutputSpacing.Fill(1.0);
50  m_OutputOrigin.Fill(0.0);
51  m_OutputDirection.SetIdentity();
52 
53  m_UseReferenceImage = false;
54 
55  m_Size.Fill( 0 );
56  m_OutputStartIndex.Fill( 0 );
57 
58  typedef double CoordRepType;
61  m_DefaultPixelValue = 0;
62 }
63 
64 
70 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
71 void
73 ::PrintSelf(std::ostream& os, Indent indent) const
74 {
75  Superclass::PrintSelf(os,indent);
76 
77  os << indent << "DefaultPixelValue: "
78  << static_cast<typename NumericTraits<PixelType>::PrintType>(m_DefaultPixelValue)
79  << std::endl;
80  os << indent << "Size: " << m_Size << std::endl;
81  os << indent << "OutputStartIndex: " << m_OutputStartIndex << std::endl;
82  os << indent << "OutputOrigin: " << m_OutputOrigin << std::endl;
83  os << indent << "OutputSpacing: " << m_OutputSpacing << std::endl;
84  os << indent << "OutputDirection: " << m_OutputDirection << std::endl;
85  os << indent << "Transform: " << m_Transform.GetPointer() << std::endl;
86  os << indent << "Interpolator: " << m_Interpolator.GetPointer() << std::endl;
87  os << indent << "UseReferenceImage: " << (m_UseReferenceImage ? "On" : "Off") << std::endl;
88  return;
89 }
90 
94 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
95 void
98  const double* spacing)
99 {
100  SpacingType s(spacing);
101  this->SetOutputSpacing( s );
102 }
103 
104 
108 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
109 void
112  const double* origin)
113 {
114  OriginPointType p(origin);
115  this->SetOutputOrigin( p );
116 }
117 
118 
124 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
125 void
128 {
129  if( !m_Transform )
130  {
131  itkExceptionMacro(<< "Transform not set");
132  }
133 
134  if( !m_Interpolator )
135  {
136  itkExceptionMacro(<< "Interpolator not set");
137  }
138 
139  // Connect input image to interpolator
140  m_Interpolator->SetInputImage( this->GetInput() );
141 
142 }
143 
147 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
148 void
151 {
152  // Disconnect input image from the interpolator
153  m_Interpolator->SetInputImage( NULL );
154 
155 }
156 
160 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
161 void
164  const OutputImageRegionType& outputRegionForThread,
165  int threadId)
166 {
167  // Check whether the input or the output is a
168  // SpecialCoordinatesImage. If either are, then we cannot use the
169  // fast path since index mapping will definately not be linear.
170  typedef SpecialCoordinatesImage<PixelType, ImageDimension> OutputSpecialCoordinatesImageType;
171  typedef SpecialCoordinatesImage<InputPixelType, InputImageDimension> InputSpecialCoordinatesImageType;
172 
173  // Our friend the SGI needs these declarations to avoid unresolved
174  // linker errors.
175 #ifdef __sgi
176  InputSpecialCoordinatesImageType::Pointer foo =
177  InputSpecialCoordinatesImageType::New();
178  OutputSpecialCoordinatesImageType::Pointer bar =
179  OutputSpecialCoordinatesImageType::New();
180 #endif
181  if (dynamic_cast<const InputSpecialCoordinatesImageType *>(this->GetInput())
182  || dynamic_cast<const OutputSpecialCoordinatesImageType *>(this->GetOutput()))
183  {
184  this->NonlinearThreadedGenerateData(outputRegionForThread, threadId);
185  return;
186  }
187 
188  // Check whether we can use a fast path for resampling. Fast path
189  // can be used if the transformation is linear. Transform respond
190  // to the IsLinear() call.
191  if( m_Transform->IsLinear() )
192  {
193  this->LinearThreadedGenerateData(outputRegionForThread, threadId);
194  return;
195  }
196 
197  // Otherwise, we use the normal method where the transform is called
198  // for computing the transformation of every point.
199  this->NonlinearThreadedGenerateData(outputRegionForThread, threadId);
200 
201 }
202 
203 
204 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
205 void
208  const OutputImageRegionType& outputRegionForThread,
209  int threadId)
210 {
211  // Get the output pointers
212  OutputImagePointer outputPtr = this->GetOutput();
213 
214  // Get ths input pointers
215  InputImageConstPointer inputPtr=this->GetInput();
216 
217  // Create an iterator that will walk the output region for this thread.
218  typedef ImageRegionIteratorWithIndex<TOutputImage> OutputIterator;
219 
220  OutputIterator outIt(outputPtr, outputRegionForThread);
221 
222  // Define a few indices that will be used to translate from an input pixel
223  // to an output pixel
224  PointType outputPoint; // Coordinates of current output pixel
225  PointType inputPoint; // Coordinates of current input pixel
226 
227  typedef double CoordRepType;
228  typedef ContinuousIndex<CoordRepType, ImageDimension> ContinuousIndexType;
229  ContinuousIndexType inputIndex;
230 
231  // Support for progress methods/callbacks
232  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
233 
234  typedef typename InterpolatorType::OutputType OutputType;
235 
236  // Min/max values of the output pixel type AND these values
237  // represented as the output type of the interpolator
238  const PixelType minValue = NumericTraits<PixelType >::NonpositiveMin();
239  const PixelType maxValue = NumericTraits<PixelType >::max();
240 
241  const OutputType minOutputValue = static_cast<OutputType>(minValue);
242  const OutputType maxOutputValue = static_cast<OutputType>(maxValue);
243 
244  // Walk the output region
245  outIt.GoToBegin();
246 
247 
248  // This fix works for images up to approximately 2^25 pixels in
249  // any dimension. If the image is larger than this, this constant
250  // needs to be made lower.
251  double precisionConstant = 1<<(NumericTraits<double>::digits>>1);
252 
253  while ( !outIt.IsAtEnd() )
254  {
255  // Determine the index of the current output pixel
256  outputPtr->TransformIndexToPhysicalPoint( outIt.GetIndex(), outputPoint );
257 
258  // Compute corresponding input pixel position
259  inputPoint = m_Transform->TransformPoint(outputPoint);
260  inputPtr->TransformPhysicalPointToContinuousIndex(inputPoint, inputIndex);
261 
262  // The inputIndex is precise to many decimal points, but this precision
263  // involves some error in the last bits.
264  // Sometimes, when an index should be inside of the image, the
265  // index will be slightly
266  // greater than the largest index in the image, like 255.00000000002
267  // for a image of size 256. This can cause an empty row to show up
268  // at the bottom of the image.
269  // Therefore, the following routine uses a
270  // precisionConstant that specifies the number of relevant bits,
271  // and the value is truncated to this precision.
272  for (int i=0; i < ImageDimension; ++i)
273  {
274  double roundedInputIndex = vcl_floor(inputIndex[i]);
275  double inputIndexFrac = inputIndex[i] - roundedInputIndex;
276  double newInputIndexFrac = vcl_floor(precisionConstant * inputIndexFrac)/precisionConstant;
277  inputIndex[i] = roundedInputIndex + newInputIndexFrac;
278  }
279 
280  // Evaluate input at right position and copy to the output
281  if( m_Interpolator->IsInsideBuffer(inputIndex) )
282  {
283  PixelType pixval;
284  const OutputType value
285  = m_Interpolator->EvaluateAtContinuousIndex(inputIndex);
286  pixval = static_cast<PixelType>(
287  NumericTraits<OutputType>::Clamp(value,minOutputValue,maxOutputValue)
288  );
289  outIt.Set( pixval );
290  }
291  else
292  {
293  outIt.Set(m_DefaultPixelValue); // default background value
294  }
295 
296  progress.CompletedPixel();
297  ++outIt;
298  }
299 
300  return;
301 }
302 
303 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
304 void
307  const OutputImageRegionType& outputRegionForThread,
308  int threadId)
309 {
310  // Get the output pointers
311  OutputImagePointer outputPtr = this->GetOutput();
312 
313  // Get ths input pointers
314  InputImageConstPointer inputPtr=this->GetInput();
315 
316  // Create an iterator that will walk the output region for this thread.
317  typedef ImageLinearIteratorWithIndex<TOutputImage> OutputIterator;
318 
319  OutputIterator outIt(outputPtr, outputRegionForThread);
320  outIt.SetDirection( 0 );
321 
322  // Define a few indices that will be used to translate from an input pixel
323  // to an output pixel
324  PointType outputPoint; // Coordinates of current output pixel
325  PointType inputPoint; // Coordinates of current input pixel
326  PointType tmpOutputPoint;
327  PointType tmpInputPoint;
328 
329  typedef double CoordRepType;
330  typedef ContinuousIndex<CoordRepType, ImageDimension> ContinuousIndexType;
331  ContinuousIndexType inputIndex;
332  ContinuousIndexType tmpInputIndex;
333 
334  typedef typename PointType::VectorType VectorType;
335  VectorType delta; // delta in input continuous index coordinate frame
336  IndexType index;
337 
338  // Support for progress methods/callbacks
339  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
340 
341  typedef typename InterpolatorType::OutputType OutputType;
342 
343  // Cache information from the superclass
344  PixelType defaultValue = this->GetDefaultPixelValue();
345 
346  // Min/max values of the output pixel type AND these values
347  // represented as the output type of the interpolator
348  const PixelType minValue = NumericTraits<PixelType >::NonpositiveMin();
349  const PixelType maxValue = NumericTraits<PixelType >::max();
350 
351  const OutputType minOutputValue = static_cast<OutputType>(minValue);
352  const OutputType maxOutputValue = static_cast<OutputType>(maxValue);
353 
354 
355  // Determine the position of the first pixel in the scanline
356  index = outIt.GetIndex();
357  outputPtr->TransformIndexToPhysicalPoint( index, outputPoint );
358 
359 
360  // Compute corresponding input pixel position
361  inputPoint = m_Transform->TransformPoint(outputPoint);
362  inputPtr->TransformPhysicalPointToContinuousIndex(inputPoint, inputIndex);
363 
364  // As we walk across a scan line in the output image, we trace
365  // an oriented/scaled/translated line in the input image. Cache
366  // the delta along this line in continuous index space of the input
367  // image. This allows us to use vector addition to model the
368  // transformation.
369  //
370  // To find delta, we take two pixels adjacent in a scanline
371  // and determine the continuous indices of these pixels when
372  // mapped to the input coordinate frame. We use the difference
373  // between these two continuous indices as the delta to apply
374  // to an index to trace line in the input image as we move
375  // across the scanline of the output image.
376  //
377  // We determine delta in this manner so that Images and
378  // OrientedImages are both handled properly (with the delta for
379  // OrientedImages taking into account the direction cosines).
380  //
381  ++index[0];
382  outputPtr->TransformIndexToPhysicalPoint( index, tmpOutputPoint );
383  tmpInputPoint = m_Transform->TransformPoint( tmpOutputPoint );
384  inputPtr->TransformPhysicalPointToContinuousIndex(tmpInputPoint,
385  tmpInputIndex);
386  delta = tmpInputIndex - inputIndex;
387 
388 
389  // This fix works for images up to approximately 2^25 pixels in
390  // any dimension. If the image is larger than this, this constant
391  // needs to be made lower.
392  double precisionConstant = 1<<(NumericTraits<double>::digits>>1);
393 
394  // Delta is precise to many decimal points, but this precision
395  // involves some error in the last bits. This error can accumulate
396  // as the delta values are added.
397  // Sometimes, when the accumulated delta should be inside of the
398  // image, it will be slightly
399  // greater than the largest index in the image, like 255.00000000002
400  // for a image of size 256. This can cause an empty column to show up
401  // at the right side of the image. If we instead
402  // truncate this delta value to some precision, this solves the problem.
403  // Therefore, the following routine uses a
404  // precisionConstant that specifies the number of relevant bits,
405  // and the value is truncated to this precision.
406  for (int i=0; i < ImageDimension; ++i)
407  {
408  double roundedDelta = vcl_floor(delta[i]);
409  double deltaFrac = delta[i] - roundedDelta;
410  double newDeltaFrac = vcl_floor(precisionConstant * deltaFrac)/precisionConstant;
411  delta[i] = roundedDelta + newDeltaFrac;
412  }
413 
414 
415  while ( !outIt.IsAtEnd() )
416  {
417  // Determine the continuous index of the first pixel of output
418  // scanline when mapped to the input coordinate frame.
419  //
420 
421  // First get the position of the pixel in the output coordinate frame
422  index = outIt.GetIndex();
423  outputPtr->TransformIndexToPhysicalPoint( index, outputPoint );
424 
425  // Compute corresponding input pixel continuous index, this index
426  // will incremented in the scanline loop
427  inputPoint = m_Transform->TransformPoint(outputPoint);
428  inputPtr->TransformPhysicalPointToContinuousIndex(inputPoint, inputIndex);
429 
430  // The inputIndex is precise to many decimal points, but this precision
431  // involves some error in the last bits.
432  // Sometimes, when an index should be inside of the image, the
433  // index will be slightly
434  // greater than the largest index in the image, like 255.00000000002
435  // for a image of size 256. This can cause an empty row to show up
436  // at the bottom of the image.
437  // Therefore, the following routine uses a
438  // precisionConstant that specifies the number of relevant bits,
439  // and the value is truncated to this precision.
440  for (int i=0; i < ImageDimension; ++i)
441  {
442  double roundedInputIndex = vcl_floor(inputIndex[i]);
443  double inputIndexFrac = inputIndex[i] - roundedInputIndex;
444  double newInputIndexFrac = vcl_floor(precisionConstant * inputIndexFrac)/precisionConstant;
445  inputIndex[i] = roundedInputIndex + newInputIndexFrac;
446  }
447 
448 
449  while( !outIt.IsAtEndOfLine() )
450  {
451  // Evaluate input at right position and copy to the output
452  if( m_Interpolator->IsInsideBuffer(inputIndex) )
453  {
454  PixelType pixval;
455  const OutputType value
456  = m_Interpolator->EvaluateAtContinuousIndex(inputIndex);
457 
458  pixval = static_cast<PixelType>(
459  NumericTraits<OutputType>::Clamp(value,minOutputValue,maxOutputValue)
460  );
461  outIt.Set( pixval );
462  }
463  else
464  {
465  outIt.Set(defaultValue); // default background value
466  }
467 
468  progress.CompletedPixel();
469  ++outIt;
470  inputIndex += delta;
471  }
472  outIt.NextLine();
473  }
474 
475  return;
476 }
477 
478 
486 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
487 void
490 {
491  // call the superclass's implementation of this method
492  Superclass::GenerateInputRequestedRegion();
493 
494  if ( !this->GetInput() )
495  {
496  return;
497  }
498 
499  // get pointers to the input and output
500  InputImagePointer inputPtr =
501  const_cast< TInputImage *>( this->GetInput() );
502 
503  // Request the entire input image
504  InputImageRegionType inputRegion;
505  inputRegion = inputPtr->GetLargestPossibleRegion();
506  inputPtr->SetRequestedRegion(inputRegion);
507 
508  return;
509 }
510 
511 
516 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
520 {
521  Self * surrogate = const_cast< Self * >( this );
522  const OutputImageType * referenceImage =
523  static_cast<const OutputImageType *>(surrogate->ProcessObject::GetInput(1));
524  return referenceImage;
525 }
526 
527 
532 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
533 void
535 ::SetReferenceImage( const TOutputImage *image )
536 {
537  itkDebugMacro("setting input ReferenceImage to " << image);
538  if( image != static_cast<const TOutputImage *>(this->ProcessObject::GetInput( 1 )) )
539  {
540  this->ProcessObject::SetNthInput(1, const_cast< TOutputImage *>( image ) );
541  this->Modified();
542  }
543 }
544 
546 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
547 void
550 {
551  this->SetOutputOrigin ( image->GetOrigin() );
552  this->SetOutputSpacing ( image->GetSpacing() );
553  this->SetOutputDirection ( image->GetDirection() );
554  this->SetOutputStartIndex ( image->GetLargestPossibleRegion().GetIndex() );
555  this->SetSize ( image->GetLargestPossibleRegion().GetSize() );
556 }
557 
558 #if !defined(ITK_LEGACY_REMOVE)
559 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
560 void
562 ::SetOutputParametersFromConstImage ( const ImageBaseType * image )
563 {
564  itkGenericLegacyReplaceBodyMacro(itk::ResampleImageFilter::SetOutputParametersFromConstImage,
565  3.14,
567  this->SetOutputParametersFromImage(image);
568 }
569 #endif
570 
574 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
575 void
578 {
579  // call the superclass' implementation of this method
580  Superclass::GenerateOutputInformation();
581 
582  // get pointers to the input and output
583  OutputImagePointer outputPtr = this->GetOutput();
584  if ( !outputPtr )
585  {
586  return;
587  }
588 
589  const OutputImageType * referenceImage = this->GetReferenceImage();
590 
591  // Set the size of the output region
592  if( m_UseReferenceImage && referenceImage )
593  {
594  outputPtr->SetLargestPossibleRegion( referenceImage->GetLargestPossibleRegion() );
595  }
596  else
597  {
598  typename TOutputImage::RegionType outputLargestPossibleRegion;
599  outputLargestPossibleRegion.SetSize( m_Size );
600  outputLargestPossibleRegion.SetIndex( m_OutputStartIndex );
601  outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );
602  }
603 
604  // Set spacing and origin
605  if (m_UseReferenceImage && referenceImage)
606  {
607  outputPtr->SetOrigin( referenceImage->GetOrigin() );
608  outputPtr->SetSpacing( referenceImage->GetSpacing() );
609  outputPtr->SetDirection( referenceImage->GetDirection() );
610  }
611  else
612  {
613  outputPtr->SetOrigin( m_OutputOrigin );
614  outputPtr->SetSpacing( m_OutputSpacing );
615  outputPtr->SetDirection( m_OutputDirection );
616  }
617  return;
618 }
619 
623 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
624 unsigned long
626 ::GetMTime( void ) const
627 {
628  unsigned long latestTime = Object::GetMTime();
629 
630  if( m_Transform )
631  {
632  if( latestTime < m_Transform->GetMTime() )
633  {
634  latestTime = m_Transform->GetMTime();
635  }
636  }
637 
638  if( m_Interpolator )
639  {
640  if( latestTime < m_Interpolator->GetMTime() )
641  {
642  latestTime = m_Interpolator->GetMTime();
643  }
644  }
645 
646  return latestTime;
647 }
648 
649 } // end namespace itk
650 
651 #endif
652 
653 #endif

Generated at Sun Feb 3 2013 00:03:24 for Orfeo Toolbox with doxygen 1.8.1.1