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

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

mode.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
35
36 #ifndef __INCLUDE_MIST_MODE__
37 #define __INCLUDE_MIST_MODE__
38
39
40 #ifndef __INCLUDE_MIST_H__
41 #include "../mist.h"
42 #endif
43
44 #ifndef __INCLUDE_MIST_LIMITS__
45 #include "../limits.h"
46 #endif
47
48
49 #ifndef __INCLUDE_MIST_THREAD__
50 #include "../thread.h"
51 #endif
52
53 #include <vector>
54 #include <cmath>
55
56
57 // mist名前空間の始まり
58 _MIST_BEGIN
59
60
61
69
70
75 namespace mode_filter
76 {
78 struct point
79 {
80 typedef ptrdiff_t difference_type;
81 difference_type x;
82 difference_type y;
83 difference_type z;
84
91 point( difference_type xx, difference_type yy, difference_type zz ) : x( xx ), y( yy ), z( zz )
92 {
93 }
94 };
95
96
102 struct mode_structure
103 {
104 typedef std::vector< point > list_type;
105 list_type object;
106 list_type update_in;
107 list_type update_out;
108 size_t margin_x;
109 size_t margin_y;
110 size_t margin_z;
111 };
112
113
124 inline mode_structure circle( double radius, double resoX, double resoY )
125 {
126 typedef array2< bool >::size_type size_type;
127 typedef array2< bool >::difference_type difference_type;
128
129 double max_reso = resoX > resoY ? resoX: resoY;
130
131 double ax = resoX / max_reso;
132 double ay = resoY / max_reso;
133 double xx, yy, rr = radius * radius;
134 difference_type rx = static_cast< size_type >( ceil( radius / ax ) );
135 difference_type ry = static_cast< size_type >( ceil( radius / ay ) );
136 difference_type x, y;
137
138 size_type ox = rx + 1;
139 size_type oy = ry + 1;
140
141 size_type w = 2 * ox + 1;
142 size_type h = 2 * oy + 1;
143
144 mode_structure s;
145 array2< bool > m( w, h );
146
147 // 円の構造要素を作成する
148 for( y = -ry ; y <= ry ; y++ )
149 {
150 yy = y * y * ay * ay;
151 for( x = -rx ; x <= rx ; x++ )
152 {
153 xx = x * x * ax * ax;
154 if( xx + yy <= rr )
155 {
156 m( x + ox, y + oy ) = true;
157 }
158 }
159 }
160
161 // 円の構造要素の各点を設定する
162 for( y = -ry ; y <= ry ; y++ )
163 {
164 for( x = -rx ; x <= rx ; x++ )
165 {
166 if( m( x + ox, y + oy ) )
167 {
168 s.object.push_back( point( x, y, 0 ) );
169 if( !m( x + ox + 1, y + oy ) )
170 {
171 s.update_in.push_back( point( x, y, 0 ) );
172 }
173 if( !m( x + ox - 1, y + oy ) )
174 {
175 s.update_out.push_back( point( x - 1, y, 0 ) );
176 }
177 }
178 }
179 }
180
181 s.margin_x = rx;
182 s.margin_y = ry;
183 s.margin_z = 0;
184
185 return( s );
186 }
187
188
189
201 inline mode_structure sphere( double radius, double resoX, double resoY, double resoZ )
202 {
203 typedef array3< bool >::size_type size_type;
204 typedef array3< bool >::difference_type difference_type;
205
206 double max_reso = resoX > resoY ? resoX: resoY;
207 max_reso = max_reso > resoZ ? max_reso : resoZ;
208
209 double ax = resoX / max_reso;
210 double ay = resoY / max_reso;
211 double az = resoZ / max_reso;
212 double xx, yy, zz, rr = radius * radius;
213 difference_type rx = static_cast< size_type >( ceil( radius / ax ) );
214 difference_type ry = static_cast< size_type >( ceil( radius / ay ) );
215 difference_type rz = static_cast< size_type >( ceil( radius / az ) );
216 difference_type x, y, z;
217
218 size_type ox = rx + 1;
219 size_type oy = ry + 1;
220 size_type oz = rz + 1;
221
222 size_type w = 2 * ox + 1;
223 size_type h = 2 * oy + 1;
224 size_type d = 2 * oz + 1;
225
226 mode_structure s;
227 array3< bool > m( w, h, d );
228
229 // 球の構造要素を作成する
230 for( z = -rz ; z <= rz ; z++ )
231 {
232 zz = z * z * az * az;
233 for( y = -ry ; y <= ry ; y++ )
234 {
235 yy = y * y * ay * ay;
236 for( x = -rx ; x <= rx ; x++ )
237 {
238 xx = x * x * ax * ax;
239 if( xx + yy + zz <= rr )
240 {
241 m( x + ox, y + oy, z + oz ) = true;
242 }
243 }
244 }
245 }
246
247 // 球の構造要素の各点を設定する
248 for( z = -rz ; z <= rz ; z++ )
249 {
250 for( y = -ry ; y <= ry ; y++ )
251 {
252 for( x = -rx ; x <= rx ; x++ )
253 {
254 if( m( x + ox, y + oy, z + oz ) )
255 {
256 s.object.push_back( point( x, y, z ) );
257 if( !m( x + ox + 1, y + oy, z + oz ) )
258 {
259 s.update_in.push_back( point( x, y, z ) );
260 }
261 if( !m( x + ox - 1, y + oy, z + oz ) )
262 {
263 s.update_out.push_back( point( x - 1, y, z ) );
264 }
265 }
266 }
267 }
268 }
269
270 s.margin_x = rx;
271 s.margin_y = ry;
272 s.margin_z = rz;
273
274 return( s );
275 }
276
277
278
289 inline mode_structure square( double radius, double resoX, double resoY )
290 {
291 using namespace std;
292 typedef array2< bool >::size_type size_type;
293 typedef array2< bool >::difference_type difference_type;
294
295 double max_reso = resoX > resoY ? resoX: resoY;
296
297 double ax = resoX / max_reso;
298 double ay = resoY / max_reso;
299 double xx, yy;
300 difference_type rx = static_cast< size_type >( ceil( radius / ax ) );
301 difference_type ry = static_cast< size_type >( ceil( radius / ay ) );
302 difference_type x, y;
303
304 size_type ox = rx + 1;
305 size_type oy = ry + 1;
306
307 size_type w = 2 * ox + 1;
308 size_type h = 2 * oy + 1;
309
310 mode_structure s;
311 array2< bool > m( w, h );
312
313 // 正方形の構造要素を作成する
314 for( y = -ry ; y <= ry ; y++ )
315 {
316 yy = y * ay;
317 for( x = -rx ; x <= rx ; x++ )
318 {
319 xx = x * ax;
320 if( std::abs( xx ) <= radius && std::abs( yy ) <= radius )
321 {
322 m( x + ox, y + oy ) = true;
323 }
324 }
325 }
326
327 // 正方形の構造要素の各点を設定する
328 for( y = -ry ; y <= ry ; y++ )
329 {
330 for( x = -rx ; x <= rx ; x++ )
331 {
332 if( m( x + ox, y + oy ) )
333 {
334 s.object.push_back( point( x, y, 0 ) );
335 if( !m( x + ox + 1, y + oy ) )
336 {
337 s.update_in.push_back( point( x, y, 0 ) );
338 }
339 if( !m( x + ox - 1, y + oy ) )
340 {
341 s.update_out.push_back( point( x - 1, y, 0 ) );
342 }
343 }
344 }
345 }
346
347 s.margin_x = rx;
348 s.margin_y = ry;
349 s.margin_z = 0;
350
351 return( s );
352 }
353
354
366 inline mode_structure cube( double radius, double resoX, double resoY, double resoZ )
367 {
368 using namespace std;
369 typedef array3< bool >::size_type size_type;
370 typedef array3< bool >::difference_type difference_type;
371
372 double max_reso = resoX > resoY ? resoX: resoY;
373 max_reso = max_reso > resoZ ? max_reso : resoZ;
374
375 double ax = resoX / max_reso;
376 double ay = resoY / max_reso;
377 double az = resoZ / max_reso;
378 double xx, yy, zz;
379 difference_type rx = static_cast< size_type >( ceil( radius / ax ) );
380 difference_type ry = static_cast< size_type >( ceil( radius / ay ) );
381 difference_type rz = static_cast< size_type >( ceil( radius / az ) );
382 difference_type x, y, z;
383
384 size_type ox = rx + 1;
385 size_type oy = ry + 1;
386 size_type oz = rz + 1;
387
388 size_type w = 2 * ox + 1;
389 size_type h = 2 * oy + 1;
390 size_type d = 2 * oz + 1;
391
392 mode_structure s;
393 array3< bool > m( w, h, d );
394
395 // 立方体の構造要素を作成する
396 for( z = -rz ; z <= rz ; z++ )
397 {
398 zz = z * az;
399 for( y = -ry ; y <= ry ; y++ )
400 {
401 yy = y * ay;
402 for( x = -rx ; x <= rx ; x++ )
403 {
404 xx = x * ax;
405 if( std::abs( xx ) <= radius && std::abs( yy ) <= radius && std::abs( zz ) <= radius )
406 {
407 m( x + ox, y + oy, z + oz ) = true;
408 }
409 }
410 }
411 }
412
413 // 立方体の構造要素の各点を設定する
414 for( z = -rz ; z <= rz ; z++ )
415 {
416 for( y = -ry ; y <= ry ; y++ )
417 {
418 for( x = -rx ; x <= rx ; x++ )
419 {
420 if( m( x + ox, y + oy, z + oz ) )
421 {
422 s.object.push_back( point( x, y, z ) );
423 if( !m( x + ox + 1, y + oy, z + oz ) )
424 {
425 s.update_in.push_back( point( x, y, z ) );
426 }
427 if( !m( x + ox - 1, y + oy, z + oz ) )
428 {
429 s.update_out.push_back( point( x - 1, y, z ) );
430 }
431 }
432 }
433 }
434 }
435
436 s.margin_x = rx;
437 s.margin_y = ry;
438 s.margin_z = rz;
439
440 return( s );
441 }
442
443
444
456 template < class Array >
457 inline mode_structure create_mode_structure( const Array &in, typename Array::size_type cx, typename Array::size_type cy = 0, typename Array::size_type cz = 0 )
458 {
459 using namespace std;
460 typedef typename Array::size_type size_type;
461 typedef typename Array::difference_type difference_type;
462 difference_type x, y, z;
463
464 difference_type w = in.width( );
465 difference_type h = in.height( );
466 difference_type d = in.depth( );
467
468 mode_structure s;
469 marray< Array > m( in, 1 );
470
471 // 構造要素の形を作成する
472 for( z = 0 ; z < d ; z++ )
473 {
474 for( y = 0 ; y < h ; y++ )
475 {
476 for( x = 0 ; x < w ; x++ )
477 {
478 m( x, y, z ) = in( x, y, z ) == 0 ? false : true;
479 }
480 }
481 }
482
483 // 構造要素の各点を設定する
484 for( z = 0 ; z < d ; z++ )
485 {
486 for( y = 0 ; y < h ; y++ )
487 {
488 size_t life = 0;
489 for( x = 0 ; x < w ; x++ )
490 {
491 if( m( x, y, z ) )
492 {
493 s.object.push_back( point( x - cx, y - cy, z - cz ) );
494 if( !m( x + 1, y, z ) )
495 {
496 s.update_in.push_back( point( x - cx, y - cy, z - cz ) );
497 }
498 if( !m( x - 1, y, z ) )
499 {
500 s.update_out.push_back( point( x - cx - 1, y - cy, z - cz ) );
501 }
502 }
503 }
504 }
505 }
506
507 s.margin_x = cx > w - cx - 1 ? cx : w - cx;
508 s.margin_y = cy > h - cy - 1 ? cy : h - cy;
509 s.margin_z = cz > d - cz - 1 ? cz : d - cz;
510
511 return( s );
512 }
513
514
524 template < class Array >
525 inline std::vector< ptrdiff_t > create_pointer_diff_list( const Array &in, const std::vector< point > &list )
526 {
527 typedef typename Array::size_type size_type;
528 typedef typename Array::const_pointer const_pointer;
529 size_type cx = in.width( ) / 2;
530 size_type cy = in.height( ) / 2;
531 size_type cz = in.depth( ) / 2;
532 const_pointer p = &( in( cx, cy, cz ) );
533
534 std::vector< ptrdiff_t > out;
535
536 for( size_type i = 0 ; i < list.size( ) ; i++ )
537 {
538 const point &pt = list[ i ];
539 const_pointer pp = &in( cx + pt.x, cy + pt.y, cz + pt.z );
540 out.push_back( pp - p );
541 }
542
543 return( out );
544 }
545 }
546
547
549 // 最頻値フィルタグループの終わり
550
551
552 namespace __mode__
553 {
554 template < class Array1, class Array2, class Functor >
555 void mode( const Array1 &in, Array2 &out,
556 const std::vector< ptrdiff_t > &object, const std::vector< ptrdiff_t > &update_in, const std::vector< ptrdiff_t > &update_out,
557 typename Array1::size_type thread_idy, typename Array1::size_type thread_numy,
558 typename Array1::size_type thread_idz, typename Array1::size_type thread_numz, Functor f )
559 {
560 typedef typename Array1::size_type size_type;
561 typedef typename Array1::value_type value_type;
562 typedef typename Array1::const_pointer const_pointer;
563 typedef typename Array1::difference_type difference_type;
564 typedef typename Array2::value_type out_value_type;
565 typedef typename Array2::value_type out_value_type;
566 typedef std::vector< ptrdiff_t > list_type;
567 typedef list_type::const_iterator const_iterator;
568
569 size_type w = in.width( );
570 size_type h = in.height( );
571 size_type d = in.depth( );
572
573 const bool bprogress1 = thread_idy == 0 && d == 1;
574 const bool bprogress2 = thread_idz == 0 && d > 1;
575
576 for( size_type k = thread_idz ; k < d ; k += thread_numz )
577 {
578 for( size_type j = thread_idy ; j < h ; j += thread_numy )
579 {
580 const_pointer p = &in( 0, j, k );
581 difference_type count[ 2 ] = { 0, 0 };
582 for( const_iterator ite = object.begin( ) ; ite != object.end( ) ; ++ite )
583 {
584 count[ p[ *ite ] > 0 ]++;
585 }
586
587 out( 0, j, k ) = static_cast< out_value_type >( count[ 0 ] > count[ 1 ] ? 0 : 1 );
588
589 for( size_type i = 1 ; i < w ; i++ )
590 {
591 p = &in( i, j, k );
592
593 // 構造要素から抜けた分だけ減算する
594 for( const_iterator ite = update_out.begin( ) ; ite != update_out.end( ) ; ++ite )
595 {
596 count[ p[ *ite ] > 0 ]--;
597 }
598
599 // 構造要素に新しく入った分を加える
600 for( const_iterator ite = update_in.begin( ) ; ite != update_in.end( ) ; ++ite )
601 {
602 count[ p[ *ite ] > 0 ]++;
603 }
604
605 out( i, j, k ) = static_cast< out_value_type >( count[ 0 ] > count[ 1 ] ? 0 : 1 );
606 }
607
608 if( bprogress1 )
609 {
610 f( static_cast< double >( j + 1 ) / static_cast< double >( h ) * 100.0 );
611 }
612 }
613
614 if( bprogress2 )
615 {
616 f( static_cast< double >( k + 1 ) / static_cast< double >( d ) * 100.0 );
617 }
618 }
619 }
620 }
621
622
623
624
625 // 最頻値フィルタのスレッド実装
626 namespace __mode_controller__
627 {
628 // 各次元をラッピングするための関数
629 template < class T1, class Allocator1, class T2, class Allocator2, class Functor >
630 void mode( const marray< array< T1, Allocator1 > > &in, array< T2, Allocator2 > &out,
631 const std::vector< ptrdiff_t > &object, const std::vector< ptrdiff_t > &update_in, const std::vector< ptrdiff_t > &update_out,
632 typename array< T1, Allocator1 >::size_type thread_id, typename array< T1, Allocator1 >::size_type thread_num, Functor f )
633 {
634 __mode__::mode( in, out, object, update_in, update_out, 0, 1, thread_id, thread_num, f );
635 }
636
637 template < class T1, class Allocator1, class T2, class Allocator2, class Functor >
638 void mode( const marray< array1< T1, Allocator1 > > &in, array1< T2, Allocator2 > &out,
639 const std::vector< ptrdiff_t > &object, const std::vector< ptrdiff_t > &update_in, const std::vector< ptrdiff_t > &update_out,
640 typename array1< T1, Allocator1 >::size_type thread_id, typename array1< T1, Allocator1 >::size_type thread_num, Functor f )
641 {
642 __mode__::mode( in, out, object, update_in, update_out, 0, 1, thread_id, thread_num, f );
643 }
644
645 template < class T1, class Allocator1, class T2, class Allocator2, class Functor >
646 void mode( const marray< array2< T1, Allocator1 > > &in, array2< T2, Allocator2 > &out,
647 const std::vector< ptrdiff_t > &object, const std::vector< ptrdiff_t > &update_in, const std::vector< ptrdiff_t > &update_out,
648 typename array2< T1, Allocator1 >::size_type thread_id, typename array2< T1, Allocator1 >::size_type thread_num, Functor f )
649 {
650 __mode__::mode( in, out, object, update_in, update_out, thread_id, thread_num, 0, 1, f );
651 }
652
653 template < class T1, class Allocator1, class T2, class Allocator2, class Functor >
654 void mode( const marray< array3< T1, Allocator1 > > &in, array3< T2, Allocator2 > &out,
655 const std::vector< ptrdiff_t > &object, const std::vector< ptrdiff_t > &update_in, const std::vector< ptrdiff_t > &update_out,
656 typename array3< T1, Allocator1 >::size_type thread_id, typename array3< T1, Allocator1 >::size_type thread_num, Functor f )
657 {
658 __mode__::mode( in, out, object, update_in, update_out, 0, 1, thread_id, thread_num, f );
659 }
660
661
662 template < class T1, class T2, class Functor >
663 class mode_thread : public mist::thread< mode_thread< T1, T2, Functor > >
664 {
665 public:
666 typedef mist::thread< mode_thread< T1, T2, Functor > > base;
667 typedef typename base::thread_exit_type thread_exit_type;
668 typedef typename T1::size_type size_type;
669 typedef typename T1::value_type value_type;
670 typedef typename T1::difference_type difference_type;
671 typedef std::vector< difference_type > list_type;
672
673 private:
674 size_t thread_id_;
675 size_t thread_num_;
676
677 // 入出力用の画像へのポインタ
678 const T1 *in_;
679 T2 *out_;
680 list_type *object_;
681 list_type *update_in_;
682 list_type *update_out_;
683
684 Functor f_;
685
686 public:
687 void setup_parameters( const T1 &in, T2 &out, list_type &object, list_type &update_in, list_type &update_out, size_type thread_id, size_type thread_num, Functor f )
688 {
689 in_ = &in;
690 out_ = &out;
691 object_ = &object;
692 update_in_ = &update_in;
693 update_out_ = &update_out;
694 thread_id_ = thread_id;
695 thread_num_ = thread_num;
696 f_ = f;
697 }
698
699 const mode_thread& operator =( const mode_thread &p )
700 {
701 if( &p != this )
702 {
703 base::operator =( p );
704 thread_id_ = p.thread_id_;
705 thread_num_ = p.thread_num_;
706 in_ = p.in_;
707 out_ = p.out_;
708 object_ = p.object_;
709 update_in_ = p.update_in_;
710 update_out_ = p.update_out_;
711 f_ = p.f_;
712 }
713 return( *this );
714 }
715
716 mode_thread( size_type id = 0, size_type num = 1 ) : thread_id_( id ), thread_num_( num ),
717 in_( NULL ), out_( NULL ), object_( NULL ), update_in_( NULL ), update_out_( NULL )
718 {
719 }
720 mode_thread( const mode_thread &p ) : base( p ), thread_id_( p.thread_id_ ), thread_num_( p.thread_num_ ),
721 in_( p.in_ ), out_( p.out_ ), object_( p.object_ ), update_in_( p.update_in_ ), update_out_( p.update_out_ )
722 {
723 }
724
725 protected:
726 // 継承した先で必ず実装されるスレッド関数
727 virtual thread_exit_type thread_function( )
728 {
729 mode( *in_, *out_, *object_, *update_in_, *update_out_, thread_id_, thread_num_, f_ );
730 return( true );
731 }
732 };
733 }
734
735
738
739
753 template < class T, class Allocator, class Functor >
754 bool mode( array2< T, Allocator > &in, const mode_filter::mode_structure &s, Functor f, typename array2< T, Allocator >::size_type thread_num )
755 {
756 if( in.empty( ) )
757 {
758 return( false );
759 }
760
761 typedef typename array2< T, Allocator >::value_type value_type;
762 typedef typename array2< T, Allocator >::size_type size_type;
763 typedef typename array2< T, Allocator >::difference_type difference_type;
764 typedef __mode_controller__::mode_thread< marray< array2< T, Allocator > >, array2< T, Allocator >, Functor > mode_thread;
765 typedef std::vector< difference_type > list_type;
766
767 if( thread_num == 0 )
768 {
769 thread_num = static_cast< size_type >( get_cpu_num( ) );
770 }
771
772 marray< array2< T, Allocator > > out( in, s.margin_x, s.margin_y, 0 );
773
774 list_type object = mode_filter::create_pointer_diff_list( out, s.object );
775 list_type update_in = mode_filter::create_pointer_diff_list( out, s.update_in );
776 list_type update_out = mode_filter::create_pointer_diff_list( out, s.update_out );
777
778 mode_thread *thread = new mode_thread[ thread_num ];
779
780 for( size_type i = 0 ; i < thread_num ; i++ )
781 {
782 thread[ i ].setup_parameters( out, in, object, update_in, update_out, i, thread_num, f );
783 }
784
785 f( 0.0 );
786
787 // スレッドを実行して，終了まで待機する
788 do_threads_( thread, thread_num );
789
790 f( 100.1 );
791
792 delete [] thread;
793
794 return( true );
795 }
796
797
810 template < class T, class Allocator >
811 bool mode( array2< T, Allocator > &in, const mode_filter::mode_structure &s, typename array2< T, Allocator >::size_type thread_num = 0 )
812 {
813 return( mode( in, s, __mist_dmy_callback__( ), thread_num ) );
814 }
815
816
817
831 template < class T, class Allocator, class Functor >
832 inline bool mode( array2< T, Allocator > &in, double radius, Functor f, typename array2< T, Allocator >::size_type thread_num )
833 {
834 return( mode( in, mode_filter::circle( radius, in.reso1( ), in.reso2( ) ), f, thread_num ) );
835 }
836
837
850 template < class T, class Allocator >
851 inline bool mode( array2< T, Allocator > &in, double radius, typename array2< T, Allocator >::size_type thread_num = 0 )
852 {
853 return( mode( in, mode_filter::circle( radius, in.reso1( ), in.reso2( ) ), __mist_dmy_callback__( ), thread_num ) );
854 }
855
856
857
858
859
860
861
875 template < class T, class Allocator, class Functor >
876 bool mode( array3< T, Allocator > &in, const mode_filter::mode_structure &s, Functor f, typename array3< T, Allocator >::size_type thread_num )
877 {
878 if( in.empty( ) )
879 {
880 return( false );
881 }
882
883 typedef typename array3< T, Allocator >::value_type value_type;
884 typedef typename array3< T, Allocator >::size_type size_type;
885 typedef typename array3< T, Allocator >::difference_type difference_type;
886 typedef __mode_controller__::mode_thread< marray< array3< T, Allocator > >, array3< T, Allocator >, Functor > mode_thread;
887 typedef std::vector< difference_type > list_type;
888
889 if( thread_num == 0 )
890 {
891 thread_num = static_cast< size_type >( get_cpu_num( ) );
892 }
893
894 marray< array3< T, Allocator > > out( in, s.margin_x, s.margin_y, s.margin_z, 0 );
895
896 list_type object = mode_filter::create_pointer_diff_list( out, s.object );
897 list_type update_in = mode_filter::create_pointer_diff_list( out, s.update_in );
898 list_type update_out = mode_filter::create_pointer_diff_list( out, s.update_out );
899
900 mode_thread *thread = new mode_thread[ thread_num ];
901
902 for( size_type i = 0 ; i < thread_num ; i++ )
903 {
904 thread[ i ].setup_parameters( out, in, object, update_in, update_out, i, thread_num, f );
905 }
906
907 f( 0.0 );
908
909 // スレッドを実行して，終了まで待機する
910 do_threads_( thread, thread_num );
911
912 f( 100.1 );
913
914 delete [] thread;
915
916 return( true );
917 }
918
919
932 template < class T, class Allocator >
933 bool mode( array3< T, Allocator > &in, const mode_filter::mode_structure &s, typename array3< T, Allocator >::size_type thread_num = 0 )
934 {
935 return( mode( in, s, __mist_dmy_callback__( ), thread_num ) );
936 }
937
938
939
940
954 template < class T, class Allocator, class Functor >
955 inline bool mode( array3< T, Allocator > &in, double radius, Functor f, typename array3< T, Allocator >::size_type thread_num )
956 {
957 return( mode( in, mode_filter::sphere( radius, in.reso1( ), in.reso2( ), in.reso3( ) ), f, thread_num ) );
958 }
959
960
961
962
975 template < class T, class Allocator >
976 inline bool mode( array3< T, Allocator > &in, double radius, typename array3< T, Allocator >::size_type thread_num = 0 )
977 {
978 return( mode( in, mode_filter::sphere( radius, in.reso1( ), in.reso2( ), in.reso3( ) ), __mist_dmy_callback__( ), thread_num ) );
979 }
980
981
982
984 // 最頻値フィルタグループの終わり
985
986
987 // mist名前空間の終わり
988 _MIST_END
989
990
991 #endif // __INCLUDE_MIST_MODE__
992