cmtkImagePairAffineRegistration.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2477 $
00026 //
00027 //  $LastChangedDate: 2010-10-20 13:33:20 -0700 (Wed, 20 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkImagePairAffineRegistration.h"
00034 
00035 #include <System/cmtkTimers.h>
00036 
00037 #include <Base/cmtkVector.h>
00038 #include <Base/cmtkXform.h>
00039 #include <Base/cmtkAffineXform.h>
00040 #include <Base/cmtkTypedArrayFunctionHistogramMatching.h>
00041 #include <Base/cmtkVolume.h>
00042 #include <Base/cmtkUniformVolume.h>
00043 #include <Base/cmtkFunctional.h>
00044 
00045 #include <Registration/cmtkImagePairAffineRegistrationFunctional.h>
00046 #include <Registration/cmtkOptimizer.h>
00047 #include <Registration/cmtkBestNeighbourOptimizer.h>
00048 #include <Registration/cmtkReformatVolume.h>
00049 
00050 namespace
00051 cmtk
00052 {
00053 
00056 
00057 ImagePairAffineRegistration::ImagePairAffineRegistration () :
00058   m_Initializer( MakeInitialAffineTransformation::FOV ),
00059   m_MatchFltToRefHistogram( false )
00060 { 
00061 }
00062 
00063 ImagePairAffineRegistration::~ImagePairAffineRegistration () 
00064 {
00065 }
00066 
00067 CallbackResult 
00068 ImagePairAffineRegistration::InitRegistration ()
00069 {
00070   CallbackResult result = this->Superclass::InitRegistration();
00071   if ( result != CALLBACK_OK ) return result;
00072 
00073   this->m_ReferenceVolume = this->m_Volume_1;
00074   this->m_FloatingVolume = this->m_Volume_2;
00075   
00076   if ( this->m_MatchFltToRefHistogram )
00077     {
00078     this->GetVolume_2()->GetData()->ApplyFunctionObject( TypedArrayFunctionHistogramMatching( *(this->GetVolume_2()->GetData()), *(this->GetVolume_1()->GetData()) ) );
00079     }
00080   
00081   AffineXform::SmartPtr affineXform;
00082 
00083   if ( this->m_InitialTransformation )
00084     {
00085     if ( this->m_InitialXformIsInverse )
00086       {
00087       affineXform = AffineXform::SmartPtr( this->m_InitialTransformation->MakeInverse() );
00088       } 
00089     else
00090       {
00091       affineXform = AffineXform::SmartPtr( this->m_InitialTransformation );
00092       }
00093     } 
00094   else 
00095     {
00096     affineXform = AffineXform::SmartPtr( MakeInitialAffineTransformation::Create( *this->m_ReferenceVolume, *this->m_FloatingVolume, this->m_Initializer ) );
00097     }
00098   
00099   this->m_Xform = affineXform;
00100   
00101   Vector3D center = this->m_ReferenceVolume->GetCenterCropRegion();
00102   affineXform->ChangeCenter( center );
00103 
00104   if ( this->m_UseOriginalData ) 
00105     {
00106     this->m_ParameterStack.push( Self::LevelParameters::SmartPtr( new Self::LevelParameters( -1 ) ) );
00107     }
00108   
00109   Types::Coordinate currSampling = std::max( this->m_Sampling, 2 * std::min( this->m_ReferenceVolume->GetMinDelta(), this->m_FloatingVolume->GetMinDelta()));
00110   
00111   double coarsest = this->m_CoarsestResolution;
00112   if ( coarsest <= 0 ) coarsest = this->m_MaxStepSize;
00113 
00114   for ( ; (currSampling<=coarsest); currSampling *= 2 ) 
00115     {
00116     this->m_ParameterStack.push( Self::LevelParameters::SmartPtr( new Self::LevelParameters( currSampling ) ) );
00117     }
00118   
00119   this->m_Optimizer = Optimizer::SmartPtr( new BestNeighbourOptimizer( this->m_OptimizerStepFactor ) );   
00120   this->m_Optimizer->SetCallback( this->m_Callback );
00121   
00122   // default to rigid transformation
00123   if ( NumberDOFs.empty() )
00124     NumberDOFs.push_back( 6 );
00125   
00126   // push guard elements
00127   NumberDOFs.push_back( -1 );
00128   NumberDOFsFinal.push_back( -1 );
00129   // intialize iterator.
00130   NumberDOFsIterator = NumberDOFs.begin();
00131 
00132   return CALLBACK_OK;
00133 }
00134 
00135 Functional* 
00136 ImagePairAffineRegistration
00137 ::MakeFunctional( const int /*level*/, const Superclass::LevelParameters* parameters )
00138 {
00139   const Self::LevelParameters* levelParameters = dynamic_cast<const Self::LevelParameters*>( parameters );
00140   if ( ! levelParameters )
00141     {
00142     StdErr << "CODING ERROR: wrong RTTI for 'parameters'\n";
00143     exit( 1 );
00144     }
00145 
00146   AffineXform::SmartPtr affineXform = AffineXform::SmartPtr::DynamicCastFrom( this->m_Xform );
00147   if ( ! affineXform )
00148     {
00149     StdErr << "CODING ERROR: wrong RTTI for 'this->m_Xform'\n";
00150     exit( 1 );
00151     }
00152   
00153   UniformVolume::SmartPtr nextRef, nextFlt;
00154   if ( levelParameters->m_Resolution > 0 )
00155     {
00156     nextRef = UniformVolume::SmartPtr( new UniformVolume( *this->m_ReferenceVolume, levelParameters->m_Resolution ) );
00157     nextFlt = UniformVolume::SmartPtr( new UniformVolume( *this->m_FloatingVolume, levelParameters->m_Resolution ) );
00158     }
00159   else
00160     {
00161     // for final, original resolution just take input volumes.
00162     nextRef = this->m_ReferenceVolume;
00163     nextFlt = this->m_FloatingVolume;
00164     }
00165   
00166   ImagePairAffineRegistrationFunctional *functional = ImagePairAffineRegistrationFunctional::Create( this->m_Metric, nextRef, nextFlt, this->m_FloatingImageInterpolation, affineXform );
00167   functional->SetForceOutside( this->m_ForceOutsideFlag, this->m_ForceOutsideValue );
00168   return functional;
00169 }
00170 
00171 void
00172 ImagePairAffineRegistration::EnterResolution
00173 ( CoordinateVector::SmartPtr& v, Functional::SmartPtr& f, const int level, const int total ) 
00174 {
00175   if ( *NumberDOFsIterator < 0 )
00176     {
00177     if ( (level == total) && (NumberDOFsFinal.size()>1) )
00178       NumberDOFsIterator = NumberDOFsFinal.begin();
00179     else
00180       NumberDOFsIterator = NumberDOFs.begin();
00181     }
00182 
00183   AffineXform::SmartPtr affineXform = AffineXform::SmartPtr::DynamicCastFrom( this->m_Xform );
00184   if ( affineXform ) 
00185     {
00186     affineXform->SetNumberDOFs( *NumberDOFsIterator );
00187     if ( this->m_Callback ) 
00188       {
00189       char buffer[64];
00190       snprintf( buffer, sizeof( buffer ), "Setting Number DOFs to %d.",  *NumberDOFsIterator );
00191       this->m_Callback->Comment( buffer );
00192       }
00193     }
00194   this->Superclass::EnterResolution( v, f, level, total );
00195 }
00196 
00197 int 
00198 ImagePairAffineRegistration::DoneResolution
00199 ( CoordinateVector::SmartPtr& v, Functional::SmartPtr& f,
00200   const int level, const int total )
00201 {
00202   this->Superclass::DoneResolution( v, f, level, total );
00203   
00204   NumberDOFsIterator++;
00205   return (*NumberDOFsIterator < 0);
00206 }
00207 
00208 AffineXform::SmartPtr
00209 ImagePairAffineRegistration::GetTransformation() const
00210 {
00211   AffineXform::SmartPtr affineXform = AffineXform::SmartPtr::DynamicCastFrom( this->m_Xform );
00212   return affineXform;
00213 }
00214 
00215 const UniformVolume::SmartPtr
00216 ImagePairAffineRegistration::GetReformattedFloatingImage( Interpolators::InterpolationEnum interpolator ) const
00217 {
00218   ReformatVolume reformat;
00219   reformat.SetInterpolation( interpolator );
00220   reformat.SetReferenceVolume( this->m_ReferenceVolume );
00221   reformat.SetFloatingVolume( this->m_FloatingVolume );
00222 
00223   AffineXform::SmartPtr affineXform( this->GetTransformation() );
00224   reformat.SetAffineXform( affineXform );
00225 
00226   return reformat.PlainReformat();
00227 }
00228 
00229 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines