cmtkGroupwiseRegistrationFunctionalXformTemplate_SplineWarp.cxx

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     // create all-zero parameter vector
00059     CoordinateVector v( initialAffineXformsVector[i]->ParamVectorDim(), 0.0 );
00060     // copy rotation angles
00061     for ( size_t p = 3; p < 6; ++p )
00062       v[p] = initialAffineXformsVector[i]->GetParameter( p );
00063     // create rotation-only transformation
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 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines