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 "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
00123 if ( NumberDOFs.empty() )
00124 NumberDOFs.push_back( 6 );
00125
00126
00127 NumberDOFs.push_back( -1 );
00128 NumberDOFsFinal.push_back( -1 );
00129
00130 NumberDOFsIterator = NumberDOFs.begin();
00131
00132 return CALLBACK_OK;
00133 }
00134
00135 Functional*
00136 ImagePairAffineRegistration
00137 ::MakeFunctional( const int , 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
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 }