Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "cmtkImagePairRegistration.h"
00034
00035 #include <Base/cmtkVector.h>
00036 #include <Base/cmtkXform.h>
00037 #include <Base/cmtkAffineXform.h>
00038 #include <Base/cmtkFunctional.h>
00039
00040 #include <System/cmtkTimers.h>
00041 #include <System/cmtkProgress.h>
00042
00043 #ifdef HAVE_SYS_UTSNAME_H
00044 # include <sys/utsname.h>
00045 #endif
00046
00047 namespace
00048 cmtk
00049 {
00050
00053
00054 ImagePairRegistration::ImagePairRegistration ()
00055 : m_Metric( 0 ),
00056 m_FloatingImageInterpolation( Interpolators::DEFAULT ),
00057 m_AutoMultiLevels( 0 ),
00058 m_MaxStepSize( -1 ),
00059 m_MinStepSize( -1 ),
00060 m_DeltaFThreshold( 0.0 ),
00061 m_Sampling( -1 ),
00062 m_ForceOutsideFlag( false ),
00063 m_ForceOutsideValue( 0.0 ),
00064 m_PreprocessorRef( "Reference", "ref" ),
00065 m_PreprocessorFlt( "Floating", "flt" ),
00066 m_InitialTransformation( NULL ),
00067 m_InitialXformIsInverse( false ),
00068 m_Xform( NULL ),
00069 m_Optimizer( NULL )
00070 {
00071 this->m_Callback = RegistrationCallback::SmartPtr( new RegistrationCallback() );
00072
00073 this->m_Sampling = -1;
00074 this->m_CoarsestResolution = -1;
00075 this->m_UseOriginalData = true;
00076
00077 this->m_Algorithm = 0;
00078 this->m_UseMaxNorm = true;
00079 this->m_OptimizerStepFactor = 0.5;
00080 }
00081
00082 CallbackResult
00083 ImagePairRegistration::InitRegistration ()
00084 {
00085 if ( this->m_AutoMultiLevels > 0 )
00086 {
00087 const Types::Coordinate minDelta = std::min( this->m_Volume_1->GetMinDelta(), this->m_Volume_2->GetMinDelta() );
00088 const Types::Coordinate maxDelta = std::max( this->m_Volume_1->GetMaxDelta(), this->m_Volume_2->GetMaxDelta() );
00089
00090 this->m_MinStepSize = 0.1 * minDelta;
00091 this->m_Sampling = maxDelta;
00092 this->m_MaxStepSize = maxDelta * (1<<(this->m_AutoMultiLevels-1));
00093 }
00094
00095 if ( this->m_Sampling <= 0 )
00096 this->m_Sampling = std::max( this->m_Volume_1->GetMaxDelta(), this->m_Volume_2->GetMaxDelta() );
00097
00098 if ( this->m_MaxStepSize <= 0 )
00099 this->m_MaxStepSize = 8.0 * this->m_Sampling;
00100
00101 if ( this->m_MinStepSize <= 0 )
00102 this->m_MinStepSize = this->m_Sampling / 128;
00103
00104 this->m_TimeStartLevel = this->m_TimeStartRegistration = cmtk::Timers::GetTimeProcess();
00105 this->m_WalltimeStartLevel = this->m_WalltimeStartRegistration = cmtk::Timers::GetWalltime();
00106 this->m_ThreadTimeStartLevel = this->m_ThreadTimeStartRegistration = cmtk::Timers::GetTimeThread();
00107
00108 return CALLBACK_OK;
00109 }
00110
00111 CallbackResult
00112 ImagePairRegistration::Register ()
00113 {
00114 CallbackResult irq = this->InitRegistration();
00115 if ( irq != CALLBACK_OK )
00116 {
00117 this->DoneRegistration();
00118 return irq;
00119 }
00120
00121 this->m_Optimizer->SetDeltaFThreshold( this->m_DeltaFThreshold );
00122
00123 Types::Coordinate currentExploration = this->m_MaxStepSize;
00124 CoordinateVector::SmartPtr v( new CoordinateVector() );
00125 const size_t NumResolutionLevels = this->m_ParameterStack.size();
00126
00127 Progress::Begin( 0, NumResolutionLevels, 1, "Multi-level Registration" );
00128
00129 unsigned int index = 1;
00130 while ( ! this->m_ParameterStack.empty() && ( irq == CALLBACK_OK ) )
00131 {
00132 Functional::SmartPtr nextFunctional( this->MakeFunctional( index-1, this->m_ParameterStack.top() ) );
00133 this->m_ParameterStack.pop();
00134
00135
00136
00137
00138
00139 this->m_Optimizer->SetFunctional( nextFunctional );
00140
00141 int doneResolution = 0;
00142 while ( ! doneResolution && ( irq == CALLBACK_OK ) )
00143 {
00144 this->EnterResolution( v, nextFunctional, index, NumResolutionLevels );
00145
00146 if ( irq == CALLBACK_OK )
00147 {
00148 Types::Coordinate effectiveAccuracy = (index == NumResolutionLevels) ? std::max<Types::Coordinate>( this->m_MinStepSize, currentExploration/1024 ) : this->m_MinStepSize;
00149
00150 irq = this->m_Optimizer->Optimize( *v, currentExploration, effectiveAccuracy );
00151 this->m_Xform->SetParamVector( *v );
00152 }
00153
00154 doneResolution = this->DoneResolution( v, nextFunctional, index, NumResolutionLevels );
00155 }
00156
00157 this->m_Optimizer->SetFunctional( Functional::SmartPtr::Null );
00158
00159 currentExploration *= 0.5;
00160
00161 Progress::SetProgress( index );
00162
00163 ++index;
00164 }
00165
00166 Progress::Done();
00167
00168 this->OutputResult( v );
00169 this->DoneRegistration( v );
00170
00171 return irq;
00172 }
00173
00174 void
00175 ImagePairRegistration::DoneRegistration( const CoordinateVector* v )
00176 {
00177 if ( v )
00178 this->m_Xform->SetParamVector( *v );
00179 }
00180
00181 void
00182 ImagePairRegistration::EnterResolution
00183 ( CoordinateVector::SmartPtr& v, Functional::SmartPtr& f,
00184 const int idx, const int total )
00185 {
00186 if ( this->m_Callback )
00187 {
00188 char comment[128];
00189 snprintf( comment, sizeof( comment ), "Entering resolution level %d out of %d.", idx, total );
00190 this->m_Callback->Comment( comment );
00191 }
00192
00193 this->m_TimeStartLevel = cmtk::Timers::GetTimeProcess();
00194 this->m_WalltimeStartLevel = cmtk::Timers::GetWalltime();
00195 this->m_ThreadTimeStartLevel = cmtk::Timers::GetTimeThread();
00196
00197 f->GetParamVector( *v );
00198 }
00199
00200 }