35 #ifndef AIMS_MORPHOLOGY_MORPHOGREYLEVEL_D_H
36 #define AIMS_MORPHOLOGY_MORPHOGREYLEVEL_D_H
47 _use_chamfer( true ), _chamfer_factor( 50.F ),
48 _chamfer_mask_size( 3, 3, 3 )
63 int_radius[0] = int(ceil( radius/voxelsize[0] ));
64 int_radius[1] = int(ceil( radius/voxelsize[1] ));
65 int_radius[2] = int(ceil( radius/voxelsize[2] ));
67 std::cout <<
"Radius = " << radius <<
" mm" << std::endl;
68 std::cout <<
"Voxel size = " << voxelsize <<
" mm" << std::endl;
69 std::cout <<
"Integer radius = " << int_radius <<
" voxel(s)" << std::endl;
72 if( (int_radius[0]==0) || (int_radius[1]==0) || (int_radius[2]==0) )
74 std::cout <<
"ERROR: Radius too small according to voxelsize !!! STOP.\n" << std::endl;
75 throw std::runtime_error(
"Radius too small according to voxelsize" );
78 if( (int_radius[0]==1) || (int_radius[1]==1) || (int_radius[2]==1) )
80 std::cout <<
"WARNING: Radius generate a single voxel !!! STOP.\n" << std::endl;
90 std::vector<Point3d> MorphoGreyLevel<T>::doStructElement(
91 float radius,
const Point4df & voxelsize )
95 float sqradius = radius * radius;
98 for(
int u = -int_radius[0]; u <= int_radius[0]; ++u)
99 for(
int v = -int_radius[1]; v <= int_radius[1]; ++v)
100 for(
int w = -int_radius[2]; w <= int_radius[2]; ++w)
102 if(
sqr(
float(u) * voxelsize[0] ) +
103 sqr(
float(v) * voxelsize[1] ) +
104 sqr(
float(w) * voxelsize[2] ) <= sqradius )
106 list.push_back(
Point3d(u, v, w) );
110 std::cout <<
"Number of voxels in the structuring element = "
111 << list.size() << std::endl << std::endl;
122 std::cout <<
"EROSION" << std::endl;
126 dataOut = tryChamferErosion( dataIn, radius );
133 Point4df voxelsize( vs[0], vs[1], vs[2], vs[3] );
145 dataOut->
fill( T(0) );
148 int_radius = computeIntRadius( radius, voxelsize );
149 list = doStructElement( radius, voxelsize );
151 for(
int t = 0; t < dim[3]; ++t)
152 for(
int z = 0; z < dim[2]; ++z)
156 for(
int y = 0; y < dim[1]; ++y)
157 for(
int x = 0; x < dim[0]; ++x)
160 for(
int l = 0; l < int(list.size()); ++l)
166 if( (coord[0]>=0) && (coord[0]<dim[0] )
167 && (coord[1]>=0) && (coord[1]<dim[1] )
168 && (coord[2]>=0) && (coord[2]<dim[2] ) )
170 tmp = dataIn->
at( coord[0], coord[1], coord[2] );
171 if( tmp <
min )
min = tmp;
174 dataOut->
at( x, y, z, t ) =
min;
177 std::cout << std::endl;
186 std::cout <<
"DILATION" << std::endl;
190 dataOut = tryChamferDilation( dataIn, radius );
197 Point4df voxelsize( vs[0], vs[1], vs[2], vs[3] );
209 dataOut->
fill( T(0) );
212 int_radius = computeIntRadius( radius, voxelsize );
213 list = doStructElement( radius, voxelsize );
215 for(
int t = 0; t < dim[3]; ++t)
216 for(
int z = 0; z < dim[2]; ++z)
218 float pct = float(z*100./dim[2]);
219 std::cout <<
"\rPercent done : " << pct << std::flush;
220 for(
int y = 0; y < dim[1]; ++y)
221 for(
int x = 0; x < dim[0]; ++x)
224 for(
int l = 0; l < int(list.size()); ++l)
230 if( (coord[0]>=0) && (coord[0]<dim[0] )
231 && (coord[1]>=0) && (coord[1]<dim[1] )
232 && (coord[2]>=0) && (coord[2]<dim[2] ) )
234 tmp = dataIn->
at( coord[0], coord[1], coord[2] );
235 if( tmp >
max )
max = tmp;
238 dataOut->
at( x, y, z, t ) =
max;
241 std::cout << std::endl;
252 dataOut = tryChamferClosing( dataIn, radius );
256 dataOut = doDilation( dataIn, radius );
257 dataOut = doErosion( dataOut, radius );
269 dataOut = tryChamferOpening( dataIn, radius );
273 dataOut = doErosion( dataIn, radius );
274 dataOut = doDilation( dataOut, radius );
317 if( _use_chamfer && isBinary( dataIn ) )
322 radius, _chamfer_mask_size[0], _chamfer_mask_size[0],
323 _chamfer_mask_size[0], _chamfer_factor );
333 if( _use_chamfer && isBinary( dataIn ) )
338 radius, _chamfer_mask_size[0], _chamfer_mask_size[0],
339 _chamfer_mask_size[0], _chamfer_factor );
349 if( _use_chamfer && isBinary( dataIn ) )
354 radius, _chamfer_mask_size[0], _chamfer_mask_size[0],
355 _chamfer_mask_size[0], _chamfer_factor );
365 if( _use_chamfer && isBinary( dataIn ) )
372 radius, 3, 3, 3, _chamfer_factor );
374 dataOut = reallocateVolume( dataOut, -size_diff, 1 );
392 offset = (int) ( radius / *f.rbegin() );
393 float dist = distanceToBorder( dataIn );
397 std::cout <<
"The distance between the object and the border is less "
398 "than the radius. Copying it.\n";
400 int border_width = 1;
413 int needed_border = neededBorderWidth();
422 border = *b.rbegin() / 2;
424 if( border < needed_border )
425 return reallocateVolume( dataIn, 0, needed_border );
435 int distance = dx + dy + dz;
437 for(x=0; x < dx; ++x)
438 for(y=0; y < dy; ++y)
439 for(z=0; z < dz; ++z)
440 if ( vol->
at(x,y,z) == 32767 )
445 if ( (dx - x) < distance && (dx - x) >= 0 )
451 if ( (dy - y) < distance && (dy - y) >= 0 )
457 if ( (dz - z) < distance && (dz - z) >= 0 )
469 int x, y, z, ox = 0, oy = 0, oz = 0;
474 dy + 2 * added_width,
475 dz + 2 * added_width,
478 if( added_width < 0 )
489 volBig->copyHeaderFrom( dataIn->
header() );
493 for(z=oz; z < dz; ++z)
494 for(y=oy; y < dy; ++y)
495 for(x=ox; x < dx; ++x)
496 volBig->at( x + added_width, y + added_width, z+added_width )
497 = dataIn->
at( x, y, z );
511 for(z=0; z < dz; ++z)
512 for(y=0; y < dy; ++y)
513 for(x=0; x < dx; ++x)
515 v = dataIn->
at( x, y, z );
524 else if( value != v )
535 std::set<unsigned> s;
536 s.insert( _chamfer_mask_size[0] );
537 s.insert( _chamfer_mask_size[1] );
538 s.insert( _chamfer_mask_size[2] );
539 int dimMax = *s.rbegin();
540 return (
int) (dimMax - 1) / 2;
Grey-level mathematical morphology.
carto::VolumeRef< T > doClosing(const carto::VolumeRef< T > &dataIn, float radius)
carto::VolumeRef< T > doErosion(const carto::VolumeRef< T > &dataIn, float radius)
virtual ~MorphoGreyLevel()
static bool isBinary(const carto::VolumeRef< T > &dataIn)
int neededBorderWidth() const
carto::VolumeRef< T > doDilation(const carto::VolumeRef< T > &dataIn, float radius)
carto::VolumeRef< T > doOpening(const carto::VolumeRef< T > &dataIn, float radius)
std::vector< float > getVoxelSize() const
virtual void copyHeaderFrom(const PropertySet &other)
rc_ptr< Volume< T > > refVolume() const
const T & at(long x, long y=0, long z=0, long t=0) const
const PropertySet & header() const
void fill(const T &value)
float min(float x, float y)
float max(float x, float y)
carto::VolumeRef< T > AimsMorphoChamferErosion(const carto::rc_ptr< carto::Volume< T > > &vol, float size, int xmask=3, int ymask=3, int zmask=3, float mult_fact=50)
carto::VolumeRef< T > AimsMorphoChamferDilation(const carto::rc_ptr< carto::Volume< T > > &vol, float size, int xmask=3, int ymask=3, int zmask=3, float mult_fact=50)
carto::VolumeRef< T > AimsMorphoChamferClosing(const carto::rc_ptr< carto::Volume< T > > &vol, float size, int xmask=3, int ymask=3, int zmask=3, float mult_fact=50)
carto::VolumeRef< T > AimsMorphoChamferOpening(const carto::rc_ptr< carto::Volume< T > > &vol, float size, int xmask=3, int ymask=3, int zmask=3, float mult_fact=50)