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名前空間の始まり
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 
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 
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:
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 

Generated on Wed Nov 12 2014 19:44:15 for MIST by doxygen 1.8.1.2