Orfeo Toolbox  3.16
itkOptImageToImageMetric.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkOptImageToImageMetric.txx,v $
5  Language: C++
6  Date: $Date: 2010-03-27 20:54:43 $
7  Version: $Revision: 1.40 $
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 __itkOptImageToImageMetric_txx
18 #define __itkOptImageToImageMetric_txx
19 
20 
24 
25 namespace itk
26 {
27 
31 template <class TFixedImage, class TMovingImage>
34 {
35  m_NumberOfFixedImageSamples = 50000;
36  m_UseAllPixels = false;
37  m_UseSequentialSampling = false;
38  m_UseFixedImageIndexes = false;
39  m_UseFixedImageSamplesIntensityThreshold = false;
40  m_FixedImageSamplesIntensityThreshold = 0;
41  m_ReseedIterator = false;
42  m_RandomSeed = -1;
43 
44  m_TransformIsBSpline = false;
45  m_NumBSplineWeights = 0;
46  m_BSplineTransform = NULL;
47 
48  m_Threader = MultiThreaderType::New();
49  m_ThreaderParameter.metric = this;
50  m_ThreaderNumberOfMovingImageSamples = NULL;
51  m_WithinThreadPreProcess = false;
52  m_WithinThreadPostProcess = false;
53 
54  m_FixedImage = 0; // has to be provided by the user.
55  m_FixedImageMask = 0;
56 
57  m_MovingImage = 0; // has to be provided by the user.
58  m_MovingImageMask = 0;
59  m_NumberOfPixelsCounted = 0;
60 
61  m_Transform = NULL; // has to be provided by the user.
62  m_ThreaderTransform = NULL; // constructed at initialization.
63 
64  m_Interpolator = 0; // has to be provided by the user.
65 
66  m_GradientImage = 0; // will receive the output of the filter;
67  m_ComputeGradient = true; // metric computes gradient by default
68  m_GradientImage = NULL; // computed at initialization
69 
70  m_InterpolatorIsBSpline = false;
71  m_BSplineInterpolator = NULL;
72  m_DerivativeCalculator = NULL;
73 
74  m_NumberOfThreads = m_Threader->GetNumberOfThreads();
75 
76  this->m_ThreaderBSplineTransformWeights = NULL;
77  this->m_ThreaderBSplineTransformIndices = NULL;
78 
79  this->m_UseCachingOfBSplineWeights = true;
80 
81  /* if 100% backward compatible, we should include this...but...
82  typename BSplineTransformType::Pointer transformer =
83  BSplineTransformType::New();
84  this->SetTransform (transformer);
85 
86  typename BSplineInterpolatorType::Pointer interpolator =
87  BSplineInterpolatorType::New();
88  this->SetInterpolator (interpolator);
89  */
90 }
91 
92 template <class TFixedImage, class TMovingImage>
95 {
96 
97  if(m_ThreaderNumberOfMovingImageSamples != NULL)
98  {
99  delete [] m_ThreaderNumberOfMovingImageSamples;
100  }
101  m_ThreaderNumberOfMovingImageSamples = NULL;
102 
103  if(m_ThreaderTransform != NULL)
104  {
105  delete [] m_ThreaderTransform;
106  }
107  m_ThreaderTransform = NULL;
108 
109  if( this->m_ThreaderBSplineTransformWeights != NULL )
110  {
111  delete [] this->m_ThreaderBSplineTransformWeights;
112  }
113  this->m_ThreaderBSplineTransformWeights = NULL;
114 
115  if( this->m_ThreaderBSplineTransformIndices != NULL )
116  {
117  delete [] this->m_ThreaderBSplineTransformIndices;
118  }
119  this->m_ThreaderBSplineTransformIndices = NULL;
120 }
121 
126 template <class TFixedImage, class TMovingImage>
127 void
129 ::SetNumberOfThreads( unsigned int numberOfThreads )
130 {
131  m_Threader->SetNumberOfThreads( numberOfThreads);
132  m_NumberOfThreads = m_Threader->GetNumberOfThreads();
133 }
134 
138 template <class TFixedImage, class TMovingImage>
139 void
141 ::SetTransformParameters( const ParametersType & parameters ) const
142 {
143  if( !m_Transform )
144  {
145  itkExceptionMacro(<<"Transform has not been assigned");
146  }
147  m_Transform->SetParameters( parameters );
148 
149  m_Parameters = parameters;
150 }
151 
152 template <class TFixedImage, class TMovingImage>
153 void
155 ::SetNumberOfFixedImageSamples( unsigned long numSamples )
156 {
157  if( numSamples != m_NumberOfFixedImageSamples )
158  {
159  m_NumberOfFixedImageSamples = numSamples;
160  if( m_NumberOfFixedImageSamples != this->m_FixedImageRegion.GetNumberOfPixels() )
161  {
162  this->SetUseAllPixels( false );
163  }
164  this->Modified();
165  }
166 }
167 
168 template <class TFixedImage, class TMovingImage>
169 void
172 {
173  this->SetUseFixedImageIndexes( true );
174  m_NumberOfFixedImageSamples = indexes.size();
175  m_FixedImageIndexes.resize( m_NumberOfFixedImageSamples );
176  for(unsigned int i=0; i<m_NumberOfFixedImageSamples; i++)
177  {
178  m_FixedImageIndexes[i] = indexes[i];
179  }
180 }
181 
182 template <class TFixedImage, class TMovingImage>
183 void
185 ::SetUseFixedImageIndexes( bool useIndexes )
186 {
187  if( useIndexes != m_UseFixedImageIndexes )
188  {
189  m_UseFixedImageIndexes = useIndexes;
190  if( m_UseFixedImageIndexes )
191  {
192  this->SetUseAllPixels( false );
193  }
194  else
195  {
196  this->Modified();
197  }
198  }
199 }
200 
201 template <class TFixedImage, class TMovingImage>
202 void
205 {
206  if( thresh != m_FixedImageSamplesIntensityThreshold )
207  {
208  m_FixedImageSamplesIntensityThreshold = thresh;
209  this->SetUseFixedImageSamplesIntensityThreshold( true );
210  this->Modified();
211  }
212 }
213 
214 template <class TFixedImage, class TMovingImage>
215 void
218 {
219  if( useThresh != m_UseFixedImageSamplesIntensityThreshold )
220  {
221  m_UseFixedImageSamplesIntensityThreshold = useThresh;
222  if( m_UseFixedImageSamplesIntensityThreshold )
223  {
224  this->SetUseAllPixels( false );
225  }
226  else
227  {
228  this->Modified();
229  }
230  }
231 }
232 
233 template <class TFixedImage, class TMovingImage>
234 void
237 {
238  if( reg != m_FixedImageRegion )
239  {
240  m_FixedImageRegion = reg;
241  if( this->GetUseAllPixels() )
242  {
243  this->SetNumberOfFixedImageSamples( this->m_FixedImageRegion.GetNumberOfPixels() );
244  }
245  }
246 }
247 
248 template <class TFixedImage, class TMovingImage>
249 void
251 ::SetUseAllPixels( bool useAllPixels )
252 {
253  if( useAllPixels != m_UseAllPixels )
254  {
255  m_UseAllPixels = useAllPixels;
256  if( m_UseAllPixels )
257  {
258  this->SetUseFixedImageSamplesIntensityThreshold( false );
259  this->SetNumberOfFixedImageSamples( this->m_FixedImageRegion.GetNumberOfPixels() );
260  this->SetUseSequentialSampling( true );
261  }
262  else
263  {
264  this->SetUseSequentialSampling( false );
265  this->Modified();
266  }
267  }
268 }
269 
270 
271 template <class TFixedImage, class TMovingImage>
272 void
274 ::SetUseSequentialSampling( bool useSequential )
275 {
276  if( useSequential != m_UseSequentialSampling )
277  {
278  m_UseSequentialSampling = useSequential;
279  if( !m_UseSequentialSampling )
280  {
281  this->SetUseAllPixels( false );
282  }
283  else
284  {
285  this->Modified();
286  }
287  }
288 }
289 
293 template <class TFixedImage, class TMovingImage>
294 void
296 ::Initialize(void) throw ( ExceptionObject )
297 {
298 
299  if( !m_Transform )
300  {
301  itkExceptionMacro(<<"Transform is not present");
302  }
303  m_NumberOfParameters = m_Transform->GetNumberOfParameters();
304 
305  if( !m_Interpolator )
306  {
307  itkExceptionMacro(<<"Interpolator is not present");
308  }
309 
310  if( !m_MovingImage )
311  {
312  itkExceptionMacro(<<"MovingImage is not present");
313  }
314 
315  if( !m_FixedImage )
316  {
317  itkExceptionMacro(<<"FixedImage is not present");
318  }
319 
320  if( m_FixedImageRegion.GetNumberOfPixels() == 0 )
321  {
322  itkExceptionMacro(<<"FixedImageRegion is empty");
323  }
324 
325  // If the image is provided by a source, update the source.
326  if( m_MovingImage->GetSource() )
327  {
328  m_MovingImage->GetSource()->Update();
329  }
330 
331  // If the image is provided by a source, update the source.
332  if( m_FixedImage->GetSource() )
333  {
334  m_FixedImage->GetSource()->Update();
335  }
336 
337  // Make sure the FixedImageRegion is within the FixedImage buffered region
338  if ( !m_FixedImageRegion.Crop( m_FixedImage->GetBufferedRegion() ) )
339  {
340  itkExceptionMacro(
341  <<"FixedImageRegion does not overlap the fixed image buffered region" );
342  }
343 
344  m_Interpolator->SetInputImage( m_MovingImage );
345 
346  if ( m_ComputeGradient )
347  {
348  ComputeGradient();
349  }
350 
351  // If there are any observers on the metric, call them to give the
352  // user code a chance to set parameters on the metric
353  this->InvokeEvent( InitializeEvent() );
354 
355 }
356 
357 
361 template <class TFixedImage, class TMovingImage>
362 void
364 ::MultiThreadingInitialize(void) throw ( ExceptionObject )
365 {
366 
367  m_Threader->SetNumberOfThreads( m_NumberOfThreads );
368 
369  if(m_ThreaderNumberOfMovingImageSamples != NULL)
370  {
371  delete [] m_ThreaderNumberOfMovingImageSamples;
372  }
373  m_ThreaderNumberOfMovingImageSamples = new unsigned int[m_NumberOfThreads-1];
374 
375  // Allocate the array of transform clones to be used in every thread
376  if(m_ThreaderTransform != NULL)
377  {
378  delete [] m_ThreaderTransform;
379  }
380  m_ThreaderTransform = new TransformPointer[m_NumberOfThreads-1];
381  for( unsigned int ithread=0; ithread < m_NumberOfThreads-1; ++ithread)
382  {
383  // Create a copy of the main transform to be used in this thread.
384  LightObject::Pointer anotherTransform = this->m_Transform->CreateAnother();
385  // This static_cast should always work since the pointer was created by
386  // CreateAnother() called from the transform itself.
387  TransformType * transformCopy = static_cast< TransformType * >( anotherTransform.GetPointer() );
391  transformCopy->SetFixedParameters( this->m_Transform->GetFixedParameters() );
392  transformCopy->SetParameters( this->m_Transform->GetParameters() );
393  this->m_ThreaderTransform[ithread] = transformCopy;
394  }
395 
396  m_FixedImageSamples.resize( m_NumberOfFixedImageSamples );
397  if( m_UseSequentialSampling )
398  {
399  //
400  // Take all the pixels within the fixed image region)
401  // to create the sample points list.
402  //
403  SampleFullFixedImageRegion( m_FixedImageSamples );
404  }
405  else
406  {
407  if( m_UseFixedImageIndexes )
408  {
409  //
410  // Use the list of indexes passed to the SetFixedImageIndexes
411  // member function .
412  //
413  SampleFixedImageIndexes( m_FixedImageSamples );
414  }
415  else
416  {
417  //
418  // Uniformly sample the fixed image (within the fixed image region)
419  // to create the sample points list.
420  //
421  SampleFixedImageRegion( m_FixedImageSamples );
422  }
423  }
424 
425  //
426  // Check if the interpolator is of type BSplineInterpolateImageFunction.
427  // If so, we can make use of its EvaluateDerivatives method.
428  // Otherwise, we instantiate an external central difference
429  // derivative calculator.
430  //
431  m_InterpolatorIsBSpline = true;
432 
433  BSplineInterpolatorType * testPtr = dynamic_cast<BSplineInterpolatorType *>(
434  this->m_Interpolator.GetPointer() );
435  if ( !testPtr )
436  {
437  m_InterpolatorIsBSpline = false;
438 
439  m_DerivativeCalculator = DerivativeFunctionType::New();
440 
441 #ifdef ITK_USE_ORIENTED_IMAGE_DIRECTION
442  m_DerivativeCalculator->UseImageDirectionOn();
443 #endif
444 
445  m_DerivativeCalculator->SetInputImage( this->m_MovingImage );
446 
447  m_BSplineInterpolator = NULL;
448  itkDebugMacro( "Interpolator is not BSpline" );
449  }
450  else
451  {
452  m_BSplineInterpolator = testPtr;
453  m_BSplineInterpolator->SetNumberOfThreads( m_NumberOfThreads );
454 
455 #ifdef ITK_USE_ORIENTED_IMAGE_DIRECTION
456  m_BSplineInterpolator->UseImageDirectionOn();
457 #endif
458 
459  m_DerivativeCalculator = NULL;
460  itkDebugMacro( "Interpolator is BSpline" );
461  }
462 
463  //
464  // Check if the transform is of type BSplineDeformableTransform.
465  //
466  // If so, several speed up features are implemented.
467  // [1] Precomputing the results of bulk transform for each sample point.
468  // [2] Precomputing the BSpline weights for each sample point,
469  // to be used later to directly compute the deformation vector
470  // [3] Precomputing the indices of the parameters within the
471  // the support region of each sample point.
472  //
473  m_TransformIsBSpline = true;
474 
475  BSplineTransformType * testPtr2 = dynamic_cast<BSplineTransformType *>(
476  this->m_Transform.GetPointer() );
477  if( !testPtr2 )
478  {
479  m_TransformIsBSpline = false;
480  m_BSplineTransform = NULL;
481  itkDebugMacro( "Transform is not BSplineDeformable" );
482  }
483  else
484  {
485  m_BSplineTransform = testPtr2;
486  m_NumBSplineWeights = m_BSplineTransform->GetNumberOfWeights();
487  itkDebugMacro( "Transform is BSplineDeformable" );
488  }
489 
490  if( this->m_TransformIsBSpline )
491  {
492  // First, deallocate memory that may have been used from previous run of the Metric
493  this->m_BSplineTransformWeightsArray.SetSize( 1, 1 );
494  this->m_BSplineTransformIndicesArray.SetSize( 1, 1 );
495  this->m_BSplinePreTransformPointsArray.resize( 1 );
496  this->m_WithinBSplineSupportRegionArray.resize( 1 );
497  this->m_BSplineTransformWeights.SetSize( 1 );
498  this->m_BSplineTransformIndices.SetSize( 1 );
499 
500  if( this->m_ThreaderBSplineTransformWeights != NULL )
501  {
502  delete [] this->m_ThreaderBSplineTransformWeights;
503  }
504  this->m_ThreaderBSplineTransformWeights = NULL;
505 
506  if( this->m_ThreaderBSplineTransformIndices != NULL )
507  {
508  delete [] this->m_ThreaderBSplineTransformIndices;
509  }
510  this->m_ThreaderBSplineTransformIndices = NULL;
511 
512  if( this->m_UseCachingOfBSplineWeights )
513  {
514  m_BSplineTransformWeightsArray.SetSize(
515  m_NumberOfFixedImageSamples, m_NumBSplineWeights );
516  m_BSplineTransformIndicesArray.SetSize(
517  m_NumberOfFixedImageSamples, m_NumBSplineWeights );
518  m_BSplinePreTransformPointsArray.resize( m_NumberOfFixedImageSamples );
519  m_WithinBSplineSupportRegionArray.resize( m_NumberOfFixedImageSamples );
520 
521  this->PreComputeTransformValues();
522  }
523  else
524  {
525  this->m_BSplineTransformWeights.SetSize( this->m_NumBSplineWeights );
526  this->m_BSplineTransformIndices.SetSize( this->m_NumBSplineWeights );
527 
528  this->m_ThreaderBSplineTransformWeights = new BSplineTransformWeightsType[m_NumberOfThreads-1];
529  this->m_ThreaderBSplineTransformIndices = new BSplineTransformIndexArrayType[m_NumberOfThreads-1];
530 
531  for( unsigned int ithread=0; ithread < m_NumberOfThreads-1; ++ithread)
532  {
533  this->m_ThreaderBSplineTransformWeights[ithread].SetSize( this->m_NumBSplineWeights );
534  this->m_ThreaderBSplineTransformIndices[ithread].SetSize( this->m_NumBSplineWeights );
535  }
536  }
537 
538  for ( unsigned int j = 0; j < FixedImageDimension; j++ )
539  {
540  this->m_BSplineParametersOffset[j] = j * this->m_BSplineTransform->GetNumberOfParametersPerDimension();
541  }
542  }
543 
544 }
545 
546 
550 template < class TFixedImage, class TMovingImage >
551 void
554 {
555  typename FixedImageSampleContainer::iterator iter;
556 
557  unsigned long len = m_FixedImageIndexes.size();
558  if( len != m_NumberOfFixedImageSamples
559  || samples.size() != m_NumberOfFixedImageSamples )
560  {
561  throw ExceptionObject(__FILE__, __LINE__,
562  "Index list size does not match desired number of samples" );
563  }
564 
565  iter=samples.begin();
566  for(unsigned long i=0; i<len; i++)
567  {
568  // Get sampled index
569  FixedImageIndexType index = m_FixedImageIndexes[i];
570  // Translate index to point
571  m_FixedImage->TransformIndexToPhysicalPoint( index, (*iter).point );
572 
573  // Get sampled fixed image value
574  (*iter).value = m_FixedImage->GetPixel( index );
575  (*iter).valueIndex = 0;
576 
577  ++iter;
578  }
579 }
580 
584 template < class TFixedImage, class TMovingImage >
585 void
588 {
589  if( samples.size() != m_NumberOfFixedImageSamples )
590  {
591  throw ExceptionObject(__FILE__, __LINE__,
592  "Sample size does not match desired number of samples" );
593  }
594 
595  // Set up a random interator within the user specified fixed image region.
597  RandomIterator randIter( m_FixedImage, GetFixedImageRegion() );
598 
599  typename FixedImageSampleContainer::iterator iter;
600  typename FixedImageSampleContainer::const_iterator end=samples.end();
601 
602  if( m_FixedImageMask.IsNotNull()
603  || m_UseFixedImageSamplesIntensityThreshold )
604  {
605  InputPointType inputPoint;
606 
607  iter=samples.begin();
608  unsigned long int samplesFound = 0;
609  randIter.SetNumberOfSamples( m_NumberOfFixedImageSamples * 1000 );
610  randIter.GoToBegin();
611  while( iter != end )
612  {
613  if( randIter.IsAtEnd() )
614  {
615  // Must be a small mask since after many random samples we don't
616  // have enough to fill the desired number. So, we will replicate
617  // the samples we've found so far to fill-in the desired number
618  // of samples
619  unsigned long int count = 0;
620  while( iter != end )
621  {
622  (*iter).point = samples[count].point;
623  (*iter).value = samples[count].value;
624  (*iter).valueIndex = 0;
625  ++count;
626  if(count >= samplesFound)
627  {
628  count = 0;
629  }
630  ++iter;
631  }
632  break;
633  }
634 
635  // Get sampled index
636  FixedImageIndexType index = randIter.GetIndex();
637  // Check if the Index is inside the mask, translate index to point
638  m_FixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
639 
640  if( m_FixedImageMask.IsNotNull() )
641  {
642  double val;
643  if( m_FixedImageMask->ValueAt( inputPoint, val ) )
644  {
645  if( val == 0 )
646  {
647  ++randIter; // jump to another random position
648  continue;
649  }
650  }
651  else
652  {
653  ++randIter; // jump to another random position
654  continue;
655  }
656  }
657 
658  if( m_UseFixedImageSamplesIntensityThreshold &&
659  randIter.Get() < m_FixedImageSamplesIntensityThreshold )
660  {
661  ++randIter;
662  continue;
663  }
664 
665  // Translate index to point
666  (*iter).point = inputPoint;
667  // Get sampled fixed image value
668  (*iter).value = randIter.Get();
669  (*iter).valueIndex = 0;
670 
671  ++samplesFound;
672  ++randIter;
673  ++iter;
674  }
675  }
676  else
677  {
678  randIter.SetNumberOfSamples( m_NumberOfFixedImageSamples );
679  randIter.GoToBegin();
680  for( iter=samples.begin(); iter != end; ++iter )
681  {
682  // Get sampled index
683  FixedImageIndexType index = randIter.GetIndex();
684  // Translate index to point
685  m_FixedImage->TransformIndexToPhysicalPoint( index,
686  (*iter).point );
687  // Get sampled fixed image value
688  (*iter).value = randIter.Get();
689  (*iter).valueIndex = 0;
690 
691  // Jump to random position
692  ++randIter;
693  }
694  }
695 }
696 
700 template < class TFixedImage, class TMovingImage >
701 void
704 {
705 
706  if( samples.size() != m_NumberOfFixedImageSamples )
707  {
708  throw ExceptionObject(__FILE__, __LINE__,
709  "Sample size does not match desired number of samples" );
710  }
711 
712  // Set up a region interator within the user specified fixed image region.
714  RegionIterator regionIter( m_FixedImage, GetFixedImageRegion() );
715 
716  regionIter.GoToBegin();
717 
718  typename FixedImageSampleContainer::iterator iter;
719  typename FixedImageSampleContainer::const_iterator end=samples.end();
720 
721  if( m_FixedImageMask.IsNotNull()
722  || m_UseFixedImageSamplesIntensityThreshold )
723  {
724  InputPointType inputPoint;
725 
726  // repeat until we get enough samples to fill the array
727  iter=samples.begin();
728  while( iter != end )
729  {
730  // Get sampled index
731  FixedImageIndexType index = regionIter.GetIndex();
732  // Check if the Index is inside the mask, translate index to point
733  m_FixedImage->TransformIndexToPhysicalPoint( index, inputPoint );
734 
735  if( m_FixedImageMask.IsNotNull() )
736  {
737  // If not inside the mask, ignore the point
738  if( !m_FixedImageMask->IsInside( inputPoint ) )
739  {
740  ++regionIter; // jump to next pixel
741  if( regionIter.IsAtEnd() )
742  {
743  regionIter.GoToBegin();
744  }
745  continue;
746  }
747  }
748 
749  if( m_UseFixedImageSamplesIntensityThreshold &&
750  regionIter.Get() < m_FixedImageSamplesIntensityThreshold )
751  {
752  ++regionIter; // jump to next pixel
753  if( regionIter.IsAtEnd() )
754  {
755  regionIter.GoToBegin();
756  }
757  continue;
758  }
759 
760  // Translate index to point
761  (*iter).point = inputPoint;
762  // Get sampled fixed image value
763  (*iter).value = regionIter.Get();
764  (*iter).valueIndex = 0;
765 
766  ++regionIter;
767  if( regionIter.IsAtEnd() )
768  {
769  regionIter.GoToBegin();
770  }
771  ++iter;
772  }
773  }
774  else // not restricting sample throwing to a mask
775  {
776  for( iter=samples.begin(); iter != end; ++iter )
777  {
778  // Get sampled index
779  FixedImageIndexType index = regionIter.GetIndex();
780 
781  // Translate index to point
782  m_FixedImage->TransformIndexToPhysicalPoint( index,
783  (*iter).point );
784  // Get sampled fixed image value
785  (*iter).value = regionIter.Get();
786  (*iter).valueIndex = 0;
787 
788  ++regionIter;
789  if( regionIter.IsAtEnd() )
790  {
791  regionIter.GoToBegin();
792  }
793  }
794  }
795 }
796 
800 template <class TFixedImage, class TMovingImage>
801 void
804 {
805  GradientImageFilterPointer gradientFilter = GradientImageFilterType::New();
806 
807  gradientFilter->SetInput( m_MovingImage );
808 
809  const typename MovingImageType::SpacingType & spacing = m_MovingImage
810  ->GetSpacing();
811  double maximumSpacing=0.0;
812  for(unsigned int i=0; i<MovingImageDimension; i++)
813  {
814  if( spacing[i] > maximumSpacing )
815  {
816  maximumSpacing = spacing[i];
817  }
818  }
819  gradientFilter->SetSigma( maximumSpacing );
820  gradientFilter->SetNormalizeAcrossScale( true );
821  gradientFilter->SetNumberOfThreads( m_NumberOfThreads );
822 
823 #ifdef ITK_USE_ORIENTED_IMAGE_DIRECTION
824  gradientFilter->SetUseImageDirection( true );
825 #endif
826 
827  gradientFilter->Update();
828 
829  m_GradientImage = gradientFilter->GetOutput();
830 }
831 
832 // Method to reinitialize the seed of the random number generator
833 template < class TFixedImage, class TMovingImage > void
836 {
838 }
839 
840 // Method to reinitialize the seed of the random number generator
841 template < class TFixedImage, class TMovingImage > void
844 {
846  seed);
847 }
848 
849 
853 template < class TFixedImage, class TMovingImage >
854 void
857 {
858  // Note: This code is specific to the b-spline deformable transform.
859 
860  // Unfortunately, the BSplineDeformableTransform stores a
861  // pointer to parameters passed to SetParameters(). Since
862  // we're creating a dummy set of parameters below on the
863  // stack, this can cause a crash if the transform's
864  // parameters are not later reset with a more properly
865  // scoped set of parameters. In addition, we're overwriting
866  // any previously set parameters. In order to be kinder,
867  // we'll save a pointer to the current set of parameters
868  // and restore them after we're done.
869 
870  // Note the address operator.
871  // const TransformParametersType* previousParameters = & m_Transform->GetParameters();
872 
873  // Create all zero dummy transform parameters
874  ParametersType dummyParameters( m_NumberOfParameters );
875  dummyParameters.Fill( 0.0 );
876  m_Transform->SetParameters( dummyParameters );
877 
878  // Cycle through each sampled fixed image point
879  BSplineTransformWeightsType weights( m_NumBSplineWeights );
880  BSplineTransformIndexArrayType indices( m_NumBSplineWeights );
881  bool valid;
882  MovingImagePointType mappedPoint;
883 
884  // Declare iterators for iteration over the sample container
885  typename FixedImageSampleContainer::const_iterator fiter;
886  typename FixedImageSampleContainer::const_iterator fend =
887  m_FixedImageSamples.end();
888  unsigned long counter = 0;
889 
890  for( fiter = m_FixedImageSamples.begin(); fiter != fend; ++fiter, counter++ )
891  {
892  m_BSplineTransform->TransformPoint( m_FixedImageSamples[counter].point,
893  mappedPoint, weights, indices, valid );
894 
895  for( unsigned long k = 0; k < m_NumBSplineWeights; k++ )
896  {
897  m_BSplineTransformWeightsArray[counter][k] = weights[k];
898  m_BSplineTransformIndicesArray[counter][k] = indices[k];
899  }
900 
901  m_BSplinePreTransformPointsArray[counter] = mappedPoint;
902  m_WithinBSplineSupportRegionArray[counter] = valid;
903  }
904 
905  // Restore the previous parameters.
906  // m_Transform->SetParameters( *previousParameters );
907 }
908 
909 
914 template < class TFixedImage, class TMovingImage >
915 void
917 ::TransformPoint( unsigned int sampleNumber,
918  MovingImagePointType & mappedPoint,
919  bool & sampleOk,
920  double & movingImageValue,
921  unsigned int threadID ) const
922 {
923  sampleOk = true;
924  TransformType * transform;
925 
926  if( threadID > 0 )
927  {
928  transform = this->m_ThreaderTransform[threadID-1];
929  }
930  else
931  {
932  transform = this->m_Transform;
933  }
934 
935  if ( !m_TransformIsBSpline )
936  {
937  // Use generic transform to compute mapped position
938  mappedPoint = transform->TransformPoint( m_FixedImageSamples[sampleNumber].point );
939  sampleOk = true;
940  }
941  else
942  {
943  if( this->m_UseCachingOfBSplineWeights )
944  {
945  sampleOk = m_WithinBSplineSupportRegionArray[sampleNumber];
946 
947  if(sampleOk)
948  {
949  // If the transform is BSplineDeformable, we can use the precomputed
950  // weights and indices to obtained the mapped position
951  const WeightsValueType * weights =
952  m_BSplineTransformWeightsArray[sampleNumber];
953  const IndexValueType * indices =
954  m_BSplineTransformIndicesArray[sampleNumber];
955 
956  for( unsigned int j = 0; j < FixedImageDimension; j++ )
957  {
958  mappedPoint[j] = m_BSplinePreTransformPointsArray[sampleNumber][j];
959  }
960 
961  for ( unsigned int k = 0; k < m_NumBSplineWeights; k++ )
962  {
963  for ( unsigned int j = 0; j < FixedImageDimension; j++ )
964  {
965  mappedPoint[j] += weights[k] * m_Parameters[ indices[k]
966  + m_BSplineParametersOffset[j] ];
967  }
968  }
969  }
970  }
971  else
972  {
973  BSplineTransformWeightsType * weightsHelper;
974  BSplineTransformIndexArrayType * indicesHelper;
975 
976  if( threadID > 0 )
977  {
978  weightsHelper = &(this->m_ThreaderBSplineTransformWeights[threadID-1]);
979  indicesHelper = &(this->m_ThreaderBSplineTransformIndices[threadID-1]);
980  }
981  else
982  {
983  weightsHelper = &(this->m_BSplineTransformWeights);
984  indicesHelper = &(this->m_BSplineTransformIndices);
985  }
986 
987  // If not caching values, we invoke the Transform to recompute the
988  // mapping of the point.
989  this->m_BSplineTransform->TransformPoint(
990  this->m_FixedImageSamples[sampleNumber].point,
991  mappedPoint, *weightsHelper, *indicesHelper, sampleOk);
992  }
993  }
994 
995  if(sampleOk)
996  {
997  // If user provided a mask over the Moving image
998  if ( m_MovingImageMask )
999  {
1000  // Check if mapped point is within the support region of the moving image
1001  // mask
1002  sampleOk = sampleOk && m_MovingImageMask->IsInside( mappedPoint );
1003  }
1004 
1005 
1006  if( m_InterpolatorIsBSpline )
1007  {
1008  // Check if mapped point inside image buffer
1009  sampleOk = sampleOk && m_BSplineInterpolator->IsInsideBuffer( mappedPoint );
1010  if( sampleOk )
1011  {
1012  movingImageValue = m_BSplineInterpolator->Evaluate( mappedPoint, threadID );
1013  }
1014  }
1015  else
1016  {
1017  // Check if mapped point inside image buffer
1018  sampleOk = sampleOk && m_Interpolator->IsInsideBuffer( mappedPoint );
1019  if( sampleOk )
1020  {
1021  movingImageValue = m_Interpolator->Evaluate( mappedPoint );
1022  }
1023  }
1024  }
1025 }
1026 
1027 
1032 template < class TFixedImage, class TMovingImage >
1033 void
1035 ::TransformPointWithDerivatives( unsigned int sampleNumber,
1036  MovingImagePointType& mappedPoint,
1037  bool& sampleOk,
1038  double& movingImageValue,
1039  ImageDerivativesType & movingImageGradient,
1040  unsigned int threadID ) const
1041 {
1042  TransformType * transform;
1043  sampleOk = true;
1044 
1045  if( threadID > 0 )
1046  {
1047  transform = this->m_ThreaderTransform[threadID-1];
1048  }
1049  else
1050  {
1051  transform = this->m_Transform;
1052  }
1053 
1054  if ( !m_TransformIsBSpline )
1055  {
1056  // Use generic transform to compute mapped position
1057  mappedPoint = transform->TransformPoint( m_FixedImageSamples[sampleNumber].point );
1058  sampleOk = true;
1059  }
1060  else
1061  {
1062  if( this->m_UseCachingOfBSplineWeights )
1063  {
1064  sampleOk = m_WithinBSplineSupportRegionArray[sampleNumber];
1065 
1066  if(sampleOk)
1067  {
1068  // If the transform is BSplineDeformable, we can use the precomputed
1069  // weights and indices to obtained the mapped position
1070  const WeightsValueType * weights =
1071  m_BSplineTransformWeightsArray[sampleNumber];
1072  const IndexValueType * indices =
1073  m_BSplineTransformIndicesArray[sampleNumber];
1074 
1075  for( unsigned int j = 0; j < FixedImageDimension; j++ )
1076  {
1077  mappedPoint[j] = m_BSplinePreTransformPointsArray[sampleNumber][j];
1078  }
1079 
1080  for ( unsigned int k = 0; k < m_NumBSplineWeights; k++ )
1081  {
1082  for ( unsigned int j = 0; j < FixedImageDimension; j++ )
1083  {
1084  mappedPoint[j] += weights[k] * m_Parameters[ indices[k]
1085  + m_BSplineParametersOffset[j] ];
1086  }
1087  }
1088  }
1089  }
1090  else
1091  {
1092  BSplineTransformWeightsType * weightsHelper;
1093  BSplineTransformIndexArrayType * indicesHelper;
1094 
1095  if( threadID > 0 )
1096  {
1097  weightsHelper = &(this->m_ThreaderBSplineTransformWeights[threadID-1]);
1098  indicesHelper = &(this->m_ThreaderBSplineTransformIndices[threadID-1]);
1099  }
1100  else
1101  {
1102  weightsHelper = &(this->m_BSplineTransformWeights);
1103  indicesHelper = &(this->m_BSplineTransformIndices);
1104  }
1105 
1106  // If not caching values, we invoke the Transform to recompute the
1107  // mapping of the point.
1108  this->m_BSplineTransform->TransformPoint(
1109  this->m_FixedImageSamples[sampleNumber].point,
1110  mappedPoint, *weightsHelper, *indicesHelper, sampleOk);
1111  }
1112  }
1113 
1114  if(sampleOk)
1115  {
1116  // If user provided a mask over the Moving image
1117  if ( m_MovingImageMask )
1118  {
1119  // Check if mapped point is within the support region of the moving image
1120  // mask
1121  sampleOk = sampleOk && m_MovingImageMask->IsInside( mappedPoint );
1122  }
1123 
1124 
1125  if( m_InterpolatorIsBSpline )
1126  {
1127  // Check if mapped point inside image buffer
1128  sampleOk = sampleOk && m_BSplineInterpolator->IsInsideBuffer( mappedPoint );
1129  if( sampleOk )
1130  {
1131  this->m_BSplineInterpolator->EvaluateValueAndDerivative(mappedPoint,
1132  movingImageValue,
1133  movingImageGradient,
1134  threadID);
1135  }
1136  }
1137  else
1138  {
1139  // Check if mapped point inside image buffer
1140  sampleOk = sampleOk && m_Interpolator->IsInsideBuffer( mappedPoint );
1141  if( sampleOk )
1142  {
1143  this->ComputeImageDerivatives( mappedPoint, movingImageGradient, threadID );
1144  movingImageValue = this->m_Interpolator->Evaluate( mappedPoint );
1145  }
1146  }
1147  }
1148 }
1149 
1155 template < class TFixedImage, class TMovingImage >
1156 void
1159  ImageDerivativesType & gradient,
1160  unsigned int threadID) const
1161 {
1162 
1163  if( m_InterpolatorIsBSpline )
1164  {
1165  // Computed moving image gradient using derivative BSpline kernel.
1166  gradient = m_BSplineInterpolator->EvaluateDerivative( mappedPoint,
1167  threadID );
1168  }
1169  else
1170  {
1171  if ( m_ComputeGradient )
1172  {
1174  m_MovingImage->TransformPhysicalPointToContinuousIndex( mappedPoint,
1175  tempIndex );
1176  MovingImageIndexType mappedIndex;
1177  mappedIndex.CopyWithRound( tempIndex );
1178  gradient = m_GradientImage->GetPixel( mappedIndex );
1179  }
1180  else
1181  {
1182  // if not using the gradient image
1183  gradient = m_DerivativeCalculator->Evaluate( mappedPoint );
1184  }
1185  }
1186 
1187 }
1188 
1189 template < class TFixedImage, class TMovingImage >
1190 void
1193 {
1194  this->SynchronizeTransforms();
1195 
1196  m_Threader->SetSingleMethod(GetValueMultiThreadedPreProcess,
1197  (void *)(&m_ThreaderParameter));
1198  m_Threader->SingleMethodExecute();
1199 }
1200 
1201 template < class TFixedImage, class TMovingImage >
1202 void
1205 {
1206 
1207  this->SynchronizeTransforms();
1208 
1209  m_Threader->SetSingleMethod(GetValueMultiThreaded,
1210  const_cast<void *>(static_cast<const void *>(&m_ThreaderParameter)));
1211  m_Threader->SingleMethodExecute();
1212 
1213  for( unsigned int threadID = 0; threadID<m_NumberOfThreads-1; threadID++ )
1214  {
1215  this->m_NumberOfPixelsCounted += m_ThreaderNumberOfMovingImageSamples[threadID];
1216  }
1217 }
1218 
1219 template < class TFixedImage, class TMovingImage >
1220 void
1223 {
1224  m_Threader->SetSingleMethod(GetValueMultiThreadedPostProcess,
1225  const_cast<void *>(static_cast<const void *>(&m_ThreaderParameter)));
1226  m_Threader->SingleMethodExecute();
1227 }
1228 
1232 template < class TFixedImage, class TMovingImage >
1236 {
1237  int threadID;
1238  MultiThreaderParameterType * mtParam;
1239 
1240  threadID = ((MultiThreaderType::ThreadInfoStruct *)(arg))->ThreadID;
1241 
1242  mtParam = (MultiThreaderParameterType *)
1243  (((MultiThreaderType::ThreadInfoStruct *)(arg))->UserData);
1244 
1245  mtParam->metric->GetValueThreadPreProcess(threadID, false);
1246 
1247  return ITK_THREAD_RETURN_VALUE;
1248 }
1249 
1250 
1254 template < class TFixedImage, class TMovingImage >
1258 {
1259  int threadID;
1260  MultiThreaderParameterType * mtParam;
1261 
1262  threadID = ((MultiThreaderType::ThreadInfoStruct *)(arg))->ThreadID;
1263 
1264  mtParam = (MultiThreaderParameterType *)
1265  (((MultiThreaderType::ThreadInfoStruct *)(arg))->UserData);
1266 
1267  mtParam->metric->GetValueThread(threadID);
1268 
1269  return ITK_THREAD_RETURN_VALUE;
1270 }
1274 template < class TFixedImage, class TMovingImage >
1278 {
1279  int threadID;
1280  MultiThreaderParameterType * mtParam;
1281 
1282  threadID = ((MultiThreaderType::ThreadInfoStruct *)(arg))->ThreadID;
1283 
1284  mtParam = (MultiThreaderParameterType *)
1285  (((MultiThreaderType::ThreadInfoStruct *)(arg))->UserData);
1286 
1287  mtParam->metric->GetValueThreadPostProcess(threadID, false);
1288 
1289  return ITK_THREAD_RETURN_VALUE;
1290 }
1291 
1292 
1293 template < class TFixedImage, class TMovingImage >
1294 void
1296 ::GetValueThread( unsigned int threadID ) const
1297 {
1298  // Figure out how many samples to process
1299  int chunkSize = m_NumberOfFixedImageSamples / m_NumberOfThreads;
1300 
1301  // Skip to this thread's samples to process
1302  unsigned int fixedImageSample = threadID * chunkSize;
1303 
1304  if(threadID == m_NumberOfThreads - 1)
1305  {
1306  chunkSize = m_NumberOfFixedImageSamples
1307  - ((m_NumberOfThreads-1)
1308  * chunkSize);
1309  }
1310 
1311  int numSamples = 0;
1312 
1313  if(m_WithinThreadPreProcess)
1314  {
1315  this->GetValueThreadPreProcess(threadID, true);
1316  }
1317 
1318  // Process the samples
1319  MovingImagePointType mappedPoint;
1320  bool sampleOk;
1321  double movingImageValue;
1322  for( int count=0; count < chunkSize; ++count, ++fixedImageSample )
1323  {
1324  // Get moving image value
1325  this->TransformPoint( fixedImageSample, mappedPoint, sampleOk, movingImageValue,
1326  threadID );
1327 
1328  if( sampleOk )
1329  {
1330  // CALL USER FUNCTION
1331  if(GetValueThreadProcessSample(threadID, fixedImageSample,
1332  mappedPoint, movingImageValue))
1333  {
1334  ++numSamples;
1335  }
1336  }
1337  }
1338 
1339  if(threadID > 0)
1340  {
1341  m_ThreaderNumberOfMovingImageSamples[threadID-1] = numSamples;
1342  }
1343  else
1344  {
1345  m_NumberOfPixelsCounted = numSamples;
1346  }
1347 
1348  if(m_WithinThreadPostProcess)
1349  {
1350  this->GetValueThreadPostProcess(threadID, true);
1351  }
1352 }
1353 
1354 template < class TFixedImage, class TMovingImage >
1355 void
1358 {
1359  this->SynchronizeTransforms();
1360 
1361  m_Threader->SetSingleMethod(GetValueAndDerivativeMultiThreadedPreProcess,
1362  (void *)(&m_ThreaderParameter));
1363  m_Threader->SingleMethodExecute();
1364 }
1365 
1366 template < class TFixedImage, class TMovingImage >
1367 void
1370 {
1371  this->SynchronizeTransforms();
1372 
1373  m_Threader->SetSingleMethod(GetValueAndDerivativeMultiThreaded,
1374  const_cast<void *>(static_cast<const void *>(&m_ThreaderParameter)));
1375  m_Threader->SingleMethodExecute();
1376 
1377  for( unsigned int threadID = 0; threadID<m_NumberOfThreads-1; threadID++ )
1378  {
1379  this->m_NumberOfPixelsCounted += m_ThreaderNumberOfMovingImageSamples[threadID];
1380  }
1381 }
1382 
1383 template < class TFixedImage, class TMovingImage >
1384 void
1387 {
1388  m_Threader->SetSingleMethod(GetValueAndDerivativeMultiThreadedPostProcess,
1389  (void *)(&m_ThreaderParameter));
1390  m_Threader->SingleMethodExecute();
1391 }
1392 
1396 template < class TFixedImage, class TMovingImage >
1400 {
1401  int threadID;
1402  MultiThreaderParameterType * mtParam;
1403 
1404  threadID = ((MultiThreaderType::ThreadInfoStruct *)(arg))->ThreadID;
1405 
1406  mtParam = (MultiThreaderParameterType *)
1407  (((MultiThreaderType::ThreadInfoStruct *)(arg))->UserData);
1408 
1409  mtParam->metric->GetValueAndDerivativeThreadPreProcess(threadID, false);
1410 
1411  return ITK_THREAD_RETURN_VALUE;
1412 }
1413 
1417 template < class TFixedImage, class TMovingImage >
1421 {
1422  int threadID;
1423  MultiThreaderParameterType * mtParam;
1424 
1425  threadID = ((MultiThreaderType::ThreadInfoStruct *)(arg))->ThreadID;
1426 
1427  mtParam = (MultiThreaderParameterType *)
1428  (((MultiThreaderType::ThreadInfoStruct *)(arg))->UserData);
1429 
1430  mtParam->metric->GetValueAndDerivativeThread(threadID);
1431 
1432  return ITK_THREAD_RETURN_VALUE;
1433 }
1434 
1438 template < class TFixedImage, class TMovingImage >
1442 {
1443  int threadID;
1444  MultiThreaderParameterType * mtParam;
1445 
1446  threadID = ((MultiThreaderType::ThreadInfoStruct *)(arg))->ThreadID;
1447 
1448  mtParam = (MultiThreaderParameterType *)
1449  (((MultiThreaderType::ThreadInfoStruct *)(arg))->UserData);
1450 
1451  mtParam->metric->GetValueAndDerivativeThreadPostProcess(threadID, false);
1452 
1453  return ITK_THREAD_RETURN_VALUE;
1454 }
1455 
1456 template < class TFixedImage, class TMovingImage >
1457 void
1459 ::GetValueAndDerivativeThread( unsigned int threadID ) const
1460 {
1461  // Figure out how many samples to process
1462  int chunkSize = m_NumberOfFixedImageSamples / m_NumberOfThreads;
1463 
1464  // Skip to this thread's samples to process
1465  unsigned int fixedImageSample = threadID * chunkSize;
1466 
1467  if(threadID == m_NumberOfThreads - 1)
1468  {
1469  chunkSize = m_NumberOfFixedImageSamples
1470  - ((m_NumberOfThreads-1)
1471  * chunkSize);
1472  }
1473 
1474  int numSamples = 0;
1475 
1476  if(m_WithinThreadPreProcess)
1477  {
1478  this->GetValueAndDerivativeThreadPreProcess(threadID, true);
1479  }
1480 
1481  // Process the samples
1482  MovingImagePointType mappedPoint;
1483  bool sampleOk;
1484  double movingImageValue;
1485  ImageDerivativesType movingImageGradientValue;
1486  for( int count=0; count < chunkSize; ++count, ++fixedImageSample )
1487  {
1488  // Get moving image value
1489  TransformPointWithDerivatives( fixedImageSample, mappedPoint, sampleOk,
1490  movingImageValue, movingImageGradientValue,
1491  threadID );
1492 
1493  if( sampleOk )
1494  {
1495  // CALL USER FUNCTION
1496  if( this->GetValueAndDerivativeThreadProcessSample( threadID,
1497  fixedImageSample,
1498  mappedPoint,
1499  movingImageValue,
1500  movingImageGradientValue ))
1501  {
1502  ++numSamples;
1503  }
1504  }
1505  }
1506 
1507  if(threadID > 0)
1508  {
1509  m_ThreaderNumberOfMovingImageSamples[threadID-1] = numSamples;
1510  }
1511  else
1512  {
1513  m_NumberOfPixelsCounted = numSamples;
1514  }
1515 
1516  if(m_WithinThreadPostProcess)
1517  {
1518  this->GetValueAndDerivativeThreadPostProcess(threadID, true);
1519  }
1520 }
1521 
1522 
1526 template <class TFixedImage, class TMovingImage>
1527 void
1529 ::PrintSelf(std::ostream& os, Indent indent) const
1530 {
1531  Superclass::PrintSelf( os, indent );
1532 
1533  os << indent << "NumberOfFixedImageSamples: ";
1534  os << m_NumberOfFixedImageSamples << std::endl;
1535 
1536  os << indent << "FixedImageSamplesIntensityThreshold: "
1537  << static_cast<typename NumericTraits<FixedImagePixelType>::PrintType>(m_FixedImageSamplesIntensityThreshold)
1538  << std::endl;
1539 
1540  os << indent << "UseFixedImageSamplesIntensityThreshold: ";
1541  os << m_UseFixedImageSamplesIntensityThreshold << std::endl;
1542 
1543  if( m_UseFixedImageIndexes )
1544  {
1545  os << indent << "Use Fixed Image Indexes: True" << std::endl;
1546  os << indent << "Number of Fixed Image Indexes = "
1547  << m_FixedImageIndexes.size() << std::endl;
1548  }
1549  else
1550  {
1551  os << indent << "Use Fixed Image Indexes: False" << std::endl;
1552  }
1553 
1554  if( m_UseSequentialSampling )
1555  {
1556  os << indent << "Use Sequential Sampling: True" << std::endl;
1557  }
1558  else
1559  {
1560  os << indent << "Use Sequential Sampling: False" << std::endl;
1561  }
1562 
1563  os << indent << "UseAllPixels: ";
1564  os << m_UseAllPixels << std::endl;
1565 
1566  os << indent << "Threader: " << m_Threader << std::endl;
1567  os << indent << "Number of Threads: " << m_NumberOfThreads << std::endl;
1568  os << indent << "ThreaderParameter: " << std::endl;
1569  os << indent << "ThreaderNumberOfMovingImageSamples: " << std::endl;
1570  if( m_ThreaderNumberOfMovingImageSamples )
1571  {
1572  for(unsigned int i=0; i<m_NumberOfThreads-1; i++)
1573  {
1574  os << " Thread[" << i << "]= " << (unsigned int)m_ThreaderNumberOfMovingImageSamples[i] << std::endl;
1575  }
1576  }
1577 
1578  os << indent << "ComputeGradient: "
1579  << static_cast<typename NumericTraits<bool>::PrintType>(m_ComputeGradient)
1580  << std::endl;
1581  os << indent << "Moving Image: " << m_MovingImage.GetPointer() << std::endl;
1582  os << indent << "Fixed Image: " << m_FixedImage.GetPointer() << std::endl;
1583  os << indent << "Gradient Image: " << m_GradientImage.GetPointer()
1584  << std::endl;
1585  os << indent << "Transform: " << m_Transform.GetPointer() << std::endl;
1586  os << indent << "Interpolator: " << m_Interpolator.GetPointer() << std::endl;
1587  os << indent << "FixedImageRegion: " << m_FixedImageRegion << std::endl;
1588  os << indent << "Moving Image Mask: " << m_MovingImageMask.GetPointer()
1589  << std::endl;
1590  os << indent << "Fixed Image Mask: " << m_FixedImageMask.GetPointer()
1591  << std::endl;
1592  os << indent << "Number of Moving Image Samples: " << m_NumberOfPixelsCounted
1593  << std::endl;
1594 
1595  os << indent << "UseCachingOfBSplineWeights: ";
1596  os << this->m_UseCachingOfBSplineWeights << std::endl;
1597 }
1598 
1603 template <class TFixedImage, class TMovingImage>
1604 void
1607 {
1608  for( unsigned int threadID = 0; threadID<m_NumberOfThreads-1; threadID++ )
1609  {
1613  this->m_ThreaderTransform[threadID]->SetFixedParameters( this->m_Transform->GetFixedParameters() );
1614  this->m_ThreaderTransform[threadID]->SetParameters( this->m_Transform->GetParameters() );
1615  }
1616 }
1617 
1618 } // end namespace itk
1619 
1620 #endif

Generated at Sat May 18 2013 23:58:05 for Orfeo Toolbox with doxygen 1.8.3.1