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 "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
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
00250 for ( int x=0; x < dims[0]; ++x )
00251 {
00252
00253 Types::DataItem correctOverlap = filter[0];
00254
00255 pixelBufferTo[x] = pixelBufferFrom[x] * filter[0];
00256
00257 for ( int t=1; t < (int)filterSize; ++t )
00258 {
00259
00260 if ( x >= t )
00261 {
00262
00263 pixelBufferTo[x] += pixelBufferFrom[x-t] * filter[t];
00264 correctOverlap += filter[t];
00265 }
00266
00267
00268 if ( x+t < dims[0] )
00269 {
00270 pixelBufferTo[x] += pixelBufferFrom[x+t] * filter[t];
00271 correctOverlap += filter[t];
00272 }
00273 }
00274
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
00329 pixelBufferTo[y] /= correctOverlap;
00330 }
00331
00332
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
00383 pixelBufferTo[z] /= correctOverlap;
00384 }
00385
00386
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 }