cmtkAffineRegistration.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: 2398 $
00026 //
00027 //  $LastChangedDate: 2010-10-05 14:54:37 -0700 (Tue, 05 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include <Registration/cmtkAffineRegistration.h>
00034 
00035 #include <Base/cmtkVector.h>
00036 
00037 #include <Base/cmtkXform.h>
00038 #include <Base/cmtkAffineXform.h>
00039 
00040 #include <Base/cmtkVolume.h>
00041 #include <Base/cmtkUniformVolume.h>
00042 #include <Base/cmtkFunctional.h>
00043 
00044 #include <Registration/cmtkVoxelMatchingAffineFunctional.h>
00045 #include <Registration/cmtkImagePairAffineRegistrationFunctional.h>
00046 #include <Base/cmtkTypedArrayFunctionHistogramMatching.h>
00047 
00048 #include <Registration/cmtkOptimizer.h>
00049 #include <Registration/cmtkBestNeighbourOptimizer.h>
00050 
00051 #include <Registration/cmtkReformatVolume.h>
00052 
00053 #include <System/cmtkTimers.h>
00054 
00055 namespace
00056 cmtk
00057 {
00058 
00061 
00062 AffineRegistration::AffineRegistration () :
00063   m_MatchFltToRefHistogram( false )
00064 { 
00065   this->m_InitialAlignCenters = false;
00066   this->m_NoSwitch = false;
00067 }
00068 
00069 AffineRegistration::~AffineRegistration () 
00070 {
00071 }
00072 
00073 CallbackResult 
00074 AffineRegistration::InitRegistration ()
00075 {
00076   CallbackResult result = this->Superclass::InitRegistration();
00077   if ( result != CALLBACK_OK ) return result;
00078 
00079   if ( this->m_NoSwitch || (this->m_Volume_1->AverageVoxelVolume() >= this->m_Volume_2->AverageVoxelVolume()) ) 
00080     {
00081     this->m_ReferenceVolume = this->m_Volume_1;
00082     this->m_FloatingVolume = this->m_Volume_2;
00083     SwitchVolumes = false;
00084     } 
00085   else
00086     {
00087     this->m_ReferenceVolume = this->m_Volume_2;
00088     this->m_FloatingVolume = this->m_Volume_1;
00089     SwitchVolumes = true;
00090     }
00091   
00092   if ( this->m_MatchFltToRefHistogram )
00093     {
00094     this->GetVolume_2()->GetData()->ApplyFunctionObject( TypedArrayFunctionHistogramMatching( *(this->GetVolume_2()->GetData()), *(this->GetVolume_1()->GetData()) ) );
00095     }
00096   
00097   AffineXform::SmartPtr affineXform;
00098 
00099   if ( this->m_InitialTransformation )
00100     {
00101     if ( SwitchVolumes ^ this->m_InitialXformIsInverse )
00102       {
00103       affineXform = AffineXform::SmartPtr( this->m_InitialTransformation->MakeInverse() );
00104       } 
00105     else
00106       {
00107       affineXform = AffineXform::SmartPtr( this->m_InitialTransformation );
00108       }
00109   } 
00110   else 
00111     {
00112     affineXform = AffineXform::SmartPtr( new AffineXform );
00113     }
00114 
00115   if ( this->m_InitialAlignCenters ) 
00116     {
00117     Vector3D deltaCenter = ( this->m_FloatingVolume->GetCenterCropRegion() - this->m_ReferenceVolume->GetCenterCropRegion() );
00118     affineXform->SetXlate( deltaCenter.begin() );
00119     }
00120   
00121   this->m_Xform = affineXform;
00122   
00123   Vector3D center = this->m_ReferenceVolume->GetCenterCropRegion();
00124   affineXform->ChangeCenter( center );
00125 
00126   if ( this->m_UseOriginalData ) 
00127     {
00128     Functional::SmartPtr newFunctional( VoxelMatchingAffineFunctional::Create( this->m_Metric, this->m_ReferenceVolume, this->m_FloatingVolume, affineXform ) );
00129     FunctionalStack.push( newFunctional );
00130     }
00131   
00132   Types::Coordinate currSampling = std::max( this->m_Sampling, 2 * std::min( this->m_ReferenceVolume->GetMinDelta(), this->m_FloatingVolume->GetMinDelta()));
00133   
00134   double coarsest = CoarsestResolution;
00135   if ( coarsest <= 0 ) coarsest = this->m_Exploration;
00136 
00137   UniformVolume::SmartPtr currRef( this->m_ReferenceVolume );
00138   UniformVolume::SmartPtr currFlt( this->m_FloatingVolume );
00139   
00140   for ( ; (currSampling<=coarsest); currSampling *= 2 ) 
00141     {
00142     UniformVolume::SmartPtr nextRef( new UniformVolume( *currRef, currSampling ) );
00143     UniformVolume::SmartPtr nextFlt( new UniformVolume( *currFlt, currSampling ) );
00144     
00145     Functional::SmartPtr newFunctional( VoxelMatchingAffineFunctional::Create( this->m_Metric, nextRef, nextFlt, affineXform ) );
00146     FunctionalStack.push( newFunctional );
00147     
00148     currRef = nextRef;
00149     currFlt = nextFlt;
00150     }
00151 
00152   this->m_Optimizer = Optimizer::SmartPtr( new BestNeighbourOptimizer( OptimizerStepFactor ) );   
00153   this->m_Optimizer->SetCallback( this->m_Callback );
00154   
00155   // default to rigid transformation
00156   if ( NumberDOFs.empty() )
00157     NumberDOFs.push_back( 6 );
00158   
00159   // push guard elements
00160   NumberDOFs.push_back( -1 );
00161   NumberDOFsFinal.push_back( -1 );
00162   // intialize iterator.
00163   NumberDOFsIterator = NumberDOFs.begin();
00164 
00165   return CALLBACK_OK;
00166 }
00167 
00168 void
00169 AffineRegistration::EnterResolution
00170 ( CoordinateVector::SmartPtr& v, Functional::SmartPtr& f, const int level, const int total ) 
00171 {
00172   if ( *NumberDOFsIterator < 0 )
00173     {
00174     if ( (level == total) && (NumberDOFsFinal.size()>1) )
00175       NumberDOFsIterator = NumberDOFsFinal.begin();
00176     else
00177       NumberDOFsIterator = NumberDOFs.begin();
00178     }
00179 
00180   AffineXform::SmartPtr affineXform = AffineXform::SmartPtr::DynamicCastFrom( this->m_Xform );
00181   if ( affineXform ) 
00182     {
00183     int numberDOFs = std::min<int>( 12, *NumberDOFsIterator );
00184     affineXform->SetNumberDOFs( numberDOFs );
00185     if ( this->m_Callback ) 
00186       {
00187       char buffer[64];
00188       snprintf( buffer, sizeof( buffer ), "Setting Number DOFs to %d.", numberDOFs );
00189       this->m_Callback->Comment( buffer );
00190       }
00191     }
00192   this->Superclass::EnterResolution( v, f, level, total );
00193 }
00194 
00195 int 
00196 AffineRegistration::DoneResolution
00197 ( CoordinateVector::SmartPtr& v, Functional::SmartPtr& f,
00198   const int level, const int total )
00199 {
00200   this->Superclass::DoneResolution( v, f, level, total );
00201   
00202   NumberDOFsIterator++;
00203   return (*NumberDOFsIterator < 0);
00204 }
00205 
00206 AffineXform::SmartPtr
00207 AffineRegistration::GetTransformation() const
00208 {
00209   AffineXform::SmartPtr affineXform = AffineXform::SmartPtr::DynamicCastFrom( this->m_Xform );
00210   if ( affineXform && SwitchVolumes ) 
00211     {
00212     return affineXform->GetInverse();
00213     } 
00214   else 
00215     {
00216     return affineXform;
00217     }
00218 }
00219 
00220 const UniformVolume::SmartPtr
00221 AffineRegistration::GetReformattedFloatingImage( Interpolators::InterpolationEnum interpolator ) const
00222 {
00223   ReformatVolume reformat;
00224   reformat.SetInterpolation( interpolator );
00225   reformat.SetReferenceVolume( this->SwitchVolumes ? this->m_Volume_2 :  this->m_Volume_1 );
00226   reformat.SetFloatingVolume(  this->SwitchVolumes ? this->m_Volume_1 : this->m_Volume_2 );
00227 
00228   AffineXform::SmartPtr affineXform( this->GetTransformation() );
00229   reformat.SetAffineXform( affineXform );
00230 
00231   return reformat.PlainReformat();
00232 }
00233 
00234 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines