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 #ifndef __cmtkVoxelMatchingAffineFunctionalTemplate_h_included_
00033 #define __cmtkVoxelMatchingAffineFunctionalTemplate_h_included_
00034
00035 #include <cmtkconfig.h>
00036
00037 #include <Registration/cmtkVoxelMatchingAffineFunctional.h>
00038 #include <Registration/cmtkVoxelMatchingFunctional.h>
00039
00040 #include <Base/cmtkTransformedVolumeAxes.h>
00041
00042 namespace
00043 cmtk
00044 {
00045
00048
00058 template<class VM>
00059 class VoxelMatchingAffineFunctionalTemplate :
00061 public VoxelMatchingAffineFunctional,
00063 public VoxelMatchingFunctional_Template<VM>
00064 {
00065 public:
00067 typedef VoxelMatchingAffineFunctionalTemplate<VM> Self;
00068
00070 typedef SmartPointer<Self> SmartPtr;
00071
00073 typedef VoxelMatchingAffineFunctional Superclass;
00074
00076 typedef Functional::ReturnType ReturnType;
00077
00085 VoxelMatchingAffineFunctionalTemplate( UniformVolume::SmartPtr& reference, UniformVolume::SmartPtr& floating, AffineXform::SmartPtr& affineXform )
00086 : VoxelMatchingAffineFunctional( reference, floating, affineXform ),
00087 VoxelMatchingFunctional_Template<VM>( reference, floating ),
00088 m_NumberOfThreads( ThreadPool::GetGlobalThreadPool().GetNumberOfThreads() )
00089 {
00090 this->m_ThreadMetric.resize( m_NumberOfThreads, dynamic_cast<const VM&>( *(this->Metric) ) );
00091 }
00092
00094 virtual ~VoxelMatchingAffineFunctionalTemplate() {}
00095
00097 virtual typename Self::ReturnType EvaluateAt ( CoordinateVector& v )
00098 {
00099 this->m_AffineXform->SetParamVector( v );
00100 return this->Evaluate();
00101 }
00102
00115 virtual typename Self::ReturnType Evaluate()
00116 {
00117 const TransformedVolumeAxes axesHash( *this->ReferenceGrid, this->m_AffineXform, this->FloatingGrid->Deltas().begin(), this->FloatingGrid->m_Offset.begin() );
00118 const Vector3D *axesHashX = axesHash[0], *axesHashY = axesHash[1], *axesHashZ = axesHash[2];
00119
00120 this->Metric->Reset();
00121
00122 const DataGrid::IndexType& Dims = this->ReferenceGrid->GetDims();
00123 const int DimsX = Dims[0], DimsY = Dims[1], DimsZ = Dims[2];
00124
00125 this->Clipper.SetDeltaX( axesHashX[DimsX-1] - axesHashX[0] );
00126 this->Clipper.SetDeltaY( axesHashY[DimsY-1] - axesHashY[0] );
00127 this->Clipper.SetDeltaZ( axesHashZ[DimsZ-1] - axesHashZ[0] );
00128 this->Clipper.SetClippingBoundaries( this->m_FloatingCropRegionFractional );
00129
00130 DataGrid::IndexType::ValueType startZ, endZ;
00131 if ( this->ClipZ( this->Clipper, axesHashZ[0], startZ, endZ ) )
00132 {
00133 startZ = std::max<DataGrid::IndexType::ValueType>( startZ, this->m_ReferenceCropRegion.From()[2] );
00134 endZ = std::min<DataGrid::IndexType::ValueType>( endZ, this->m_ReferenceCropRegion.To()[2] + 1 );
00135
00136 const int numberOfTasks = std::min<size_t>( 4 * this->m_NumberOfThreads - 3, endZ - startZ + 1 );
00137 this->m_EvaluateTaskInfo.resize( numberOfTasks );
00138
00139 for ( int taskIdx = 0; taskIdx < numberOfTasks; ++taskIdx )
00140 {
00141 this->m_EvaluateTaskInfo[taskIdx].thisObject = this;
00142 this->m_EvaluateTaskInfo[taskIdx].AxesHash = &axesHash;
00143 this->m_EvaluateTaskInfo[taskIdx].StartZ = startZ;
00144 this->m_EvaluateTaskInfo[taskIdx].EndZ = endZ;
00145 }
00146
00147 ThreadPool::GetGlobalThreadPool().Run( EvaluateThread, this->m_EvaluateTaskInfo );
00148 }
00149 return this->Metric->Get();
00150 }
00151
00159 size_t m_NumberOfThreads;
00160
00162 std::vector<VM> m_ThreadMetric;
00163
00165 MutexLock m_MetricMutex;
00166
00172 typedef struct
00173 {
00175 Self *thisObject;
00177 const TransformedVolumeAxes* AxesHash;
00179 DataGrid::IndexType::ValueType StartZ;
00181 DataGrid::IndexType::ValueType EndZ;
00182 } EvaluateTaskInfo;
00183
00185 std::vector<typename Self::EvaluateTaskInfo> m_EvaluateTaskInfo;
00186
00195 static void EvaluateThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t threadIdx, const size_t )
00196 {
00197 typename Self::EvaluateTaskInfo *info = static_cast<typename Self::EvaluateTaskInfo*>( args );
00198
00199 Self *me = info->thisObject;
00200 const VM* Metric = me->Metric;
00201
00202 VM& threadMetric = me->m_ThreadMetric[threadIdx];
00203 threadMetric.Reset();
00204
00205 const Vector3D *hashX = (*info->AxesHash)[0], *hashY = (*info->AxesHash)[1], *hashZ = (*info->AxesHash)[2];
00206 Vector3D pFloating;
00207
00208 const DataGrid::IndexType& Dims = me->ReferenceGrid->GetDims();
00209 const int DimsX = Dims[0], DimsY = Dims[1];
00210
00211 int fltIdx[3];
00212 Types::Coordinate fltFrac[3];
00213
00214 const int FltDimsX = me->FloatingDims[0], FltDimsY = me->FloatingDims[1];
00215
00216 Vector3D rowStart;
00217 Vector3D planeStart;
00218
00219 int offset;
00220 DataGrid::IndexType::ValueType pX, pY, pZ;
00221
00222 for ( pZ = info->StartZ + taskIdx; pZ < info->EndZ; pZ += taskCnt )
00223 {
00224
00225 int r = pZ * DimsX * DimsY;
00226
00227 planeStart = hashZ[pZ];
00228
00229 DataGrid::IndexType::ValueType startY, endY;
00230 if ( me->ClipY( me->Clipper, planeStart, startY, endY ) )
00231 {
00232 startY = std::max<DataGrid::IndexType::ValueType>( startY, me->m_ReferenceCropRegion.From()[1] );
00233 endY = std::min<DataGrid::IndexType::ValueType>( endY, me->m_ReferenceCropRegion.To()[1] + 1 );
00234 r += startY * DimsX;
00235
00236
00237 for ( pY = startY; pY<endY; ++pY )
00238 {
00239 (rowStart = planeStart) += hashY[pY];
00240
00241 DataGrid::IndexType::ValueType startX, endX;
00242 if ( me->ClipX( me->Clipper, rowStart, startX, endX ) )
00243 {
00244 startX = std::max<DataGrid::IndexType::ValueType>( startX, me->m_ReferenceCropRegion.From()[0] );
00245 endX = std::min<DataGrid::IndexType::ValueType>( endX, me->m_ReferenceCropRegion.To()[0] + 1 );
00246
00247 r += startX;
00248
00249 for ( pX = startX; pX<endX; ++pX, ++r )
00250 {
00251 (pFloating = rowStart) += hashX[pX];
00252
00253
00254 if ( me->FloatingGrid->FindVoxelByIndex( pFloating, fltIdx, fltFrac ) )
00255 {
00256
00257
00258 offset = fltIdx[0]+FltDimsX*(fltIdx[1]+FltDimsY*fltIdx[2]);
00259
00260
00261 threadMetric.Increment( Metric->GetSampleX( r ), Metric->GetSampleY( offset, fltFrac ) );
00262 }
00263 }
00264 r += (DimsX-endX);
00265 }
00266 else
00267 {
00268 r += DimsX;
00269 }
00270 }
00271
00272 r += (DimsY-endY) * DimsX;
00273 }
00274 else
00275 {
00276 r += DimsY * DimsX;
00277 }
00278 }
00279
00280 me->m_MetricMutex.Lock();
00281 me->Metric->AddMetric( threadMetric );
00282 me->m_MetricMutex.Unlock();
00283 }
00284 };
00285
00287
00288 }
00289
00290 #endif // #ifndef __cmtkVoxelMatchingAffineFunctionalTemplate_h_included_