33 #ifndef __INCLUDE_MIST_FIGURE_DECOMPOSITION__
34 #define __INCLUDE_MIST_FIGURE_DECOMPOSITION__
37 #ifndef __INCLUDE_MIST_H__
41 #ifndef __INCLUDE_MIST_LIMITS__
42 #include "../limits.h"
45 #ifndef __INCLUDE_MIST_DISTANCE_TRANSFORM__
49 #ifndef __INCLUDE_MIST_LABELING__
65 namespace __figure_dedomposition__
69 typedef ptrdiff_t difference_type;
70 difference_type RADIUS;
72 difference_type index;
74 Position( difference_type r = 0,
double R = 0, difference_type indx = 0 ) : RADIUS( r ), radius( R - std::sqrt( static_cast< double >( r ) ) ), index( indx )
78 bool operator <(
const Position &p )
const
80 return( RADIUS > p.RADIUS );
84 template <
class T,
class Allocator >
85 inline typename array2< T, Allocator >::size_type do_labeling( array2< T, Allocator > &in )
90 template <
class T,
class Allocator >
91 inline typename array3< T, Allocator >::size_type do_labeling( array3< T, Allocator > &in )
97 template <
class T,
class Allocator >
98 bool has_voxel_at_side(
const array2< T, Allocator > &in )
100 typedef typename array2< T, Allocator >::size_type size_type;
102 for( size_type i = 0 ; i < in.width( ) ; i++ )
104 if( in( i, 0 ) != 0 || in( i, in.height( ) - 1 ) != 0 )
110 for( size_type j = 0 ; j < in.height( ) ; j++ )
112 if( in( 0, j ) != 0 || in( in.width( ) - 1, j ) != 0 )
122 template <
class T,
class Allocator >
123 bool has_voxel_at_side(
const array3< T, Allocator > &in )
125 typedef typename array2< T, Allocator >::size_type size_type;
127 if( in.depth( ) == 1 )
129 for( size_type i = 0 ; i < in.width( ) ; i++ )
131 if( in( i, 0, 0 ) != 0 || in( i, in.height( ) - 1, 0 ) != 0 )
137 for( size_type j = 0 ; j < in.height( ) ; j++ )
139 if( in( 0, j, 0 ) != 0 || in( in.width( ) - 1, j, 0 ) != 0 )
147 for( size_type j = 0 ; j < in.height( ) ; j++ )
149 for( size_type i = 0 ; i < in.width( ) ; i++ )
151 if( in( i, j, 0 ) != 0 || in( i, j, in.depth( ) - 1 ) != 0 )
158 for( size_type k = 0 ; k < in.depth( ) ; k++ )
160 for( size_type i = 0 ; i < in.width( ) ; i++ )
162 if( in( i, 0, k ) != 0 || in( i, in.height( ) - 1, k ) != 0 )
169 for( size_type k = 0 ; k < in.depth( ) ; k++ )
171 for( size_type j = 0 ; j < in.height( ) ; j++ )
173 if( in( 0, j, k ) != 0 || in( in.width( ) - 1, j, k ) != 0 )
184 struct __mist_dmy_fd_callback__
194 template <
class Array1,
class Array2 >
195 void operator()(
size_t loop,
size_t label_num,
double radius,
const Array1 &in,
const Array2 &out )
const
224 template <
class Array1,
class Array2,
class Functor >
225 typename Array1::size_type
figure_decomposition(
const Array1 &in, Array2 &out,
double max_distance, Functor f )
232 typedef typename Array1::size_type size_type;
233 typedef typename Array1::difference_type difference_type;
234 typedef typename Array1::const_pointer const_pointer;
235 typedef typename Array2::value_type value_type;
236 typedef typename Array2::template rebind< size_type >::other distance_type;
237 typedef typename Array2::template rebind< double >::other mask_type;
240 dist.resize( in.width( ), in.height( ), in.depth( ) );
246 for( size_type i = 0 ; i < in.size( ) ; i++ )
248 dist[ i ] = in[ i ] != 0 ? 1 : 0;
251 if( __figure_dedomposition__::has_voxel_at_side( in ) )
255 distance_type &dist_tmp_map = dist_tmp;
260 for( size_type k = 0 ; k < dist.depth( ) ; k++ )
262 for( size_type j = 0 ; j < dist.height( ) ; j++ )
264 for( size_type i = 0 ; i < dist.width( ) ; i++ )
266 dist( i, j, k ) = dist_tmp( i, j, k );
277 typedef __figure_dedomposition__::Position position_type;
280 std::map< size_type, size_type > distance_list;
281 for( size_type l = 0 ; l < dist.size( ) ; l++ )
283 distance_list[ dist[ l ] ]++;
286 size_type label_count = 0;
287 size_type loop_count = 0;
288 size_type current_label = 0;
292 mask_type mask( in );
294 out.resize( in.width( ), in.height( ), in.depth( ) );
295 out.reso1( in.reso1( ) );
296 out.reso2( in.reso2( ) );
297 out.reso3( in.reso3( ) );
300 typename std::map< size_type, size_type >::reverse_iterator dite = distance_list.rbegin( );
303 if( max_distance > 0 )
305 double md = max_distance * max_distance;
306 double Md = ( max_distance + 1 ) * ( max_distance + 1 );
307 for( size_type l = 0 ; l < dist.size( ) ; l++ )
309 if( dist[ l ] >= md )
314 for( ; dite != distance_list.rend( ) ; ++dite )
316 if( dite->first < Md )
322 label_count = __figure_dedomposition__::do_labeling( out );
325 f( 0, label_count, std::sqrt( static_cast< double >( dite->first ) ), in, out );
328 for( ; dite != distance_list.rend( ) ; ++dite )
330 size_type rr = dite->first;
331 difference_type count = dite->second;
339 double r = std::sqrt( static_cast< double >( rr ) );
341 std::vector< difference_type > list;
342 list.reserve( count );
343 for( size_type i = 0 ; i < dist.size( ) ; i++ )
346 if( dist[ i ] == rr && r >= mask[ i ] )
354 difference_type rx =
static_cast< difference_type
>( std::ceil( r ) );
355 difference_type ry = in.height( ) < 2 ? 0 : rx;
356 difference_type rz = in.depth( ) < 2 ? 0 : rx;
357 size_type RR = ( rx + 1 ) * ( rx + 1 );
361 std::vector< position_type >
sphere;
362 sphere.reserve( ( 2 * rx + 1 ) * ( 2 * ry + 1 ) * ( 2 * rz + 1 ) );
364 difference_type cx = out.width( ) / 2;
365 difference_type cy = out.height( ) / 2;
366 difference_type cz = out.depth( ) / 2;
367 const_pointer cp = &out( cx, cy, cz );
368 for( difference_type k = -rz ; k <= rz ; k++ )
370 size_type kk = k * k;
372 for( difference_type j = -ry ; j <= ry ; j++ )
374 size_type jj = j * j;
376 for( difference_type i = -rx ; i <= rx ; i++ )
378 size_type ii = i * i;
380 size_type rrr = ii + jj + kk;
384 sphere.push_back( position_type( rrr, r, &out( cx + i, cy + j, cz + k ) - cp ) );
391 difference_type csize = list.size( );
394 difference_type cindex = 0;
395 for( ; cindex < csize ; cindex++ )
397 if( out[ list[ cindex ] ] != 0 )
403 if( cindex == csize )
408 difference_type index = list[ cindex ];
409 list[ cindex ] = list[ csize - 1 ];
412 if( out[ index ] == 0 )
416 if( label_count > label_max )
419 label_count = label_max + 1;
421 current_label =
static_cast< value_type
>( label_count );
426 current_label = out[ index ];
429 for( size_type i = 0 ; i < sphere.size( ) ; i++ )
431 const position_type &pt = sphere[ i ];
432 const difference_type indx = index + pt.index;
433 if( mask[ indx ] < pt.radius )
435 if( dist[ indx ] + pt.RADIUS < RR )
437 mask[ indx ] = pt.radius;
438 out[ indx ] =
static_cast< value_type
>( current_label );
447 difference_type csize = list.size( );
452 difference_type cindex = 0;
453 for( ; cindex < csize ; cindex++ )
455 difference_type indx = list[ cindex ];
456 difference_type z = indx / ( out.width( ) * out.height( ) );
457 difference_type y = ( indx - z * out.width( ) * out.height( ) ) / out.width( );
458 difference_type x = indx - ( y + z * out.height( ) ) * out.width( );
462 for( difference_type k = -rz ; k <= rz ; k++ )
464 size_type pz = k + z;
465 if( pz < 0 || pz >= in.depth( ) )
continue;
466 double kk =
static_cast< double >( k * k );
468 for( difference_type j = -ry ; j <= ry ; j++ )
470 size_type py = j + y;
471 if( py < 0 || py >= in.height( ) )
continue;
472 double jj =
static_cast< double >( j * j );
474 for( difference_type i = -rx ; i <= rx ; i++ )
476 size_type px = i + x;
477 if( px < 0 || px >= in.width( ) )
continue;
478 double rR =
static_cast< double >( i * i + jj + kk );
480 size_type cl =
static_cast< size_type
>( out( px, py, pz ) );
481 if( cl != 0 && min > rR )
489 if( current_label != 0 )
495 if( cindex == csize )
500 difference_type index = list[ cindex ];
501 list[ cindex ] = list[ csize - 1 ];
504 if( current_label == 0 )
508 if( label_count > label_max )
511 label_count = label_max + 1;
513 out[ index ] =
static_cast< value_type
>( label_count );
518 out[ index ] =
static_cast< value_type
>( current_label );
523 f( ++loop_count, label_count, r, in, out );
527 for( size_type j = 0 ; j < out.size( ) ; j++ )
529 out[ j ] =
static_cast< size_type
>( out[ j ] ) > label_max ? 0 : out[ j ];
532 return( label_count );
545 template <
class Array1,
class Array2 >
548 return(
figure_decomposition( in, out, max_distance, __figure_dedomposition__::__mist_dmy_fd_callback__( ) ) );
560 #endif // __INCLUDE_MIST_FIGURE_DECOMPOSITION__