Go to the documentation of this file.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 namespace
00034 cmtk
00035 {
00036
00039
00040 UniformVolume*
00041 ReformatVolume::GetTransformedReference
00042 ( const std::vector<SplineWarpXform::SmartPtr>* xformList,
00043 std::vector<UniformVolume::SmartPtr>* volumeList,
00044 Types::Coordinate *const volumeOffset,
00045 const bool includeReferenceData )
00046 {
00047 UniformVolume* result = NULL;
00048 unsigned int numberOfImages = 0;
00049
00050 std::vector<UniformVolumeInterpolatorBase::SmartConstPtr> interpolatorList;
00051 interpolatorList.push_back( this->CreateInterpolator( this->ReferenceVolume ) );
00052 if ( volumeList )
00053 {
00054 numberOfImages = 1 + volumeList->size();
00055 for ( unsigned int img = 0; img < numberOfImages-1; ++img )
00056 {
00057 interpolatorList.push_back( this->CreateInterpolator( (*volumeList)[img] ) );
00058 }
00059 }
00060
00061 const SplineWarpXform* splineXform = dynamic_cast<const SplineWarpXform*>( this->m_WarpXform.GetConstPtr() );
00062 if ( ! splineXform )
00063 {
00064 StdErr << "ERROR: ReformatVolume::GetTransformedReference supports spline warp only.\n";
00065 return NULL;
00066 }
00067
00068 DataClass dataClass = ReferenceVolume->GetData()->GetDataClass();
00069 int maxLabel = 0;
00070 if ( dataClass == DATACLASS_LABEL )
00071 {
00072 const Types::DataItemRange rangeRef = ReferenceVolume->GetData()->GetRange();
00073 maxLabel = static_cast<int>( rangeRef.m_UpperBound );
00074
00075 for ( unsigned int img = 0; img < numberOfImages-1; ++img )
00076 {
00077 const Types::DataItemRange rangeFlt = (*volumeList)[img]->GetData()->GetRange();
00078 maxLabel = std::max( maxLabel, static_cast<int>( rangeFlt.m_UpperBound ) );
00079 }
00080 }
00081
00082
00083 Types::Coordinate bbFrom[3], delta[3];
00084 result = this->CreateTransformedReference( bbFrom, delta, volumeOffset );
00085
00086 const ScalarDataType dtype = (this->m_UserDataType != TYPE_NONE) ? this->m_UserDataType : ReferenceVolume->GetData()->GetType();
00087 TypedArray::SmartPtr dataArray( TypedArray::Create( dtype, result->GetNumberOfPixels() ) );
00088 if ( this->m_UsePaddingValue )
00089 dataArray->SetPaddingValue( this->m_PaddingValue );
00090 result->SetData( dataArray );
00091
00092 const size_t numberOfThreads = Threads::GetNumberOfThreads();
00093 std::vector<GetTransformedReferenceTP> params( numberOfThreads );
00094
00095 for ( size_t thr = 0; thr < numberOfThreads; ++thr )
00096 {
00097 params[thr].thisObject = this;
00098 params[thr].ThisThreadIndex = thr;
00099 params[thr].NumberOfThreads = numberOfThreads;
00100 params[thr].dims = result->GetDims();
00101 params[thr].bbFrom = bbFrom;
00102 params[thr].delta = delta;
00103 params[thr].splineXform = splineXform;
00104 params[thr].numberOfImages = numberOfImages;
00105 params[thr].xformList = xformList;
00106 params[thr].volumeList = volumeList;
00107 params[thr].interpolatorList = &interpolatorList;
00108 params[thr].dataArray = dataArray;
00109 params[thr].maxLabel = maxLabel;
00110 params[thr].IncludeReferenceData = includeReferenceData;
00111 }
00112
00113 switch ( dataClass )
00114 {
00115 default:
00116 case DATACLASS_GREY:
00117 {
00118 if ( xformList && !xformList->empty() )
00119 Threads::RunThreads( GetTransformedReferenceGreyAvg, numberOfThreads, ¶ms[0] );
00120 else
00121 Threads::RunThreads( GetTransformedReferenceGrey, numberOfThreads, ¶ms[0] );
00122 }
00123 break;
00124 case DATACLASS_LABEL:
00125 {
00126 Threads::RunThreads( GetTransformedReferenceLabel, numberOfThreads, ¶ms[0] );
00127 }
00128 break;
00129 }
00130
00131 return result;
00132 }
00133
00134 CMTK_THREAD_RETURN_TYPE
00135 ReformatVolume::GetTransformedReferenceGreyAvg( void *const arg )
00136 {
00137 GetTransformedReferenceTP* params = static_cast<GetTransformedReferenceTP*>( arg );
00138
00139 TypedArray::SmartPtr dataArray = params->dataArray;
00140 const SplineWarpXform* splineXform = params->splineXform;
00141 const Types::Coordinate* delta = params->delta;
00142 const Types::Coordinate* bbFrom = params->bbFrom;
00143 const DataGrid::IndexType& dims = params->dims;
00144
00145 const std::vector<SplineWarpXform::SmartPtr>* xformList = params->xformList;
00146 const std::vector<UniformVolumeInterpolatorBase::SmartConstPtr>* interpolatorList = params->interpolatorList;
00147
00148 Types::Coordinate minDelta = std::min( delta[0], std::min( delta[1], delta[2] ) );
00149
00150 std::vector<Types::DataItem> value( params->numberOfImages );
00151
00152 std::vector<const SplineWarpXform*> xforms( params->numberOfImages-1 );
00153
00154 for ( unsigned int img = 0; img < params->numberOfImages-1; ++img )
00155 {
00156 xforms[img] = (*xformList)[img];
00157 }
00158
00159 int cx = params->ThisThreadIndex % dims[0];
00160 int cy = (params->ThisThreadIndex / dims[0]) % dims[1];
00161 int cz = params->ThisThreadIndex / (dims[0] * dims[1]) ;
00162
00163 UniformVolume::CoordinateVectorType xyz;
00164 xyz[0] = bbFrom[0] + cx * delta[0];
00165 xyz[1] = bbFrom[1] + cy * delta[1];
00166 xyz[2] = bbFrom[2] + cz * delta[2];
00167
00168 const size_t numberOfPixels = dims[0] * dims[1] * dims[2];
00169 const size_t statusUpdateIncrement = std::max<size_t>( 1, numberOfPixels / 100 );
00170
00171 UniformVolume::CoordinateVectorType u, v;
00172 for ( size_t offset = params->ThisThreadIndex; offset < numberOfPixels; offset += params->NumberOfThreads )
00173 {
00174 if ( ! params->ThisThreadIndex && ! (offset % statusUpdateIncrement) )
00175 Progress::SetProgress( offset );
00176
00177 v = xyz;
00178 const bool success = splineXform->ApplyInverseInPlace( v, 0.1 * minDelta );
00179 u = v;
00180
00181 unsigned int toIdx = 0;
00182 if ( success )
00183 {
00184 if ( params->IncludeReferenceData )
00185 {
00186 if ( (*interpolatorList)[0]->GetDataAt( v, value[toIdx] ) )
00187 ++toIdx;
00188 }
00189
00190 for ( unsigned int img = 0; img < params->numberOfImages-1; ++img )
00191 {
00192 v = u;
00193 xforms[img]->ApplyInPlace( v );
00194
00195 if ( (*interpolatorList)[img+1]->GetDataAt( v, value[toIdx] ) )
00196 ++toIdx;
00197 }
00198 }
00199 if ( toIdx && success )
00200 {
00201 Types::DataItem avg = value[0];
00202 for ( unsigned int idx = 1; idx < toIdx; ++idx )
00203 avg += value[idx];
00204 dataArray->Set( avg / toIdx, offset );
00205 }
00206 else
00207 dataArray->SetPaddingAt( offset );
00208
00209 cx += params->NumberOfThreads;
00210 if ( cx >= dims[0] )
00211 {
00212 cy += cx / dims[0];
00213 cx %= dims[0];
00214
00215 if ( cy >= dims[1] )
00216 {
00217 cz += cy / dims[1];
00218 cy %= dims[1];
00219 xyz[2] = bbFrom[2] + cz * delta[2];
00220 }
00221 xyz[1] = bbFrom[1] + cy * delta[1];
00222 }
00223 xyz[0] = bbFrom[0] + cx * delta[0];
00224 }
00225
00226 return CMTK_THREAD_RETURN_VALUE;
00227 }
00228
00229 }