Orfeo Toolbox  3.16
itkBSplineDeformableTransform.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkBSplineDeformableTransform.txx,v $
5  Language: C++
6  Date: $Date: 2010-03-05 18:38:59 $
7  Version: $Revision: 1.49 $
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 __itkBSplineDeformableTransform_txx
18 #define __itkBSplineDeformableTransform_txx
19 
21 #include "itkContinuousIndex.h"
22 #include "itkImageRegionIterator.h"
25 #include "itkIdentityTransform.h"
26 
27 namespace itk
28 {
29 
30 // Constructor with default arguments
31 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
34 {
35 
36  // Instantiate a weights function
37  m_WeightsFunction = WeightsFunctionType::New();
38  m_SupportSize = m_WeightsFunction->GetSupportSize();
39 
40  // Instantiate an identity transform
41  typedef IdentityTransform<ScalarType, SpaceDimension> IdentityTransformType;
42  typename IdentityTransformType::Pointer id = IdentityTransformType::New();
43  m_BulkTransform = id;
44 
45  // Default grid size is zero
46  typename RegionType::SizeType size;
47  typename RegionType::IndexType index;
48  size.Fill( 0 );
49  index.Fill( 0 );
50  m_GridRegion.SetSize( size );
51  m_GridRegion.SetIndex( index );
52 
53  m_GridOrigin.Fill( 0.0 ); // default origin is all zeros
54  m_GridSpacing.Fill( 1.0 ); // default spacing is all ones
55  m_GridDirection.SetIdentity(); // default spacing is all ones
56 
57  m_InternalParametersBuffer = ParametersType(0);
58  // Make sure the parameters pointer is not NULL after construction.
59  m_InputParametersPointer = &m_InternalParametersBuffer;
60 
61  // Initialize coeffient images
62  for ( unsigned int j = 0; j < SpaceDimension; j++ )
63  {
64  m_WrappedImage[j] = ImageType::New();
65  m_WrappedImage[j]->SetRegions( m_GridRegion );
66  m_WrappedImage[j]->SetOrigin( m_GridOrigin.GetDataPointer() );
67  m_WrappedImage[j]->SetSpacing( m_GridSpacing.GetDataPointer() );
68  m_WrappedImage[j]->SetDirection( m_GridDirection );
69  m_CoefficientImage[j] = NULL;
70  }
71 
72  // Setup variables for computing interpolation
73  m_Offset = SplineOrder / 2;
74  if ( SplineOrder % 2 )
75  {
76  m_SplineOrderOdd = true;
77  }
78  else
79  {
80  m_SplineOrderOdd = false;
81  }
82  m_ValidRegion = m_GridRegion;
83 
84  // Initialize jacobian images
85  for ( unsigned int j = 0; j < SpaceDimension; j++ )
86  {
87  m_JacobianImage[j] = ImageType::New();
88  m_JacobianImage[j]->SetRegions( m_GridRegion );
89  m_JacobianImage[j]->SetOrigin( m_GridOrigin.GetDataPointer() );
90  m_JacobianImage[j]->SetSpacing( m_GridSpacing.GetDataPointer() );
91  m_JacobianImage[j]->SetDirection( m_GridDirection );
92  }
93 
101  this->m_FixedParameters.SetSize ( NDimensions * (NDimensions + 3) );
102  this->m_FixedParameters.Fill ( 0.0 );
103  for (unsigned int i=0; i<NDimensions; i++)
104  {
105  this->m_FixedParameters[2*NDimensions+i] = m_GridSpacing[i];
106  }
107  for (unsigned int di=0; di<NDimensions; di++)
108  {
109  for (unsigned int dj=0; dj<NDimensions; dj++)
110  {
111  this->m_FixedParameters[3*NDimensions+(di*NDimensions+dj)] = m_GridDirection[di][dj];
112  }
113  }
114 
115  DirectionType scale;
116  for( unsigned int i=0; i<SpaceDimension; i++)
117  {
118  scale[i][i] = m_GridSpacing[i];
119  }
120 
121  m_IndexToPoint = m_GridDirection * scale;
122  m_PointToIndex = m_IndexToPoint.GetInverse();
123 
124 
125  m_LastJacobianIndex = m_ValidRegion.GetIndex();
126 
127 }
128 
129 
130 // Destructor
131 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
134 {
135 
136 }
137 
138 
139 // Explicit New() method, used here because we need to split the itkNewMacro()
140 // in order to overload the CreateAnother() method.
141 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
144 ::New(void)
145 {
147  if(smartPtr.IsNull())
148  {
149  smartPtr = static_cast<Pointer>(new Self);
150  }
151  smartPtr->UnRegister();
152  return smartPtr;
153 }
154 
155 
156 // Explicit New() method, used here because we need to split the itkNewMacro()
157 // in order to overload the CreateAnother() method.
158 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
161 ::CreateAnother(void) const
162 {
164  Pointer copyPtr = Self::New().GetPointer();
165 
166  copyPtr->m_BulkTransform = this->GetBulkTransform();
167 
168  smartPtr = static_cast<Pointer>(copyPtr);
169 
170  return smartPtr;
171 }
172 
173 // Get the number of parameters
174 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
175 unsigned int
178 {
179 
180  // The number of parameters equal SpaceDimension * number of
181  // of pixels in the grid region.
182  return ( static_cast<unsigned int>( SpaceDimension ) *
183  static_cast<unsigned int>( m_GridRegion.GetNumberOfPixels() ) );
184 
185 }
186 
187 
188 // Get the number of parameters per dimension
189 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
190 unsigned int
193 {
194  // The number of parameters per dimension equal number of
195  // of pixels in the grid region.
196  return ( static_cast<unsigned int>( m_GridRegion.GetNumberOfPixels() ) );
197 
198 }
199 
200 
201 // Set the grid region
202 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
203 void
205 ::SetGridRegion( const RegionType& region )
206 {
207  if ( m_GridRegion != region )
208  {
209 
210  m_GridRegion = region;
211 
212  // set regions for each coefficient and jacobian image
213  for ( unsigned int j = 0; j < SpaceDimension; j++ )
214  {
215  m_WrappedImage[j]->SetRegions( m_GridRegion );
216  m_JacobianImage[j]->SetRegions( m_GridRegion );
217  }
218 
219  // Set the valid region
220  // If the grid spans the interval [start, last].
221  // The valid interval for evaluation is [start+offset, last-offset]
222  // when spline order is even.
223  // The valid interval for evaluation is [start+offset, last-offset)
224  // when spline order is odd.
225  // Where offset = floor(spline / 2 ).
226  // Note that the last pixel is not included in the valid region
227  // with odd spline orders.
228  typename RegionType::SizeType size = m_GridRegion.GetSize();
229  typename RegionType::IndexType index = m_GridRegion.GetIndex();
230  for ( unsigned int j = 0; j < SpaceDimension; j++ )
231  {
232  index[j] += static_cast< typename RegionType::IndexValueType >( m_Offset );
233  size[j] -= static_cast< typename RegionType::SizeValueType> ( 2 * m_Offset );
234  m_ValidRegionFirst[j] = index[j];
235  m_ValidRegionLast[j] = index[j] + static_cast< typename RegionType::IndexValueType >( size[j] ) - 1;
236  }
237  m_ValidRegion.SetSize( size );
238  m_ValidRegion.SetIndex( index );
239 
240  //
241  // If we are using the default parameters, update their size and set to identity.
242  //
243 
244  // Input parameters point to internal buffer => using default parameters.
245  if (m_InputParametersPointer == &m_InternalParametersBuffer)
246  {
247  // Check if we need to resize the default parameter buffer.
248  if ( m_InternalParametersBuffer.GetSize() != this->GetNumberOfParameters() )
249  {
250  m_InternalParametersBuffer.SetSize( this->GetNumberOfParameters() );
251  // Fill with zeros for identity.
252  m_InternalParametersBuffer.Fill( 0 );
253  }
254  }
255 
256  this->Modified();
257  }
258 }
259 
260 
261 // Set the grid spacing
262 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
263 void
265 ::SetGridSpacing( const SpacingType& spacing )
266 {
267  if ( m_GridSpacing != spacing )
268  {
269  m_GridSpacing = spacing;
270 
271  // set spacing for each coefficient and jacobian image
272  for ( unsigned int j = 0; j < SpaceDimension; j++ )
273  {
274  m_WrappedImage[j]->SetSpacing( m_GridSpacing.GetDataPointer() );
275  m_JacobianImage[j]->SetSpacing( m_GridSpacing.GetDataPointer() );
276  }
277 
278  DirectionType scale;
279  for( unsigned int i=0; i<SpaceDimension; i++)
280  {
281  scale[i][i] = m_GridSpacing[i];
282  }
283 
284  m_IndexToPoint = m_GridDirection * scale;
285  m_PointToIndex = m_IndexToPoint.GetInverse();
286 
287  this->Modified();
288  }
289 
290 }
291 
292 // Set the grid direction
293 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
294 void
296 ::SetGridDirection( const DirectionType & direction )
297 {
298  if ( m_GridDirection != direction )
299  {
300  m_GridDirection = direction;
301 
302  // set direction for each coefficient and jacobian image
303  for ( unsigned int j = 0; j < SpaceDimension; j++ )
304  {
305  m_WrappedImage[j]->SetDirection( m_GridDirection );
306  m_JacobianImage[j]->SetDirection( m_GridDirection );
307  }
308 
309  DirectionType scale;
310  for( unsigned int i=0; i<SpaceDimension; i++)
311  {
312  scale[i][i] = m_GridSpacing[i];
313  }
314 
315  m_IndexToPoint = m_GridDirection * scale;
316  m_PointToIndex = m_IndexToPoint.GetInverse();
317 
318  this->Modified();
319  }
320 
321 }
322 
323 
324 // Set the grid origin
325 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
326 void
328 ::SetGridOrigin( const OriginType& origin )
329 {
330  if ( m_GridOrigin != origin )
331  {
332  m_GridOrigin = origin;
333 
334  // set spacing for each coefficient and jacobianimage
335  for ( unsigned int j = 0; j < SpaceDimension; j++ )
336  {
337  m_WrappedImage[j]->SetOrigin( m_GridOrigin.GetDataPointer() );
338  m_JacobianImage[j]->SetOrigin( m_GridOrigin.GetDataPointer() );
339  }
340 
341  this->Modified();
342  }
343 
344 }
345 
346 
347 // Set the parameters
348 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
349 void
352 {
353  if( m_InputParametersPointer )
354  {
355  ParametersType * parameters =
356  const_cast<ParametersType *>( m_InputParametersPointer );
357  parameters->Fill( 0.0 );
358  this->Modified();
359  }
360  else
361  {
362  itkExceptionMacro( << "Input parameters for the spline haven't been set ! "
363  << "Set them using the SetParameters or SetCoefficientImage method first." );
364  }
365 }
366 
367 // Set the parameters
368 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
369 void
371 ::SetParameters( const ParametersType & parameters )
372 {
373 
374  // check if the number of parameters match the
375  // expected number of parameters
376  if ( parameters.Size() != this->GetNumberOfParameters() )
377  {
378  itkExceptionMacro(<<"Mismatch between parameters size "
379  << parameters.Size()
380  << " and expected number of parameters "
381  << this->GetNumberOfParameters()
382  << (m_GridRegion.GetNumberOfPixels() == 0 ?
383  ". \nSince the size of the grid region is 0, perhaps you forgot to SetGridRegion or SetFixedParameters before setting the Parameters." : ""));
384  }
385 
386  // Clean up buffered parameters
387  m_InternalParametersBuffer = ParametersType( 0 );
388 
389  // Keep a reference to the input parameters
390  m_InputParametersPointer = &parameters;
391 
392  // Wrap flat array as images of coefficients
393  this->WrapAsImages();
394 
395  // Modified is always called since we just have a pointer to the
396  // parameters and cannot know if the parameters have changed.
397  this->Modified();
398 }
399 
400 // Set the Fixed Parameters
401 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
402 void
404 ::SetFixedParameters( const ParametersType & passedParameters )
405 {
406 
407  ParametersType parameters( NDimensions * (3 + NDimensions) );
408 
409  // check if the number of parameters match the
410  // expected number of parameters
411  if ( passedParameters.Size() == NDimensions * 3 )
412  {
413  parameters.Fill( 0.0 );
414  for(unsigned int i=0; i<3 * NDimensions; i++)
415  {
416  parameters[i] = passedParameters[i];
417  }
418  for (unsigned int di=0; di<NDimensions; di++)
419  {
420  parameters[3*NDimensions+(di*NDimensions+di)] = 1;
421  }
422  }
423  else if ( passedParameters.Size() != NDimensions * (3 + NDimensions) )
424  {
425  itkExceptionMacro(<< "Mismatched between parameters size "
426  << passedParameters.size()
427  << " and number of fixed parameters "
428  << NDimensions * (3 + NDimensions) );
429  }
430  else
431  {
432  for(unsigned int i=0; i<NDimensions * (3 + NDimensions); i++)
433  {
434  parameters[i] = passedParameters[i];
435  }
436  }
437 
438  /*********************************************************
439  Fixed Parameters store the following information:
440  Grid Size
441  Grid Origin
442  Grid Spacing
443  Grid Direction
444  The size of these is equal to the NInputDimensions
445  *********************************************************/
446 
448  SizeType gridSize;
449  for (unsigned int i=0; i<NDimensions; i++)
450  {
451  gridSize[i] = static_cast<int> (parameters[i]);
452  }
453  RegionType bsplineRegion;
454  bsplineRegion.SetSize( gridSize );
455 
457  OriginType origin;
458  for (unsigned int i=0; i<NDimensions; i++)
459  {
460  origin[i] = parameters[NDimensions+i];
461  }
462 
464  SpacingType spacing;
465  for (unsigned int i=0; i<NDimensions; i++)
466  {
467  spacing[i] = parameters[2*NDimensions+i];
468  }
469 
471  DirectionType direction;
472  for (unsigned int di=0; di<NDimensions; di++)
473  {
474  for (unsigned int dj=0; dj<NDimensions; dj++)
475  {
476  direction[di][dj] = parameters[3*NDimensions+(di*NDimensions+dj)];
477  }
478  }
479 
480 
481  this->SetGridSpacing( spacing );
482  this->SetGridDirection( direction );
483  this->SetGridOrigin( origin );
484  this->SetGridRegion( bsplineRegion );
485 
486  this->Modified();
487 }
488 
489 
490 // Wrap flat parameters as images
491 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
492 void
495 {
496 
502  PixelType * dataPointer =
503  const_cast<PixelType *>(( m_InputParametersPointer->data_block() ));
504  unsigned int numberOfPixels = m_GridRegion.GetNumberOfPixels();
505 
506  for ( unsigned int j = 0; j < SpaceDimension; j++ )
507  {
508  m_WrappedImage[j]->GetPixelContainer()->
509  SetImportPointer( dataPointer, numberOfPixels );
510  dataPointer += numberOfPixels;
511  m_CoefficientImage[j] = m_WrappedImage[j];
512  }
513 
518  this->m_Jacobian.set_size( SpaceDimension, this->GetNumberOfParameters() );
519  this->m_Jacobian.Fill( NumericTraits<JacobianPixelType>::Zero );
520  m_LastJacobianIndex = m_ValidRegion.GetIndex();
521  JacobianPixelType * jacobianDataPointer = this->m_Jacobian.data_block();
522 
523  for ( unsigned int j = 0; j < SpaceDimension; j++ )
524  {
525  m_JacobianImage[j]->GetPixelContainer()->
526  SetImportPointer( jacobianDataPointer, numberOfPixels );
527  jacobianDataPointer += this->GetNumberOfParameters() + numberOfPixels;
528  }
529 }
530 
531 
532 // Set the parameters by value
533 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
534 void
537 {
538 
539  // check if the number of parameters match the
540  // expected number of parameters
541  if ( parameters.Size() != this->GetNumberOfParameters() )
542  {
543  itkExceptionMacro(<<"Mismatched between parameters size "
544  << parameters.size()
545  << " and region size "
546  << m_GridRegion.GetNumberOfPixels() );
547  }
548 
549  // copy it
550  m_InternalParametersBuffer = parameters;
551  m_InputParametersPointer = &m_InternalParametersBuffer;
552 
553  // wrap flat array as images of coefficients
554  this->WrapAsImages();
555 
556  // Modified is always called since we just have a pointer to the
557  // parameters and cannot know if the parameters have changed.
558  this->Modified();
559 
560 }
561 
562 // Get the parameters
563 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
564 const
566 ::ParametersType &
568 ::GetParameters( void ) const
569 {
573  if (NULL == m_InputParametersPointer)
574  {
575  itkExceptionMacro( <<"Cannot GetParameters() because m_InputParametersPointer is NULL. Perhaps SetCoefficientImage() has been called causing the NULL pointer." );
576  }
577 
578  return (*m_InputParametersPointer);
579 }
580 
581 
582 // Get the parameters
583 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
584 const
586 ::ParametersType &
588 ::GetFixedParameters( void ) const
589 {
590  RegionType resRegion = this->GetGridRegion( );
591 
592  for (unsigned int i=0; i<NDimensions; i++)
593  {
594  this->m_FixedParameters[i] = (resRegion.GetSize())[i];
595  }
596  for (unsigned int i=0; i<NDimensions; i++)
597  {
598  this->m_FixedParameters[NDimensions+i] = (this->GetGridOrigin())[i];
599  }
600  for (unsigned int i=0; i<NDimensions; i++)
601  {
602  this->m_FixedParameters[2*NDimensions+i] = (this->GetGridSpacing())[i];
603  }
604  for (unsigned int di=0; di<NDimensions; di++)
605  {
606  for (unsigned int dj=0; dj<NDimensions; dj++)
607  {
608  this->m_FixedParameters[3*NDimensions+(di*NDimensions+dj)] = (this->GetGridDirection())[di][dj];
609  }
610  }
611 
612  return (this->m_FixedParameters);
613 }
614 
615 
616 // Set the B-Spline coefficients using input images
617 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
618 void
621 {
622  if ( images[0] )
623  {
624  this->SetGridRegion( images[0]->GetBufferedRegion() );
625  this->SetGridOrigin( images[0]->GetOrigin() );
626  this->SetGridSpacing( images[0]->GetSpacing() );
627  this->SetGridDirection( images[0]->GetDirection() );
628 
629  for( unsigned int j = 0; j < SpaceDimension; j++ )
630  {
631  m_CoefficientImage[j] = images[j];
632  }
633 
634  // Clean up buffered parameters
635  m_InternalParametersBuffer = ParametersType( 0 );
636  m_InputParametersPointer = NULL;
637 
638  }
639 
640 }
641 
642 // Print self
643 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
644 void
646 ::PrintSelf(std::ostream &os, Indent indent) const
647 {
648 
649  unsigned int j;
650 
651  this->Superclass::PrintSelf(os, indent);
652 
653  os << indent << "GridRegion: " << m_GridRegion << std::endl;
654  os << indent << "GridOrigin: " << m_GridOrigin << std::endl;
655  os << indent << "GridSpacing: " << m_GridSpacing << std::endl;
656  os << indent << "GridDirection: " << m_GridDirection << std::endl;
657  os << indent << "IndexToPoint: " << m_IndexToPoint << std::endl;
658  os << indent << "PointToIndex: " << m_PointToIndex << std::endl;
659 
660  os << indent << "CoefficientImage: [ ";
661  for ( j = 0; j < SpaceDimension - 1; j++ )
662  {
663  os << m_CoefficientImage[j].GetPointer() << ", ";
664  }
665  os << m_CoefficientImage[j].GetPointer() << " ]" << std::endl;
666 
667  os << indent << "WrappedImage: [ ";
668  for ( j = 0; j < SpaceDimension - 1; j++ )
669  {
670  os << m_WrappedImage[j].GetPointer() << ", ";
671  }
672  os << m_WrappedImage[j].GetPointer() << " ]" << std::endl;
673 
674  os << indent << "InputParametersPointer: "
675  << m_InputParametersPointer << std::endl;
676  os << indent << "ValidRegion: " << m_ValidRegion << std::endl;
677  os << indent << "LastJacobianIndex: " << m_LastJacobianIndex << std::endl;
678  os << indent << "BulkTransform: ";
679  os << m_BulkTransform.GetPointer() << std::endl;
680  os << indent << "WeightsFunction: ";
681  os << m_WeightsFunction.GetPointer() << std::endl;
682 
683  if ( m_BulkTransform )
684  {
685  os << indent << "BulkTransformType: "
686  << m_BulkTransform->GetNameOfClass() << std::endl;
687  }
688 
689 }
690 
691 // Transform a point
692 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
693 bool
696  const ContinuousIndexType& index ) const
697 {
698  bool inside = true;
699 
700 #ifndef ITK_USE_CENTERED_PIXEL_COORDINATES_CONSISTENTLY
701  if( !m_ValidRegion.IsInside( index ) )
702  {
703  inside = false;
704  }
705 #endif
706 
707  if ( inside && m_SplineOrderOdd )
708  {
709  typedef typename ContinuousIndexType::ValueType ValueType;
710  for( unsigned int j = 0; j < SpaceDimension; j++ )
711  {
712  if ( index[j] >= static_cast<ValueType>( m_ValidRegionLast[j] ) )
713  {
714  inside = false;
715  break;
716  }
717 #ifdef ITK_USE_CENTERED_PIXEL_COORDINATES_CONSISTENTLY
718  if ( index[j] < static_cast<ValueType>( m_ValidRegionFirst[j] ) )
719  {
720  inside = false;
721  break;
722  }
723 #endif
724  }
725  }
726 
727  return inside;
728 }
729 
730 // Transform a point
731 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
732 void
735  const InputPointType & point,
736  OutputPointType & outputPoint,
737  WeightsType & weights,
738  ParameterIndexArrayType & indices,
739  bool& inside ) const
740 {
741  unsigned int j;
742  IndexType supportIndex;
743 
744  inside = true;
745 
746  InputPointType transformedPoint;
747  if ( m_BulkTransform )
748  {
749  transformedPoint = m_BulkTransform->TransformPoint( point );
750  }
751  else
752  {
753  transformedPoint = point;
754  }
755 
756  if ( m_CoefficientImage[0] )
757  {
758  ContinuousIndexType index;
759 
760  this->TransformPointToContinuousIndex( point, index );
761 
762  // NOTE: if the support region does not lie totally within the grid
763  // we assume zero displacement and return the input point
764  inside = this->InsideValidRegion( index );
765  if ( !inside )
766  {
767  outputPoint = transformedPoint;
768  return;
769  }
770 
771  // Compute interpolation weights
772  m_WeightsFunction->Evaluate( index, weights, supportIndex );
773 
774  // For each dimension, correlate coefficient with weights
775  RegionType supportRegion;
776  supportRegion.SetSize( m_SupportSize );
777  supportRegion.SetIndex( supportIndex );
778 
779  outputPoint.Fill( NumericTraits<ScalarType>::Zero );
780 
781  typedef ImageRegionConstIterator<ImageType> IteratorType;
782  IteratorType m_Iterator[ SpaceDimension ];
783  unsigned long counter = 0;
784  const PixelType * basePointer = m_CoefficientImage[0]->GetBufferPointer();
785 
786  for ( j = 0; j < SpaceDimension; j++ )
787  {
788  m_Iterator[j] = IteratorType( m_CoefficientImage[j], supportRegion );
789  }
790 
791  while ( ! m_Iterator[0].IsAtEnd() )
792  {
793 
794  // multiply weigth with coefficient
795  for ( j = 0; j < SpaceDimension; j++ )
796  {
797  outputPoint[j] += static_cast<ScalarType>(
798  weights[counter] * m_Iterator[j].Get());
799  }
800 
801  // populate the indices array
802  indices[counter] = &(m_Iterator[0].Value()) - basePointer;
803 
804  // go to next coefficient in the support region
805  ++ counter;
806  for ( j = 0; j < SpaceDimension; j++ )
807  {
808  ++( m_Iterator[j] );
809  }
810  }
811 
812  // return results
813  for ( j = 0; j < SpaceDimension; j++ )
814  {
815  outputPoint[j] += transformedPoint[j];
816  }
817 
818  }
819  else
820  {
821 
822  itkWarningMacro( << "B-spline coefficients have not been set" );
823 
824  for ( j = 0; j < SpaceDimension; j++ )
825  {
826  outputPoint[j] = transformedPoint[j];
827  }
828 
829  }
830 
831 }
832 
833 // Transform a point
834 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
836 ::OutputPointType
838 ::TransformPoint(const InputPointType &point) const
839 {
840 
841  WeightsType weights( m_WeightsFunction->GetNumberOfWeights() );
842  ParameterIndexArrayType indices( m_WeightsFunction->GetNumberOfWeights() );
843  OutputPointType outputPoint;
844  bool inside;
845 
846  this->TransformPoint( point, outputPoint, weights, indices, inside );
847 
848  return outputPoint;
849 
850 }
851 
852 
853 // Compute the Jacobian in one position
854 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
855 const
857 ::JacobianType &
859 ::GetJacobian( const InputPointType & point ) const
860 {
861  // Can only compute Jacobian if parameters are set via
862  // SetParameters or SetParametersByValue
863  if( m_InputParametersPointer == NULL )
864  {
865  itkExceptionMacro( <<"Cannot compute Jacobian: parameters not set" );
866  }
867 
868  // Zero all components of jacobian
869  // NOTE: for efficiency, we only need to zero out the coefficients
870  // that got fill last time this method was called.
871  RegionType supportRegion;
872  supportRegion.SetSize( m_SupportSize );
873  supportRegion.SetIndex( m_LastJacobianIndex );
874 
875  typedef ImageRegionIterator<JacobianImageType> IteratorType;
876  IteratorType m_Iterator[ SpaceDimension ];
877  unsigned int j;
878 
879  for ( j = 0; j < SpaceDimension; j++ )
880  {
881  m_Iterator[j] = IteratorType( m_JacobianImage[j], supportRegion );
882  }
883 
884  while ( ! m_Iterator[0].IsAtEnd() )
885  {
886 
887  // zero out jacobian elements
888  for ( j = 0; j < SpaceDimension; j++ )
889  {
890  m_Iterator[j].Set( NumericTraits<JacobianPixelType>::Zero );
891  }
892 
893  for ( j = 0; j < SpaceDimension; j++ )
894  {
895  ++( m_Iterator[j] );
896  }
897  }
898 
899 
900  ContinuousIndexType index;
901 
902  this->TransformPointToContinuousIndex( point, index );
903 
904  // NOTE: if the support region does not lie totally within the grid
905  // we assume zero displacement and return the input point
906  if ( !this->InsideValidRegion( index ) )
907  {
908  return this->m_Jacobian;
909  }
910 
911  // Compute interpolation weights
912  WeightsType weights( m_WeightsFunction->GetNumberOfWeights() );
913  IndexType supportIndex;
914 
915  m_WeightsFunction->Evaluate( index, weights, supportIndex );
916  m_LastJacobianIndex = supportIndex;
917 
918  // For each dimension, copy the weight to the support region
919  supportRegion.SetIndex( supportIndex );
920  unsigned long counter = 0;
921 
922  for ( j = 0; j < SpaceDimension; j++ )
923  {
924  m_Iterator[j] = IteratorType( m_JacobianImage[j], supportRegion );
925  }
926 
927  while ( ! m_Iterator[0].IsAtEnd() )
928  {
929 
930  // copy weight to jacobian image
931  for ( j = 0; j < SpaceDimension; j++ )
932  {
933  m_Iterator[j].Set( static_cast<JacobianPixelType>( weights[counter] ) );
934  }
935 
936  // go to next coefficient in the support region
937  ++ counter;
938  for ( j = 0; j < SpaceDimension; j++ )
939  {
940  ++( m_Iterator[j] );
941  }
942  }
943 
944 
945  // Return the results
946  return this->m_Jacobian;
947 
948 }
949 
950 
951 // Compute the Jacobian in one position
952 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
953 void
955 ::GetJacobian( const InputPointType & point, WeightsType& weights, ParameterIndexArrayType& indexes) const
956 {
957 
958  RegionType supportRegion;
959  supportRegion.SetSize( m_SupportSize );
960  const PixelType * basePointer = m_CoefficientImage[0]->GetBufferPointer();
961 
962  ContinuousIndexType index;
963 
964  this->TransformPointToContinuousIndex( point, index );
965 
966  // NOTE: if the support region does not lie totally within the grid
967  // we assume zero displacement and return the input point
968  if ( !this->InsideValidRegion( index ) )
969  {
970  weights.Fill(0.0);
971  indexes.Fill(0);
972  return;
973  }
974 
975  // Compute interpolation weights
976  IndexType supportIndex;
977 
978  m_WeightsFunction->Evaluate( index, weights, supportIndex );
979 
980  // For each dimension, copy the weight to the support region
981  supportRegion.SetIndex( supportIndex );
982  unsigned long counter = 0;
983 
984  typedef ImageRegionIterator<JacobianImageType> IteratorType;
985 
986  IteratorType m_Iterator = IteratorType( m_CoefficientImage[0], supportRegion );
987 
988 
989  while ( ! m_Iterator.IsAtEnd() )
990  {
991 
992 
993  indexes[counter] = &(m_Iterator.Value()) - basePointer;
994 
995  // go to next coefficient in the support region
996  ++ counter;
997  ++m_Iterator;
998 
999  }
1000 
1001 }
1002 
1003 
1004 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
1005 void
1008 {
1009  unsigned int j;
1010 
1012 
1013  for ( j = 0; j < SpaceDimension; j++ )
1014  {
1015  tvector[j] = point[j] - this->m_GridOrigin[j];
1016  }
1017 
1019 
1020  cvector = m_PointToIndex * tvector;
1021 
1022  for ( j = 0; j < SpaceDimension; j++ )
1023  {
1024  index[j] = static_cast< typename ContinuousIndexType::CoordRepType >( cvector[j] );
1025  }
1026 }
1027 
1028 
1029 template<class TScalarType, unsigned int NDimensions, unsigned int VSplineOrder>
1030 unsigned int
1033 {
1034  return m_WeightsFunction->GetNumberOfWeights();
1035 }
1036 
1037 } // namespace
1038 
1039 #endif

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