cmtkDataGridFilter.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: 2464 $
00026 //
00027 //  $LastChangedDate: 2010-10-19 09:54:33 -0700 (Tue, 19 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torsten_at_home $
00030 //
00031 */
00032 
00033 #include "cmtkDataGridFilter.h"
00034 
00035 #include <System/cmtkException.h>
00036 #include <System/cmtkMemory.h>
00037 #include <System/cmtkProgress.h>
00038 #include <System/cmtkThreadPool.h>
00039 
00040 #include <vector>
00041 
00042 namespace
00043 cmtk
00044 {
00045 
00046 DataGridFilter
00047 ::DataGridFilter( DataGrid::SmartPtr dataGrid )
00048   : m_DataGrid( dataGrid )
00049 {
00050   if ( !this->m_DataGrid->GetData() )
00051     throw Exception( "ERROR: DataGrid object given to DataGridFilter constructor does not have a data array" );
00052 }
00053 
00054 TypedArray::SmartPtr
00055 DataGridFilter::GetDataMedianFiltered( const int radiusX, const int radiusY, const int radiusZ ) const
00056 {
00057   const TypedArray* data = this->m_DataGrid->GetData();
00058   TypedArray::SmartPtr result = TypedArray::Create( data->GetType(), data->GetDataSize() );
00059   
00060   const int widthX = 1 + 2*radiusX;
00061   const int widthY = 1 + 2*radiusY;
00062   const int widthZ = 1 + 2*radiusZ;
00063   Types::DataItem *sort = Memory::AllocateArray<Types::DataItem>(  widthX*widthY*widthZ  );
00064   
00065   int offset = 0;
00066   Progress::Begin( 0, this->m_DataGrid->m_Dims[2], 1 );
00067 
00068   Progress::ResultEnum status = Progress::OK;
00069   for ( int z = 0; z < this->m_DataGrid->m_Dims[2]; ++z ) 
00070     {
00071     status = Progress::SetProgress( z );
00072     if ( status != Progress::OK ) break;
00073     
00074     int zFrom = ( z > radiusZ ) ? ( z - radiusZ ) : 0;
00075     int zTo = std::min( z+radiusZ+1, this->m_DataGrid->m_Dims[2] );
00076     
00077     for ( int y = 0; y < this->m_DataGrid->m_Dims[1]; ++y ) 
00078       {      
00079       int yFrom = ( y > radiusY ) ? ( y - radiusY ) : 0;
00080       int yTo = std::min( y+radiusY+1, this->m_DataGrid->m_Dims[1] );
00081       
00082       for ( int x = 0; x < this->m_DataGrid->m_Dims[0]; ++x, ++offset ) 
00083         {
00084         int xFrom = ( x > radiusX ) ? ( x - radiusX ) : 0;
00085         int xTo = std::min( x+radiusX+1, this->m_DataGrid->m_Dims[0] );
00086         
00087         int source = 0;
00088         int ofsZ = yFrom + this->m_DataGrid->m_Dims[1] * zFrom;
00089         for ( int zz = zFrom; zz < zTo; ++zz, ofsZ += this->m_DataGrid->m_Dims[1] ) 
00090           {
00091           int ofsYZ = this->m_DataGrid->m_Dims[0] * ofsZ ;
00092           for ( int yy = yFrom; yy < yTo; ++yy, ofsYZ += this->m_DataGrid->m_Dims[0] ) 
00093             {
00094             int toYZ = ofsYZ + xTo;
00095             for ( int xx = xFrom + ofsYZ; xx < toYZ; ++xx, ++source ) 
00096               {
00097               data->Get( sort[source], xx );
00098               }
00099             }
00100           }
00101         
00102 #ifdef CMTK_DATA_FLOAT  
00103         qsort( sort, source, sizeof( *sort ), MathUtil::CompareFloat );
00104 #else
00105         qsort( sort, source, sizeof( *sort ), MathUtil::CompareDouble );
00106 #endif
00107         
00108         if ( source % 2 )
00109           result->Set( sort[source/2], offset );
00110         else
00111           result->Set( (Types::DataItem) ( 0.5 * (sort[source/2] + sort[source/2-1]) ), offset );
00112         }
00113       }
00114     }
00115   Progress::Done();
00116   
00117   Memory::DeleteArray( sort );
00118   
00119   if ( status != Progress::OK ) 
00120     {
00121     result = TypedArray::SmartPtr( NULL );
00122     }
00123   
00124   return result;
00125 }
00126 
00127 TypedArray::SmartPtr
00128 DataGridFilter::GetDataSobelFiltered() const
00129 {
00130   const TypedArray* data = this->m_DataGrid->GetData();
00131   TypedArray::SmartPtr result = TypedArray::Create( data->GetType(), data->GetDataSize() );
00132 
00133   Types::DataItem value = 0;
00134   Types::DataItem fov[3][3][3];
00135 
00136   Progress::Begin( 0, this->m_DataGrid->m_Dims[2], 1 );
00137 
00138   size_t offset = 0;
00139   for ( int z = 0; z < this->m_DataGrid->m_Dims[2]; ++z ) 
00140     {
00141     Progress::SetProgress( z );
00142     for ( int y = 0; y < this->m_DataGrid->m_Dims[1]; ++y )
00143       for ( int x = 0; x < this->m_DataGrid->m_Dims[0]; ++x, ++offset ) 
00144         {
00145         if ( x && y && z && ( x<this->m_DataGrid->m_Dims[0]-1 ) && ( y<this->m_DataGrid->m_Dims[1]-1 ) && ( z<this->m_DataGrid->m_Dims[2]-1 ) ) 
00146           {
00147           for ( int dz=-1; dz<2; ++dz )
00148             for ( int dy=-1; dy<2; ++dy )
00149               for ( int dx=-1; dx<2; ++dx )
00150                 if ( ! data->Get( fov[1+dx][1+dy][1+dz], offset+this->m_DataGrid->GetOffsetFromIndex( dx, dy, dz ) ) )
00151                   fov[1+dx][1+dy][1+dz] = 0;
00152           
00153           value = (Types::DataItem)
00154             ( fabs( fov[0][0][1] - fov[2][0][1] + 
00155                     2 * ( fov[0][1][1] - fov[2][1][1] ) +
00156                     fov[0][2][1] - fov[2][2][1] ) +
00157               fabs( fov[0][0][1] - fov[0][2][1] + 
00158                     2 * ( fov[1][0][1] - fov[1][2][1] ) +
00159                     fov[2][0][1] - fov[2][2][1] )+
00160               fabs( fov[0][1][0] - fov[2][1][0] + 
00161                     2 * ( fov[0][1][1] - fov[2][1][1] ) +
00162                     fov[0][1][2] - fov[2][1][2] ) +
00163               fabs( fov[0][1][0] - fov[0][1][2] + 
00164                     2 * ( fov[1][1][0] - fov[1][1][2] ) +
00165                     fov[2][1][0] - fov[2][1][2] ) +
00166               fabs( fov[1][0][0] - fov[1][2][0] + 
00167                     2 * ( fov[1][0][1] - fov[1][2][1] ) +
00168                     fov[1][0][2] - fov[1][2][2] ) +
00169               fabs( fov[1][0][0] - fov[1][0][2] + 
00170                     2 * ( fov[1][1][0] - fov[1][1][2] ) +
00171                     fov[1][2][0] - fov[1][2][2] ) ) / 6;
00172           
00173           result->Set( value, offset );
00174           } 
00175         else
00176           {
00177           result->Set( 0, offset );
00178           }
00179         }
00180     }
00181   
00182   Progress::Done();
00183 
00184   return result;
00185 }
00186 
00187 TypedArray::SmartPtr
00188 DataGridFilter::GetDataKernelFiltered
00189 ( const std::vector<Types::DataItem>& filterX, 
00190   const std::vector<Types::DataItem>& filterY,
00191   const std::vector<Types::DataItem>& filterZ ) const
00192 {
00193   TypedArray::SmartPtr result = TypedArray::Create( this->m_DataGrid->GetData()->GetType(), this->m_DataGrid->GetNumberOfPixels() );
00194   
00195   ThreadPool& threadPool = ThreadPool::GetGlobalThreadPool();
00196   const size_t numberOfTasks = 4 * threadPool.GetNumberOfThreads() - 3;
00197 
00198   std::vector<FilterThreadParameters> params( numberOfTasks );
00199   for ( size_t task = 0; task < numberOfTasks; ++task )
00200     {
00201     params[task].thisObject = this;
00202     params[task].m_Filter = &filterX;
00203     params[task].m_Result = result;
00204     }
00205   threadPool.Run( GetFilteredDataThreadX, params );
00206 
00207   for ( size_t task = 0; task < numberOfTasks; ++task )
00208     {
00209     params[task].m_Filter = &filterY;
00210     }
00211   threadPool.Run( GetFilteredDataThreadY, params );
00212 
00213   for ( size_t task = 0; task < numberOfTasks; ++task )
00214     {
00215     params[task].m_Filter = &filterZ;
00216     }
00217   threadPool.Run( GetFilteredDataThreadZ, params );
00218   
00219   return result;
00220 }
00221 
00222 void
00223 DataGridFilter
00224 ::GetFilteredDataThreadX( void* args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00225 {
00226   FilterThreadParameters* params = static_cast<FilterThreadParameters*>( args );
00227   const Self* ThisConst = params->thisObject;
00228   
00229   const DataGrid::IndexType& dims = ThisConst->m_DataGrid->m_Dims;
00230   unsigned int maxDim = std::max( dims[0], std::max( dims[1], dims[2] ) );
00231 
00232   const std::vector<Types::DataItem>& filter = *(params->m_Filter);
00233   const size_t filterSize = filter.size();
00234 
00235   std::vector<Types::DataItem> pixelBufferFrom( maxDim );
00236   std::vector<Types::DataItem> pixelBufferTo( maxDim );
00237   TypedArray::SmartPtr& result = params->m_Result;
00238 
00239   for ( int z=taskIdx; z < dims[2]; z += taskCnt ) 
00240     {
00241     for ( int y=0; y < dims[1]; ++y ) 
00242       {
00243       // copy row data to buffer
00244       size_t ofs = ThisConst->m_DataGrid->GetOffsetFromIndex( 0, y, z );
00245       for ( int x=0; x < dims[0]; ++x, ++ofs )
00246         if ( !ThisConst->m_DataGrid->GetDataAt( pixelBufferFrom[x], ofs ) )
00247           pixelBufferFrom[x] = 0;
00248       
00249       // convolve row with filter
00250       for ( int x=0; x < dims[0]; ++x ) 
00251         {
00252         // this keeps track of outside FOV data
00253         Types::DataItem correctOverlap = filter[0];
00254         // central element first to initialize target value
00255         pixelBufferTo[x] = pixelBufferFrom[x] * filter[0];
00256         // now convolve side elements
00257         for ( int t=1; t < (int)filterSize; ++t ) 
00258           {
00259           // is x-t still inside the image?
00260           if ( x >= t )
00261             {
00262             // yes: convolve
00263             pixelBufferTo[x] += pixelBufferFrom[x-t] * filter[t];
00264             correctOverlap += filter[t];
00265             }
00266           
00267           // same for x+t:
00268           if ( x+t < dims[0] )
00269             {
00270             pixelBufferTo[x] += pixelBufferFrom[x+t] * filter[t];
00271             correctOverlap += filter[t];
00272             }
00273           }
00274         // correct value scaling for all missing (outside) elements
00275         pixelBufferTo[x] /= correctOverlap;
00276         }
00277       
00278       ofs = ThisConst->m_DataGrid->GetOffsetFromIndex( 0, y, z );
00279       for ( int x=0; x < dims[0]; ++x, ++ofs )
00280         result->Set( pixelBufferTo[x], ofs );
00281       }
00282     }
00283 }
00284 
00285 void
00286 DataGridFilter
00287 ::GetFilteredDataThreadY( void* args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00288 {
00289   FilterThreadParameters* params = static_cast<FilterThreadParameters*>( args );
00290   const Self* ThisConst = params->thisObject;
00291   
00292   const DataGrid::IndexType& dims = ThisConst->m_DataGrid->m_Dims;
00293   unsigned int maxDim = std::max( dims[0], std::max( dims[1], dims[2] ) );
00294 
00295   const std::vector<Types::DataItem>& filter = *(params->m_Filter);
00296   const size_t filterSize = filter.size();
00297 
00298   std::vector<Types::DataItem> pixelBufferFrom( maxDim );
00299   std::vector<Types::DataItem> pixelBufferTo( maxDim );
00300   TypedArray::SmartPtr& result = params->m_Result;
00301 
00302   for ( int z=taskIdx; z < dims[2]; z+=taskCnt ) 
00303     {
00304     for ( int x=0; x < dims[0]; ++x ) 
00305       {
00306       for ( int y=0; y < dims[1]; ++y )
00307         if ( !result->Get( pixelBufferFrom[y], ThisConst->m_DataGrid->GetOffsetFromIndex( x, y, z ) ) ) 
00308           pixelBufferFrom[y] = 0;
00309       
00310       for ( int y=0; y < dims[1]; ++y ) 
00311         {
00312         Types::DataItem correctOverlap = filter[0];
00313         pixelBufferTo[y] = pixelBufferFrom[y] * filter[0];
00314         for ( int t=1; t < (int)filterSize; ++t ) 
00315           {
00316           if ( y >= t ) 
00317             {
00318             pixelBufferTo[y] += pixelBufferFrom[y-t] * filter[t];
00319             correctOverlap += filter[t];
00320             }
00321           
00322           if ( y+t < dims[1] )
00323             {
00324             pixelBufferTo[y] += pixelBufferFrom[y+t] * filter[t];
00325             correctOverlap += filter[t];
00326             }
00327           }
00328         // correct value scaling for all missing (outside) elements
00329         pixelBufferTo[y] /= correctOverlap;
00330         }
00331       
00332       // write back convolved data
00333       for ( int y=0; y < dims[1]; ++y )
00334         result->Set( pixelBufferTo[y], ThisConst->m_DataGrid->GetOffsetFromIndex( x, y, z ) );
00335       }
00336     }
00337 }
00338 
00339 void
00340 DataGridFilter
00341 ::GetFilteredDataThreadZ( void* args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t )
00342 { 
00343   FilterThreadParameters* params = static_cast<FilterThreadParameters*>( args );
00344   const Self* ThisConst = params->thisObject;
00345   
00346   const DataGrid::IndexType& dims = ThisConst->m_DataGrid->m_Dims;
00347   unsigned int maxDim = std::max( dims[0], std::max( dims[1], dims[2] ) );
00348 
00349   const std::vector<Types::DataItem>& filter = *(params->m_Filter);
00350   const size_t filterSize = filter.size();
00351 
00352   std::vector<Types::DataItem> pixelBufferFrom( maxDim );
00353   std::vector<Types::DataItem> pixelBufferTo( maxDim );
00354   TypedArray::SmartPtr& result = params->m_Result;
00355 
00356   for ( int y=taskIdx; y < dims[1]; y+=taskCnt ) 
00357     {
00358     for ( int x=0; x < dims[0]; ++x ) 
00359       {
00360       for ( int z=0; z < dims[2]; ++z )
00361         if ( !result->Get( pixelBufferFrom[z], ThisConst->m_DataGrid->GetOffsetFromIndex( x, y, z ) ) ) 
00362           pixelBufferFrom[z] = 0;
00363       
00364       for ( int z=0; z < dims[2]; ++z ) 
00365         {
00366         Types::DataItem correctOverlap = filter[0];
00367         pixelBufferTo[z] = pixelBufferFrom[z] * filter[0];
00368         for ( int t=1; t < (int)filterSize; ++t ) 
00369           {
00370           if ( z >= t )
00371             {
00372             pixelBufferTo[z] += pixelBufferFrom[z-t] * filter[t];
00373             correctOverlap += filter[t];
00374             }
00375           
00376           if ( z+t < dims[2] )
00377             {
00378             pixelBufferTo[z] += pixelBufferFrom[z+t] * filter[t];
00379             correctOverlap += filter[t];
00380             }
00381           }
00382         // correct value scaling for all missing (outside) elements
00383         pixelBufferTo[z] /= correctOverlap;
00384         }
00385       
00386       // write back convolved data
00387       for ( int z=0; z < dims[2]; ++z )
00388         result->Set( pixelBufferTo[z], ThisConst->m_DataGrid->GetOffsetFromIndex( x, y, z ) );
00389       }
00390     }
00391 }
00392 
00393 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines