36 #ifndef __INCLUDE_MIST_MORPHOLOGY__
37 #define __INCLUDE_MIST_MORPHOLOGY__
40 #ifndef __INCLUDE_MIST_H__
44 #ifndef __INCLUDE_MIST_LIMITS__
45 #include "../limits.h"
49 #ifndef __INCLUDE_MIST_THREAD__
50 #include "../thread.h"
148 if( radiusInPhysicalCoords )
155 double max_reso = resoX > resoY ? resoX: resoY;
157 ax = resoX / max_reso;
158 ay = resoY / max_reso;
161 double xx, yy, rr = radius * radius;
162 difference_type rx =
static_cast< size_type
>( ceil( radius / ax ) );
163 difference_type ry =
static_cast< size_type
>( ceil( radius / ay ) );
164 difference_type x, y;
166 size_type ox = rx + 1;
167 size_type oy = ry + 1;
169 size_type w = 2 * ox + 1;
170 size_type h = 2 * oy + 1;
176 for( y = -ry ; y <= ry ; y++ )
178 yy = y * y * ay * ay;
179 for( x = -rx ; x <= rx ; x++ )
181 xx = x * x * ax * ax;
184 m( x + ox, y + oy ) =
true;
190 for( y = -ry ; y <= ry ; y++ )
193 for( x = -rx ; x <= rx ; x++ )
195 if( m( x + ox, y + oy ) )
203 if( m( x + ox, y + oy ) && !m( x + ox + 1, y + oy ) )
237 if( radiusInPhysicalCoords )
245 double max_reso = resoX > resoY ? resoX: resoY;
246 max_reso = max_reso > resoZ ? max_reso : resoZ;
248 ax = resoX / max_reso;
249 ay = resoY / max_reso;
250 az = resoZ / max_reso;
253 double xx, yy, zz, rr = radius * radius;
254 difference_type rx =
static_cast< size_type
>( ceil( radius / ax ) );
255 difference_type ry =
static_cast< size_type
>( ceil( radius / ay ) );
256 difference_type rz =
static_cast< size_type
>( ceil( radius / az ) );
257 difference_type x, y, z;
259 size_type ox = rx + 1;
260 size_type oy = ry + 1;
261 size_type oz = rz + 1;
263 size_type w = 2 * ox + 1;
264 size_type h = 2 * oy + 1;
265 size_type d = 2 * oz + 1;
271 for( z = -rz ; z <= rz ; z++ )
273 zz = z * z * az * az;
274 for( y = -ry ; y <= ry ; y++ )
276 yy = y * y * ay * ay;
277 for( x = -rx ; x <= rx ; x++ )
279 xx = x * x * ax * ax;
280 if( xx + yy + zz <= rr )
282 m( x + ox, y + oy, z + oz ) =
true;
289 for( z = -rz ; z <= rz ; z++ )
291 for( y = -ry ; y <= ry ; y++ )
294 for( x = -rx ; x <= rx ; x++ )
296 if( m( x + ox, y + oy, z + oz ) )
304 if( m( x + ox, y + oy, z + oz ) && !m( x + ox + 1, y + oy, z + oz ) )
339 if( radiusInPhysicalCoords )
346 double max_reso = resoX > resoY ? resoX: resoY;
348 ax = resoX / max_reso;
349 ay = resoY / max_reso;
353 difference_type rx =
static_cast< size_type
>( ceil( radius / ax ) );
354 difference_type ry =
static_cast< size_type
>( ceil( radius / ay ) );
355 difference_type x, y;
357 size_type ox = rx + 1;
358 size_type oy = ry + 1;
360 size_type w = 2 * ox + 1;
361 size_type h = 2 * oy + 1;
367 for( y = -ry ; y <= ry ; y++ )
370 for( x = -rx ; x <= rx ; x++ )
373 if( std::abs( xx ) <= radius && std::abs( yy ) <= radius )
375 m( x + ox, y + oy ) =
true;
381 for( y = -ry ; y <= ry ; y++ )
384 for( x = -rx ; x <= rx ; x++ )
386 if( m( x + ox, y + oy ) )
388 s.object.push_back(
point( x, y, 0, ++life ) );
394 if( m( x + ox, y + oy ) && !m( x + ox + 1, y + oy ) )
396 s.update.push_back(
point( x, y, 0, life ) );
428 if( radiusInPhysicalCoords )
436 double max_reso = resoX > resoY ? resoX: resoY;
437 max_reso = max_reso > resoZ ? max_reso : resoZ;
439 ax = resoX / max_reso;
440 ay = resoY / max_reso;
441 az = resoZ / max_reso;
445 difference_type rx =
static_cast< size_type
>( ceil( radius / ax ) );
446 difference_type ry =
static_cast< size_type
>( ceil( radius / ay ) );
447 difference_type rz =
static_cast< size_type
>( ceil( radius / az ) );
448 difference_type x, y, z;
450 size_type ox = rx + 1;
451 size_type oy = ry + 1;
452 size_type oz = rz + 1;
454 size_type w = 2 * ox + 1;
455 size_type h = 2 * oy + 1;
456 size_type d = 2 * oz + 1;
462 for( z = -rz ; z <= rz ; z++ )
465 for( y = -ry ; y <= ry ; y++ )
468 for( x = -rx ; x <= rx ; x++ )
471 if( std::abs( xx ) <= radius && std::abs( yy ) <= radius && std::abs( zz ) <= radius )
473 m( x + ox, y + oy, z + oz ) =
true;
480 for( z = -rz ; z <= rz ; z++ )
482 for( y = -ry ; y <= ry ; y++ )
485 for( x = -rx ; x <= rx ; x++ )
487 if( m( x + ox, y + oy, z + oz ) )
489 s.object.push_back(
point( x, y, z, ++life ) );
495 if( m( x + ox, y + oy, z + oz ) && !m( x + ox + 1, y + oy, z + oz ) )
497 s.update.push_back(
point( x, y, z, life ) );
523 template <
class Array >
527 typedef typename Array::size_type size_type;
528 typedef typename Array::difference_type difference_type;
529 difference_type x, y, z;
531 difference_type w = in.width( );
532 difference_type h = in.height( );
533 difference_type d = in.depth( );
539 for( z = 0 ; z < d ; z++ )
541 for( y = 0 ; y < h ; y++ )
543 for( x = 0 ; x < w ; x++ )
545 m( x, y, z ) = in( x, y, z ) == 0 ?
false :
true;
551 for( z = 0 ; z < d ; z++ )
553 for( y = 0 ; y < h ; y++ )
556 for( x = 0 ; x < w ; x++ )
560 s.object.push_back(
point( x - cx, y - cy, z - cz, ++life ) );
566 if( m( x, y, z ) && !m( x + 1, y, z ) )
568 s.update.push_back(
point( x - cx, y - cy, z - cz, life ) );
574 s.margin_x = cx > w - cx - 1 ? cx : w - cx;
575 s.margin_y = cy > h - cy - 1 ? cy : h - cy;
576 s.margin_z = cz > d - cz - 1 ? cz : d - cz;
591 template <
class Array >
594 typedef typename Array::size_type size_type;
595 typedef typename Array::const_pointer const_pointer;
596 size_type cx = in.width( ) / 2;
597 size_type cy = in.height( ) / 2;
598 size_type cz = in.depth( ) / 2;
599 const_pointer p = &( in( cx, cy, cz ) );
601 std::vector< pointer_diff > out;
603 for( size_type i = 0 ; i < list.size( ) ; i++ )
605 const point &pt = list[ i ];
606 const_pointer pp = &( in( cx + pt.
x, cy + pt.
y, cz + pt.
z ) );
619 namespace __erosion__
621 template <
class Array1,
class Array2,
class Functor >
622 void erosion(
const Array1 &in, Array2 &out,
623 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
624 typename Array1::size_type thread_idy,
typename Array1::size_type thread_numy,
625 typename Array1::size_type thread_idz,
typename Array1::size_type thread_numz, Functor f )
627 typedef typename Array1::size_type size_type;
628 typedef typename Array1::value_type value_type;
629 typedef typename Array1::const_pointer const_pointer;
630 typedef typename Array1::difference_type difference_type;
631 typedef typename Array2::value_type out_value_type;
632 typedef morphology::pointer_diff pointer_diff;
633 typedef std::vector< pointer_diff > list_type;
635 list_type::const_iterator ite;
642 size_type w = in.width( );
643 size_type h = in.height( );
644 size_type d = in.depth( );
646 const bool bprogress1 = thread_idy == 0 && d == 1;
647 const bool bprogress2 = thread_idz == 0 && d > 1;
649 for( k = thread_idz ; k < d ; k += thread_numz )
651 for( j = thread_idy ; j < h ; j += thread_numy )
653 p = &( in( 0, j, k ) );
654 ite =
object.begin( );
655 min = p[ ite->diff ];
658 for( ; ite !=
object.end( ) ; ++ite )
660 if( min > p[ ite->diff ] || ( min == p[ ite->diff ] && life < ite->life ) )
662 min = p[ ite->diff ];
667 out( 0, j, k ) =
static_cast< out_value_type
>( min );
670 for( i = 1 ; i < w ; i++ )
672 p = &( in( i, j, k ) );
677 ite =
object.begin( );
678 min = p[ ite->diff ];
681 for( ; ite !=
object.end( ) ; ++ite )
683 if( min > p[ ite->diff ] || ( min == p[ ite->diff ] && life < ite->life ) )
685 min = p[ ite->diff ];
693 for( ite = update.begin( ) ; ite != update.end( ) ; ++ite )
695 if( min > p[ ite->diff ] || ( min == p[ ite->diff ] && life < ite->life ) )
697 min = p[ ite->diff ];
703 out( i, j, k ) =
static_cast< out_value_type
>( min );
709 f( static_cast< double >( j + 1 ) / static_cast< double >( h ) * 100.0 );
715 f( static_cast< double >( k + 1 ) / static_cast< double >( d ) * 100.0 );
722 namespace __dilation__
724 template <
class Array1,
class Array2,
class Functor >
725 void dilation(
const Array1 &in, Array2 &out,
726 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
727 typename Array1::size_type thread_idy,
typename Array1::size_type thread_numy,
728 typename Array1::size_type thread_idz,
typename Array1::size_type thread_numz, Functor f )
730 typedef typename Array1::size_type size_type;
731 typedef typename Array1::value_type value_type;
732 typedef typename Array1::const_pointer const_pointer;
733 typedef typename Array1::difference_type difference_type;
734 typedef typename Array2::value_type out_value_type;
735 typedef morphology::pointer_diff pointer_diff;
736 typedef std::vector< pointer_diff > list_type;
738 list_type::const_iterator ite;
745 size_type w = in.width( );
746 size_type h = in.height( );
747 size_type d = in.depth( );
749 const bool bprogress1 = thread_idy == 0 && d == 1;
750 const bool bprogress2 = thread_idz == 0 && d > 1;
752 for( k = thread_idz ; k < d ; k += thread_numz )
754 for( j = thread_idy ; j < h ; j += thread_numy )
756 p = &( in( 0, j, k ) );
757 ite =
object.begin( );
758 max = p[ ite->diff ];
761 for( ; ite !=
object.end( ) ; ++ite )
763 if( max < p[ ite->diff ] || ( max == p[ ite->diff ] && life < ite->life ) )
765 max = p[ ite->diff ];
770 out( 0, j, k ) =
static_cast< out_value_type
>( max );
773 for( i = 1 ; i < w ; i++ )
775 p = &( in( i, j, k ) );
780 ite =
object.begin( );
781 max = p[ ite->diff ];
784 for( ; ite !=
object.end( ) ; ++ite )
786 if( max < p[ ite->diff ] || ( max == p[ ite->diff ] && life < ite->life ) )
788 max = p[ ite->diff ];
796 for( ite = update.begin( ) ; ite != update.end( ) ; ++ite )
798 if( max < p[ ite->diff ] || ( max == p[ ite->diff ] && life < ite->life ) )
800 max = p[ ite->diff ];
806 out( i, j, k ) =
static_cast< out_value_type
>( max );
812 f( static_cast< double >( j + 1 ) / static_cast< double >( h ) * 100.0 );
818 f( static_cast< double >( k + 1 ) / static_cast< double >( d ) * 100.0 );
826 namespace __morphology_controller__
829 template <
class T1,
class Allocator1,
class T2,
class Allocator2,
class Functor >
830 void erosion(
const marray< array< T1, Allocator1 > > &in, array< T2, Allocator2 > &out,
831 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
832 typename array< T1, Allocator1 >::size_type thread_id,
typename array< T1, Allocator1 >::size_type thread_num, Functor f )
834 __erosion__::erosion( in, out,
object, update, 0, 1, thread_id, thread_num, f );
837 template <
class T1,
class Allocator1,
class T2,
class Allocator2,
class Functor >
838 void erosion(
const marray< array1< T1, Allocator1 > > &in, array1< T2, Allocator2 > &out,
839 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
840 typename array1< T1, Allocator1 >::size_type thread_id,
typename array1< T1, Allocator1 >::size_type thread_num, Functor f )
842 __erosion__::erosion( in, out,
object, update, 0, 1, thread_id, thread_num, f );
845 template <
class T1,
class Allocator1,
class T2,
class Allocator2,
class Functor >
846 void erosion(
const marray< array2< T1, Allocator1 > > &in, array2< T2, Allocator2 > &out,
847 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
848 typename array2< T1, Allocator1 >::size_type thread_id,
typename array2< T1, Allocator1 >::size_type thread_num, Functor f )
850 __erosion__::erosion( in, out,
object, update, thread_id, thread_num, 0, 1, f );
853 template <
class T1,
class Allocator1,
class T2,
class Allocator2,
class Functor >
854 void erosion(
const marray< array3< T1, Allocator1 > > &in, array3< T2, Allocator2 > &out,
855 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
856 typename array3< T1, Allocator1 >::size_type thread_id,
typename array3< T1, Allocator1 >::size_type thread_num, Functor f )
858 __erosion__::erosion( in, out,
object, update, 0, 1, thread_id, thread_num, f );
863 template <
class T1,
class Allocator1,
class T2,
class Allocator2,
class Functor >
864 void dilation(
const marray< array< T1, Allocator1 > > &in, array< T2, Allocator2 > &out,
865 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
866 typename array< T1, Allocator1 >::size_type thread_id,
typename array< T1, Allocator1 >::size_type thread_num, Functor f )
868 __dilation__::dilation( in, out,
object, update, 0, 1, thread_id, thread_num, f );
871 template <
class T1,
class Allocator1,
class T2,
class Allocator2,
class Functor >
872 void dilation(
const marray< array1< T1, Allocator1 > > &in, array1< T2, Allocator2 > &out,
873 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
874 typename array1< T1, Allocator1 >::size_type thread_id,
typename array1< T1, Allocator1 >::size_type thread_num, Functor f )
876 __dilation__::dilation( in, out,
object, update, 0, 1, thread_id, thread_num, f );
879 template <
class T1,
class Allocator1,
class T2,
class Allocator2,
class Functor >
880 void dilation(
const marray< array2< T1, Allocator1 > > &in, array2< T2, Allocator2 > &out,
881 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
882 typename array2< T1, Allocator1 >::size_type thread_id,
typename array2< T1, Allocator1 >::size_type thread_num, Functor f )
884 __dilation__::dilation( in, out,
object, update, thread_id, thread_num, 0, 1, f );
887 template <
class T1,
class Allocator1,
class T2,
class Allocator2,
class Functor >
888 void dilation(
const marray< array3< T1, Allocator1 > > &in, array3< T2, Allocator2 > &out,
889 const std::vector< morphology::pointer_diff > &
object,
const std::vector< morphology::pointer_diff > &update,
890 typename array3< T1, Allocator1 >::size_type thread_id,
typename array3< T1, Allocator1 >::size_type thread_num, Functor f )
892 __dilation__::dilation( in, out,
object, update, 0, 1, thread_id, thread_num, f );
896 template <
class T1,
class T2,
class Functor >
897 class morphology_thread :
public mist::thread< morphology_thread< T1, T2, Functor > >
901 typedef typename base::thread_exit_type thread_exit_type;
902 typedef typename T1::size_type size_type;
903 typedef typename T1::value_type value_type;
904 typedef morphology::pointer_diff pointer_diff;
905 typedef std::vector< pointer_diff > list_type;
921 void setup_parameters(
const T1 &in, T2 &out, list_type &
object, list_type &update,
bool is_erosion, size_type thread_id, size_type thread_num, Functor f )
927 is_erosion_ = is_erosion;
928 thread_id_ = thread_id;
929 thread_num_ = thread_num;
933 const morphology_thread& operator =(
const morphology_thread &p )
937 base::operator =( p );
938 thread_id_ = p.thread_id_;
939 thread_num_ = p.thread_num_;
942 is_erosion_ = p.is_erosion_;
950 morphology_thread( size_type
id = 0, size_type num = 1 ) : thread_id_( id ), thread_num_( num ),
951 in_( NULL ), out_( NULL ), object_( NULL ), update_( NULL ), is_erosion_( true )
954 morphology_thread(
const morphology_thread &p ) : base( p ), thread_id_( p.thread_id_ ), thread_num_( p.thread_num_ ),
955 in_( p.in_ ), out_( p.out_ ), object_( p.object_ ), update_( p.update_ ), is_erosion_( p.is_erosion_ )
961 virtual thread_exit_type thread_function( )
965 erosion( *in_, *out_, *object_, *update_, thread_id_, thread_num_, f_ );
969 dilation( *in_, *out_, *object_, *update_, thread_id_, thread_num_, f_ );
994 template <
class Array,
class Functor >
1002 typedef typename Array::value_type value_type;
1003 typedef typename Array::size_type size_type;
1004 typedef __morphology_controller__::morphology_thread< marray< Array >, Array, Functor > morphology_thread;
1006 typedef std::vector< pointer_diff > list_type;
1008 if( thread_num == 0 )
1010 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
1020 morphology_thread *
thread =
new morphology_thread[ thread_num ];
1023 for( i = 0 ; i < thread_num ; i++ )
1025 thread[ i ].setup_parameters( out, in,
object, update,
true, i, thread_num, f );
1053 template <
class Array >
1073 template <
class Array,
class Functor >
1081 typedef typename Array::value_type value_type;
1082 typedef typename Array::size_type size_type;
1083 typedef __morphology_controller__::morphology_thread< marray< Array >, Array, Functor > morphology_thread;
1085 typedef std::vector< pointer_diff > list_type;
1087 if( thread_num == 0 )
1089 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
1099 morphology_thread *
thread =
new morphology_thread[ thread_num ];
1102 for( i = 0 ; i < thread_num ; i++ )
1104 thread[ i ].setup_parameters( out, in,
object, update,
false, i, thread_num, f );
1132 template <
class Array >
1152 template <
class Array,
class Functor >
1160 typedef typename Array::value_type value_type;
1161 typedef typename Array::size_type size_type;
1163 typedef __morphology_controller__::morphology_thread< marray< Array >, Array, CallBack > morphology_thread;
1165 typedef std::vector< pointer_diff > list_type;
1167 if( thread_num == 0 )
1169 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
1180 morphology_thread *
thread =
new morphology_thread[ thread_num ];
1187 for( i = 0 ; i < thread_num ; i++ )
1189 thread[ i ].setup_parameters( out, in,
object, update,
true, i, thread_num, CallBack( f, 0, 50 ) );
1201 for( i = 0 ; i < thread_num ; i++ )
1203 thread[ i ].setup_parameters( out, in,
object, update,
false, i, thread_num, CallBack( f, 50, 100 ) );
1230 template <
class Array >
1250 template <
class Array,
class Functor >
1258 typedef typename Array::value_type value_type;
1259 typedef typename Array::size_type size_type;
1261 typedef __morphology_controller__::morphology_thread< marray< Array >, Array, CallBack > morphology_thread;
1263 typedef std::vector< pointer_diff > list_type;
1265 if( thread_num == 0 )
1267 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
1278 morphology_thread *
thread =
new morphology_thread[ thread_num ];
1285 for( i = 0 ; i < thread_num ; i++ )
1287 thread[ i ].setup_parameters( out, in,
object, update,
false, i, thread_num, CallBack( f, 0, 50 ) );
1299 for( i = 0 ; i < thread_num ; i++ )
1301 thread[ i ].setup_parameters( out, in,
object, update,
true, i, thread_num, CallBack( f, 50, 100 ) );
1328 template <
class Array >
1349 template <
class Array,
class Functor >
1350 inline bool erosion( Array &in,
double radius, Functor f,
typename Array::size_type thread_num )
1352 if( in.depth( ) == 1 )
1354 return( erosion( in,
morphology::circle( radius, in.reso1( ), in.reso2( ) ), f, thread_num ) );
1358 return( erosion( in,
morphology::sphere( radius, in.reso1( ), in.reso2( ), in.reso3( ) ), f, thread_num ) );
1376 template <
class Array,
class Functor >
1377 inline bool dilation( Array &in,
double radius, Functor f,
typename Array::size_type thread_num )
1379 if( in.depth( ) == 1 )
1381 return( dilation( in,
morphology::circle( radius, in.reso1( ), in.reso2( ) ), f, thread_num ) );
1385 return( dilation( in,
morphology::sphere( radius, in.reso1( ), in.reso2( ), in.reso3( ) ), f, thread_num ) );
1403 template <
class Array,
class Functor >
1404 inline bool opening( Array &in,
double radius, Functor f,
typename Array::size_type thread_num )
1406 if( in.depth( ) == 1 )
1430 template <
class Array,
class Functor >
1431 inline bool closing( Array &in,
double radius, Functor f,
typename Array::size_type thread_num )
1433 if( in.depth( ) == 1 )
1457 template <
class Array >
1458 inline bool erosion( Array &in,
double radius,
typename Array::size_type thread_num = 0 )
1476 template <
class Array >
1477 inline bool dilation( Array &in,
double radius,
typename Array::size_type thread_num = 0 )
1495 template <
class Array >
1496 inline bool opening( Array &in,
double radius,
typename Array::size_type thread_num = 0 )
1514 template <
class Array >
1515 inline bool closing( Array &in,
double radius,
typename Array::size_type thread_num = 0 )
1529 #endif // __INCLUDE_MIST_MORPHOLOGY__