Orfeo Toolbox  3.16
itkKernelTransform.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkKernelTransform.txx,v $
5  Language: C++
6  Date: $Date: 2009-05-17 14:27:02 $
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 __itkKernelTransform_txx
18 #define __itkKernelTransform_txx
19 #include "itkKernelTransform.h"
20 
21 namespace itk
22 {
23 
24 
28 template <class TScalarType, unsigned int NDimensions>
31  NDimensions,
32  NDimensions )
33 // the second NDimensions is associated is provided as
34 // a tentative number for initializing the Jacobian.
35 // The matrix can be resized at run time so this number
36 // here is irrelevant. The correct size of the Jacobian
37 // will be NDimension X NDimension.NumberOfLandMarks.
38 {
39 
40  this->m_I.set_identity();
44  this->m_WMatrixComputed = false;
45 
46  this->m_Stiffness = 0.0;
47 }
48 
52 template <class TScalarType, unsigned int NDimensions>
55 {
56 }
57 
58 
62 template <class TScalarType, unsigned int NDimensions>
63 void
66 {
67  itkDebugMacro("setting SourceLandmarks to " << landmarks );
68  if (this->m_SourceLandmarks != landmarks)
69  {
70  this->m_SourceLandmarks = landmarks;
71  this->UpdateParameters();
72  this->Modified();
73  }
74 }
75 
76 
80 template <class TScalarType, unsigned int NDimensions>
81 void
84 {
85  itkDebugMacro("setting TargetLandmarks to " << landmarks );
86  if (this->m_TargetLandmarks != landmarks)
87  {
88  this->m_TargetLandmarks = landmarks;
89  this->UpdateParameters();
90  this->Modified();
91  }
92 }
93 
94 
99 #if !defined(ITK_LEGACY_REMOVE)
100 template <class TScalarType, unsigned int NDimensions>
103 ComputeG( const InputVectorType & ) const
104 {
105  itkLegacyReplaceBodyMacro( itkKernelTransform::ComputeG_vector, 3.6,
106  itkKernelTransform::ComputeG_vector_gmatrix );
107  return m_GMatrix;
108 }
109 #endif
110 
114 template <class TScalarType, unsigned int NDimensions>
115 void
117 ComputeG( const InputVectorType &, GMatrixType & itkNotUsed( gmatrix ) ) const
118 {
119  itkExceptionMacro( << "ComputeG(vector,gmatrix) must be reimplemented"
120  << " in subclasses of KernelTransform." );
121 }
122 
126 template <class TScalarType, unsigned int NDimensions>
127 const typename KernelTransform<TScalarType, NDimensions>::GMatrixType &
130 {
131  m_GMatrix.fill( NumericTraits< TScalarType >::Zero );
132  m_GMatrix.fill_diagonal( m_Stiffness );
133 
134  return m_GMatrix;
135 }
136 
137 
142 template <class TScalarType, unsigned int NDimensions>
143 void
146  OutputPointType & result ) const
147 {
148 
149  unsigned long numberOfLandmarks = this->m_SourceLandmarks
150  ->GetNumberOfPoints();
151 
152  PointsIterator sp = this->m_SourceLandmarks->GetPoints()->Begin();
153 
154  GMatrixType Gmatrix;
155 
156  for(unsigned int lnd=0; lnd < numberOfLandmarks; lnd++ )
157  {
158  this->ComputeG( thisPoint - sp->Value(), Gmatrix );
159  for(unsigned int dim=0; dim < NDimensions; dim++ )
160  {
161  for(unsigned int odim=0; odim < NDimensions; odim++ )
162  {
163  result[ odim ] += Gmatrix(dim, odim ) * m_DMatrix(dim,lnd);
164  }
165  }
166  ++sp;
167  }
168 
169 }
170 
171 
175 template <class TScalarType, unsigned int NDimensions>
178 {
179  unsigned long numberOfLandmarks = this->m_SourceLandmarks
180  ->GetNumberOfPoints();
181 
182  PointsIterator sp = this->m_SourceLandmarks->GetPoints()->Begin();
183  PointsIterator tp = this->m_TargetLandmarks->GetPoints()->Begin();
184  PointsIterator end = this->m_SourceLandmarks->GetPoints()->End();
185 
186  this->m_Displacements->Reserve( numberOfLandmarks );
187  typename VectorSetType::Iterator vt = this->m_Displacements->Begin();
188 
189  while( sp != end )
190  {
191  vt->Value() = tp->Value() - sp->Value();
192  vt++;
193  sp++;
194  tp++;
195  }
196 }
197 
201 template <class TScalarType, unsigned int NDimensions>
204 {
205 
206  typedef vnl_svd<TScalarType> SVDSolverType;
207 
208  this->ComputeL();
209  this->ComputeY();
210  SVDSolverType svd( this->m_LMatrix, 1e-8 );
211  this->m_WMatrix = svd.solve( this->m_YMatrix );
212 
213  this->ReorganizeW();
214 
215 }
216 
220 template <class TScalarType, unsigned int NDimensions>
222 ComputeL(void)
223 {
224  unsigned long numberOfLandmarks = this->m_SourceLandmarks
225  ->GetNumberOfPoints();
226  vnl_matrix<TScalarType> O2(NDimensions*(NDimensions+1),
227  NDimensions*(NDimensions+1), 0);
228 
229  this->ComputeP();
230  this->ComputeK();
231 
232  this->m_LMatrix.set_size(
233  NDimensions*(numberOfLandmarks+NDimensions+1),
234  NDimensions*(numberOfLandmarks+NDimensions+1) );
235 
236  this->m_LMatrix.fill( 0.0 );
237 
238  this->m_LMatrix.update( this->m_KMatrix, 0, 0 );
239  this->m_LMatrix.update( this->m_PMatrix, 0, this->m_KMatrix.columns() );
240  this->m_LMatrix.update( this->m_PMatrix.transpose(),
241  this->m_KMatrix.rows(), 0);
242  this->m_LMatrix.update( O2, this->m_KMatrix.rows(),
243  this->m_KMatrix.columns());
244 
245 }
246 
247 
251 template <class TScalarType, unsigned int NDimensions>
253 ComputeK(void)
254 {
255  unsigned long numberOfLandmarks = this->m_SourceLandmarks
256  ->GetNumberOfPoints();
257  GMatrixType G;
258 
259  this->ComputeD();
260 
261  this->m_KMatrix.set_size( NDimensions * numberOfLandmarks,
262  NDimensions * numberOfLandmarks );
263 
264  this->m_KMatrix.fill( 0.0 );
265 
266  PointsIterator p1 = this->m_SourceLandmarks->GetPoints()->Begin();
267  PointsIterator end = this->m_SourceLandmarks->GetPoints()->End();
268 
269  // K matrix is symmetric, so only evaluate the upper triangle and
270  // store the values in bot the upper and lower triangle
271  unsigned int i = 0;
272  while( p1 != end )
273  {
274  PointsIterator p2 = p1; // start at the diagonal element
275  unsigned int j = i;
276 
277  // Compute the block diagonal element, i.e. kernel for pi->pi
278  G = this->ComputeReflexiveG(p1);
279  this->m_KMatrix.update(G, i*NDimensions, i*NDimensions);
280  p2++;
281  j++;
282 
283  // Compute the upper (and copy into lower) triangular part of K
284  while( p2 != end )
285  {
286  const InputVectorType s = p1.Value() - p2.Value();
287  this->ComputeG(s, G);
288  // write value in upper and lower triangle of matrix
289  this->m_KMatrix.update(G, i*NDimensions, j*NDimensions);
290  this->m_KMatrix.update(G, j*NDimensions, i*NDimensions);
291  p2++;
292  j++;
293  }
294  p1++;
295  i++;
296  }
297 }
298 
302 template <class TScalarType, unsigned int NDimensions>
305 {
306  unsigned long numberOfLandmarks = this->m_SourceLandmarks
307  ->GetNumberOfPoints();
308  IMatrixType I;
309  IMatrixType temp;
310  InputPointType p;
311 
312  I.set_identity();
313  this->m_PMatrix.set_size( NDimensions*numberOfLandmarks,
314  NDimensions*(NDimensions+1) );
315  this->m_PMatrix.fill( 0.0 );
316  for (unsigned int i = 0; i < numberOfLandmarks; i++)
317  {
318  this->m_SourceLandmarks->GetPoint(i, &p);
319  for (unsigned int j = 0; j < NDimensions; j++)
320  {
321  temp = I * p[j];
322  this->m_PMatrix.update(temp, i*NDimensions, j*NDimensions);
323  }
324  this->m_PMatrix.update(I, i*NDimensions, NDimensions*NDimensions);
325  }
326 }
327 
331 template <class TScalarType, unsigned int NDimensions>
333 ComputeY(void)
334 {
335  unsigned long numberOfLandmarks = this->m_SourceLandmarks
336  ->GetNumberOfPoints();
337 
338  typename VectorSetType::ConstIterator displacement =
339  this->m_Displacements->Begin();
340 
341  this->m_YMatrix.set_size( NDimensions*(numberOfLandmarks+NDimensions+1), 1);
342 
343  this->m_YMatrix.fill( 0.0 );
344 
345  for (unsigned int i = 0; i < numberOfLandmarks; i++)
346  {
347  for (unsigned int j = 0; j < NDimensions; j++)
348  {
349  this->m_YMatrix.put(i*NDimensions+j, 0, displacement.Value()[j]);
350  }
351  displacement++;
352  }
353 
354  for (unsigned int i = 0; i < NDimensions*(NDimensions+1); i++)
355  {
356  this->m_YMatrix.put(numberOfLandmarks*NDimensions+i, 0, 0);
357  }
358 }
359 
360 
364 template <class TScalarType, unsigned int NDimensions>
365 void
368 {
369  unsigned long numberOfLandmarks = this->m_SourceLandmarks
370  ->GetNumberOfPoints();
371 
372  // The deformable (non-affine) part of the registration goes here
373  this->m_DMatrix.set_size(NDimensions,numberOfLandmarks);
374  unsigned int ci = 0;
375  for(unsigned int lnd=0; lnd < numberOfLandmarks; lnd++ )
376  {
377  for(unsigned int dim=0; dim < NDimensions; dim++ )
378  {
379  this->m_DMatrix(dim,lnd) = this->m_WMatrix(ci++,0);
380  }
381  }
382 
383  // This matrix holds the rotational part of the Affine component
384  for(unsigned int j=0; j < NDimensions; j++ )
385  {
386  for(unsigned int i=0; i < NDimensions; i++ )
387  {
388  this->m_AMatrix(i,j) = this->m_WMatrix(ci++,0);
389  }
390  }
391 
392  // This vector holds the translational part of the Affine component
393  for(unsigned int k=0; k < NDimensions; k++ )
394  {
395  this->m_BVector(k) = this->m_WMatrix(ci++,0);
396  }
397 
398  // release WMatrix memory by assigning a small one.
399  this->m_WMatrix = WMatrixType(1,1);
400 
401 }
402 
406 template <class TScalarType, unsigned int NDimensions>
409 ::TransformPoint( const InputPointType& thisPoint ) const
410 {
411 
412  OutputPointType result;
413 
414  typedef typename OutputPointType::ValueType ValueType;
415 
417 
418  this->ComputeDeformationContribution( thisPoint, result );
419 
420  // Add the rotational part of the Affine component
421  for(unsigned int j=0; j < NDimensions; j++ )
422  {
423  for(unsigned int i=0; i < NDimensions; i++ )
424  {
425  result[i] += this->m_AMatrix(i,j) * thisPoint[j];
426  }
427  }
428 
429 
430 
431  // This vector holds the translational part of the Affine component
432  for(unsigned int k=0; k < NDimensions; k++ )
433  {
434  result[k] += this->m_BVector(k) + thisPoint[k];
435  }
436 
437  return result;
438 
439 }
440 
441 // Compute the Jacobian in one position
442 template <class TScalarType, unsigned int NDimensions>
445 GetJacobian( const InputPointType & ) const
446 {
447 
448 
449  this->m_Jacobian.Fill( 0.0 );
450 
451  // FIXME: TODO
452  // The Jacobian should be computable in terms of the matrices
453  // used to Transform points...
454  itkExceptionMacro(<< "GetJacobian must be implemented in subclasses"
455  << " of KernelTransform.");
456 
457  return this->m_Jacobian;
458 
459 }
460 
461 
462 // Set the parameters
463 // NOTE that in this transformation both the Source and Target
464 // landmarks could be considered as parameters. It is assumed
465 // here that the Target landmarks are provided by the user and
466 // are not changed during the optimization process required for
467 // registration.
468 template <class TScalarType, unsigned int NDimensions>
469 void
471 SetParameters( const ParametersType & parameters )
472 {
473  typename PointsContainer::Pointer landmarks = PointsContainer::New();
474  const unsigned int numberOfLandmarks = parameters.Size() / NDimensions;
475  landmarks->Reserve( numberOfLandmarks );
476 
477  PointsIterator itr = landmarks->Begin();
478  PointsIterator end = landmarks->End();
479 
480  InputPointType landMark;
481 
482  unsigned int pcounter = 0;
483  while( itr != end )
484  {
485  for(unsigned int dim=0; dim<NDimensions; dim++)
486  {
487  landMark[ dim ] = parameters[ pcounter ];
488  pcounter++;
489  }
490  itr.Value() = landMark;
491  itr++;
492  }
493 
494  this->m_SourceLandmarks->SetPoints( landmarks );
495 
496  // Modified is always called since we just have a pointer to the
497  // parameters and cannot know if the parameters have changed.
498  this->Modified();
499 
500 }
501 
502 // Set the fixed parameters
503 // Since the API of the SetParameters() function sets the
504 // source landmarks, this function was added to support the
505 // setting of the target landmarks, and allowing the Transform
506 // I/O mechanism to be supported.
507 template <class TScalarType, unsigned int NDimensions>
508 void
510 SetFixedParameters( const ParametersType & parameters )
511 {
512  typename PointsContainer::Pointer landmarks = PointsContainer::New();
513  const unsigned int numberOfLandmarks = parameters.Size() / NDimensions;
514 
515  landmarks->Reserve( numberOfLandmarks );
516 
517  PointsIterator itr = landmarks->Begin();
518  PointsIterator end = landmarks->End();
519 
520  InputPointType landMark;
521 
522  unsigned int pcounter = 0;
523  while( itr != end )
524  {
525  for(unsigned int dim=0; dim<NDimensions; dim++)
526  {
527  landMark[ dim ] = parameters[ pcounter ];
528  pcounter++;
529  }
530  itr.Value() = landMark;
531  itr++;
532  }
533 
534  this->m_TargetLandmarks->SetPoints( landmarks );
535 }
536 
537 
538 // Update parameters array
539 // They are the components of all the landmarks in the source space
540 template <class TScalarType, unsigned int NDimensions>
541 void
543 UpdateParameters( void ) const
544 {
545  this->m_Parameters = ParametersType( this->m_SourceLandmarks
546  ->GetNumberOfPoints()
547  * NDimensions );
548 
549  PointsIterator itr = this->m_SourceLandmarks->GetPoints()->Begin();
550  PointsIterator end = this->m_SourceLandmarks->GetPoints()->End();
551 
552  unsigned int pcounter = 0;
553  while( itr != end )
554  {
555  InputPointType landmark = itr.Value();
556  for(unsigned int dim=0; dim<NDimensions; dim++)
557  {
558  this->m_Parameters[ pcounter ] = landmark[ dim ];
559  pcounter++;
560  }
561  itr++;
562  }
563 }
564 
565 // Get the parameters
566 // They are the components of all the landmarks in the source space
567 template <class TScalarType, unsigned int NDimensions>
570 GetParameters( void ) const
571 {
572  this->UpdateParameters();
573  return this->m_Parameters;
574 
575 }
576 
577 
578 // Get the fixed parameters
579 // This returns the target landmark locations
580 // This was added to support the Transform Reader/Writer mechanism
581 template <class TScalarType, unsigned int NDimensions>
584 GetFixedParameters( void ) const
585 {
586  this->m_FixedParameters = ParametersType( this->m_TargetLandmarks
587  ->GetNumberOfPoints()
588  * NDimensions );
589 
590  PointsIterator itr = this->m_TargetLandmarks->GetPoints()->Begin();
591  PointsIterator end = this->m_TargetLandmarks->GetPoints()->End();
592 
593  unsigned int pcounter = 0;
594  while( itr != end )
595  {
596  InputPointType landmark = itr.Value();
597  for(unsigned int dim=0; dim<NDimensions; dim++)
598  {
599  this->m_FixedParameters[ pcounter ] = landmark[ dim ];
600  pcounter++;
601  }
602  itr++;
603  }
604 
605  return this->m_FixedParameters;
606 
607 }
608 
609 template <class TScalarType, unsigned int NDimensions>
610 void
612 PrintSelf(std::ostream& os, Indent indent) const
613 {
614  Superclass::PrintSelf(os,indent);
615  if( this->m_SourceLandmarks )
616  {
617  os << indent << "SourceLandmarks: " << std::endl;
618  this->m_SourceLandmarks->Print(os,indent.GetNextIndent());
619  }
620  if( this->m_TargetLandmarks )
621  {
622  os << indent << "TargetLandmarks: " << std::endl;
623  this->m_TargetLandmarks->Print(os,indent.GetNextIndent());
624  }
625  if( this->m_Displacements )
626  {
627  os << indent << "Displacements: " << std::endl;
628  this->m_Displacements->Print(os,indent.GetNextIndent());
629  }
630  os << indent << "Stiffness: " << this->m_Stiffness << std::endl;
631 }
632 } // namespace itk
633 
634 #endif

Generated at Sat May 18 2013 23:48:14 for Orfeo Toolbox with doxygen 1.8.3.1