Go to the documentation of this file.00001 #include <Registration/cmtkGroupwiseRegistrationFunctionalXformTemplate.h>
00002
00003 namespace
00004 cmtk
00005 {
00006
00007 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00008 ::GroupwiseRegistrationFunctionalXformTemplate()
00009 : m_ForceZeroSumNoAffine( false )
00010 {
00011 this->m_ParametersPerXform = 0;
00012 this->m_WarpFastMode = true;
00013 this->m_PartialGradientMode = false;
00014 this->m_PartialGradientThreshold = static_cast<Types::DataItem>( 0.01 );
00015 this->m_DeactivateUninformativeMode = false;
00016 this->m_NumberOfActiveControlPoints = 0;
00017 this->m_JacobianConstraintWeight = 0.0;
00018 this->m_BendingEnergyWeight = 0.0;
00019
00020 this->SetFreeAndRereadImages( true );
00021 }
00022
00023 void
00024 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00025 ::SetTemplateGrid
00026 ( UniformVolume::SmartPtr& templateGrid, const int downsample, const bool useTemplateData )
00027 {
00028 this->Superclass::SetTemplateGrid( templateGrid, downsample, useTemplateData );
00029
00030 if ( this->m_XformVector.size() )
00031 {
00032 for ( size_t i = 0; i < this->m_XformVector.size(); ++i )
00033 {
00034 dynamic_cast<SplineWarpXform&>( *(this->m_XformVector[i]) ).RegisterVolume( this->m_TemplateGrid );
00035 }
00036 this->UpdateVolumesOfInfluence();
00037 }
00038 }
00039
00040 void
00041 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00042 ::InitializeXformsFromAffine
00043 ( const Types::Coordinate gridSpacing, std::vector<AffineXform::SmartPtr> initialAffineXformsVector, const bool exactSpacing )
00044 {
00045 this->m_InitialAffineXformsVector = initialAffineXformsVector;
00046
00047 this->m_XformVector.resize( this->m_ImageVector.size() );
00048 this->m_InitialRotationsVector.resize( this->m_ImageVector.size() );
00049
00050 for ( size_t i = 0; i < this->m_ImageVector.size(); ++i )
00051 {
00052 SplineWarpXform::SmartPtr xform( new SplineWarpXform( this->m_TemplateGrid->Size, gridSpacing, initialAffineXformsVector[i], exactSpacing ) );
00053 xform->RegisterVolume( this->m_TemplateGrid );
00054 this->m_XformVector[i] = xform;
00055
00056 this->m_InitialRotationsVector[i] = AffineXform::SmartPtr( initialAffineXformsVector[i] );
00057
00058
00059 CoordinateVector v( initialAffineXformsVector[i]->ParamVectorDim(), 0.0 );
00060
00061 for ( size_t p = 3; p < 6; ++p )
00062 v[p] = initialAffineXformsVector[i]->GetParameter( p );
00063
00064 this->m_InitialRotationsVector[i]->SetParamVector( v );
00065 }
00066
00067 this->m_ParametersPerXform = this->m_XformVector[0]->VariableParamVectorDim();
00068
00069 this->UpdateVolumesOfInfluence();
00070 }
00071
00072 void
00073 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00074 ::RefineTransformationGrids()
00075 {
00076
00077 for ( size_t i = 0; i < this->m_XformVector.size(); ++i )
00078 {
00079 this->GetXformByIndex(i)->Refine();
00080 dynamic_cast<SplineWarpXform&>( *(this->m_XformVector[i]) ).RegisterVolume( this->m_TemplateGrid );
00081 }
00082
00083 this->m_ParametersPerXform = this->m_XformVector[0]->VariableParamVectorDim();
00084
00085 this->UpdateVolumesOfInfluence();
00086 }
00087
00088 void
00089 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00090 ::UpdateVolumesOfInfluence()
00091 {
00092 const Vector3D templateFrom( this->m_TemplateGrid->m_Offset );
00093 const Vector3D templateTo( this->m_TemplateGrid->m_Offset + this->m_TemplateGrid->Size );
00094
00095 this->m_VolumeOfInfluenceArray.resize( this->m_ParametersPerXform / 3 );
00096
00097 this->m_MaximumNumberOfPixelsPerLineVOI = 0;
00098 this->m_MaximumNumberOfPixelsVOI = 0;
00099
00100 const SplineWarpXform* xform0 = this->GetXformByIndex(0);
00101 for ( size_t param = 0; param < this->m_ParametersPerXform; param += 3 )
00102 {
00103 Vector3D fromVOI, toVOI;
00104 xform0->GetVolumeOfInfluence( param, templateFrom, templateTo, fromVOI, toVOI );
00105
00106 DataGrid::RegionType& voi = this->m_VolumeOfInfluenceArray[param/3];
00107 voi = this->m_TemplateGrid->GetGridRange( fromVOI, toVOI );
00108
00109 this->m_MaximumNumberOfPixelsVOI = std::max<size_t>( voi.Size(), this->m_MaximumNumberOfPixelsVOI );
00110 this->m_MaximumNumberOfPixelsPerLineVOI = std::max<size_t>( voi.To()[0]-voi.From()[0], this->m_MaximumNumberOfPixelsPerLineVOI );
00111 }
00112 }
00113
00114 bool
00115 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00116 ::UpdateParamStepArray()
00117 {
00118 bool changed = false;
00119
00120 this->m_ParamStepArray.resize( this->ParamVectorDim() );
00121
00122 if ( this->m_DeactivateUninformativeMode &&
00123 ( this->m_ActiveControlPointFlags.size() == this->m_ParametersPerXform / 3 ) )
00124 {
00125 for ( size_t param = 0; param < this->ParamVectorDim(); ++param )
00126 {
00127 const Types::Coordinate pOld = this->m_ParamStepArray[param];
00128 this->m_ParamStepArray[param] = this->GetParamStep( param );
00129 if ( ! this->m_ActiveControlPointFlags[(param%this->m_ParametersPerXform)/3] )
00130 {
00131 this->m_ParamStepArray[param] = 0;
00132 }
00133 if ( pOld != this->m_ParamStepArray[param] )
00134 changed = true;
00135 }
00136 }
00137 else
00138 {
00139 for ( size_t param = 0; param < this->ParamVectorDim(); ++param )
00140 {
00141 const Types::Coordinate pOld = this->m_ParamStepArray[param];
00142 this->m_ParamStepArray[param] = this->GetParamStep( param );
00143 if ( pOld != this->m_ParamStepArray[param] )
00144 changed = true;
00145 }
00146 }
00147
00148 return changed;
00149 }
00150
00151 void
00152 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00153 ::ForceZeroSumGradient( CoordinateVector& g ) const
00154 {
00155 const size_t numberOfXforms = this->m_XformVector.size();
00156
00157 if ( this->m_ForceZeroSumNoAffine )
00158 {
00159 for ( size_t xform = 0; xform < numberOfXforms; ++xform )
00160 {
00161 Types::Coordinate* gX = &g[xform*this->m_ParametersPerXform];
00162 const AffineXform* affineXform = this->m_InitialRotationsVector[xform]->GetInverse();
00163 if ( affineXform )
00164 {
00165 #pragma omp parallel for
00166 for ( size_t param = 0; param < this->m_ParametersPerXform; param += 3 )
00167 {
00168 const FixedVector<3,Types::Coordinate> projected( affineXform->RotateScaleShear( FixedVector<3,Types::Coordinate>( gX+param ) ) );
00169 for ( size_t i = 0; i<3; ++i )
00170 gX[param+i] = projected[i];
00171 }
00172 }
00173 }
00174 }
00175
00176 this->Superclass::ForceZeroSumGradient( g );
00177
00178 if ( this->m_ForceZeroSumNoAffine )
00179 {
00180 for ( size_t xform = 0; xform < numberOfXforms; ++xform )
00181 {
00182 Types::Coordinate* gX = &g[xform*this->m_ParametersPerXform];
00183 const AffineXform* affineXform = this->m_InitialRotationsVector[xform];
00184 if ( affineXform )
00185 {
00186 #pragma omp parallel for
00187 for ( size_t param = 0; param < this->m_ParametersPerXform; param += 3 )
00188 {
00189 const FixedVector<3,Types::Coordinate> projected( affineXform->RotateScaleShear( FixedVector<3,Types::Coordinate>( gX+param ) ) );
00190 for ( size_t i = 0; i<3; ++i )
00191 gX[param+i] = projected[i];
00192 }
00193 }
00194 }
00195 }
00196 }
00197
00198 bool
00199 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00200 ::Wiggle()
00201 {
00202 bool wiggle = this->Superclass::Wiggle();
00203
00204 if ( this->m_PartialGradientMode )
00205 {
00206 wiggle = wiggle || this->UpdateParamStepArray();
00207 }
00208
00209 return wiggle;
00210 }
00211
00212 void
00213 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00214 ::InterpolateImage
00215 ( const size_t idx, byte* const destination )
00216 {
00217 ThreadPool& threadPool = ThreadPool::GetGlobalThreadPool();
00218 const size_t numberOfThreads = threadPool.GetNumberOfThreads();
00219 std::vector<InterpolateImageThreadParameters> params( numberOfThreads );
00220
00221 for ( size_t thread = 0; thread < numberOfThreads; ++thread )
00222 {
00223 params[thread].thisObject = this;
00224 params[thread].m_Idx = idx;
00225 params[thread].m_Destination = destination;
00226 }
00227
00228 threadPool.Run( InterpolateImageThread, params );
00229 }
00230
00231 void
00232 GroupwiseRegistrationFunctionalXformTemplate<SplineWarpXform>
00233 ::InterpolateImageThread
00234 ( void* args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00235 {
00236 InterpolateImageThreadParameters* threadParameters = static_cast<InterpolateImageThreadParameters*>( args );
00237
00238 const Self* This = threadParameters->thisObject;
00239 const size_t idx = threadParameters->m_Idx;
00240 byte* destination = threadParameters->m_Destination;
00241
00242 const SplineWarpXform* xform = This->GetXformByIndex(idx);
00243 const UniformVolume* target = This->m_ImageVector[idx];
00244 const byte* dataPtr = static_cast<const byte*>( target->GetData()->GetDataPtr() );
00245
00246 const byte paddingValue = This->m_PaddingValue;
00247 const byte backgroundValue = This->m_UserBackgroundFlag ? This->m_PrivateUserBackgroundValue : paddingValue;
00248
00249 const int dimsX = This->m_TemplateGrid->GetDims()[AXIS_X];
00250 const int dimsY = This->m_TemplateGrid->GetDims()[AXIS_Y];
00251 const int dimsZ = This->m_TemplateGrid->GetDims()[AXIS_Z];
00252
00253 std::vector<Xform::SpaceVectorType> v( dimsX );
00254 byte value;
00255
00256 const int rowCount = ( dimsY * dimsZ );
00257 const int rowFrom = ( rowCount / taskCnt ) * taskIdx;
00258 const int rowTo = ( taskIdx == (taskCnt-1) ) ? rowCount : ( rowCount / taskCnt ) * ( taskIdx + 1 );
00259 int rowsToDo = rowTo - rowFrom;
00260
00261 int yFrom = rowFrom % dimsY;
00262 int zFrom = rowFrom / dimsY;
00263
00264 byte *wptr = destination + rowFrom * dimsX;
00265 for ( int z = zFrom; (z < dimsZ) && rowsToDo; ++z )
00266 {
00267 for ( int y = yFrom; (y < dimsY) && rowsToDo; yFrom = 0, ++y, --rowsToDo )
00268 {
00269 xform->GetTransformedGridRow( dimsX, &v[0], 0, y, z );
00270 for ( int x = 0; x < dimsX; ++x )
00271 {
00272 if ( target->ProbeData( value, dataPtr, v[x] ) )
00273 {
00274 *wptr = value;
00275 }
00276 else
00277 {
00278 *wptr = backgroundValue;
00279 }
00280
00281 ++wptr;
00282 }
00283 }
00284 }
00285 }
00286
00287 }