35 #ifndef AIMS_MORPHOLOGY_MORPHOGREYLEVEL_D_H 36 #define AIMS_MORPHOLOGY_MORPHOGREYLEVEL_D_H 48 _use_chamfer( true ), _chamfer_factor( 50.F ),
49 _chamfer_mask_size( 3, 3, 3 )
64 int_radius[0] = int(ceil( radius/voxelsize[0] ));
65 int_radius[1] = int(ceil( radius/voxelsize[1] ));
66 int_radius[2] = int(ceil( radius/voxelsize[2] ));
68 std::cout <<
"Radius = " << radius <<
" mm" << std::endl;
69 std::cout <<
"Voxel size = " << voxelsize <<
" mm" << std::endl;
70 std::cout <<
"Integer radius = " << int_radius <<
" voxel(s)" << std::endl;
73 if( (int_radius[0]==0) || (int_radius[1]==0) || (int_radius[2]==0) )
75 std::cout <<
"ERROR: Radius too small according to voxelsize !!! STOP.\n" << std::endl;
76 throw std::runtime_error(
"Radius too small according to voxelsize" );
79 if( (int_radius[0]==1) || (int_radius[1]==1) || (int_radius[2]==1) )
81 std::cout <<
"WARNING: Radius generate a single voxel !!! STOP.\n" << std::endl;
92 float radius,
const Point4df & voxelsize )
104 float sqradius = radius * radius;
107 for(
int u = -int_radius[0]; u <= int_radius[0]; ++u)
108 for(
int v = -int_radius[1]; v <= int_radius[1]; ++v)
109 for(
int w = -int_radius[2]; w <= int_radius[2]; ++w)
111 if(
sqr(
float(u) * voxelsize[0] ) +
112 sqr(
float(v) * voxelsize[1] ) +
113 sqr(
float(w) * voxelsize[2] ) <= sqradius )
115 list.push_back(
Point3d(u, v, w) );
121 std::cout <<
"Number of voxels in the structuring element = " 122 << list.size() << std::endl << std::endl;
133 std::cout <<
"EROSION" << std::endl;
137 dataOut = tryChamferErosion( dataIn, radius );
144 Point4df voxelsize( vs[0], vs[1], vs[2], vs[3] );
156 dataOut->
fill( T(0) );
159 int_radius = computeIntRadius( radius, voxelsize );
160 list = doStructElement( radius, voxelsize );
162 for(
int t = 0; t < dim[3]; ++t)
163 for(
int z = 0; z < dim[2]; ++z)
167 for(
int y = 0; y < dim[1]; ++y)
168 for(
int x = 0; x < dim[0]; ++x)
171 for(
int l = 0; l < int(list.size()); ++l)
177 if( (coord[0]>=0) && (coord[0]<dim[0] )
178 && (coord[1]>=0) && (coord[1]<dim[1] )
179 && (coord[2]>=0) && (coord[2]<dim[2] ) )
181 tmp = dataIn->
at( coord[0], coord[1], coord[2] );
182 if( tmp < min ) min = tmp;
185 dataOut->
at( x, y, z, t ) =
min;
188 std::cout << std::endl;
197 std::cout <<
"DILATION" << std::endl;
201 dataOut = tryChamferDilation( dataIn, radius );
208 Point4df voxelsize( vs[0], vs[1], vs[2], vs[3] );
220 dataOut->
fill( T(0) );
223 int_radius = computeIntRadius( radius, voxelsize );
224 list = doStructElement( radius, voxelsize );
226 for(
int t = 0; t < dim[3]; ++t)
227 for(
int z = 0; z < dim[2]; ++z)
229 float pct = float(z*100./dim[2]);
230 std::cout <<
"\rPercent done : " << pct << std::flush;
231 for(
int y = 0; y < dim[1]; ++y)
232 for(
int x = 0; x < dim[0]; ++x)
235 for(
int l = 0; l < int(list.size()); ++l)
241 if( (coord[0]>=0) && (coord[0]<dim[0] )
242 && (coord[1]>=0) && (coord[1]<dim[1] )
243 && (coord[2]>=0) && (coord[2]<dim[2] ) )
245 tmp = dataIn->
at( coord[0], coord[1], coord[2] );
246 if( tmp > max ) max = tmp;
249 dataOut->
at( x, y, z, t ) =
max;
252 std::cout << std::endl;
263 dataOut = tryChamferClosing( dataIn, radius );
280 dataOut = tryChamferOpening( dataIn, radius );
328 if( _use_chamfer &&
isBinary( dataIn ) )
334 radius, _chamfer_mask_size[0], _chamfer_mask_size[0],
335 _chamfer_mask_size[0], _chamfer_factor ).volume();
345 if( _use_chamfer &&
isBinary( dataIn ) )
351 radius, _chamfer_mask_size[0], _chamfer_mask_size[0],
352 _chamfer_mask_size[0], _chamfer_factor ).volume();
362 if( _use_chamfer &&
isBinary( dataIn ) )
368 radius, _chamfer_mask_size[0], _chamfer_mask_size[0],
369 _chamfer_mask_size[0], _chamfer_factor ).volume();
379 if( _use_chamfer &&
isBinary( dataIn ) )
387 radius, 3, 3, 3, _chamfer_factor ).volume();
389 dataOut = reallocateVolume( dataOut, -size_diff, 1 );
407 offset = (int) ( radius / *f.rbegin() );
408 float dist = distanceToBorder( dataIn );
412 std::cout <<
"The distance between the object and the border is less " 413 "than the radius. Copying it.\n";
415 int border_width = 1;
437 border = *b.rbegin() / 2;
439 if( border < needed_border )
440 return reallocateVolume( dataIn, 0, needed_border );
450 int distance = dx + dy + dz;
452 for(x=0; x < dx; ++x)
453 for(y=0; y < dy; ++y)
454 for(z=0; z < dz; ++z)
455 if ( vol->
at(x,y,z) == 32767 )
460 if ( (dx - x) < distance && (dx - x) >= 0 )
466 if ( (dy - y) < distance && (dy - y) >= 0 )
472 if ( (dz - z) < distance && (dz - z) >= 0 )
484 int x, y, z, ox = 0, oy = 0, oz = 0;
489 dy + 2 * added_width,
490 dz + 2 * added_width,
493 if( added_width < 0 )
508 for(z=oz; z < dz; ++z)
509 for(y=oy; y < dy; ++y)
510 for(x=ox; x < dx; ++x)
511 volBig->
at( x + added_width, y + added_width, z+added_width )
512 = dataIn->
at( x, y, z );
526 for(z=0; z < dz; ++z)
527 for(y=0; y < dy; ++y)
528 for(x=0; x < dx; ++x)
530 v = dataIn->
at( x, y, z );
539 else if( value != v )
550 std::set<unsigned> s;
551 s.insert( _chamfer_mask_size[0] );
552 s.insert( _chamfer_mask_size[1] );
553 s.insert( _chamfer_mask_size[2] );
554 int dimMax = *s.rbegin();
555 return (
int) (dimMax - 1) / 2;
float min(float x, float y)
AIMSALGO_API AimsData< T > AimsMorphoChamferDilation(const AimsData< T > &vol, float size, int xmask=3, int ymask=3, int zmask=3, float mult_fact=50)
float max(float x, float y)
carto::VolumeRef< T > doDilation(const carto::VolumeRef< T > &dataIn, float radius)
AIMSALGO_API AimsData< T > AimsMorphoChamferClosing(const AimsData< T > &vol, float size, int xmask=3, int ymask=3, int zmask=3, float mult_fact=50)
carto::VolumeRef< T > doErosion(const carto::VolumeRef< T > &dataIn, float radius)
const T & at(long x, long y=0, long z=0, long t=0) const
const PropertySet & header() const
std::vector< float > getVoxelSize() const
virtual ~MorphoGreyLevel()
void fill(const T &value)
carto::VolumeRef< T > doClosing(const carto::VolumeRef< T > &dataIn, float radius)
carto::VolumeRef< T > doOpening(const carto::VolumeRef< T > &dataIn, float radius)
AIMSALGO_API AimsData< T > AimsMorphoChamferErosion(const AimsData< T > &vol, float size, int xmask=3, int ymask=3, int zmask=3, float mult_fact=50)
rc_ptr< Volume< T > > refVolume() const
Volume< T > * get() const
virtual void copyHeaderFrom(const PropertySet &other)
AIMSALGO_API AimsData< T > AimsMorphoChamferOpening(const AimsData< T > &vol, float size, int xmask=3, int ymask=3, int zmask=3, float mult_fact=50)
static bool isBinary(const carto::VolumeRef< T > &dataIn)
void reset(Volume< T > *p=NULL)
Grey-level mathematical morphology.
int neededBorderWidth() const