Orfeo Toolbox  3.16
itkPDEDeformableRegistrationFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkPDEDeformableRegistrationFilter.txx,v $
5  Language: C++
6  Date: $Date: 2009-01-26 21:45:56 $
7  Version: $Revision: 1.32 $
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 __itkPDEDeformableRegistrationFilter_txx
18 #define __itkPDEDeformableRegistrationFilter_txx
19 
21 
22 #include "itkExceptionObject.h"
23 #include "itkImageRegionIterator.h"
25 #include "itkDataObject.h"
26 
27 #include "itkGaussianOperator.h"
29 
30 #include "vnl/vnl_math.h"
31 
32 namespace itk {
33 
37 template <class TFixedImage, class TMovingImage, class TDeformationField>
40 {
41 
42  this->SetNumberOfRequiredInputs(2);
43 
44  this->SetNumberOfIterations(10);
45 
46  unsigned int j;
47  for( j = 0; j < ImageDimension; j++ )
48  {
49  m_StandardDeviations[j] = 1.0;
50  m_UpdateFieldStandardDeviations[j] = 1.0;
51  }
52 
53  m_TempField = DeformationFieldType::New();
54  m_MaximumError = 0.1;
55  m_MaximumKernelWidth = 30;
56  m_StopRegistrationFlag = false;
57 
58  m_SmoothDeformationField = true;
59  m_SmoothUpdateField = false;
60 }
61 
62 
63 /*
64  * Set the fixed image.
65  */
66 template <class TFixedImage, class TMovingImage, class TDeformationField>
67 void
70  const FixedImageType * ptr )
71 {
72  this->ProcessObject::SetNthInput( 1, const_cast< FixedImageType * >( ptr ) );
73 }
74 
75 
76 /*
77  * Get the fixed image.
78  */
79 template <class TFixedImage, class TMovingImage, class TDeformationField>
81 ::FixedImageType *
84 {
85  return dynamic_cast< const FixedImageType * >
86  ( this->ProcessObject::GetInput( 1 ) );
87 }
88 
89 
90 /*
91  * Set the moving image.
92  */
93 template <class TFixedImage, class TMovingImage, class TDeformationField>
94 void
97  const MovingImageType * ptr )
98 {
99  this->ProcessObject::SetNthInput( 2, const_cast< MovingImageType * >( ptr ) );
100 }
101 
102 
103 /*
104  * Get the moving image.
105  */
106 template <class TFixedImage, class TMovingImage, class TDeformationField>
108 ::MovingImageType *
111 {
112  return dynamic_cast< const MovingImageType * >
113  ( this->ProcessObject::GetInput( 2 ) );
114 }
115 
116 
117 /*
118  *
119  */
120 template <class TFixedImage, class TMovingImage, class TDeformationField>
121 std::vector<SmartPointer<DataObject> >::size_type
124 {
125  typename std::vector<SmartPointer<DataObject> >::size_type num = 0;
126 
127  if (this->GetFixedImage())
128  {
129  num++;
130  }
131 
132  if (this->GetMovingImage())
133  {
134  num++;
135  }
136 
137  return num;
138 }
139 
140 
144 template <class TFixedImage, class TMovingImage, class TDeformationField>
145 void
148  double value )
149 {
150 
151  unsigned int j;
152  for( j = 0; j < ImageDimension; j++ )
153  {
154  if( value != m_StandardDeviations[j] )
155  {
156  break;
157  }
158  }
159  if( j < ImageDimension )
160  {
161  this->Modified();
162  for( j = 0; j < ImageDimension; j++ )
163  {
164  m_StandardDeviations[j] = value;
165  }
166  }
167 
168 }
169 
170 /*
171  * Set the standard deviations.
172  */
173 template <class TFixedImage, class TMovingImage, class TDeformationField>
174 void
177  double value )
178 {
179 
180  unsigned int j;
181  for( j = 0; j < ImageDimension; j++ )
182  {
183  if( value != m_UpdateFieldStandardDeviations[j] )
184  {
185  break;
186  }
187  }
188  if( j < ImageDimension )
189  {
190  this->Modified();
191  for( j = 0; j < ImageDimension; j++ )
192  {
193  m_UpdateFieldStandardDeviations[j] = value;
194  }
195  }
196 
197 }
198 
199 
200 /*
201  * Standard PrintSelf method.
202  */
203 template <class TFixedImage, class TMovingImage, class TDeformationField>
204 void
206 ::PrintSelf(std::ostream& os, Indent indent) const
207 {
208  Superclass::PrintSelf(os, indent);
209  os << indent << "Smooth deformation field: "
210  << (m_SmoothDeformationField ? "on" : "off") << std::endl;
211  os << indent << "Standard deviations: [";
212  unsigned int j;
213  for( j = 0; j < ImageDimension - 1; j++ )
214  {
215  os << m_StandardDeviations[j] << ", ";
216  }
217  os << m_StandardDeviations[j] << "]" << std::endl;
218  os << indent << "Smooth update field: "
219  << (m_SmoothUpdateField ? "on" : "off") << std::endl;
220  os << indent << "Update field standard deviations: [";
221  for( j = 0; j < ImageDimension - 1; j++ )
222  {
223  os << m_UpdateFieldStandardDeviations[j] << ", ";
224  }
225  os << m_UpdateFieldStandardDeviations[j] << "]" << std::endl;
226  os << indent << "StopRegistrationFlag: ";
227  os << m_StopRegistrationFlag << std::endl;
228  os << indent << "MaximumError: ";
229  os << m_MaximumError << std::endl;
230  os << indent << "MaximumKernelWidth: ";
231  os << m_MaximumKernelWidth << std::endl;
232 
233 }
234 
235 
236 /*
237  * Set the function state values before each iteration
238  */
239 template <class TFixedImage, class TMovingImage, class TDeformationField>
240 void
243 {
244 
245  MovingImageConstPointer movingPtr = this->GetMovingImage();
246  FixedImageConstPointer fixedPtr = this->GetFixedImage();
247 
248  if( !movingPtr || !fixedPtr )
249  {
250  itkExceptionMacro( << "Fixed and/or moving image not set" );
251  }
252 
253  // update variables in the equation object
256  (this->GetDifferenceFunction().GetPointer());
257 
258  if ( !f )
259  {
260  itkExceptionMacro(<<"FiniteDifferenceFunction not of type PDEDeformableRegistrationFilterFunction");
261  }
262 
263  f->SetFixedImage( fixedPtr );
264  f->SetMovingImage( movingPtr );
265 
266  this->Superclass::InitializeIteration();
267 
268 }
269 
270 
271 /*
272  * Override the default implemenation for the case when the
273  * initial deformation is not set.
274  * If the initial deformation is not set, the output is
275  * fill with zero vectors.
276  */
277 template <class TFixedImage, class TMovingImage, class TDeformationField>
278 void
281 {
282 
283  typename Superclass::InputImageType::ConstPointer inputPtr = this->GetInput();
284 
285  if( inputPtr )
286  {
287  this->Superclass::CopyInputToOutput();
288  }
289  else
290  {
291  typename Superclass::PixelType zeros;
292  for( unsigned int j = 0; j < ImageDimension; j++ )
293  {
294  zeros[j] = 0;
295  }
296 
297  typename OutputImageType::Pointer output = this->GetOutput();
298 
299  ImageRegionIterator<OutputImageType> out(output, output->GetRequestedRegion());
300 
301  while( ! out.IsAtEnd() )
302  {
303  out.Value() = zeros;
304  ++out;
305  }
306  }
307 }
308 
309 
310 template <class TFixedImage, class TMovingImage, class TDeformationField>
311 void
314 {
315 
316  typename DataObject::Pointer output;
317 
318  if( this->GetInput(0) )
319  {
320  // Initial deformation field is set.
321  // Copy information from initial field.
322  this->Superclass::GenerateOutputInformation();
323 
324  }
325  else if( this->GetFixedImage() )
326  {
327  // Initial deforamtion field is not set.
328  // Copy information from the fixed image.
329  for (unsigned int idx = 0; idx <
330  this->GetNumberOfOutputs(); ++idx )
331  {
332  output = this->GetOutput(idx);
333  if (output)
334  {
335  output->CopyInformation(this->GetFixedImage());
336  }
337  }
338 
339  }
340 
341 }
342 
343 
344 template <class TFixedImage, class TMovingImage, class TDeformationField>
345 void
348 {
349 
350  // call the superclass's implementation
351  Superclass::GenerateInputRequestedRegion();
352 
353  // request the largest possible region for the moving image
354  MovingImagePointer movingPtr =
355  const_cast< MovingImageType * >( this->GetMovingImage() );
356  if( movingPtr )
357  {
358  movingPtr->SetRequestedRegionToLargestPossibleRegion();
359  }
360 
361  // just propagate up the output requested region for
362  // the fixed image and initial deformation field.
363  DeformationFieldPointer inputPtr =
364  const_cast< DeformationFieldType * >( this->GetInput() );
365  DeformationFieldPointer outputPtr = this->GetOutput();
366  FixedImagePointer fixedPtr =
367  const_cast< FixedImageType *>( this->GetFixedImage() );
368 
369  if( inputPtr )
370  {
371  inputPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
372  }
373 
374  if( fixedPtr )
375  {
376  fixedPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
377  }
378 
379 }
380 
381 
382 /*
383  * Release memory of internal buffers
384  */
385 template <class TFixedImage, class TMovingImage, class TDeformationField>
386 void
389 {
390  this->Superclass::PostProcessOutput();
391  m_TempField->Initialize();
392 }
393 
394 
395 /*
396  * Initialize flags
397  */
398 template <class TFixedImage, class TMovingImage, class TDeformationField>
399 void
402 {
403  this->Superclass::Initialize();
404  m_StopRegistrationFlag = false;
405 }
406 
407 
408 /*
409  * Smooth deformation using a separable Gaussian kernel
410  */
411 template <class TFixedImage, class TMovingImage, class TDeformationField>
412 void
415 {
416 
417  DeformationFieldPointer field = this->GetOutput();
418 
419  // copy field to TempField
420  m_TempField->SetOrigin( field->GetOrigin() );
421  m_TempField->SetSpacing( field->GetSpacing() );
422  m_TempField->SetDirection( field->GetDirection() );
423  m_TempField->SetLargestPossibleRegion(
424  field->GetLargestPossibleRegion() );
425  m_TempField->SetRequestedRegion(
426  field->GetRequestedRegion() );
427  m_TempField->SetBufferedRegion( field->GetBufferedRegion() );
428  m_TempField->Allocate();
429 
430  typedef typename DeformationFieldType::PixelType VectorType;
431  typedef typename VectorType::ValueType ScalarType;
432  typedef GaussianOperator<ScalarType,ImageDimension> OperatorType;
435  DeformationFieldType> SmootherType;
436 
437  OperatorType * oper = new OperatorType;
438  typename SmootherType::Pointer smoother = SmootherType::New();
439 
440  typedef typename DeformationFieldType::PixelContainerPointer
441  PixelContainerPointer;
442  PixelContainerPointer swapPtr;
443 
444  // graft the output field onto the mini-pipeline
445  smoother->GraftOutput( m_TempField );
446 
447  for( unsigned int j = 0; j < ImageDimension; j++ )
448  {
449  // smooth along this dimension
450  oper->SetDirection( j );
451  double variance = vnl_math_sqr( m_StandardDeviations[j] );
452  oper->SetVariance( variance );
453  oper->SetMaximumError( m_MaximumError );
454  oper->SetMaximumKernelWidth( m_MaximumKernelWidth );
455  oper->CreateDirectional();
456 
457  // todo: make sure we only smooth within the buffered region
458  smoother->SetOperator( *oper );
459  smoother->SetInput( field );
460  smoother->Update();
461 
462  if ( j < ImageDimension - 1 )
463  {
464  // swap the containers
465  swapPtr = smoother->GetOutput()->GetPixelContainer();
466  smoother->GraftOutput( field );
467  field->SetPixelContainer( swapPtr );
468  smoother->Modified();
469  }
470 
471  }
472 
473  // graft the output back to this filter
474  m_TempField->SetPixelContainer( field->GetPixelContainer() );
475  this->GraftOutput( smoother->GetOutput() );
476 
477  delete oper;
478 
479 }
480 
481 /*
482  * Smooth deformation using a separable Gaussian kernel
483  */
484 template <class TFixedImage, class TMovingImage, class TDeformationField>
485 void
488 {
489  // The update buffer will be overwritten with new data.
490  DeformationFieldPointer field = this->GetUpdateBuffer();
491 
492  typedef typename DeformationFieldType::PixelType VectorType;
493  typedef typename VectorType::ValueType ScalarType;
494  typedef GaussianOperator<ScalarType,ImageDimension> OperatorType;
497  DeformationFieldType> SmootherType;
498 
499  OperatorType opers[ImageDimension];
500  typename SmootherType::Pointer smoothers[ImageDimension];
501 
502  for( unsigned int j = 0; j < ImageDimension; j++ )
503  {
504  // smooth along this dimension
505  opers[j].SetDirection( j );
506  double variance = vnl_math_sqr( this->GetUpdateFieldStandardDeviations()[j] );
507  //double variance = vnl_math_sqr( 1.0 );
508  opers[j].SetVariance( variance );
509  opers[j].SetMaximumError( this->GetMaximumError() );
510  opers[j].SetMaximumKernelWidth( this->GetMaximumKernelWidth() );
511  opers[j].CreateDirectional();
512 
513  smoothers[j] = SmootherType::New();
514  smoothers[j]->SetOperator( opers[j] );
515  smoothers[j]->ReleaseDataFlagOn();
516 
517  if (j > 0)
518  {
519  smoothers[j]->SetInput( smoothers[j-1]->GetOutput() );
520  }
521  }
522  smoothers[0]->SetInput( field );
523  smoothers[ImageDimension-1]->GetOutput()
524  ->SetRequestedRegion( field->GetBufferedRegion() );
525 
526  smoothers[ImageDimension-1]->Update();
527 
528  // field to contain the final smoothed data, do the equivalent of a graft
529  field->SetPixelContainer( smoothers[ImageDimension-1]->GetOutput()
530  ->GetPixelContainer() );
531  field->SetRequestedRegion( smoothers[ImageDimension-1]->GetOutput()
532  ->GetRequestedRegion() );
533  field->SetBufferedRegion( smoothers[ImageDimension-1]->GetOutput()
534  ->GetBufferedRegion() );
535  field->SetLargestPossibleRegion( smoothers[ImageDimension-1]->GetOutput()
536  ->GetLargestPossibleRegion() );
537  field->CopyInformation( smoothers[ImageDimension-1]->GetOutput() );
538 }
539 
540 
541 } // end namespace itk
542 
543 #endif

Generated at Sun May 19 2013 00:00:06 for Orfeo Toolbox with doxygen 1.8.3.1