ANIMA  4.0
animaResampleImageFilter.hxx
Go to the documentation of this file.
1 #pragma once
2 
4 #include <itkObjectFactory.h>
5 #include <itkIdentityTransform.h>
6 #include <itkLinearInterpolateImageFunction.h>
7 #include <itkProgressReporter.h>
8 #include <itkImageRegionIteratorWithIndex.h>
9 #include <itkImageLinearIteratorWithIndex.h>
10 #include <itkSpecialCoordinatesImage.h>
11 
12 #include <vnl/vnl_det.h>
13 
14 namespace anima
15 {
16 
20 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
23 {
24  m_OutputSpacing.Fill(1.0);
25  m_OutputOrigin.Fill(0.0);
26  m_OutputDirection.SetIdentity();
27 
28  m_UseReferenceImage = false;
29 
30  m_Size.Fill( 0 );
31  m_OutputStartIndex.Fill( 0 );
32 
33  m_Transform = itk::IdentityTransform<TInterpolatorPrecisionType, ImageDimension>::New();
34  m_Interpolator = nullptr;
35  m_DefaultPixelValue = 0;
36 
37  m_ScaleIntensitiesWithJacobian = false;
38  m_LinearTransform = false;
39 }
40 
45 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
46 void
48 ::PrintSelf(std::ostream& os, itk::Indent indent) const
49 {
50  Superclass::PrintSelf(os,indent);
51 
52  os << indent << "DefaultPixelValue: "
53  << static_cast<typename itk::NumericTraits<PixelType>::PrintType>(m_DefaultPixelValue)
54  << std::endl;
55  os << indent << "Size: " << m_Size << std::endl;
56  os << indent << "OutputStartIndex: " << m_OutputStartIndex << std::endl;
57  os << indent << "OutputOrigin: " << m_OutputOrigin << std::endl;
58  os << indent << "OutputSpacing: " << m_OutputSpacing << std::endl;
59  os << indent << "OutputDirection: " << m_OutputDirection << std::endl;
60  os << indent << "Transform: " << m_Transform.GetPointer() << std::endl;
61  os << indent << "Interpolator: " << m_Interpolator.GetPointer() << std::endl;
62  os << indent << "UseReferenceImage: " << (m_UseReferenceImage ? "On" : "Off") << std::endl;
63  os << indent << "Scale intensities with Jacobian : " << (m_ScaleIntensitiesWithJacobian ? "On" : "Off") << std::endl;
64  return;
65 }
66 
71 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
72 itk::LightObject::Pointer
75 {
76  itk::LightObject::Pointer outputPointer = Superclass::InternalClone();
77 
78  Self *castPointer = dynamic_cast <Self *> (outputPointer.GetPointer());
79  castPointer->SetScaleIntensitiesWithJacobian(m_ScaleIntensitiesWithJacobian);
80 
81  return outputPointer;
82 }
83 
87 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
88 void
90 ::SetOutputSpacing(const double* spacing)
91 {
92  SpacingType s(spacing);
93  this->SetOutputSpacing( s );
94 }
95 
96 
100 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
101 void
103 ::SetOutputOrigin(const double* origin)
104 {
105  OriginPointType p(origin);
106  this->SetOutputOrigin( p );
107 }
108 
109 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
110 void
113 {
114  if (m_Transform != transform)
115  {
116  m_Transform = transform;
117 
118  const MatrixTransformType *tmpTrsf = dynamic_cast < const MatrixTransformType *> (transform);
119  m_LinearTransform = (tmpTrsf != 0);
120 
121  this->Modified();
122  }
123 }
124 
130 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
131 void
134 {
135  if (!m_Transform)
136  {
137  itkExceptionMacro(<< "Transform not set");
138  }
139 
140  if (!m_Interpolator)
141  m_Interpolator = itk::LinearInterpolateImageFunction<InputImageType, TInterpolatorPrecisionType>::New();
142 
143  // Connect input image to interpolator
144  m_Interpolator->SetInputImage(this->GetInput());
145 }
146 
150 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
151 void
154 {
155  // Disconnect input image from the interpolator
156  m_Interpolator->SetInputImage(nullptr);
157 }
158 
162 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
163 void
166 {
167  // Get the output pointers
168  OutputImagePointer outputPtr = this->GetOutput();
169 
170  // Get ths input pointers
171  InputImageConstPointer inputPtr=this->GetInput();
172 
173  // Create an iterator that will walk the output region for this thread.
174  typedef itk::ImageRegionIteratorWithIndex<TOutputImage> OutputIterator;
175 
176  OutputIterator outIt(outputPtr, outputRegionForThread);
177 
178  // Define a few indices that will be used to translate from an input pixel
179  // to an output pixel
180  PointType outputPoint; // Coordinates of current output pixel
181  PointType inputPoint; // Coordinates of current input pixel
182 
183  typedef itk::ContinuousIndex<TInterpolatorPrecisionType, ImageDimension> ContinuousIndexType;
184  ContinuousIndexType inputIndex;
185 
186  typedef typename InterpolatorType::OutputType OutputType;
187 
188  // Min/max values of the output pixel type AND these values
189  // represented as the output type of the interpolator
190  const PixelType minValue = itk::NumericTraits<PixelType >::NonpositiveMin();
191  const PixelType maxValue = itk::NumericTraits<PixelType >::max();
192 
193  const OutputType minOutputValue = static_cast<OutputType>(minValue);
194  const OutputType maxOutputValue = static_cast<OutputType>(maxValue);
195 
196  // Walk the output region
197  outIt.GoToBegin();
198 
199  while ( !outIt.IsAtEnd() )
200  {
201  // Determine the index of the current output pixel
202  outputPtr->TransformIndexToPhysicalPoint( outIt.GetIndex(), outputPoint );
203 
204  // Compute corresponding input pixel position
205  inputPoint = m_Transform->TransformPoint(outputPoint);
206  inputPtr->TransformPhysicalPointToContinuousIndex(inputPoint, inputIndex);
207 
208  // Evaluate input at right position and copy to the output
209  if( m_Interpolator->IsInsideBuffer(inputIndex) )
210  {
211  PixelType pixval;
212  OutputType value = m_Interpolator->EvaluateAtContinuousIndex(inputIndex);
213 
214  if (m_ScaleIntensitiesWithJacobian)
215  {
216  double jacobianValue = 1;
217  if (m_LinearTransform)
218  jacobianValue = this->ComputeLinearJacobianValue();
219  else
220  jacobianValue = this->ComputeLocalJacobianValue(outIt.GetIndex());
221 
222  value *= jacobianValue;
223  }
224 
225  if( value < minOutputValue )
226  {
227  pixval = minValue;
228  }
229  else if( value > maxOutputValue )
230  {
231  pixval = maxValue;
232  }
233  else
234  {
235  pixval = static_cast<PixelType>( value );
236  }
237  outIt.Set( pixval );
238  }
239  else
240  {
241  outIt.Set(m_DefaultPixelValue); // default background value
242  }
243 
244  ++outIt;
245  }
246 }
247 
255 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
256 void
259 {
260  // call the superclass's implementation of this method
261  Superclass::GenerateInputRequestedRegion();
262 
263  if ( !this->GetInput() )
264  {
265  return;
266  }
267 
268  // get pointers to the input and output
269  InputImagePointer inputPtr =
270  const_cast< TInputImage *>( this->GetInput() );
271 
272  // Request the entire input image
273  InputImageRegionType inputRegion;
274  inputRegion = inputPtr->GetLargestPossibleRegion();
275  inputPtr->SetRequestedRegion(inputRegion);
276 
277  return;
278 }
279 
284 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
288 {
289  Self * surrogate = const_cast< Self * >( this );
290  const OutputImageType * referenceImage =
291  static_cast<const OutputImageType *>(surrogate->itk::ProcessObject::GetInput(1));
292  return referenceImage;
293 }
294 
295 
300 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
301 void
303 ::SetReferenceImage( const TOutputImage *image )
304 {
305  itkDebugMacro("setting input ReferenceImage to " << image);
306  if( image != static_cast<const TOutputImage *>(this->itk::ProcessObject::GetInput( 1 )) )
307  {
308  this->itk::ProcessObject::SetNthInput(1, const_cast< TOutputImage *>( image ) );
309  this->Modified();
310  }
311 }
312 
314 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
315 void
318 {
319  this->SetOutputOrigin ( image->GetOrigin() );
320  this->SetOutputSpacing ( image->GetSpacing() );
321  this->SetOutputDirection ( image->GetDirection() );
322  this->SetOutputStartIndex ( image->GetLargestPossibleRegion().GetIndex() );
323  this->SetSize ( image->GetLargestPossibleRegion().GetSize() );
324 }
325 
329 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
330 void
333 {
334  // call the superclass' implementation of this method
335  Superclass::GenerateOutputInformation();
336 
337  // get pointers to the input and output
338  OutputImagePointer outputPtr = this->GetOutput();
339  if ( !outputPtr )
340  {
341  return;
342  }
343 
344  const OutputImageType * referenceImage = this->GetReferenceImage();
345 
346  // Set the size of the output region
347  if( m_UseReferenceImage && referenceImage )
348  {
349  outputPtr->SetLargestPossibleRegion( referenceImage->GetLargestPossibleRegion() );
350  }
351  else
352  {
353  typename TOutputImage::RegionType outputLargestPossibleRegion;
354  outputLargestPossibleRegion.SetSize( m_Size );
355  outputLargestPossibleRegion.SetIndex( m_OutputStartIndex );
356  outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );
357  }
358 
359  // Set spacing and origin
360  if (m_UseReferenceImage && referenceImage)
361  {
362  outputPtr->SetOrigin( referenceImage->GetOrigin() );
363  outputPtr->SetSpacing( referenceImage->GetSpacing() );
364  outputPtr->SetDirection( referenceImage->GetDirection() );
365  }
366  else
367  {
368  outputPtr->SetOrigin( m_OutputOrigin );
369  outputPtr->SetSpacing( m_OutputSpacing );
370  outputPtr->SetDirection( m_OutputDirection );
371  }
372  return;
373 }
374 
378 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
379 itk::ModifiedTimeType
381 ::GetMTime() const
382 {
383  itk::ModifiedTimeType latestTime = itk::Object::GetMTime();
384 
385  if( m_Transform )
386  {
387  if( latestTime < m_Transform->GetMTime() )
388  {
389  latestTime = m_Transform->GetMTime();
390  }
391  }
392 
393  if( m_Interpolator )
394  {
395  if( latestTime < m_Interpolator->GetMTime() )
396  {
397  latestTime = m_Interpolator->GetMTime();
398  }
399  }
400 
401  return latestTime;
402 }
403 
404 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
405 double
408 {
409  vnl_matrix_fixed <double,ImageDimension,ImageDimension> jacMatrix;
410  const MatrixTransformType *matrixTrsf = dynamic_cast <const MatrixTransformType *> (m_Transform.GetPointer());
411 
412  for (unsigned int i = 0;i < ImageDimension;++i)
413  for (unsigned int j = 0;j < ImageDimension;++j)
414  jacMatrix(i,j) = matrixTrsf->GetMatrix()(i,j);
415 
416  double jacValue = vnl_det(jacMatrix);
417  if (jacValue < 0)
418  jacValue = 0;
419 
420  return jacValue;
421 }
422 
423 template <class TInputImage, class TOutputImage, class TInterpolatorPrecisionType>
424 double
427 {
428  InputIndexType startIndDef, endIndDef;
429  startIndDef = this->GetOutput()->GetLargestPossibleRegion().GetIndex();
430  endIndDef = startIndDef + this->GetOutput()->GetLargestPossibleRegion().GetSize();
431 
432  vnl_matrix_fixed <double,ImageDimension,ImageDimension> jacMatrix;
433 
434  vnl_matrix_fixed <double,ImageDimension,ImageDimension> deltaMatrix;
435  deltaMatrix.fill(0);
436  InputIndexType posBef, posAfter;
437  PointType tmpPosBef, tmpPosAfter;
438 
439  vnl_matrix_fixed <double,ImageDimension,ImageDimension> resDiff;
440  resDiff.fill(0);
441  OutputImagePointer outputPtr = this->GetOutput();
442 
443  PointType tmpPos;
444 
445  for (unsigned int i = 0;i < ImageDimension;++i)
446  {
447  posBef = index;
448  posBef[i]--;
449 
450  if (posBef[i] < startIndDef[i])
451  posBef[i] = startIndDef[i];
452 
453  outputPtr->TransformIndexToPhysicalPoint(posBef,tmpPosBef);
454 
455  posAfter = index;
456  posAfter[i]++;
457 
458  if (posAfter[i] >= endIndDef[i])
459  posAfter[i] = endIndDef[i] - 1;
460 
461  outputPtr->TransformIndexToPhysicalPoint(posAfter,tmpPosAfter);
462 
463  if (posAfter[i] == posBef[i])
464  {
465  deltaMatrix(i,i) = 1;
466  continue;
467  }
468 
469  for (unsigned int j = 0;j < ImageDimension;++j)
470  deltaMatrix(i,j) = tmpPosAfter[j] - tmpPosBef[j];
471 
472  tmpPos = m_Transform->TransformPoint(tmpPosAfter);
473  for (unsigned int j = 0;j < ImageDimension;++j)
474  resDiff(i,j) = tmpPos[j];
475 
476  tmpPos = m_Transform->TransformPoint(tmpPosBef);
477  for (unsigned int j = 0;j < ImageDimension;++j)
478  resDiff(i,j) -= tmpPos[j];
479  }
480 
481  vnl_matrix_inverse <double> invDeltaMatrix(deltaMatrix.as_matrix());
482  deltaMatrix = invDeltaMatrix.inverse();
483 
484  for (unsigned int i = 0;i < ImageDimension;++i)
485  {
486  for (unsigned int j = 0;j < ImageDimension;++j)
487  {
488  jacMatrix(j,i) = 0;
489  for (unsigned int k = 0;k < ImageDimension;++k)
490  jacMatrix(j,i) += deltaMatrix(i,k)*resDiff(k,j);
491  }
492  }
493 
494  if (startIndDef[2] == (endIndDef[2]-1))
495  jacMatrix(2,2) = 1;
496 
497  double jacValue = vnl_det(jacMatrix);
498  if (jacValue < 0)
499  jacValue = 0;
500 
501  return jacValue;
502 }
503 
504 } // end namespace anima
InputImageType::ConstPointer InputImageConstPointer
InterpolatorType::PointType PointType
virtual void AfterThreadedGenerateData() ITK_OVERRIDE
InputImageType::Pointer InputImagePointer
TOutputImage::PointType OriginPointType
itk::ImageBase< itkGetStaticConstMacro(ImageDimension)> ImageBaseType
const TOutputImage * GetReferenceImage() const
InputImageType::RegionType InputImageRegionType
virtual void BeforeThreadedGenerateData() ITK_OVERRIDE
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) ITK_OVERRIDE
OutputImageType::Pointer OutputImagePointer
virtual void SetOutputSpacing(SpacingType _arg)
void PrintSelf(std::ostream &os, itk::Indent indent) const ITK_OVERRIDE
virtual itk::LightObject::Pointer InternalClone() const ITK_OVERRIDE
TOutputImage::PixelType PixelType
TOutputImage::SpacingType SpacingType
TOutputImage::RegionType OutputImageRegionType
void SetScaleIntensitiesWithJacobian(bool scale)
void SetReferenceImage(const TOutputImage *image)
itk::MatrixOffsetTransformBase< TInterpolatorPrecisionType, itkGetStaticConstMacro(ImageDimension), itkGetStaticConstMacro(ImageDimension)> MatrixTransformType
itk::Transform< TInterpolatorPrecisionType, itkGetStaticConstMacro(ImageDimension), itkGetStaticConstMacro(ImageDimension)> TransformType
virtual void GenerateOutputInformation() ITK_OVERRIDE
virtual void GenerateInputRequestedRegion() ITK_OVERRIDE
void SetTransform(TransformType *transform)
itk::ModifiedTimeType GetMTime() const ITK_OVERRIDE
double ComputeLocalJacobianValue(const InputIndexType &index)
InputImageType::IndexType InputIndexType
void SetOutputParametersFromImage(const ImageBaseType *image)
virtual void SetOutputOrigin(OriginPointType _arg)