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 #include "cmtkUniformVolume.h"
00034
00035 #include <Base/cmtkVolumeGridToGridLookup.h>
00036
00037 #include <System/cmtkThreadPool.h>
00038
00039 namespace
00040 cmtk
00041 {
00042
00045
00046 TypedArray::SmartPtr
00047 UniformVolume::Resample( const UniformVolume& other ) const
00048 {
00049 const TypedArray* fromData = other.GetData();
00050 const VolumeGridToGridLookup gridLookup( other, *this );
00051
00052
00053 ThreadPool& threadPool = ThreadPool::GetGlobalThreadPool();
00054 const size_t numberOfTasks = std::min<int>( 4 * threadPool.GetNumberOfThreads() - 3, this->m_Dims[2] );
00055
00056
00057 std::vector<UniformVolume::ResampleTaskInfo> taskInfoVector( numberOfTasks );
00058
00059 Types::DataItem *resampledData = Memory::AllocateArray<Types::DataItem>( this->GetNumberOfPixels() );
00060
00061 for ( size_t taskIdx = 0; taskIdx < numberOfTasks; ++taskIdx )
00062 {
00063 taskInfoVector[taskIdx].thisObject = this;
00064 taskInfoVector[taskIdx].GridLookup = &gridLookup;
00065 taskInfoVector[taskIdx].OtherVolume = &other;
00066 taskInfoVector[taskIdx].FromData = fromData;
00067 taskInfoVector[taskIdx].ResampledData = resampledData;
00068 }
00069
00070 switch ( fromData->GetDataClass() )
00071 {
00072 case DATACLASS_GREY:
00073 default:
00074 {
00075 threadPool.Run( UniformVolume::ResampleThreadPoolExecuteGrey, taskInfoVector );
00076 }
00077 break;
00078 case DATACLASS_LABEL:
00079 {
00080 threadPool.Run( UniformVolume::ResampleThreadPoolExecuteLabels, taskInfoVector );
00081 break;
00082 }
00083 }
00084
00085 TypedArray::SmartPtr result = TypedArray::Create( fromData->GetType(), this->GetNumberOfPixels() );
00086 result->SetData( resampledData );
00087 result->SetDataClass( fromData->GetDataClass() );
00088 if ( fromData->GetPaddingFlag() )
00089 {
00090 result->SetPaddingValue( fromData->GetPaddingValue() );
00091 }
00092
00093 Memory::DeleteArray( resampledData );
00094
00095 return result;
00096 }
00097
00098 void
00099 UniformVolume::ResampleThreadPoolExecuteLabels( void *const arg, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00100 {
00101 UniformVolume::ResampleTaskInfo *info = static_cast<UniformVolume::ResampleTaskInfo*>( arg );
00102
00103 const UniformVolume *me = info->thisObject;
00104 const UniformVolume *other = info->OtherVolume;
00105 Types::DataItem *dest = info->ResampledData;
00106 const VolumeGridToGridLookup *gridLookup = info->GridLookup;
00107
00108 Types::Coordinate labelWeights[256];
00109
00110 int x, y;
00111 int pX, pY, pZ;
00112 Types::DataItem value;
00113
00114 for ( int z = taskIdx; z < me->m_Dims[2]; z += taskCnt )
00115 {
00116 int offset = z * me->m_Dims[0] * me->m_Dims[1];
00117
00118 for ( y = 0; y < me->m_Dims[1]; ++y )
00119 {
00120 for ( x = 0; x < me->m_Dims[0]; ++x, ++offset )
00121 {
00122 memset( labelWeights, 0, sizeof( labelWeights ) );
00123
00124 for ( pZ=0; pZ<gridLookup->GetSourceCount(2,z); ++pZ )
00125 {
00126 const Types::Coordinate weightZ=gridLookup->GetWeight(2,z,pZ);
00127
00128 for ( pY=0; pY<gridLookup->GetSourceCount(1,y); ++pY )
00129 {
00130 const Types::Coordinate weightYZ=weightZ*gridLookup->GetWeight(1,y,pY);
00131
00132 for ( pX=0; pX<gridLookup->GetSourceCount(0,x); ++pX )
00133 {
00134 const Types::Coordinate weight=weightYZ*gridLookup->GetWeight(0,x,pX);
00135
00136 if ( other->GetDataAt( value, pX + gridLookup->GetFromIndex(0,x), pY + gridLookup->GetFromIndex(1,y), pZ + gridLookup->GetFromIndex(2,z)) )
00137 {
00138 labelWeights[static_cast<byte>( value )] += weight;
00139 }
00140 }
00141 }
00142 }
00143
00144 Types::Coordinate maxLabelWeight = 0;
00145 byte maxLabelIndex = 0;
00146 for ( int l=0; l<256; ++l )
00147 {
00148 if ( labelWeights[l] > maxLabelWeight )
00149 {
00150 maxLabelWeight = labelWeights[l];
00151 maxLabelIndex = l;
00152 }
00153 }
00154
00155 if ( maxLabelWeight > 0 )
00156 dest[offset] = maxLabelIndex;
00157 else
00158 dest[offset] = sqrt( static_cast<Types::DataItem>( -1 ) );
00159 }
00160 }
00161 }
00162 }
00163
00164 void
00165 UniformVolume::ResampleThreadPoolExecuteGrey( void *const arg, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00166 {
00167 UniformVolume::ResampleTaskInfo *info = static_cast<UniformVolume::ResampleTaskInfo*>( arg );
00168
00169 const UniformVolume *me = info->thisObject;
00170 Types::DataItem *dest = info->ResampledData;
00171 const UniformVolume *other = info->OtherVolume;
00172 const VolumeGridToGridLookup *gridLookup = info->GridLookup;
00173
00174 Types::DataItem tempValue, value;
00175
00176 int x, y;
00177 int pX, pY, pZ;
00178 bool FoundNullData;
00179
00180 for ( int z = taskIdx; z < me->m_Dims[2]; z += taskCnt )
00181 {
00182 int offset = z * me->m_Dims[0] * me->m_Dims[1];
00183
00184 const Types::Coordinate volumeZ = gridLookup->GetLength(2,z);
00185
00186 for ( y=0; y < me->m_Dims[1]; ++y )
00187 {
00188 const Types::Coordinate volumeYZ = volumeZ * gridLookup->GetLength(1,y);
00189
00190 for ( x=0; x < me->m_Dims[0]; ++x, ++offset )
00191 {
00192 tempValue = 0;
00193 FoundNullData = false;
00194
00195 for ( pZ=0; pZ<gridLookup->GetSourceCount(2,z); ++pZ )
00196 {
00197 const Types::Coordinate weightZ=gridLookup->GetWeight(2,z,pZ);
00198
00199 for ( pY=0; pY<gridLookup->GetSourceCount(1,y); ++pY )
00200 {
00201 const Types::Coordinate weightYZ=weightZ*gridLookup->GetWeight(1,y,pY);
00202
00203 for ( pX=0; pX<gridLookup->GetSourceCount(0,x); ++pX )
00204 {
00205 const Types::Coordinate weight=weightYZ*gridLookup->GetWeight(0,x,pX);
00206
00207 if ( other->GetDataAt(value,pX+gridLookup->GetFromIndex(0,x), pY+gridLookup->GetFromIndex(1,y), pZ+gridLookup->GetFromIndex(2,z) ) )
00208 {
00209 tempValue+=static_cast<Types::DataItem>( weight*value );
00210 }
00211 else
00212 {
00213 FoundNullData = true;
00214 }
00215 }
00216 }
00217 }
00218
00219 if ( ! FoundNullData )
00220 {
00221 const Types::Coordinate volume = volumeYZ*gridLookup->GetLength(0,x);
00222 dest[offset] = static_cast<Types::DataItem>( tempValue / volume );
00223 }
00224 else
00225 {
00226 dest[offset] = sqrt( static_cast<Types::DataItem>( -1 ) );
00227 }
00228 }
00229 }
00230 }
00231 }
00232
00233 }