cmtkGroupwiseRegistrationFunctionalXformTemplate_Affine.h

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2398 $
00026 //
00027 //  $LastChangedDate: 2010-10-05 14:54:37 -0700 (Tue, 05 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #ifndef __cmtkGroupwiseRegistrationFunctionalXformTemplate_Affine_h_included_
00034 #define __cmtkGroupwiseRegistrationFunctionalXformTemplate_Affine_h_included_
00035 
00036 #include <Base/cmtkTransformedVolumeAxes.h>
00037 #include <IO/cmtkClassStream.h>
00038 
00039 namespace
00040 cmtk
00041 {
00042 
00047 template<>
00048 class GroupwiseRegistrationFunctionalXformTemplate<AffineXform> : 
00050   public GroupwiseRegistrationFunctionalXformTemplateBase<AffineXform>
00051 {
00052 public:
00054   typedef GroupwiseRegistrationFunctionalXformTemplateBase<AffineXform> Superclass;
00055   
00057   typedef GroupwiseRegistrationFunctionalXformTemplate<AffineXform> Self;
00058 
00060   typedef SmartPointer<Self> SmartPtr;
00061 
00063   GroupwiseRegistrationFunctionalXformTemplate()
00064     : m_XformNumberDOFs( 9 )
00065   {
00066     this->m_ParametersPerXform = AffineXform::TotalNumberOfParameters;
00067   }
00068 
00070   virtual ~GroupwiseRegistrationFunctionalXformTemplate() {}
00071 
00073   void SetXformNumberDOFs( const int numberDOFs )
00074   { 
00075     this->m_XformNumberDOFs = numberDOFs;
00076     std::vector<Xform::SmartPtr>::iterator it = this->m_XformVector.begin();
00077     while ( it != this->m_XformVector.end() )
00078       {
00079       AffineXform::SmartPtr::DynamicCastFrom(*it)->SetNumberDOFs( this->m_XformNumberDOFs );
00080       ++it;
00081       }
00082   }
00083   
00086   void SetXforms( const std::vector<AffineXform::SmartPtr>& xformVector )
00087   {
00088     this->m_XformVector.resize( xformVector.size() );
00089     for ( size_t i = 0; i < this->m_XformVector.size(); ++i )
00090       {
00091       AffineXform::SmartPtr xform( new AffineXform( *(xformVector[i]) ) );
00092       xform->SetNumberDOFs( this->m_XformNumberDOFs );
00093       xform->SetUseLogScaleFactors( true );
00094       
00095       const Vector3D center = this->m_ImageVector[i]->GetCenterCropRegion();
00096       xform->ChangeCenter( center );
00097       
00098       this->m_XformVector[i] = xform;
00099       }
00100   }
00101   
00102 protected:
00104   int m_XformNumberDOFs;
00105 
00113   virtual void InterpolateImage( const size_t idx, byte* const destination )
00114   {
00115     const TransformedVolumeAxes gridHash( *this->m_TemplateGrid, this->GetXformByIndex( idx ) );
00116     
00117     ThreadPool& threadPool = ThreadPool::GetGlobalThreadPool();
00118 
00119     std::vector<InterpolateImageThreadParameters> params( 4 * threadPool.GetNumberOfThreads() );
00120     for ( size_t thread = 0; thread < params.size(); ++thread )
00121       {
00122       params[thread].thisObject = this;
00123       params[thread].m_Idx = idx;
00124       params[thread].m_Destination = destination;    
00125       params[thread].m_HashX = gridHash[0];
00126       params[thread].m_HashY = gridHash[1];
00127       params[thread].m_HashZ = gridHash[2];
00128       }
00129     
00130     if ( (this->m_ProbabilisticSampleDensity > 0) && (this->m_ProbabilisticSampleDensity < 1) )
00131       threadPool.Run( InterpolateImageProbabilisticThread, params );
00132     else
00133       threadPool.Run( InterpolateImageThread, params );
00134   }
00135   
00137   static void InterpolateImageThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00138   {
00139     InterpolateImageThreadParameters* threadParameters = static_cast<InterpolateImageThreadParameters*>( args );
00140     
00141     const Self* This = threadParameters->thisObject;
00142     const size_t idx = threadParameters->m_Idx;
00143     byte* destination = threadParameters->m_Destination;
00144     
00145     const UniformVolume* target = This->m_ImageVector[idx];
00146     
00147     const byte paddingValue = This->m_PaddingValue;
00148     const byte backgroundValue = This->m_UserBackgroundFlag ? This->m_PrivateUserBackgroundValue : paddingValue;
00149     
00150     Vector3D v;
00151     byte value;
00152     const byte* dataPtr = static_cast<const byte*>( target->GetData()->GetDataPtr() );
00153     
00154     const int dimsX = This->m_TemplateGrid->GetDims()[AXIS_X];
00155     const int dimsY = This->m_TemplateGrid->GetDims()[AXIS_Y];
00156     const int dimsZ = This->m_TemplateGrid->GetDims()[AXIS_Z];
00157     
00158     const int rowCount = ( dimsY * dimsZ );
00159     const int rowFrom = ( rowCount / taskCnt ) * taskIdx;
00160     const int rowTo = ( taskIdx == (taskCnt-1) ) ? rowCount : ( rowCount / taskCnt ) * ( taskIdx + 1 );
00161     int rowsToDo = rowTo - rowFrom;
00162     
00163     int yFrom = rowFrom % dimsY;
00164     int zFrom = rowFrom / dimsY;
00165     
00166     UniformVolume::CoordinateVectorType planeStart, rowStart;
00167     byte *wptr = destination + rowFrom * dimsX;
00168     for ( int z = zFrom; (z < dimsZ) && rowsToDo; ++z ) 
00169       {
00170       planeStart = threadParameters->m_HashZ[z];
00171       for ( int y = yFrom; (y < dimsY) && rowsToDo; yFrom = 0, ++y, --rowsToDo )
00172         {
00173         (rowStart = planeStart) += threadParameters->m_HashY[y];
00174         for ( int x = 0; x < dimsX; ++x )
00175           {
00176           (v = rowStart) += threadParameters->m_HashX[x];       
00177           if ( target->ProbeData( value, dataPtr, v ) )
00178             {
00179             *wptr = value;
00180             }
00181           else
00182             {
00183             *wptr = backgroundValue;
00184             }
00185           
00186           ++wptr;
00187           }
00188         }
00189       }
00190   }
00191   
00193   static void InterpolateImageProbabilisticThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00194   {
00195     InterpolateImageThreadParameters* threadParameters = static_cast<InterpolateImageThreadParameters*>( args );
00196     
00197     const Self* This = threadParameters->thisObject;
00198     const size_t idx = threadParameters->m_Idx;
00199     byte* destination = threadParameters->m_Destination;
00200     
00201     const AffineXform* xform = This->GetXformByIndex( idx );
00202     const UniformVolume* target = This->m_ImageVector[idx];
00203     
00204     const byte paddingValue = This->m_PaddingValue;
00205     const byte backgroundValue = This->m_UserBackgroundFlag ? This->m_PrivateUserBackgroundValue : paddingValue;
00206     
00207     UniformVolume::CoordinateVectorType v;
00208     byte value;
00209     const byte* dataPtr = static_cast<const byte*>( target->GetData()->GetDataPtr() );
00210     
00211     const size_t startIdx = taskIdx * (This->m_ProbabilisticSamples.size() / taskCnt);
00212     const size_t endIdx = ( taskIdx == (taskCnt-1) ) ? This->m_ProbabilisticSamples.size() : (taskIdx+1) * (This->m_ProbabilisticSamples.size() / taskCnt);
00213     
00214     byte *wptr = destination + startIdx;
00215     for ( size_t i = startIdx; i < endIdx; ++i, ++wptr )
00216       {
00217       const size_t offset = This->m_ProbabilisticSamples[i];
00218       v = This->m_TemplateGrid->GetGridLocation( offset );
00219       xform->ApplyInPlace( v );
00220       
00221       if ( target->ProbeData( value, dataPtr, v ) )
00222         {
00223         *wptr = value;
00224         }
00225       else
00226         {
00227         *wptr = backgroundValue;
00228         }
00229       }
00230   }
00231 
00232 private:
00234   class InterpolateImageThreadParameters : 
00236     public ThreadParameters<Self>
00237   {
00238   public:
00240     size_t m_Idx;
00241 
00243     byte* m_Destination;
00244 
00245     const Vector3D* m_HashX;
00246     const Vector3D* m_HashY;
00247     const Vector3D* m_HashZ;
00248   };
00249 
00250   friend ClassStream& operator<<( ClassStream& stream, const GroupwiseRegistrationFunctionalXformTemplate<AffineXform>& func );
00251   friend ClassStream& operator>>( ClassStream& stream, GroupwiseRegistrationFunctionalXformTemplate<AffineXform>& func );
00252 };
00253 
00254 ClassStream& operator<<( ClassStream& stream, const GroupwiseRegistrationFunctionalXformTemplate<AffineXform>& func );
00255 ClassStream& operator>>( ClassStream& stream, GroupwiseRegistrationFunctionalXformTemplate<AffineXform>& func );
00256 
00257 } // namespace cmtk
00258 
00259 #endif // #ifndef __cmtkGroupwiseRegistrationFunctionalXformTemplate_Affine_h_included_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines