- メインページ
- モジュール
- ネームスペース
- データ構造
- ファイル

- ファイル一覧
- グローバル

fusion.h
説明を見る。
1 //
2 // Copyright (c) 2003-2011, MIST Project, Nagoya University
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 //
15 // 3. Neither the name of the Nagoya University nor the names of its contributors
16 // may be used to endorse or promote products derived from this software
17 // without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28
33
34 #ifndef __INCLUDE_MIST_FIGURE_FUSION__
35 #define __INCLUDE_MIST_FIGURE_FUSION__
36
37
38 #ifndef __INCLUDE_MIST_H__
39 #include "../mist.h"
40 #endif
41
42 #ifndef __INCLUDE_MIST_THREAD__
43 #include "../thread.h"
44 #endif
45
46 #ifndef __INCLUDE_MIST_LIMITS__
47 #include "../limits.h"
48 #endif
49
50
51
52 // mist名前空間の始まり
53 _MIST_BEGIN
54
55
56 // 図形融合の処理関数
57 namespace __fusion_controller__
58 {
59 template < int DIMENSION >
60 struct __access__
61 {
62 template < class Array >
63 inline static typename Array::value_type &at( Array &in, typename Array::size_type _1, typename Array::size_type _2, typename Array::size_type _3 )
64 {
65 return( in( _1, _2, _3 ) );
66 }
67
68 template < class Array >
69 inline static typename Array::size_type size1( const Array &in ){ return( in.size1( ) ); }
70
71 template < class Array >
72 inline static typename Array::size_type size2( const Array &in ){ return( in.size2( ) ); }
73
74 template < class Array >
75 inline static typename Array::size_type size3( const Array &in ){ return( in.size3( ) ); }
76 };
77
78 template < >
79 struct __access__< 2 >
80 {
81 template < class Array >
82 inline static typename Array::value_type &at( Array &in, typename Array::size_type _1, typename Array::size_type _2, typename Array::size_type _3 )
83 {
84 return( in( _2, _1, _3 ) );
85 }
86
87 template < class Array >
88 inline static typename Array::size_type size1( const Array &in ){ return( in.size2( ) ); }
89
90 template < class Array >
91 inline static typename Array::size_type size2( const Array &in ){ return( in.size1( ) ); }
92
93 template < class Array >
94 inline static typename Array::size_type size3( const Array &in ){ return( in.size3( ) ); }
95 };
96
97 template < >
98 struct __access__< 3 >
99 {
100 template < class Array >
101 inline static typename Array::value_type &at( Array &in, typename Array::size_type _1, typename Array::size_type _2, typename Array::size_type _3 )
102 {
103 return( in( _2, _3, _1 ) );
104 }
105
106 template < class Array >
107 inline static typename Array::size_type size1( const Array &in ){ return( in.size3( ) ); }
108
109 template < class Array >
110 inline static typename Array::size_type size2( const Array &in ){ return( in.size1( ) ); }
111
112 template < class Array >
113 inline static typename Array::size_type size3( const Array &in ){ return( in.size2( ) ); }
114 };
115
116
118 struct __expand_mdt__
119 {
120 template < class Array1, class Array2 >
121 static void pre_process( const Array1 &in, Array2 &out )
122 {
123 typedef typename Array2::size_type size_type;
124 typedef typename Array2::value_type value_type;
125
126 value_type infinity = type_limits< value_type >::maximum( );
127 for( size_type i = 0 ; i < in.size( ) ; i++ )
128 {
129 out[ i ] = in[ i ] > 0 ? infinity : 0;
130 }
131 }
132
133 template < class Array >
134 static void post_process( Array &in )
135 {
136 typedef typename Array::size_type size_type;
137 typedef typename Array::value_type value_type;
138
139 for( size_type i = 0 ; i < in.size( ) ; i++ )
140 {
141 in[ i ] = in[ i ] > 0 ? 1 : 0;
142 }
143 }
144
145 template < class Array, int DIMENSION >
146 static void transform( Array &in, typename Array::size_type length, typename Array::size_type thread_id, typename Array::size_type thread_num, __access__< DIMENSION > dmy )
147 {
148 typedef typename Array::size_type size_type;
149 typedef typename Array::value_type value_type;
150 typedef typename Array::difference_type difference_type;
151 typedef __access__< DIMENSION > access;
152
153 difference_type i1, i2, i3, l;
154
155 difference_type _1 = access::size1( in );
156 difference_type _2 = access::size2( in );
157 difference_type _3 = access::size3( in );
158
159 value_type infinity = type_limits< value_type >::maximum( );
160
161 for( i3 = 0 ; i3 < _3 ; i3++ )
162 {
163 for( i2 = thread_id ; i2 < _2 ; i2 += thread_num )
164 {
165 for( i1 = 0, l = 0 ; i1 < _1 ; i1++ )
166 {
167 value_type &v = access::at( in, i1, i2, i3 );
168 if( v == infinity )
169 {
170 l = length;
171 }
172 else if( l > v )
173 {
174 v = static_cast< value_type >( l );
175 l--;
176 }
177 else if( v > 0 )
178 {
179 l = static_cast< difference_type >( v ) - 1;
180 }
181 }
182
183 for( i1 = _1 - 1, l = 0 ; i1 >= 0 ; i1-- )
184 {
185 value_type &v = access::at( in, i1, i2, i3 );
186 if( v == infinity )
187 {
188 l = length;
189 }
190 else if( l > v )
191 {
192 v = static_cast< value_type >( l );
193 l--;
194 }
195 else if( v > 0 )
196 {
197 l = static_cast< difference_type >( v ) - 1;
198 }
199 }
200 }
201 }
202 }
203 };
204
206 struct __shrink_mdt__
207 {
208 template < class Array1, class Array2 >
209 static void pre_process( const Array1 &in, Array2 &out )
210 {
211 typedef typename Array2::size_type size_type;
212 typedef typename Array2::value_type value_type;
213
214 value_type infinity = type_limits< value_type >::maximum( );
215 for( size_type i = 0 ; i < in.size( ) ; i++ )
216 {
217 out[ i ] = in[ i ] > 0 ? infinity : 0;
218 }
219 }
220
221 template < class Array >
222 static void post_process( Array &in )
223 {
224 typedef typename Array::size_type size_type;
225 typedef typename Array::value_type value_type;
226
227 value_type infinity = type_limits< value_type >::maximum( );
228 for( size_type i = 0 ; i < in.size( ) ; i++ )
229 {
230 in[ i ] = in[ i ] == infinity ? 1 : 0;
231 }
232 }
233
234 template < class Array, int DIMENSION >
235 static void transform( Array &in, typename Array::size_type length, typename Array::size_type thread_id, typename Array::size_type thread_num, __access__< DIMENSION > dmy )
236 {
237 typedef typename Array::size_type size_type;
238 typedef typename Array::value_type value_type;
239 typedef typename Array::difference_type difference_type;
240 typedef __access__< DIMENSION > access;
241
242 difference_type i1, i2, i3, l;
243
244 difference_type _1 = access::size1( in );
245 difference_type _2 = access::size2( in );
246 difference_type _3 = access::size3( in );
247
248 value_type infinity = type_limits< value_type >::maximum( );
249
250 for( i3 = 0 ; i3 < _3 ; i3++ )
251 {
252 for( i2 = thread_id ; i2 < _2 ; i2 += thread_num )
253 {
254 for( i1 = 0, l = 0 ; i1 < _1 ; i1++ )
255 {
256 value_type &v = access::at( in, i1, i2, i3 );
257 if( v == 0 )
258 {
259 l = length;
260 }
261 else if( v == infinity )
262 {
263 if( l > 0 )
264 {
265 v = static_cast< value_type >( l );
266 l--;
267 }
268 }
269 else if( v < l )
270 {
271 v = static_cast< value_type >( l );
272 l--;
273 }
274 else if( v > 0 )
275 {
276 l = static_cast< difference_type >( v ) - 1;
277 }
278 }
279
280 for( i1 = _1 - 1, l = 0 ; i1 >= 0 ; i1-- )
281 {
282 value_type &v = access::at( in, i1, i2, i3 );
283 if( v == 0 )
284 {
285 l = length;
286 }
287 else if( v == infinity )
288 {
289 if( l > 0 )
290 {
291 v = static_cast< value_type >( l );
292 l--;
293 }
294 }
295 else if( v < l )
296 {
297 v = static_cast< value_type >( l );
298 l--;
299 }
300 else if( v > 0 )
301 {
302 l = static_cast< difference_type >( v ) - 1;
303 }
304 }
305 }
306 }
307 }
308 };
309
310
311 // 図形融合距離変換のスレッド部分
312 template < class T, class Fusion >
313 class fusion_thread : public mist::thread< fusion_thread< T, Fusion > >
314 {
315 public:
316 typedef mist::thread< fusion_thread< T, Fusion > > base;
317 typedef typename base::thread_exit_type thread_exit_type;
318 typedef typename T::size_type size_type;
319 typedef typename T::value_type value_type;
320
321 private:
322 size_t thread_id_;
323 size_t thread_num_;
324
325 // 入出力用の画像へのポインタ
326 T *in_;
327 size_type length_;
328 size_type axis_;
329
330 public:
331 void setup_parameters( T &in, size_type axis, size_type len, size_type thread_id, size_type thread_num )
332 {
333 in_ = &in;
334 axis_ = axis;
335 length_ = len;
336 thread_id_ = thread_id;
337 thread_num_ = thread_num;
338 }
339
340 void setup_axis( size_type axis )
341 {
342 axis_ = axis;
343 }
344
345 fusion_thread( size_type id = 0, size_type num = 1 )
346 : thread_id_( id ), thread_num_( num ), in_( NULL ), length_( 1 ), axis_( 0 )
347 {
348 }
349
350 protected:
351 // 継承した先で必ず実装されるスレッド関数
352 virtual thread_exit_type thread_function( )
353 {
354 switch( axis_ )
355 {
356 case 2:
357 Fusion::transform( *in_, length_, thread_id_, thread_num_, __access__< 2 >( ) );
358 break;
359
360 case 3:
361 Fusion::transform( *in_, length_, thread_id_, thread_num_, __access__< 3 >( ) );
362 break;
363
364 case 0:
365 default:
366 Fusion::transform( *in_, length_, thread_id_, thread_num_, __access__< 1 >( ) );
367 break;
368 }
369 return( true );
370 }
371 };
372 }
373
374
375
383
384
385
386
398 template < class Array1, class Array2, class Fusion >
399 bool fusion( const Array1 &in, Array2 &out, typename Array1::size_type length, typename Array1::size_type thread_num, Fusion fusion )
400 {
401 if( in.empty( ) )
402 {
403 return( false );
404 }
405
406 typedef typename Array2::size_type size_type;
407 typedef typename Array2::value_type value_type;
408 typedef __fusion_controller__::fusion_thread< Array2, Fusion > fusion_thread;
409
410 if( thread_num == 0 )
411 {
412 thread_num = static_cast< size_type >( get_cpu_num( ) );
413 }
414
415 out.resize( in.size1( ), in.size2( ), in.size3( ) );
416 out.reso1( in.reso1( ) );
417 out.reso2( in.reso2( ) );
418 out.reso3( in.reso3( ) );
419
420 size_type i;
421
422 Fusion::pre_process( in, out );
423
424 fusion_thread *thread = new fusion_thread[ thread_num ];
425
426 if( in.width( ) > 1 )
427 {
428 // X軸方向の処理
429 for( i = 0 ; i < thread_num ; i++ )
430 {
431 thread[ i ].setup_parameters( out, 1, length, i, thread_num );
432 }
433
434 do_threads( thread, thread_num );
435 }
436
437 if( in.height( ) > 1 )
438 {
439 // Y軸方向の処理
440 for( i = 0 ; i < thread_num ; i++ )
441 {
442 thread[ i ].setup_parameters( out, 2, length, i, thread_num );
443 }
444
445 do_threads( thread, thread_num );
446 }
447
448 if( in.depth( ) > 1 )
449 {
450 // Z軸方向の処理
451 for( i = 0 ; i < thread_num ; i++ )
452 {
453 thread[ i ].setup_parameters( out, 3, length, i, thread_num );
454 }
455
456 do_threads( thread, thread_num );
457 }
458
459 delete [] thread;
460
461 Fusion::post_process( out );
462
463 return( true );
464 }
465
466
467
475
476
487 template < class Array1, class Array2 >
488 bool expand_mdt( const Array1 &in, Array2 &out, typename Array1::size_type length = 1, typename Array1::size_type thread_num = 0 )
489 {
490 return( fusion( in, out, length, thread_num, __fusion_controller__::__expand_mdt__( ) ) );
491 }
492
493
494
505 template < class Array1, class Array2 >
506 bool shrink_mdt( const Array1 &in, Array2 &out, typename Array1::size_type length = 1, typename Array1::size_type thread_num = 0 )
507 {
508 return( fusion( in, out, length, thread_num, __fusion_controller__::__shrink_mdt__( ) ) );
509 }
510
512 // マンハッタン距離グループの終わり
513
514
515
517 // 図形融合グループの終わり
518
519
520 // mist名前空間の終わり
521 _MIST_END
522
523
524 #endif // __INCLUDE_MIST_FIGURE_FUSION__
525