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 "cmtkImagePairNonrigidRegistrationFunctional.h"
00034
00035 #include <Base/cmtkSplineWarpXform.h>
00036 #include <Base/cmtkInterpolator.h>
00037
00038 #include <Registration/cmtkImagePairNonrigidRegistrationFunctionalTemplate.h>
00039
00040 #include <Registration/cmtkImagePairSimilarityMeasureCR.h>
00041 #include <Registration/cmtkImagePairSimilarityMeasureMSD.h>
00042 #include <Registration/cmtkImagePairSimilarityMeasureRMS.h>
00043 #include <Registration/cmtkImagePairSimilarityMeasureNCC.h>
00044 #include <Registration/cmtkImagePairSimilarityMeasureNMI.h>
00045 #include <Registration/cmtkImagePairSimilarityMeasureMI.h>
00046
00047 namespace
00048 cmtk
00049 {
00050
00053
00054 ImagePairNonrigidRegistrationFunctional::ImagePairNonrigidRegistrationFunctional
00055 ( UniformVolume::SmartPtr& reference, UniformVolume::SmartPtr& floating )
00056 : ImagePairRegistrationFunctional( reference, floating ),
00057 m_ActiveCoordinates( NULL )
00058 {
00059 this->m_NumberOfThreads = ThreadPool::GetGlobalThreadPool().GetNumberOfThreads();
00060 this->m_NumberOfTasks = 4 * this->m_NumberOfThreads - 3;
00061
00062 Dim = 0;
00063
00064 ReferenceFrom = UniformVolume::CoordinateVectorType( UniformVolume::CoordinateVectorType::Init( 0 ) );
00065 ReferenceTo = reference->Size;
00066
00067 this->m_AdaptiveFixParameters = false;
00068 this->m_AdaptiveFixThreshFactor = 0.5;
00069 this->VolumeOfInfluence = NULL;
00070
00071 this->m_ThreadWarp.resize( this->m_NumberOfThreads );
00072
00073 this->m_ThreadVectorCache = Memory::AllocateArray<Vector3D*>( this->m_NumberOfThreads );
00074 for ( size_t thread = 0; thread < this->m_NumberOfThreads; ++thread )
00075 this->m_ThreadVectorCache[thread] = Memory::AllocateArray<Vector3D>( this->m_ReferenceDims[0] );
00076
00077 this->m_WarpedVolume = NULL;
00078
00079 this->m_DimsX = this->m_ReferenceGrid->GetDims()[0];
00080 this->m_DimsY = this->m_ReferenceGrid->GetDims()[1];
00081 this->m_DimsZ = this->m_ReferenceGrid->GetDims()[2];
00082
00083 this->m_FltDimsX = this->m_FloatingGrid->GetDims()[0];
00084 this->m_FltDimsY = this->m_FloatingGrid->GetDims()[1];
00085 }
00086
00087 ImagePairNonrigidRegistrationFunctional::~ImagePairNonrigidRegistrationFunctional()
00088 {
00089 for ( size_t thread = 0; thread < this->m_NumberOfThreads; ++thread )
00090 if ( this->m_ThreadVectorCache[thread] )
00091 Memory::DeleteArray( this->m_ThreadVectorCache[thread] );
00092 Memory::DeleteArray( this->m_ThreadVectorCache );
00093 }
00094
00095 void
00096 ImagePairNonrigidRegistrationFunctional::WeightedDerivative
00097 ( double& lower, double& upper, SplineWarpXform& warp,
00098 const int param, const Types::Coordinate step ) const
00099 {
00100 if ( this->m_JacobianConstraintWeight > 0 )
00101 {
00102 double lowerConstraint = 0, upperConstraint = 0;
00103 warp.GetJacobianConstraintDerivative( lowerConstraint, upperConstraint, param, VolumeOfInfluence[param], step );
00104 lower -= this->m_JacobianConstraintWeight * lowerConstraint;
00105 upper -= this->m_JacobianConstraintWeight * upperConstraint;
00106 }
00107
00108 if ( this->m_GridEnergyWeight > 0 )
00109 {
00110 double lowerEnergy = 0, upperEnergy = 0;
00111 warp.GetGridEnergyDerivative( lowerEnergy, upperEnergy, param, step );
00112 lower -= this->m_GridEnergyWeight * lowerEnergy;
00113 upper -= this->m_GridEnergyWeight * upperEnergy;
00114 }
00115
00116
00117
00118 if ( !finite(upper) || !finite(lower) )
00119 {
00120 lower = upper = 0;
00121 }
00122 else
00123 {
00124 if ( this->m_MatchedLandmarkList )
00125 {
00126 double lowerMSD, upperMSD;
00127 warp.GetDerivativeLandmarksMSD( lowerMSD, upperMSD, this->m_MatchedLandmarkList, param, step );
00128 lower -= this->m_LandmarkErrorWeight * lowerMSD;
00129 upper -= this->m_LandmarkErrorWeight * upperMSD;
00130 }
00131 if ( this->m_InverseTransformation )
00132 {
00133 double lowerIC, upperIC;
00134 warp.GetDerivativeInverseConsistencyError( lowerIC, upperIC, this->m_InverseTransformation, this->m_ReferenceGrid, &(this->VolumeOfInfluence[param]), param, step );
00135 lower -= this->m_InverseConsistencyWeight * lowerIC;
00136 upper -= this->m_InverseConsistencyWeight * upperIC;
00137 }
00138 }
00139 }
00140
00141 void
00142 ImagePairNonrigidRegistrationFunctional::SetWarpXform
00143 ( SplineWarpXform::SmartPtr& warp )
00144 {
00145 this->m_Warp = warp;
00146 if ( this->m_Warp )
00147 {
00148 this->m_Warp->RegisterVolume( this->m_ReferenceGrid );
00149 if ( Dim != this->m_Warp->VariableParamVectorDim() )
00150 {
00151 Dim = this->m_Warp->VariableParamVectorDim();
00152 this->m_StepScaleVector.resize( Dim );
00153 VolumeOfInfluence = Memory::AllocateArray<DataGrid::RegionType>( Dim );
00154 }
00155
00156 DataGrid::RegionType *VOIptr = VolumeOfInfluence;
00157 Vector3D fromVOI, toVOI;
00158 for ( size_t dim=0; dim<Dim; ++dim, ++VOIptr )
00159 {
00160 this->m_StepScaleVector[dim] = this->GetParamStep( dim );
00161 this->m_Warp->GetVolumeOfInfluence( dim, ReferenceFrom, ReferenceTo, fromVOI, toVOI );
00162 *VOIptr = this->GetReferenceGridRange( fromVOI, toVOI );
00163 }
00164
00165 for ( size_t thread = 0; thread < this->m_NumberOfThreads; ++thread )
00166 {
00167 if ( thread )
00168 {
00169 this->m_ThreadWarp[thread] = this->m_Warp->Clone();
00170 this->m_ThreadWarp[thread]->RegisterVolume( this->m_ReferenceGrid );
00171 }
00172 else
00173 {
00174 this->m_ThreadWarp[thread] = this->m_Warp;
00175 }
00176 }
00177 }
00178 }
00179
00180 ImagePairNonrigidRegistrationFunctional*
00181 ImagePairNonrigidRegistrationFunctional::Create
00182 ( const int metric,
00183 UniformVolume::SmartPtr& refVolume,
00184 UniformVolume::SmartPtr& fltVolume,
00185 const Interpolators::InterpolationEnum interpolation )
00186 {
00187 switch ( metric )
00188 {
00189 case 0:
00190 return new ImagePairNonrigidRegistrationFunctionalTemplate<ImagePairSimilarityMeasureNMI>( refVolume, fltVolume, interpolation );
00191 case 1:
00192 return new ImagePairNonrigidRegistrationFunctionalTemplate<ImagePairSimilarityMeasureMI>( refVolume, fltVolume, interpolation );
00193 case 2:
00194 return new ImagePairNonrigidRegistrationFunctionalTemplate<ImagePairSimilarityMeasureCR>( refVolume, fltVolume, interpolation );
00195 case 3:
00196 return new ImagePairNonrigidRegistrationFunctionalTemplate<ImagePairSimilarityMeasureRMS>( refVolume, fltVolume, interpolation );
00197 case 4:
00198 return new ImagePairNonrigidRegistrationFunctionalTemplate<ImagePairSimilarityMeasureMSD>( refVolume, fltVolume, interpolation );
00199 case 5:
00200 return new ImagePairNonrigidRegistrationFunctionalTemplate<ImagePairSimilarityMeasureNCC>( refVolume, fltVolume, interpolation );
00201 default:
00202 return NULL;
00203 }
00204
00205 return NULL;
00206 }
00207
00208 }