cmtkUniformVolume_Resample.cxx

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: 2424 $
00026 //
00027 //  $LastChangedDate: 2010-10-07 16:05:30 -0700 (Thu, 07 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
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   // compute number of tasks: we go by image plane and use twice as many tasks as threads, so we hopefully get decent load balancing.
00053   ThreadPool& threadPool = ThreadPool::GetGlobalThreadPool();
00054   const size_t numberOfTasks = std::min<int>( 4 * threadPool.GetNumberOfThreads() - 3, this->m_Dims[2] );
00055    
00056   // Info blocks for parallel tasks that do the resampling.
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 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines