43 #ifndef __INCLUDE_MIST_DISTANCE_TRANSFORM__
44 #define __INCLUDE_MIST_DISTANCE_TRANSFORM__
48 #ifndef __INCLUDE_MIST_H__
52 #ifndef __INCLUDE_MIST_THREAD__
53 #include "../thread.h"
56 #ifndef __INCLUDE_MIST_LIMITS__
57 #include "../limits.h"
66 namespace _distance_utility_
68 template <
int DIMENSION >
71 template <
class Array >
72 inline static typename Array::value_type &at( Array &in,
typename Array::size_type _1,
typename Array::size_type _2,
typename Array::size_type _3 )
74 return( in( _1, _2, _3 ) );
77 template <
class Array >
78 inline static typename Array::size_type size1(
const Array &in ){
return( in.size1( ) ); }
80 template <
class Array >
81 inline static typename Array::size_type size2(
const Array &in ){
return( in.size2( ) ); }
83 template <
class Array >
84 inline static typename Array::size_type size3(
const Array &in ){
return( in.size3( ) ); }
86 template <
class Array >
87 inline static double aspect(
const Array &in ){
return( 1.0 ); }
91 struct __access__< 2 >
93 template <
class Array >
94 inline static typename Array::value_type &at( Array &in,
typename Array::size_type _1,
typename Array::size_type _2,
typename Array::size_type _3 )
96 return( in( _2, _1, _3 ) );
99 template <
class Array >
100 inline static typename Array::size_type size1(
const Array &in ){
return( in.size2( ) ); }
102 template <
class Array >
103 inline static typename Array::size_type size2(
const Array &in ){
return( in.size1( ) ); }
105 template <
class Array >
106 inline static typename Array::size_type size3(
const Array &in ){
return( in.size3( ) ); }
108 template <
class Array >
109 inline static double aspect(
const Array &in ){
return( in.reso2( ) / in.reso1( ) ); }
113 struct __access__< 3 >
115 template <
class Array >
116 inline static typename Array::value_type &at( Array &in,
typename Array::size_type _1,
typename Array::size_type _2,
typename Array::size_type _3 )
118 return( in( _2, _3, _1 ) );
121 template <
class Array >
122 inline static typename Array::size_type size1(
const Array &in ){
return( in.size3( ) ); }
124 template <
class Array >
125 inline static typename Array::size_type size2(
const Array &in ){
return( in.size1( ) ); }
127 template <
class Array >
128 inline static typename Array::size_type size3(
const Array &in ){
return( in.size2( ) ); }
130 template <
class Array >
131 inline static double aspect(
const Array &in ){
return( in.reso3( ) / in.reso1( ) ); }
134 template <
int DIMENSION >
137 typedef size_t size_type;
146 __range__( ) : sx( 0 ), ex( 0 ), sy( 0 ), ey( 0 ), sz( 0 ), ez( 0 )
150 __range__( size_type ssx, size_type eex, size_type ssy, size_type eey, size_type ssz, size_type eez )
151 : sx( ssx ), ex( eex ), sy( ssy ), ey( eey ), sz( ssz ), ez( eez )
156 __range__(
const __range__< DIM > &r )
157 : sx( r.sx ), ex( r.ex ), sy( r.sy ), ey( r.ey ), sz( r.sz ), ez( r.ez )
161 size_type begin1( )
const {
return( sx ); }
162 size_type end1( )
const {
return( ex ); }
164 size_type begin2( )
const {
return( sy ); }
165 size_type end2( )
const {
return( ey ); }
167 size_type begin3( )
const {
return( sz ); }
168 size_type end3( )
const {
return( ez ); }
172 struct __range__< 2 >
174 typedef size_t size_type;
183 __range__( ) : sx( 0 ), ex( 0 ), sy( 0 ), ey( 0 ), sz( 0 ), ez( 0 )
187 __range__( size_type ssx, size_type eex, size_type ssy, size_type eey, size_type ssz, size_type eez )
188 : sx( ssx ), ex( eex ), sy( ssy ), ey( eey ), sz( ssz ), ez( eez )
193 __range__(
const __range__< DIM > &r )
194 : sx( r.sx ), ex( r.ex ), sy( r.sy ), ey( r.ey ), sz( r.sz ), ez( r.ez )
198 size_type begin1( )
const {
return( sy ); }
199 size_type end1( )
const {
return( ey ); }
201 size_type begin2( )
const {
return( sx ); }
202 size_type end2( )
const {
return( ex ); }
204 size_type begin3( )
const {
return( sz ); }
205 size_type end3( )
const {
return( ez ); }
209 struct __range__< 3 >
211 typedef size_t size_type;
220 __range__( ) : sx( 0 ), ex( 0 ), sy( 0 ), ey( 0 ), sz( 0 ), ez( 0 )
224 __range__( size_type ssx, size_type eex, size_type ssy, size_type eey, size_type ssz, size_type eez )
225 : sx( ssx ), ex( eex ), sy( ssy ), ey( eey ), sz( ssz ), ez( eez )
230 __range__(
const __range__< DIM > &r )
231 : sx( r.sx ), ex( r.ex ), sy( r.sy ), ey( r.ey ), sz( r.sz ), ez( r.ez )
235 size_type begin1( )
const {
return( sz ); }
236 size_type end1( )
const {
return( ez ); }
238 size_type begin2( )
const {
return( sx ); }
239 size_type end2( )
const {
return( ex ); }
241 size_type begin3( )
const {
return( sy ); }
242 size_type end3( )
const {
return( ey ); }
251 void euclidean_distance_transform_x( T &in,
double max_length = -1.0,
typename T::size_type thread_id = 0,
typename T::size_type thread_num = 1 )
253 typedef typename T::difference_type difference_type;
254 typedef typename T::value_type value_type;
256 difference_type i, j, k;
259 const difference_type w = in.width( );
260 const difference_type h = in.height( );
261 const difference_type d = in.depth( );
263 value_type max =
static_cast< value_type
>( max_length <= 0 ? std::sqrt( static_cast< double >( type_limits< value_type >::maximum( ) ) ) : max_length );
265 for( k = 0 ; k < d ; k++ )
267 for( j = thread_id ; j < h ; j += thread_num )
269 if( in( 0, j, k ) != 0 )
271 nd =
static_cast< value_type
>( w ) < max ? static_cast< value_type >( w ) : max;
272 in( 0, j, k ) = nd * nd;
279 for( i = 1 ; i < w ; i++ )
281 if( in( i, j, k ) != 0 )
283 nd = nd + 1 < max ? nd + 1 : nd;
284 in( i, j, k ) = nd * nd;
292 if( in( w - 1, j, k ) != 0 )
294 nd =
static_cast< value_type
>( w ) < max ? static_cast< value_type >( w ) : max;
295 in( w - 1, j, k ) = in( w - 1, j, k ) < nd * nd ? in( w - 1, j, k ) : nd * nd;
302 for( i = w - 2 ; i >= 0 ; i-- )
304 if( in( i, j, k ) != 0 )
306 nd = nd + 1 < max ? nd + 1 : nd;
307 in( i, j, k ) = in( i, j, k ) < nd * nd ? in( i, j, k ) : nd * nd;
319 void euclidean_distance_transform_y( T &in,
double max_length = -1.0,
typename T::size_type thread_id = 0,
typename T::size_type thread_num = 1 )
321 typedef typename T::size_type size_type;
322 typedef typename T::value_type value_type;
323 typedef typename T::difference_type difference_type;
330 difference_type irange1, irange2;
334 size_type w = in.width( );
335 size_type h = in.height( );
336 size_type d = in.depth( );
338 value_type max =
static_cast< value_type
>( max_length <= 0 ? std::sqrt( static_cast< double >( type_limits< value_type >::maximum( ) ) ) : max_length );
340 vy = in.reso2( ) / in.reso1( );
342 work =
new double[ h ];
344 for( k = 0 ; k < d ; k++ )
346 for( i = thread_id ; i < w ; i += thread_num )
348 for( j = 0 ; j < h ; j++ )
350 work[ j ] =
static_cast< double >( in( i, j, k ) );
353 for( j = 0 ; j < h ; j++ )
359 irange =
static_cast< size_type
>( std::sqrt( wmin ) / vy ) + 1;
360 irange =
static_cast< size_type
>(
static_cast< value_type
>( irange ) < max ? irange : max );
362 irange1 = j < irange ? j : irange;
363 irange2 = j + irange >= h ? h - 1 - j : irange;
364 for( n = -irange1 ; n <= irange2 ; n++ )
366 wtmp = work[ j + n ] +
static_cast< double >( n * n * vyvy );
367 wmin = wmin > wtmp ? wtmp : wmin;
370 in( i, j, k ) =
static_cast< value_type
>( wmin );
381 void euclidean_distance_transform_z( T &in,
double max_length = -1.0,
typename T::size_type thread_id = 0,
typename T::size_type thread_num = 1 )
383 typedef typename T::size_type size_type;
384 typedef typename T::value_type value_type;
385 typedef typename T::difference_type difference_type;
391 difference_type irange1, irange2;
395 size_type w = in.width( );
396 size_type h = in.height( );
397 size_type d = in.depth( );
399 vz = in.reso3( ) / in.reso1( );
401 work =
new double[ d ];
403 value_type max =
static_cast< value_type
>( max_length <= 0 ? std::sqrt( static_cast< double >( type_limits< value_type >::maximum( ) ) ) : max_length );
405 for( j = 0 ; j < h ; j++ )
407 for( i = thread_id ; i < w ; i += thread_num )
409 for( k = 0 ; k < d ; k++ )
411 work[ k ] =
static_cast< double >( in( i, j, k ) );
414 for( k = 0 ; k < d ; k++ )
420 irange =
static_cast< size_type
>( std::sqrt( wmin ) / vz ) + 1;
421 irange =
static_cast< size_type
>(
static_cast< value_type
>( irange ) < max ? irange : max );
423 irange1 = k < irange ? k : irange;
424 irange2 = k + irange >= d ? d - 1 - k : irange;
425 for( n = -irange1 ; n <= irange2 ; n++ )
427 wtmp = work[ k + n ] +
static_cast< double >( n * n * vzvz );
428 wmin = wmin > wtmp ? wtmp : wmin;
431 in( i, j, k ) =
static_cast< value_type
>( wmin );
442 template <
int DIMENSION >
445 template <
class Array >
446 static void distance_transform( Array &in,
const _distance_utility_::__range__< DIMENSION > &range,
typename Array::size_type thread_id = 0,
typename Array::size_type thread_num = 1 )
448 typedef typename Array::size_type size_type;
449 typedef typename Array::value_type value_type;
450 typedef typename Array::pointer pointer;
451 typedef typename Array::difference_type difference_type;
452 typedef _distance_utility_::__access__< DIMENSION > access;
457 size_type _1s = range.begin1( );
458 size_type _2s = range.begin2( );
459 size_type _3s = range.begin3( );
460 size_type _1e = range.end1( );
461 size_type _2e = range.end2( );
462 size_type _3e = range.end3( );
463 difference_type inum = _1e - _1s + 1;
465 value_type *g =
new value_type[ inum + 1 ];
467 double as = access::aspect( in );
468 double as2 = as * as;
469 double _2as = 1.0 / ( 2.0 * as2 );
470 difference_type diff = &access::at( in, 1, 0, 0 ) - &access::at( in, 0, 0, 0 );
472 for( size_type i3 = _3s + thread_id ; i3 <= _3e ; i3 += thread_num )
474 for( size_type i2 = _2s ; i2 <= _2e ; i2++ )
476 pointer sp = &access::at( in, _1s, i2, i3 );
477 pointer ep = &access::at( in, _1e, i2, i3 );
479 memset( g, 0,
sizeof( value_type ) * ( _1e - _1s + 1 + 1 ) );
483 pointer p = sp + diff;
485 for( difference_type i1 = 1 ; i1 < inum ; i1++, p += diff )
489 difference_type num =
static_cast< difference_type
>( ( *op - *p - 1 ) * _2as );
491 for( difference_type n = 0 ; n <= num && pp <= ep ; n++, pp += diff )
493 double nn = *op - ( n + 1 ) * ( n + 1 ) * as2;
498 else if( g[ i1 + n ] < nn )
500 g[ i1 + n ] =
static_cast< value_type
>( nn );
504 else if( g[ i1 ] < *p )
515 for( difference_type i1 = inum - 1 ; i1 >= 0 ; i1--, p -= diff )
517 if( g[ i1 ] < g[ i1 + 1 ] )
519 difference_type num =
static_cast< difference_type
>( ( g[ i1 + 1 ] - g[ i1 ] - 1 ) * _2as );
521 for( difference_type n = 0 ; n <= num && pp >= sp ; n++, pp -= diff )
523 double nn = g[ i1 + 1 ] - ( n + 1 ) * ( n + 1 ) * as2;
524 if( g[ i1 - n ] >= nn )
530 *pp =
static_cast< value_type
>( nn );
534 else if( *p < g[ i1 ] )
550 class saito_distance_transform_thread :
public mist::thread< saito_distance_transform_thread< T > >
554 typedef typename base::thread_exit_type thread_exit_type;
555 typedef typename T::size_type size_type;
556 typedef typename T::value_type value_type;
568 void setup_parameters( T &in,
double max_length, size_type axis, size_type thread_id, size_type thread_num )
571 max_length_ = max_length;
573 thread_id_ = thread_id;
574 thread_num_ = thread_num;
577 void setup_axis( size_type axis )
582 const saito_distance_transform_thread& operator =(
const saito_distance_transform_thread &p )
586 base::operator =( p );
587 thread_id_ = p.thread_id_;
588 thread_num_ = p.thread_num_;
590 max_length_ = p.max_length;
596 saito_distance_transform_thread( size_type
id = 0, size_type num = 1 )
597 : thread_id_( id ), thread_num_( num ), in_( NULL ), max_length_( -1.0 ), axis_( 0 )
600 saito_distance_transform_thread(
const saito_distance_transform_thread &p )
601 : base( p ), thread_id_( p.thread_id_ ), thread_num_( p.thread_num_ ), in_( NULL ), max_length_( -1.0 ), axis_( p.axis_ )
607 virtual thread_exit_type thread_function( )
612 __saito__::euclidean_distance_transform_y( *in_, max_length_, thread_id_, thread_num_ );
616 __saito__::euclidean_distance_transform_z( *in_, max_length_, thread_id_, thread_num_ );
621 __saito__::euclidean_distance_transform_x( *in_, max_length_, thread_id_, thread_num_ );
629 class saito_inverse_distance_transform_thread :
public mist::thread< saito_inverse_distance_transform_thread< T > >
633 typedef typename base::thread_exit_type thread_exit_type;
634 typedef typename T::size_type size_type;
635 typedef typename T::value_type value_type;
644 _distance_utility_::__range__< 1 > range_;
647 void setup_parameters( T &in,
const _distance_utility_::__range__< 1 > &range, size_type axis, size_type thread_id, size_type thread_num )
652 thread_id_ = thread_id;
653 thread_num_ = thread_num;
656 void setup_axis( size_type axis )
661 const saito_inverse_distance_transform_thread& operator =(
const saito_inverse_distance_transform_thread &p )
665 base::operator =( p );
666 thread_id_ = p.thread_id_;
667 thread_num_ = p.thread_num_;
675 saito_inverse_distance_transform_thread( size_type
id = 0, size_type num = 1 )
676 : thread_id_( id ), thread_num_( num ), in_( NULL ), axis_( 0 )
679 saito_inverse_distance_transform_thread(
const saito_inverse_distance_transform_thread &p )
680 : base( p ), thread_id_( p.thread_id_ ), thread_num_( p.thread_num_ ), in_( NULL ), axis_( p.axis_ )
686 virtual thread_exit_type thread_function( )
713 inline bool remove_edt(
const double uR,
const double vR,
const double wR,
const double ud,
const double vd,
const double wd )
715 const double a = vd - ud;
716 const double b = wd - vd;
717 const double c = a + b;
718 return( c * vR - b * uR - a * wR - a * b * c > 0 );
723 template <
int DIMENSION >
726 template <
class Array >
727 static void distance_transform( Array &in,
const _distance_utility_::__range__< DIMENSION > &range,
typename Array::size_type thread_id = 0,
typename Array::size_type thread_num = 1 )
729 typedef typename Array::size_type size_type;
730 typedef typename Array::value_type value_type;
731 typedef typename Array::pointer pointer;
732 typedef typename Array::difference_type difference_type;
733 typedef _distance_utility_::__access__< DIMENSION > access;
735 size_type _1s = range.begin1( );
736 size_type _2s = range.begin2( );
737 size_type _3s = range.begin3( );
738 size_type _1e = range.end1( );
739 size_type _2e = range.end2( );
740 size_type _3e = range.end3( );
742 double as = access::aspect( in );
743 difference_type diff = &access::at( in, 1, 0, 0 ) - &access::at( in, 0, 0, 0 );
745 double *g =
new double[ _1e - _1s + 2 ];
746 double *h =
new double[ _1e - _1s + 2 ];
748 for( size_type i3 = _3s + thread_id ; i3 <= _3e ; i3 += thread_num )
750 for( size_type i2 = _2s ; i2 <= _2e ; i2++ )
752 pointer p = &access::at( in, 0, i2, i3 );
753 for( size_type _i1s = _1s ; _i1s <= _1e ; )
756 for( ; _i1s <= _1e ; _i1s++ )
758 if( p[ _i1s * diff ] != 0 )
772 for( _i1e = _i1s ; _i1e <= _1e ; _i1e++ )
774 if( p[ _i1e * diff ] == 0 )
789 difference_type l = 0;
791 for( size_type i1 = _i1s ; i1 <= _i1e ; i1++ )
793 double nd =
static_cast< double >( i1 - _i1s + 1 ) * as;
794 double fn =
static_cast< double >( p[ i1 * diff ] );
804 while( l >= 2 && remove_edt( g[ l - 1 ], g[ l ], fn, h[ l - 1 ], h[ l ], nd ) )
819 difference_type ns = l;
822 for( size_type i1 = _i1s ; i1 <= _i1e ; i1++ )
824 double nd = ( i1 - _i1s + 1 ) * as;
825 double len = h[ l ] - nd;
827 len = g[ l ] + len * len;
828 for( ; l < ns ; l++ )
830 double len_ = h[ l + 1 ] - nd;
831 len_ = g[ l + 1 ] + len_ * len_;
841 p[ i1 * diff ] =
static_cast< value_type
>( len );
860 template <
class Array >
861 static void distance_transform( Array &in,
const _distance_utility_::__range__< 1 > &range,
typename Array::size_type thread_id = 0,
typename Array::size_type thread_num = 1 )
863 typedef typename Array::size_type size_type;
864 typedef typename Array::value_type value_type;
865 typedef typename Array::pointer pointer;
866 typedef typename Array::difference_type difference_type;
868 const difference_type w = in.width( );
872 max =
static_cast< value_type
>( w ) < max ? static_cast< value_type >( w ) : max;
874 size_type sx = range.begin1( );
875 size_type sy = range.begin2( );
876 size_type sz = range.begin3( );
877 size_type ex = range.end1( );
878 size_type ey = range.end2( );
879 size_type ez = range.end3( );
881 for( size_type k = sz ; k <= ez ; k++ )
883 for( size_type j = sy + thread_id ; j <= ey ; j += thread_num )
885 pointer sp = &in( sx, j, k );
886 pointer ep = &in( ex, j, k );
898 for( pointer p = sp + 1 ; p <= ep ; p++ )
902 len = len + 1 < max ? len + 1 : len;
914 ep[ 0 ] = ep[ 0 ] < len * len ? ep[ 0 ] : len * len;
921 for( pointer p = ep - 1 ; p >= sp ; p-- )
925 len = len + 1 < max ? len + 1 : len;
926 *p = *p < len * len ? *p : len * len;
940 template <
int DIMENSION >
943 template <
class Array1,
class Array2 >
944 static void distance_transform( Array1 &voronoi, Array2 &dist,
const _distance_utility_::__range__< DIMENSION > &range,
typename Array2::size_type thread_id = 0,
typename Array2::size_type thread_num = 1 )
946 typedef typename Array2::size_type size_type;
947 typedef typename Array2::value_type value_type;
948 typedef typename Array1::pointer ipointer;
949 typedef typename Array2::pointer pointer;
950 typedef typename Array2::difference_type difference_type;
951 typedef _distance_utility_::__access__< DIMENSION > access;
953 size_type _1s = range.begin1( );
954 size_type _2s = range.begin2( );
955 size_type _3s = range.begin3( );
956 size_type _1e = range.end1( );
957 size_type _2e = range.end2( );
958 size_type _3e = range.end3( );
960 double as = access::aspect( dist );
961 difference_type diff = &access::at( dist, 1, 0, 0 ) - &access::at( dist, 0, 0, 0 );
963 difference_type *idx =
new difference_type[ _1e - _1s + 2 ];
964 double *g =
new double[ _1e - _1s + 2 ];
965 double *h =
new double[ _1e - _1s + 2 ];
967 for( size_type i3 = _3s + thread_id ; i3 <= _3e ; i3 += thread_num )
969 for( size_type i2 = _2s ; i2 <= _2e ; i2++ )
971 ipointer vp = &access::at( voronoi, 0, i2, i3 );
972 pointer p = &access::at( dist, 0, i2, i3 );
974 difference_type l = 0;
976 for( size_type i1 = _1s ; i1 <= _1e ; i1++ )
978 double nd =
static_cast< double >( i1 - _1s + 1 ) * as;
979 double fn =
static_cast< double >( p[ i1 * diff ] );
990 while( l >= 2 && remove_edt( g[ l - 1 ], g[ l ], fn, h[ l - 1 ], h[ l ], nd ) )
1006 difference_type ns = l;
1009 for( size_type i1 = _1s ; i1 <= _1e ; i1++ )
1011 double nd = ( i1 - _1s + 1 ) * as;
1012 double len = h[ l ] - nd;
1014 len = g[ l ] + len * len;
1015 for( ; l < ns ; l++ )
1017 double len_ = h[ l + 1 ] - nd;
1018 len_ = g[ l + 1 ] + len_ * len_;
1028 p[ i1 * diff ] =
static_cast< value_type
>( len );
1029 vp[ i1 * diff ] = vp[ idx[ l ] * diff ];
1045 template <
class Array1,
class Array2 >
1046 static void distance_transform( Array1 &voronoi, Array2 &dist,
const _distance_utility_::__range__< 1 > &range,
typename Array2::size_type thread_id = 0,
typename Array2::size_type thread_num = 1 )
1048 typedef typename Array2::size_type size_type;
1049 typedef typename Array1::value_type ivalue_type;
1050 typedef typename Array2::value_type value_type;
1051 typedef typename Array1::pointer ipointer;
1052 typedef typename Array2::pointer pointer;
1053 typedef typename Array2::difference_type difference_type;
1055 const difference_type w = dist.width( );
1057 max =
static_cast< value_type
>( w ) < max ? static_cast< value_type >( w ) : max;
1059 ivalue_type *val =
new ivalue_type[ w ];
1062 size_type sx = range.begin1( );
1063 size_type sy = range.begin2( );
1064 size_type sz = range.begin3( );
1065 size_type ex = range.end1( );
1066 size_type ey = range.end2( );
1067 size_type ez = range.end3( );
1069 for( size_type k = sz ; k <= ez ; k++ )
1071 for( size_type j = sy + thread_id ; j <= ey ; j += thread_num )
1073 ivalue_type *vp = val;
1074 ipointer ip = &voronoi( sx, j, k );
1075 pointer sp = &dist( sx, j, k );
1076 pointer ep = &dist( ex, j, k );
1082 sp[ 0 ] = len * len;
1089 for( pointer p = sp + 1 ; p <= ep ; p++, ip++ )
1094 len = len + 1 < max ? len + 1 : len;
1110 value_type len2 = len * len;
1112 if( ep[ 0 ] > len2 )
1122 for( pointer p = ep - 1 ; p >= sp ; p--, ip--, vp-- )
1126 len = len + 1 < max ? len + 1 : len;
1127 value_type len2 = len * len;
1148 template <
class Array,
int DIMENSION >
1149 bool compute_object_range(
const Array &in, _distance_utility_::__range__< DIMENSION > &range )
1151 typedef typename Array::size_type size_type;
1152 typedef typename Array::difference_type difference_type;
1154 difference_type w = in.width( );
1155 difference_type h = in.height( );
1156 difference_type d = in.depth( );
1158 difference_type sx, ex, sy, ey, sz, ez, i, j, k;
1165 for( k = 0 ; k < d ; k++ )
1168 for( j = 0 ; j < h ; j++ )
1170 for( i = 0 ; i < w ; i++ )
1172 if( in( i, j, k ) != 0 )
1199 for( k = d - 1 ; k > sz ; k-- )
1202 for( j = 0 ; j < h ; j++ )
1204 for( i = 0 ; i < w ; i++ )
1206 if( in( i, j, k ) != 0 )
1227 for( j = 0 ; j < h ; j++ )
1230 for( k = sz ; k <= ez ; k++ )
1232 for( i = 0 ; i < w ; i++ )
1234 if( in( i, j, k ) != 0 )
1255 for( j = h - 1 ; j > sy ; j-- )
1258 for( k = sz ; k <= ez ; k++ )
1260 for( i = 0 ; i < w ; i++ )
1262 if( in( i, j, k ) != 0 )
1283 for( i = 0 ; i < w ; i++ )
1286 for( k = sz ; k <= ez ; k++ )
1288 for( j = sy ; j <= ey ; j++ )
1290 if( in( i, j, k ) != 0 )
1311 for( i = w - 1 ; i > sx ; i-- )
1314 for( k = sz ; k <= ez ; k++ )
1316 for( j = sy ; j <= ey ; j++ )
1318 if( in( i, j, k ) != 0 )
1340 range.sx = sx > 0 ? sx - 1 : 0;
1341 range.ex = ex < w - 1 ? ex + 1 : w - 1;
1342 range.sy = sy > 0 ? sy - 1 : 0;
1343 range.ey = ey < h - 1 ? ey + 1 : h - 1;
1344 range.sz = sz > 0 ? sz - 1 : 0;
1345 range.ez = ez < d - 1 ? ez + 1 : d - 1;
1350 template <
class T >
1351 class calvin_distance_transform_thread :
public mist::thread< calvin_distance_transform_thread< T > >
1355 typedef typename base::thread_exit_type thread_exit_type;
1356 typedef typename T::size_type size_type;
1357 typedef typename T::value_type value_type;
1366 _distance_utility_::__range__< 1 > range_;
1369 void setup_parameters( T &in,
const _distance_utility_::__range__< 1 > &range, size_type axis, size_type thread_id, size_type thread_num )
1374 thread_id_ = thread_id;
1375 thread_num_ = thread_num;
1378 void setup_axis( size_type axis )
1383 const calvin_distance_transform_thread& operator =(
const calvin_distance_transform_thread &p )
1387 base::operator =( p );
1388 thread_id_ = p.thread_id_;
1389 thread_num_ = p.thread_num_;
1397 calvin_distance_transform_thread( size_type
id = 0, size_type num = 1 )
1398 : thread_id_( id ), thread_num_( num ), in_( NULL ), axis_( 0 )
1401 calvin_distance_transform_thread(
const calvin_distance_transform_thread &p )
1402 : base( p ), thread_id_( p.thread_id_ ), thread_num_( p.thread_num_ ), in_( NULL ), axis_( p.axis_ )
1408 virtual thread_exit_type thread_function( )
1430 template <
class T1,
class T2 >
1431 class calvin_voronoi_distance_transform_thread :
public mist::thread< calvin_voronoi_distance_transform_thread< T1, T2 > >
1435 typedef typename base::thread_exit_type thread_exit_type;
1436 typedef typename T1::size_type size_type;
1437 typedef typename T1::value_type value_type;
1447 _distance_utility_::__range__< 1 > range_;
1450 void setup_parameters( T1 &voronoi, T2 &dist,
const _distance_utility_::__range__< 1 > &range, size_type axis, size_type thread_id, size_type thread_num )
1452 voronoi_ = &voronoi;
1456 thread_id_ = thread_id;
1457 thread_num_ = thread_num;
1460 void setup_axis( size_type axis )
1465 const calvin_voronoi_distance_transform_thread& operator =(
const calvin_voronoi_distance_transform_thread &p )
1469 base::operator =( p );
1470 thread_id_ = p.thread_id_;
1471 thread_num_ = p.thread_num_;
1472 voronoi_ = p.voronoi_;
1480 calvin_voronoi_distance_transform_thread( size_type
id = 0, size_type num = 1 )
1481 : thread_id_( id ), thread_num_( num ), voronoi_( NULL ), dist_( NULL ), axis_( 0 )
1484 calvin_voronoi_distance_transform_thread(
const calvin_voronoi_distance_transform_thread &p )
1485 : base( p ), thread_id_( p.thread_id_ ), thread_num_( p.thread_num_ ), voronoi_( NULL ), dist_( NULL ), axis_( p.axis_ )
1491 virtual thread_exit_type thread_function( )
1514 namespace _meijster_distance_transform_
1518 template <
class T,
class Val >
1519 static T Func(
const T &x,
const T &i,
const Val &gi )
1521 return( static_cast< T >( std::abs( static_cast< int >( x - i ) ) + gi ) );
1524 template <
class T,
class Val >
1525 static T Sep(
const T &i,
const T &u,
const Val &gi,
const Val &gu )
1527 if( gu >= gi + u - i )
1529 return( type_limits< T >::maximum( ) );
1531 else if( gi > gu + u - i )
1533 return( type_limits< T >::minimum( ) );
1537 return( ( gu - gi + u + i ) / 2 );
1544 template <
class T,
class Val >
1545 static T Func(
const T &x,
const T &i,
const Val &gi )
1547 T v = std::abs( static_cast< int >( x - i ) );
1548 return( static_cast< T >( v > gi ? v : gi ) );
1551 template <
class T,
class Val >
1552 static T Sep(
const T &i,
const T &u,
const Val &gi,
const Val &gu )
1556 T igu =
static_cast< T
>( i + gu );
1557 T iu =
static_cast< T
>( ( i + u ) / 2 );
1558 return( igu > iu ? igu : iu );
1562 T ugi =
static_cast< T
>( u - gi );
1563 T iu =
static_cast< T
>( ( i + u ) / 2 );
1564 return( ugi < iu ? ugi : iu );
1569 template <
class Array >
1570 void distance_transform_x( Array &in,
typename Array::size_type thread_id = 0,
typename Array::size_type thread_num = 1 )
1572 typedef typename Array::difference_type difference_type;
1573 typedef typename Array::value_type value_type;
1575 difference_type i, j, k;
1577 const difference_type w = in.width( );
1578 const difference_type h = in.height( );
1579 const difference_type d = in.depth( );
1581 value_type max = type_limits< value_type >::maximum( );
1583 for( k = 0 ; k < d ; k++ )
1585 for( i = thread_id ; i < w ; i += thread_num )
1587 if( in( i, 0, k ) != 0 )
1589 in( i, 0, k ) = max;
1592 for( j = 1 ; j < h ; j++ )
1594 if( in( i, j, k ) != 0 )
1596 in( i, j, k ) = in( i, j - 1, k ) + 1;
1600 for( j = h - 2 ; j >= 0 ; j-- )
1602 if( in( i, j + 1, k ) < in( i, j, k ) )
1604 in( i, j, k ) = in( i, j + 1, k ) + 1;
1611 template <
class Array,
class Metric >
1612 void distance_transform_y( Array &in, Metric __dmy__,
typename Array::size_type thread_id = 0,
typename Array::size_type thread_num = 1 )
1614 typedef typename Array::pointer pointer;
1615 typedef typename Array::difference_type difference_type;
1616 typedef typename Array::value_type value_type;
1618 const difference_type w = in.width( );
1619 const difference_type h = in.height( );
1620 const difference_type d = in.depth( );
1622 difference_type i, j, k, q;
1623 difference_type *s =
new difference_type[ w ];
1624 difference_type *t =
new difference_type[ w ];
1626 for( k = 0 ; k < d ; k++ )
1628 for( j = thread_id ; j < h ; j += thread_num )
1630 q = s[ 0 ] = t[ 0 ] = 0;
1632 pointer pin = &in( 0, j, k );
1634 for( i = 1 ; i < w ; i++ )
1636 value_type val = in( i, j, k );
1638 while( q >= 0 && Metric::Func( t[ q ], s[ q ], pin[ s[ q ] ] ) > Metric::Func( t[ q ], i, val ) )
1650 difference_type tmp = Metric::Sep( s[ q ], i, pin[ s[ q ] ], val );
1661 for( i = w - 1 ; i >= 0 ; i-- )
1663 pin[ i ] =
static_cast< value_type
>( Metric::Func( i, s[ q ], pin[ s[ q ] ] ) );
1676 template <
class Array,
class Metric >
1677 void distance_transform_z( Array &in, Metric __dmy__,
typename Array::size_type thread_id = 0,
typename Array::size_type thread_num = 1 )
1679 typedef typename Array::pointer pointer;
1680 typedef typename Array::difference_type difference_type;
1681 typedef typename Array::value_type value_type;
1683 const difference_type w = in.width( );
1684 const difference_type h = in.height( );
1685 const difference_type d = in.depth( );
1687 difference_type i, j, k, q;
1688 difference_type *s =
new difference_type[ d ];
1689 difference_type *t =
new difference_type[ d ];
1690 difference_type diff = &in( 0, 0, 1 ) - &in( 0, 0, 0 );
1692 for( j = 0 ; j < h ; j++ )
1694 for( i = thread_id ; i < w ; i += thread_num )
1696 q = s[ 0 ] = t[ 0 ] = 0;
1698 pointer pin = &in( i, j, 0 );
1700 for( k = 1 ; k < d ; k++ )
1702 value_type val = in( i, j, k );
1704 while( q >= 0 && Metric::Func( t[ q ], s[ q ], pin[ s[ q ] * diff ] ) > Metric::Func( t[ q ], k, val ) )
1716 difference_type tmp = Metric::Sep( s[ q ], k, pin[ s[ q ] * diff ], val );
1727 for( k = d - 1 ; k >= 0 ; k-- )
1729 pin[ k * diff ] =
static_cast< value_type
>( Metric::Func( k, s[ q ], pin[ s[ q ] * diff ] ) );
1743 template <
class T,
class Metric >
1744 class distance_transform_thread :
public mist::thread< distance_transform_thread< T, Metric > >
1748 typedef typename base::thread_exit_type thread_exit_type;
1749 typedef typename T::size_type size_type;
1750 typedef typename T::value_type value_type;
1762 void setup_parameters( T &in, size_type axis, size_type thread_id, size_type thread_num )
1766 thread_id_ = thread_id;
1767 thread_num_ = thread_num;
1770 void setup_axis( size_type axis )
1775 const distance_transform_thread& operator =(
const distance_transform_thread &p )
1779 base::operator =( p );
1780 thread_id_ = p.thread_id_;
1781 thread_num_ = p.thread_num_;
1788 distance_transform_thread( size_type
id = 0, size_type num = 1 )
1789 : thread_id_( id ), thread_num_( num ), in_( NULL ), axis_( 0 )
1792 distance_transform_thread(
const distance_transform_thread &p )
1793 : base( p ), thread_id_( p.thread_id_ ), thread_num_( p.thread_num_ ), in_( NULL ), axis_( p.axis_ )
1799 virtual thread_exit_type thread_function( )
1804 distance_transform_y( *in_, dmy_, thread_id_, thread_num_ );
1808 distance_transform_z( *in_, dmy_, thread_id_, thread_num_ );
1813 distance_transform_x( *in_, thread_id_, thread_num_ );
1867 template <
class Array1,
class Array2 >
1868 void distance_transform(
const Array1 &in, Array2 &out,
double max_length = -1.0,
typename Array1::size_type thread_num = 0 )
1870 typedef typename Array2::size_type size_type;
1871 typedef typename Array2::value_type value_type;
1872 typedef __saito__::saito_distance_transform_thread< Array2 > saito_distance_transform_thread;
1874 if( thread_num == 0 )
1876 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
1879 out.resize( in.size1( ), in.size2( ), in.size3( ) );
1880 out.reso1( in.reso1( ) );
1881 out.reso2( in.reso2( ) );
1882 out.reso3( in.reso3( ) );
1886 for( i = 0 ; i < in.size( ) ; i++ )
1888 out[ i ] =
static_cast< value_type
>( in[ i ] != 0 ? 1 : 0 );
1891 saito_distance_transform_thread *
thread =
new saito_distance_transform_thread[ thread_num ];
1893 if( in.width( ) > 1 )
1896 for( i = 0 ; i < thread_num ; i++ )
1898 thread[ i ].setup_parameters( out, max_length, 0, i, thread_num );
1904 if( in.height( ) > 1 )
1907 for( i = 0 ; i < thread_num ; i++ )
1909 thread[ i ].setup_parameters( out, max_length, 1, i, thread_num );
1915 if( in.depth( ) > 1 )
1918 for( i = 0 ; i < thread_num ; i++ )
1920 thread[ i ].setup_parameters( out, max_length, 2, i, thread_num );
1948 template <
class Array1,
class Array2 >
1951 typedef typename Array2::size_type size_type;
1952 typedef typename Array2::difference_type difference_type;
1953 typedef typename Array2::value_type value_type;
1954 typedef __saito__::saito_inverse_distance_transform_thread< Array2 > saito_inverse_distance_transform_thread;
1956 if( thread_num == 0 )
1958 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
1972 _distance_utility_::__range__< 0 > object_range;
1973 object_range.sx = 0;
1974 object_range.ex = in.size1( ) - 1;
1975 object_range.sy = 0;
1976 object_range.ey = in.size2( ) - 1;
1977 object_range.sz = 0;
1978 object_range.ez = in.size3( ) - 1;
1980 saito_inverse_distance_transform_thread *
thread =
new saito_inverse_distance_transform_thread[ thread_num ];
1982 if( in.width( ) > 1 )
1985 for( size_type i = 0 ; i < thread_num ; i++ )
1987 thread[ i ].setup_parameters( out, object_range, 0, i, thread_num );
1993 if( in.height( ) > 1 )
1996 for( size_type i = 0 ; i < thread_num ; i++ )
1998 thread[ i ].setup_parameters( out, object_range, 1, i, thread_num );
2004 if( in.depth( ) > 1 )
2007 for( size_type i = 0 ; i < thread_num ; i++ )
2009 thread[ i ].setup_parameters( out, object_range, 2, i, thread_num );
2018 for( size_type i = 0 ; i < out.size( ) ; i++ )
2020 out[ i ] = out[ i ] != 0 ? 1 : 0;
2050 template <
class Array1,
class Array2 >
2053 typedef typename Array2::size_type size_type;
2054 typedef typename Array2::value_type value_type;
2055 typedef __calvin__::calvin_distance_transform_thread< Array2 > calvin_distance_transform_thread;
2057 if( thread_num == 0 )
2059 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
2062 out.resize( in.size1( ), in.size2( ), in.size3( ) );
2063 out.reso1( in.reso1( ) );
2064 out.reso2( in.reso2( ) );
2065 out.reso3( in.reso3( ) );
2069 for( i = 0 ; i < in.size( ) ; i++ )
2071 out[ i ] =
static_cast< value_type
>( in[ i ] != 0 ? 1 : 0 );
2074 _distance_utility_::__range__< 0 > object_range;
2075 if( !__calvin__::compute_object_range( out, object_range ) )
2081 calvin_distance_transform_thread *
thread =
new calvin_distance_transform_thread[ thread_num ];
2083 if( in.width( ) > 1 )
2086 for( i = 0 ; i < thread_num ; i++ )
2088 thread[ i ].setup_parameters( out, object_range, 0, i, thread_num );
2094 if( in.height( ) > 1 )
2097 for( i = 0 ; i < thread_num ; i++ )
2099 thread[ i ].setup_parameters( out, object_range, 1, i, thread_num );
2105 if( in.depth( ) > 1 )
2108 for( i = 0 ; i < thread_num ; i++ )
2110 thread[ i ].setup_parameters( out, object_range, 2, i, thread_num );
2139 template <
class Array1,
class Array2 >
2142 typedef typename Array2::size_type size_type;
2143 typedef typename Array2::value_type value_type;
2144 typedef __calvin__::calvin_voronoi_distance_transform_thread< Array1, Array2 > calvin_voronoi_distance_transform_thread;
2146 if( thread_num == 0 )
2148 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
2151 dist.resize( voronoi.size1( ), voronoi.size2( ), voronoi.size3( ) );
2152 dist.reso1( voronoi.reso1( ) );
2153 dist.reso2( voronoi.reso2( ) );
2154 dist.reso3( voronoi.reso3( ) );
2158 _distance_utility_::__range__< 0 > object_range;
2159 object_range.sx = 0;
2160 object_range.ex = voronoi.size1( ) - 1;
2161 object_range.sy = 0;
2162 object_range.ey = voronoi.size2( ) - 1;
2163 object_range.sz = 0;
2164 object_range.ez = voronoi.size3( ) - 1;
2166 calvin_voronoi_distance_transform_thread *
thread =
new calvin_voronoi_distance_transform_thread[ thread_num ];
2168 if( voronoi.width( ) > 1 )
2171 for( i = 0 ; i < thread_num ; i++ )
2173 thread[ i ].setup_parameters( voronoi, dist, object_range, 0, i, thread_num );
2179 if( voronoi.height( ) > 1 )
2182 for( i = 0 ; i < thread_num ; i++ )
2184 thread[ i ].setup_parameters( voronoi, dist, object_range, 1, i, thread_num );
2190 if( voronoi.depth( ) > 1 )
2193 for( i = 0 ; i < thread_num ; i++ )
2195 thread[ i ].setup_parameters( voronoi, dist, object_range, 2, i, thread_num );
2221 template <
class Array >
2224 double ax = voronoi.reso1( );
2225 double ay = voronoi.reso2( );
2226 double az = voronoi.reso3( );
2227 if( ax == ay && ay == az )
2229 typename Array::template rebind< unsigned int >::other dist;
2234 typename Array::template rebind< float >::other dist;
2265 template <
class Array1,
class Array2 >
2290 template <
class Array1,
class Array2 >
2325 template <
class Array1,
class Array2 >
2348 template <
class Array >
2388 template <
class Array1,
class Array2,
class Metric >
2389 void distance_transform(
const Array1 &in, Array2 &out, Metric __metric__,
typename Array1::size_type thread_num = 0 )
2391 typedef typename Array2::size_type size_type;
2392 typedef typename Array2::value_type value_type;
2393 typedef _meijster_distance_transform_::distance_transform_thread< Array2, Metric > meijster_distance_transform_thread;
2395 if( thread_num == 0 )
2397 thread_num =
static_cast< size_type
>(
get_cpu_num( ) );
2400 out.resize( in.size1( ), in.size2( ), in.size3( ) );
2401 out.reso1( in.reso1( ) );
2402 out.reso2( in.reso2( ) );
2403 out.reso3( in.reso3( ) );
2407 for( i = 0 ; i < in.size( ) ; i++ )
2409 out[ i ] =
static_cast< value_type
>( in[ i ] != 0 ? 1 : 0 );
2412 meijster_distance_transform_thread *
thread =
new meijster_distance_transform_thread[ thread_num ];
2414 if( in.width( ) > 1 )
2417 for( i = 0 ; i < thread_num ; i++ )
2419 thread[ i ].setup_parameters( out, 0, i, thread_num );
2425 if( in.height( ) > 1 )
2428 for( i = 0 ; i < thread_num ; i++ )
2430 thread[ i ].setup_parameters( out, 1, i, thread_num );
2436 if( in.depth( ) > 1 )
2439 for( i = 0 ; i < thread_num ; i++ )
2441 thread[ i ].setup_parameters( out, 2, i, thread_num );
2482 template <
class Array1,
class Array2 >
2485 _meijster_distance_transform_::MDT metric;
2508 template <
class Array1,
class Array2 >
2511 _meijster_distance_transform_::MDT metric;
2530 namespace chessboard
2546 template <
class Array1,
class Array2 >
2549 _meijster_distance_transform_::CDT metric;
2574 template <
class Array1,
class Array2 >
2577 typedef typename Array1::size_type size_type;
2578 typedef typename Array1::difference_type difference_type;
2579 typedef typename Array2::value_type value_type;
2581 out.resize( in.size1( ), in.size2( ), in.size3( ) );
2582 out.reso1( in.reso1( ) );
2583 out.reso2( in.reso2( ) );
2584 out.reso3( in.reso3( ) );
2589 for( size_type i = 0 ; i < in.size( ) ; i++ )
2594 difference_type w = in.
width( );
2595 difference_type h = in.height( );
2596 difference_type d = in.depth( );
2597 for( difference_type k = 0 ; k < d ; k++ )
2599 for( difference_type j = 0 ; j < h ; j++ )
2601 for( difference_type i = 0 ; i < w ; i++ )
2603 difference_type index = &in( i, j, k ) - &in[ 0 ];
2604 difference_type rr = in[ index ];
2611 difference_type rx =
static_cast< difference_type
>( std::ceil( std::sqrt( static_cast< double >( rr ) ) ) );
2612 difference_type ry = rx;
2613 difference_type rz = rx;
2615 for( difference_type z = -rz ; z <= rz ; z++ )
2617 difference_type pz = k + z;
2618 if( pz < 0 || d <= pz )
2623 difference_type zz = z * z;
2625 for( difference_type y = -ry ; y <= ry ; y++ )
2627 difference_type py = j + y;
2628 if( py < 0 || h <= py )
2633 difference_type yy = y * y;
2635 for( difference_type x = -rx ; x <= rx ; x++ )
2637 difference_type px = i + x;
2638 if( px < 0 || w <= px )
2643 difference_type xx = x * x;
2645 if( xx + yy + zz < rr )
2647 difference_type &p = temp( px, py, pz );
2648 if( p < 0 || in[ p ] < rr )
2660 for( size_type i = 0 ; i < in.size( ) ; i++ )
2664 temp[ temp[ i ] ] = -2;
2668 for( size_type i = 0 ; i < in.size( ) ; i++ )
2670 if( temp[ i ] != -2 )
2676 out[ i ] =
static_cast< value_type
>( in[ i ] );
2695 #endif // __INCLUDE_MIST_DISTANCE_TRANSFORM__