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 #include "cmtkDataGridMorphologicalOperators.h"
00034
00035 #include <Base/cmtkTemplateArray.h>
00036 #include <System/cmtkException.h>
00037
00038 #include <vector>
00039
00040 namespace
00041 cmtk
00042 {
00043
00044 DataGridMorphologicalOperators
00045 ::DataGridMorphologicalOperators( const DataGrid::SmartConstPtr& dataGrid )
00046 : m_DataGrid( dataGrid )
00047 {
00048 if ( !this->m_DataGrid->GetData() )
00049 throw Exception( "ERROR: DataGrid object given to DataGridMorphologicalOperators constructor does not have a data array" );
00050 }
00051
00052 bool
00053 DataGridMorphologicalOperators::EliminatePaddingVoting( const int iterations )
00054 {
00055 bool changed = false;
00056 for ( int it = 0; (it < iterations) && changed; ++it )
00057 {
00058 const TypedArray* data = this->m_DataGrid->GetData();
00059 TypedArray::SmartPtr result = data->Clone();
00060
00061 if ( !data->GetPaddingFlag() ) return changed;
00062 const Types::DataItem dataPadding = data->GetPaddingValue();
00063
00064 short valueMap[256];
00065 size_t offset = 0;
00066 for ( int z = 0; z < this->m_DataGrid->m_Dims[2]; ++z )
00067 {
00068 const int dzFrom = z ? z-1 : z, dzTo = (z<this->m_DataGrid->m_Dims[2]-1) ? z+1 : z;
00069 for ( int y = 0; y < this->m_DataGrid->m_Dims[1]; ++y )
00070 {
00071 const int dyFrom = y ? y-1 : y, dyTo = (y<this->m_DataGrid->m_Dims[1]-1) ? y+1 : y;
00072 for ( int x = 0; x < this->m_DataGrid->m_Dims[0]; ++x, ++offset )
00073 {
00074
00075 if ( data->PaddingDataAt( offset ) )
00076 {
00077
00078 memset( valueMap, 0, sizeof( valueMap ) );
00079 const int dxFrom = x ? x-1 : x, dxTo = (x<this->m_DataGrid->m_Dims[0]-1) ? x+1 : x;
00080 for ( int dz = dzFrom; (dz <= dzTo); ++dz )
00081 for ( int dy = dyFrom; (dy <= dyTo); ++dy )
00082 for ( int dx = dxFrom; (dx <= dxTo); ++dx )
00083 {
00084 Types::DataItem value;
00085 if ( this->m_DataGrid->GetDataAt( value, dx, dy, dz ) )
00086 {
00087 ++valueMap[static_cast<byte>( value )];
00088 }
00089 }
00090
00091
00092 char maxCount = 0;
00093 Types::DataItem maxValue = 0;
00094
00095 for ( int it = 0; it < 256; ++it )
00096 {
00097 if ( valueMap[it] > maxCount )
00098 {
00099 maxCount = valueMap[it];
00100 maxValue = it;
00101 }
00102 else
00103 if ( valueMap[it] == maxCount )
00104 {
00105 maxValue = dataPadding;
00106 }
00107 }
00108
00109 if ( maxValue != dataPadding )
00110 {
00111 changed = true;
00112 result->Set( maxValue, offset );
00113 }
00114 }
00115 }
00116 }
00117 }
00118 }
00119
00120 return changed;
00121 }
00122
00123 TypedArray::SmartPtr
00124 DataGridMorphologicalOperators::GetEroded( const int iterations ) const
00125 {
00126 TypedArray::SmartPtr dataArray = this->m_DataGrid->GetData();
00127 if ( dataArray->GetType() != TYPE_BYTE )
00128 {
00129 throw Exception( "ERROR: convert data to byte before calling DataGridMorphologicalOperators::GetDataErode()" );
00130 }
00131
00132 const byte* data = static_cast<const byte*>( dataArray->GetDataPtr() );
00133 std::vector<byte> tmp( dataArray->GetDataSize() );
00134
00135 ByteArray::SmartPtr erodedArray = ByteArray::Create( dataArray->GetDataSize() );
00136 byte* eroded = erodedArray->GetDataPtrConcrete();
00137
00138 memcpy( eroded, data, erodedArray->GetDataSizeBytes() );
00139
00140 for ( int i = 0; i < iterations; ++i )
00141 {
00142 size_t offset = 0;
00143 for ( int z = 0; z < this->m_DataGrid->m_Dims[2]; ++z )
00144 {
00145 int dzFrom = z ? -1 : 0, dzTo = (z<this->m_DataGrid->m_Dims[2]-1) ? 1 : 0;
00146 for ( int y = 0; y < this->m_DataGrid->m_Dims[1]; ++y )
00147 {
00148 int dyFrom = y ? -1 : 0, dyTo = (y<this->m_DataGrid->m_Dims[1]-1) ? 1 : 0;
00149 for ( int x = 0; x < this->m_DataGrid->m_Dims[0]; ++x, ++offset )
00150 {
00151 int dxFrom = x ? -1 : 0, dxTo = (x<this->m_DataGrid->m_Dims[0]-1) ? 1 : 0;
00152 if ( eroded[offset] )
00153 {
00154 bool erodePixel = false;
00155 for ( int dz = dzFrom; (dz <= dzTo) && !erodePixel; ++dz )
00156 for ( int dy = dyFrom; (dy <= dyTo) && !erodePixel; ++dy )
00157 for ( int dx = dxFrom; (dx <= dxTo) && !erodePixel; ++dx )
00158 if ( dx || dy || dz )
00159 if ( ! eroded[offset+this->m_DataGrid->GetOffsetFromIndex( dx, dy, dz )] )
00160 erodePixel = true;
00161 if ( erodePixel )
00162 tmp[offset] = 0;
00163 else
00164 tmp[offset] = eroded[offset];
00165 }
00166 else
00167 {
00168 tmp[offset] = 0;
00169 }
00170 }
00171 }
00172 }
00173
00174 memcpy( eroded, &(tmp[0]), erodedArray->GetDataSizeBytes() );
00175 }
00176
00177 return erodedArray;
00178 }
00179
00180 TypedArray::SmartPtr
00181 DataGridMorphologicalOperators::GetDilated( const int iterations ) const
00182 {
00183 TypedArray::SmartPtr dataArray = this->m_DataGrid->GetData();
00184 if ( dataArray->GetType() != TYPE_BYTE )
00185 {
00186 throw Exception( "ERROR: convert data to byte before calling DataGridMorphologicalOperators::GetDataDilate()" );
00187 }
00188
00189 const byte* data = static_cast<const byte*>( dataArray->GetDataPtr() );
00190 std::vector<byte> tmp( dataArray->GetDataSize() );
00191
00192 ByteArray::SmartPtr dilatedArray = ByteArray::Create( dataArray->GetDataSize() );
00193 byte* dilated = dilatedArray->GetDataPtrConcrete();
00194
00195 memcpy( dilated, data, dilatedArray->GetDataSizeBytes() );
00196
00197 for ( int i = 0; i < iterations; ++i )
00198 {
00199 size_t offset = 0;
00200 for ( int z = 0; z < this->m_DataGrid->m_Dims[2]; ++z )
00201 {
00202 int dzFrom = z ? -1 : 0, dzTo = (z<this->m_DataGrid->m_Dims[2]-1) ? 1 : 0;
00203 for ( int y = 0; y < this->m_DataGrid->m_Dims[1]; ++y )
00204 {
00205 int dyFrom = y ? -1 : 0, dyTo = (y<this->m_DataGrid->m_Dims[1]-1) ? 1 : 0;
00206 for ( int x = 0; x < this->m_DataGrid->m_Dims[0]; ++x, ++offset )
00207 {
00208 int dxFrom = x ? -1 : 0, dxTo = (x<this->m_DataGrid->m_Dims[0]-1) ? 1 : 0;
00209 if ( ! dilated[offset] )
00210 {
00211 byte dilatePixel = 0;
00212 for ( int dz = dzFrom; (dz <= dzTo) && !dilatePixel; ++dz )
00213 for ( int dy = dyFrom; (dy <= dyTo) && !dilatePixel; ++dy )
00214 for ( int dx = dxFrom; (dx <= dxTo) && !dilatePixel; ++dx )
00215 if ( dx || dy || dz )
00216 dilatePixel = dilated[offset+this->m_DataGrid->GetOffsetFromIndex(dx,dy,dz)];
00217 if ( dilatePixel )
00218 tmp[offset] = dilatePixel;
00219 else
00220 tmp[offset] = 0;
00221 }
00222 else
00223 {
00224 tmp[offset] = dilated[offset];
00225 }
00226 }
00227 }
00228 }
00229
00230 memcpy( dilated, &(tmp[0]), dilatedArray->GetDataSizeBytes() );
00231 }
00232
00233 return dilatedArray;
00234 }
00235
00236 TypedArray::SmartPtr
00237 DataGridMorphologicalOperators::GetBoundaryMap( const bool multiValued ) const
00238 {
00239 TypedArray::SmartPtr dataArray = this->m_DataGrid->GetData();
00240 ShortArray::SmartPtr boundaryArray = ShortArray::Create( dataArray->GetDataSize() );
00241 short* boundary = boundaryArray->GetDataPtrConcrete();
00242
00243 #pragma omp parallel for
00244 for ( int z = 0; z < this->m_DataGrid->m_Dims[2]; ++z )
00245 {
00246 size_t offset = z * this->m_DataGrid->m_Dims[0] * this->m_DataGrid->m_Dims[1];
00247
00248 Types::DataItem value, neighbor;
00249 const int dzFrom = z ? -1 : 0, dzTo = (z<this->m_DataGrid->m_Dims[2]-1) ? 1 : 0;
00250 for ( int y = 0; y < this->m_DataGrid->m_Dims[1]; ++y )
00251 {
00252 const int dyFrom = y ? -1 : 0, dyTo = (y<this->m_DataGrid->m_Dims[1]-1) ? 1 : 0;
00253 for ( int x = 0; x < this->m_DataGrid->m_Dims[0]; ++x, ++offset )
00254 {
00255 const int dxFrom = x ? -1 : 0, dxTo = (x<this->m_DataGrid->m_Dims[0]-1) ? 1 : 0;
00256 bool bp = false;
00257 if ( dataArray->Get( value, offset ) )
00258 {
00259 for ( int dz = dzFrom; (dz <= dzTo) && !bp; ++dz )
00260 for ( int dy = dyFrom; (dy <= dyTo) && !bp; ++dy )
00261 for ( int dx = dxFrom; (dx <= dxTo) && !bp; ++dx )
00262 if ( dx || dy || dz )
00263 if ( dataArray->Get( neighbor, offset+this->m_DataGrid->GetOffsetFromIndex(dx,dy,dz) ) )
00264 bp = (value != neighbor);
00265 }
00266 else
00267 {
00268 value = 0;
00269 }
00270
00271 if ( bp )
00272 {
00273 if ( multiValued )
00274 boundary[offset] = static_cast<short>( value );
00275 else
00276 boundary[offset] = 1;
00277 }
00278 else
00279 boundary[offset] = 0;
00280
00281 }
00282 }
00283 }
00284
00285 return boundaryArray;
00286 }
00287
00288 }