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

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

morphology.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_MORPHOLOGY__
37 #define __INCLUDE_MIST_MORPHOLOGY__
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 morphology
76 {
78 struct point
79 {
80 typedef ptrdiff_t difference_type;
81 difference_type x;
82 difference_type y;
83 difference_type z;
84 size_t life;
85
93 point( difference_type xx, difference_type yy, difference_type zz, size_t l ) : x( xx ), y( yy ), z( zz ), life( l )
94 {
95 }
96 };
97
98
103 struct pointer_diff
104 {
105 ptrdiff_t diff;
106 size_t life;
107
109 pointer_diff( ptrdiff_t d, size_t l ) : diff( d ), life( l )
110 {
111 }
112 };
113
114
120 struct morphology_structure
121 {
122 typedef std::vector< point > list_type;
123 list_type object;
124 list_type update;
125 size_t margin_x;
126 size_t margin_y;
127 size_t margin_z;
128 };
129
130
142 inline morphology_structure circle( double radius, double resoX, double resoY, bool radiusInPhysicalCoords = false )
143 {
144 typedef array2< bool >::size_type size_type;
145 typedef array2< bool >::difference_type difference_type;
146
147 double ax, ay;
148 if( radiusInPhysicalCoords )
149 {
150 ax = resoX;
151 ay = resoY;
152 }
153 else
154 {
155 double max_reso = resoX > resoY ? resoX: resoY;
156
157 ax = resoX / max_reso;
158 ay = resoY / max_reso;
159 }
160
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;
165
166 size_type ox = rx + 1;
167 size_type oy = ry + 1;
168
169 size_type w = 2 * ox + 1;
170 size_type h = 2 * oy + 1;
171
172 morphology_structure s;
173 array2< bool > m( w, h );
174
175 // 円の構造要素を作成する
176 for( y = -ry ; y <= ry ; y++ )
177 {
178 yy = y * y * ay * ay;
179 for( x = -rx ; x <= rx ; x++ )
180 {
181 xx = x * x * ax * ax;
182 if( xx + yy <= rr )
183 {
184 m( x + ox, y + oy ) = true;
185 }
186 }
187 }
188
189 // 円の構造要素の各点に生存期間を設定する
190 for( y = -ry ; y <= ry ; y++ )
191 {
192 size_t life = 0;
193 for( x = -rx ; x <= rx ; x++ )
194 {
195 if( m( x + ox, y + oy ) )
196 {
197 s.object.push_back( point( x, y, 0, ++life ) );
198 }
199 else
200 {
201 life = 0;
202 }
203 if( m( x + ox, y + oy ) && !m( x + ox + 1, y + oy ) )
204 {
205 s.update.push_back( point( x, y, 0, life ) );
206 }
207 }
208 }
209
210 s.margin_x = rx;
211 s.margin_y = ry;
212 s.margin_z = 0;
213
214 return( s );
215 }
216
217
218
231 inline morphology_structure sphere( double radius, double resoX, double resoY, double resoZ, bool radiusInPhysicalCoords = false )
232 {
233 typedef array3< bool >::size_type size_type;
234 typedef array3< bool >::difference_type difference_type;
235
236 double ax, ay, az;
237 if( radiusInPhysicalCoords )
238 {
239 ax = resoX;
240 ay = resoY;
241 az = resoZ;
242 }
243 else
244 {
245 double max_reso = resoX > resoY ? resoX: resoY;
246 max_reso = max_reso > resoZ ? max_reso : resoZ;
247
248 ax = resoX / max_reso;
249 ay = resoY / max_reso;
250 az = resoZ / max_reso;
251 }
252
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;
258
259 size_type ox = rx + 1;
260 size_type oy = ry + 1;
261 size_type oz = rz + 1;
262
263 size_type w = 2 * ox + 1;
264 size_type h = 2 * oy + 1;
265 size_type d = 2 * oz + 1;
266
267 morphology_structure s;
268 array3< bool > m( w, h, d );
269
270 // 球の構造要素を作成する
271 for( z = -rz ; z <= rz ; z++ )
272 {
273 zz = z * z * az * az;
274 for( y = -ry ; y <= ry ; y++ )
275 {
276 yy = y * y * ay * ay;
277 for( x = -rx ; x <= rx ; x++ )
278 {
279 xx = x * x * ax * ax;
280 if( xx + yy + zz <= rr )
281 {
282 m( x + ox, y + oy, z + oz ) = true;
283 }
284 }
285 }
286 }
287
288 // 球の構造要素の各点に生存期間を設定する
289 for( z = -rz ; z <= rz ; z++ )
290 {
291 for( y = -ry ; y <= ry ; y++ )
292 {
293 size_t life = 0;
294 for( x = -rx ; x <= rx ; x++ )
295 {
296 if( m( x + ox, y + oy, z + oz ) )
297 {
298 s.object.push_back( point( x, y, z, ++life ) );
299 }
300 else
301 {
302 life = 0;
303 }
304 if( m( x + ox, y + oy, z + oz ) && !m( x + ox + 1, y + oy, z + oz ) )
305 {
306 s.update.push_back( point( x, y, z, life ) );
307 }
308 }
309 }
310 }
311
312 s.margin_x = rx;
313 s.margin_y = ry;
314 s.margin_z = rz;
315
316 return( s );
317 }
318
319
320
332 inline morphology_structure square( double radius, double resoX, double resoY, bool radiusInPhysicalCoords = false )
333 {
334 using namespace std;
335 typedef array2< bool >::size_type size_type;
336 typedef array2< bool >::difference_type difference_type;
337
338 double ax, ay;
339 if( radiusInPhysicalCoords )
340 {
341 ax = resoX;
342 ay = resoY;
343 }
344 else
345 {
346 double max_reso = resoX > resoY ? resoX: resoY;
347
348 ax = resoX / max_reso;
349 ay = resoY / max_reso;
350 }
351
352 double xx, yy;
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;
356
357 size_type ox = rx + 1;
358 size_type oy = ry + 1;
359
360 size_type w = 2 * ox + 1;
361 size_type h = 2 * oy + 1;
362
363 morphology_structure s;
364 array2< bool > m( w, h );
365
366 // 正方形の構造要素を作成する
367 for( y = -ry ; y <= ry ; y++ )
368 {
369 yy = y * ay;
370 for( x = -rx ; x <= rx ; x++ )
371 {
372 xx = x * ax;
373 if( std::abs( xx ) <= radius && std::abs( yy ) <= radius )
374 {
375 m( x + ox, y + oy ) = true;
376 }
377 }
378 }
379
380 // 正方形の構造要素の各点に生存期間を設定する
381 for( y = -ry ; y <= ry ; y++ )
382 {
383 size_t life = 0;
384 for( x = -rx ; x <= rx ; x++ )
385 {
386 if( m( x + ox, y + oy ) )
387 {
388 s.object.push_back( point( x, y, 0, ++life ) );
389 }
390 else
391 {
392 life = 0;
393 }
394 if( m( x + ox, y + oy ) && !m( x + ox + 1, y + oy ) )
395 {
396 s.update.push_back( point( x, y, 0, life ) );
397 }
398 }
399 }
400
401 s.margin_x = rx;
402 s.margin_y = ry;
403 s.margin_z = 0;
404
405 return( s );
406 }
407
408
421 inline morphology_structure cube( double radius, double resoX, double resoY, double resoZ, bool radiusInPhysicalCoords = false )
422 {
423 using namespace std;
424 typedef array3< bool >::size_type size_type;
425 typedef array3< bool >::difference_type difference_type;
426
427 double ax, ay, az;
428 if( radiusInPhysicalCoords )
429 {
430 ax = resoX;
431 ay = resoY;
432 az = resoZ;
433 }
434 else
435 {
436 double max_reso = resoX > resoY ? resoX: resoY;
437 max_reso = max_reso > resoZ ? max_reso : resoZ;
438
439 ax = resoX / max_reso;
440 ay = resoY / max_reso;
441 az = resoZ / max_reso;
442 }
443
444 double xx, yy, zz;
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;
449
450 size_type ox = rx + 1;
451 size_type oy = ry + 1;
452 size_type oz = rz + 1;
453
454 size_type w = 2 * ox + 1;
455 size_type h = 2 * oy + 1;
456 size_type d = 2 * oz + 1;
457
458 morphology_structure s;
459 array3< bool > m( w, h, d );
460
461 // 立方体の構造要素を作成する
462 for( z = -rz ; z <= rz ; z++ )
463 {
464 zz = z * az;
465 for( y = -ry ; y <= ry ; y++ )
466 {
467 yy = y * ay;
468 for( x = -rx ; x <= rx ; x++ )
469 {
470 xx = x * ax;
471 if( std::abs( xx ) <= radius && std::abs( yy ) <= radius && std::abs( zz ) <= radius )
472 {
473 m( x + ox, y + oy, z + oz ) = true;
474 }
475 }
476 }
477 }
478
479 // 立方体の構造要素の各点に生存期間を設定する
480 for( z = -rz ; z <= rz ; z++ )
481 {
482 for( y = -ry ; y <= ry ; y++ )
483 {
484 size_t life = 0;
485 for( x = -rx ; x <= rx ; x++ )
486 {
487 if( m( x + ox, y + oy, z + oz ) )
488 {
489 s.object.push_back( point( x, y, z, ++life ) );
490 }
491 else
492 {
493 life = 0;
494 }
495 if( m( x + ox, y + oy, z + oz ) && !m( x + ox + 1, y + oy, z + oz ) )
496 {
497 s.update.push_back( point( x, y, z, life ) );
498 }
499 }
500 }
501 }
502
503 s.margin_x = rx;
504 s.margin_y = ry;
505 s.margin_z = rz;
506
507 return( s );
508 }
509
510
511
523 template < class Array >
524 inline morphology_structure create_morphology_structure( const Array &in, typename Array::size_type cx, typename Array::size_type cy = 0, typename Array::size_type cz = 0 )
525 {
526 using namespace std;
527 typedef typename Array::size_type size_type;
528 typedef typename Array::difference_type difference_type;
529 difference_type x, y, z;
530
531 difference_type w = in.width( );
532 difference_type h = in.height( );
533 difference_type d = in.depth( );
534
535 morphology_structure s;
536 marray< Array > m( in, 1 );
537
538 // 構造要素の形を作成する
539 for( z = 0 ; z < d ; z++ )
540 {
541 for( y = 0 ; y < h ; y++ )
542 {
543 for( x = 0 ; x < w ; x++ )
544 {
545 m( x, y, z ) = in( x, y, z ) == 0 ? false : true;
546 }
547 }
548 }
549
550 // 構造要素の各点に生存期間を設定する
551 for( z = 0 ; z < d ; z++ )
552 {
553 for( y = 0 ; y < h ; y++ )
554 {
555 size_t life = 0;
556 for( x = 0 ; x < w ; x++ )
557 {
558 if( m( x, y, z ) )
559 {
560 s.object.push_back( point( x - cx, y - cy, z - cz, ++life ) );
561 }
562 else
563 {
564 life = 0;
565 }
566 if( m( x, y, z ) && !m( x + 1, y, z ) )
567 {
568 s.update.push_back( point( x - cx, y - cy, z - cz, life ) );
569 }
570 }
571 }
572 }
573
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;
577
578 return( s );
579 }
580
581
591 template < class Array >
592 inline std::vector< pointer_diff > create_pointer_diff_list( const Array &in, const std::vector< point > &list )
593 {
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 ) );
600
601 std::vector< pointer_diff > out;
602
603 for( size_type i = 0 ; i < list.size( ) ; i++ )
604 {
605 const point &pt = list[ i ];
606 const_pointer pp = &( in( cx + pt.x, cy + pt.y, cz + pt.z ) );
607 out.push_back( pointer_diff( pp - p, pt.life ) );
608 }
609
610 return( out );
611 }
612 }
613
614
616 // モルフォロジ演算グループの終わり
617
618
619 namespace __erosion__
620 {
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 )
626 {
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;
634
635 list_type::const_iterator ite;
636
637 size_type i, j, k;
638 value_type min;
639 size_type life;
640 const_pointer p;
641
642 size_type w = in.width( );
643 size_type h = in.height( );
644 size_type d = in.depth( );
645
646 const bool bprogress1 = thread_idy == 0 && d == 1;
647 const bool bprogress2 = thread_idz == 0 && d > 1;
648
649 for( k = thread_idz ; k < d ; k += thread_numz )
650 {
651 for( j = thread_idy ; j < h ; j += thread_numy )
652 {
653 p = &( in( 0, j, k ) );
654 ite = object.begin( );
655 min = p[ ite->diff ];
656 life = ite->life;
657 ++ite;
658 for( ; ite != object.end( ) ; ++ite )
659 {
660 if( min > p[ ite->diff ] || ( min == p[ ite->diff ] && life < ite->life ) )
661 {
662 min = p[ ite->diff ];
663 life = ite->life;
664 }
665 }
666
667 out( 0, j, k ) = static_cast< out_value_type >( min );
668 life--;
669
670 for( i = 1 ; i < w ; i++ )
671 {
672 p = &( in( i, j, k ) );
673
674 if( life == 0 )
675 {
676 // 前回までの最小値が構造要素から出てしまったので，新たに前探索を行う
677 ite = object.begin( );
678 min = p[ ite->diff ];
679 life = ite->life;
680 ++ite;
681 for( ; ite != object.end( ) ; ++ite )
682 {
683 if( min > p[ ite->diff ] || ( min == p[ ite->diff ] && life < ite->life ) )
684 {
685 min = p[ ite->diff ];
686 life = ite->life;
687 }
688 }
689 }
690 else
691 {
692 // 前回までの最小値が構造要素内に存在するので，更新分のみから探索を行う
693 for( ite = update.begin( ) ; ite != update.end( ) ; ++ite )
694 {
695 if( min > p[ ite->diff ] || ( min == p[ ite->diff ] && life < ite->life ) )
696 {
697 min = p[ ite->diff ];
698 life = ite->life;
699 }
700 }
701 }
702
703 out( i, j, k ) = static_cast< out_value_type >( min );
704 life--;
705 }
706
707 if( bprogress1 )
708 {
709 f( static_cast< double >( j + 1 ) / static_cast< double >( h ) * 100.0 );
710 }
711 }
712
713 if( bprogress2 )
714 {
715 f( static_cast< double >( k + 1 ) / static_cast< double >( d ) * 100.0 );
716 }
717 }
718 }
719 }
720
721
722 namespace __dilation__
723 {
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 )
729 {
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;
737
738 list_type::const_iterator ite;
739
740 size_type i, j, k;
741 value_type max;
742 size_type life;
743 const_pointer p;
744
745 size_type w = in.width( );
746 size_type h = in.height( );
747 size_type d = in.depth( );
748
749 const bool bprogress1 = thread_idy == 0 && d == 1;
750 const bool bprogress2 = thread_idz == 0 && d > 1;
751
752 for( k = thread_idz ; k < d ; k += thread_numz )
753 {
754 for( j = thread_idy ; j < h ; j += thread_numy )
755 {
756 p = &( in( 0, j, k ) );
757 ite = object.begin( );
758 max = p[ ite->diff ];
759 life = ite->life;
760 ++ite;
761 for( ; ite != object.end( ) ; ++ite )
762 {
763 if( max < p[ ite->diff ] || ( max == p[ ite->diff ] && life < ite->life ) )
764 {
765 max = p[ ite->diff ];
766 life = ite->life;
767 }
768 }
769
770 out( 0, j, k ) = static_cast< out_value_type >( max );
771 life--;
772
773 for( i = 1 ; i < w ; i++ )
774 {
775 p = &( in( i, j, k ) );
776
777 if( life == 0 )
778 {
779 // 前回までの最小値が構造要素から出てしまったので，新たに前探索を行う
780 ite = object.begin( );
781 max = p[ ite->diff ];
782 life = ite->life;
783 ++ite;
784 for( ; ite != object.end( ) ; ++ite )
785 {
786 if( max < p[ ite->diff ] || ( max == p[ ite->diff ] && life < ite->life ) )
787 {
788 max = p[ ite->diff ];
789 life = ite->life;
790 }
791 }
792 }
793 else
794 {
795 // 前回までの最小値が構造要素内に存在するので，更新分のみから探索を行う
796 for( ite = update.begin( ) ; ite != update.end( ) ; ++ite )
797 {
798 if( max < p[ ite->diff ] || ( max == p[ ite->diff ] && life < ite->life ) )
799 {
800 max = p[ ite->diff ];
801 life = ite->life;
802 }
803 }
804 }
805
806 out( i, j, k ) = static_cast< out_value_type >( max );
807 life--;
808 }
809
810 if( bprogress1 )
811 {
812 f( static_cast< double >( j + 1 ) / static_cast< double >( h ) * 100.0 );
813 }
814 }
815
816 if( bprogress2 )
817 {
818 f( static_cast< double >( k + 1 ) / static_cast< double >( d ) * 100.0 );
819 }
820 }
821 }
822 }
823
824
825 // モルフォロジ演算のスレッド実装
826 namespace __morphology_controller__
827 {
828 // Erosion 演算
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 )
833 {
834 __erosion__::erosion( in, out, object, update, 0, 1, thread_id, thread_num, f );
835 }
836
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 )
841 {
842 __erosion__::erosion( in, out, object, update, 0, 1, thread_id, thread_num, f );
843 }
844
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 )
849 {
850 __erosion__::erosion( in, out, object, update, thread_id, thread_num, 0, 1, f );
851 }
852
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 )
857 {
858 __erosion__::erosion( in, out, object, update, 0, 1, thread_id, thread_num, f );
859 }
860
861
862 // Dilation 演算
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 )
867 {
868 __dilation__::dilation( in, out, object, update, 0, 1, thread_id, thread_num, f );
869 }
870
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 )
875 {
876 __dilation__::dilation( in, out, object, update, 0, 1, thread_id, thread_num, f );
877 }
878
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 )
883 {
884 __dilation__::dilation( in, out, object, update, thread_id, thread_num, 0, 1, f );
885 }
886
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 )
891 {
892 __dilation__::dilation( in, out, object, update, 0, 1, thread_id, thread_num, f );
893 }
894
895
896 template < class T1, class T2, class Functor >
897 class morphology_thread : public mist::thread< morphology_thread< T1, T2, Functor > >
898 {
899 public:
900 typedef mist::thread< morphology_thread< T1, T2, Functor > > base;
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;
906
907 private:
908 size_t thread_id_;
909 size_t thread_num_;
910
911 // 入出力用の画像へのポインタ
912 const T1 *in_;
913 T2 *out_;
914 list_type *object_;
915 list_type *update_;
916 bool is_erosion_;
917
918 Functor f_;
919
920 public:
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 )
922 {
923 in_ = &in;
924 out_ = &out;
925 object_ = &object;
926 update_ = &update;
927 is_erosion_ = is_erosion;
928 thread_id_ = thread_id;
929 thread_num_ = thread_num;
930 f_ = f;
931 }
932
933 const morphology_thread& operator =( const morphology_thread &p )
934 {
935 if( &p != this )
936 {
937 base::operator =( p );
938 thread_id_ = p.thread_id_;
939 thread_num_ = p.thread_num_;
940 in_ = p.in_;
941 out_ = p.out_;
942 is_erosion_ = p.is_erosion_;
943 object_ = p.object_;
944 update_ = p.update_;
945 f_ = p.f_;
946 }
947 return( *this );
948 }
949
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 )
952 {
953 }
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_ )
956 {
957 }
958
959 protected:
960 // 継承した先で必ず実装されるスレッド関数
961 virtual thread_exit_type thread_function( )
962 {
963 if( is_erosion_ )
964 {
965 erosion( *in_, *out_, *object_, *update_, thread_id_, thread_num_, f_ );
966 }
967 else
968 {
969 dilation( *in_, *out_, *object_, *update_, thread_id_, thread_num_, f_ );
970 }
971 return( true );
972 }
973 };
974 }
975
976
979
980
994 template < class Array, class Functor >
995 bool erosion( Array &in, const morphology::morphology_structure &s, Functor f, typename Array::size_type thread_num )
996 {
997 if( in.empty( ) )
998 {
999 return( false );
1000 }
1001
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;
1005 typedef morphology::pointer_diff pointer_diff;
1006 typedef std::vector< pointer_diff > list_type;
1007
1008 if( thread_num == 0 )
1009 {
1010 thread_num = static_cast< size_type >( get_cpu_num( ) );
1011 }
1012
1013 value_type max = type_limits< value_type >::maximum( );
1014
1015 marray< Array > out( in, s.margin_x, s.margin_y, s.margin_z, max );
1016
1017 list_type object = morphology::create_pointer_diff_list( out, s.object );
1018 list_type update = morphology::create_pointer_diff_list( out, s.update );
1019
1020 morphology_thread *thread = new morphology_thread[ thread_num ];
1021
1022 size_type i;
1023 for( i = 0 ; i < thread_num ; i++ )
1024 {
1025 thread[ i ].setup_parameters( out, in, object, update, true, i, thread_num, f );
1026 }
1027
1028 f( 0.0 );
1029
1030 // スレッドを実行して，終了まで待機する
1031 do_threads_( thread, thread_num );
1032
1033 f( 100.1 );
1034
1035 delete [] thread;
1036
1037 return( true );
1038 }
1039
1040
1053 template < class Array >
1054 bool erosion( Array &in, const morphology::morphology_structure &s, typename Array::size_type thread_num = 0 )
1055 {
1056 return( erosion( in, s, __mist_dmy_callback__( ), thread_num ) );
1057 }
1058
1059
1073 template < class Array, class Functor >
1074 bool dilation( Array &in, const morphology::morphology_structure &s, Functor f, typename Array::size_type thread_num )
1075 {
1076 if( in.empty( ) )
1077 {
1078 return( false );
1079 }
1080
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;
1084 typedef morphology::pointer_diff pointer_diff;
1085 typedef std::vector< pointer_diff > list_type;
1086
1087 if( thread_num == 0 )
1088 {
1089 thread_num = static_cast< size_type >( get_cpu_num( ) );
1090 }
1091
1092 value_type min = type_limits< value_type >::minimum( );
1093
1094 marray< Array > out( in, s.margin_x, s.margin_y, s.margin_z, min );
1095
1096 list_type object = morphology::create_pointer_diff_list( out, s.object );
1097 list_type update = morphology::create_pointer_diff_list( out, s.update );
1098
1099 morphology_thread *thread = new morphology_thread[ thread_num ];
1100
1101 size_type i;
1102 for( i = 0 ; i < thread_num ; i++ )
1103 {
1104 thread[ i ].setup_parameters( out, in, object, update, false, i, thread_num, f );
1105 }
1106
1107 f( 0.0 );
1108
1109 // スレッドを実行して，終了まで待機する
1110 do_threads_( thread, thread_num );
1111
1112 f( 100.1 );
1113
1114 delete [] thread;
1115
1116 return( true );
1117 }
1118
1119
1132 template < class Array >
1133 bool dilation( Array &in, const morphology::morphology_structure &s, typename Array::size_type thread_num = 0 )
1134 {
1135 return( dilation( in, s, __mist_dmy_callback__( ), thread_num ) );
1136 }
1137
1138
1152 template < class Array, class Functor >
1153 bool opening( Array &in, const morphology::morphology_structure &s, Functor f, typename Array::size_type thread_num )
1154 {
1155 if( in.empty( ) )
1156 {
1157 return( false );
1158 }
1159
1160 typedef typename Array::value_type value_type;
1161 typedef typename Array::size_type size_type;
1162 typedef __mist_convert_callback__< Functor > CallBack;
1163 typedef __morphology_controller__::morphology_thread< marray< Array >, Array, CallBack > morphology_thread;
1164 typedef morphology::pointer_diff pointer_diff;
1165 typedef std::vector< pointer_diff > list_type;
1166
1167 if( thread_num == 0 )
1168 {
1169 thread_num = static_cast< size_type >( get_cpu_num( ) );
1170 }
1171
1172 value_type max = type_limits< value_type >::maximum( );
1173 value_type min = type_limits< value_type >::minimum( );
1174
1175 marray< Array > out( in, s.margin_x, s.margin_y, s.margin_z, max );
1176
1177 list_type object = morphology::create_pointer_diff_list( out, s.object );
1178 list_type update = morphology::create_pointer_diff_list( out, s.update );
1179
1180 morphology_thread *thread = new morphology_thread[ thread_num ];
1181
1182 f( 0.0 );
1183
1184 size_type i;
1185 {
1186 // Erosion 演算
1187 for( i = 0 ; i < thread_num ; i++ )
1188 {
1189 thread[ i ].setup_parameters( out, in, object, update, true, i, thread_num, CallBack( f, 0, 50 ) );
1190 }
1191
1192 // スレッドを実行して，終了まで待機する
1193 do_threads_( thread, thread_num );
1194 }
1195
1196 out = in;
1197 out.fill_margin( min );
1198
1199 {
1200 // Dilation 演算
1201 for( i = 0 ; i < thread_num ; i++ )
1202 {
1203 thread[ i ].setup_parameters( out, in, object, update, false, i, thread_num, CallBack( f, 50, 100 ) );
1204 }
1205
1206 // スレッドを実行して，終了まで待機する
1207 do_threads_( thread, thread_num );
1208 }
1209
1210 f( 100.1 );
1211
1212 delete [] thread;
1213
1214 return( true );
1215 }
1216
1217
1230 template < class Array >
1231 bool opening( Array &in, const morphology::morphology_structure &s, typename Array::size_type thread_num = 0 )
1232 {
1233 return( opening( in, s, __mist_dmy_callback__( ), thread_num ) );
1234 }
1235
1236
1250 template < class Array, class Functor >
1251 bool closing( Array &in, const morphology::morphology_structure &s, Functor f, typename Array::size_type thread_num )
1252 {
1253 if( in.empty( ) )
1254 {
1255 return( false );
1256 }
1257
1258 typedef typename Array::value_type value_type;
1259 typedef typename Array::size_type size_type;
1260 typedef __mist_convert_callback__< Functor > CallBack;
1261 typedef __morphology_controller__::morphology_thread< marray< Array >, Array, CallBack > morphology_thread;
1262 typedef morphology::pointer_diff pointer_diff;
1263 typedef std::vector< pointer_diff > list_type;
1264
1265 if( thread_num == 0 )
1266 {
1267 thread_num = static_cast< size_type >( get_cpu_num( ) );
1268 }
1269
1270 value_type max = type_limits< value_type >::maximum( );
1271 value_type min = type_limits< value_type >::minimum( );
1272
1273 marray< Array > out( in, s.margin_x, s.margin_y, s.margin_z, min );
1274
1275 list_type object = morphology::create_pointer_diff_list( out, s.object );
1276 list_type update = morphology::create_pointer_diff_list( out, s.update );
1277
1278 morphology_thread *thread = new morphology_thread[ thread_num ];
1279
1280 f( 0.0 );
1281
1282 size_type i;
1283 {
1284 // Dilation 演算
1285 for( i = 0 ; i < thread_num ; i++ )
1286 {
1287 thread[ i ].setup_parameters( out, in, object, update, false, i, thread_num, CallBack( f, 0, 50 ) );
1288 }
1289
1290 // スレッドを実行して，終了まで待機する
1291 do_threads_( thread, thread_num );
1292 }
1293
1294 out = in;
1295 out.fill_margin( max );
1296
1297 {
1298 // Erosion 演算
1299 for( i = 0 ; i < thread_num ; i++ )
1300 {
1301 thread[ i ].setup_parameters( out, in, object, update, true, i, thread_num, CallBack( f, 50, 100 ) );
1302 }
1303
1304 // スレッドを実行して，終了まで待機する
1305 do_threads_( thread, thread_num );
1306 }
1307
1308 f( 100.1 );
1309
1310 delete [] thread;
1311
1312 return( true );
1313 }
1314
1315
1328 template < class Array >
1329 bool closing( Array &in, const morphology::morphology_structure &s, typename Array::size_type thread_num = 0 )
1330 {
1331 return( closing( in, s, __mist_dmy_callback__( ), thread_num ) );
1332 }
1333
1334
1335
1349 template < class Array, class Functor >
1350 inline bool erosion( Array &in, double radius, Functor f, typename Array::size_type thread_num )
1351 {
1352 if( in.depth( ) == 1 )
1353 {
1354 return( erosion( in, morphology::circle( radius, in.reso1( ), in.reso2( ) ), f, thread_num ) );
1355 }
1356 else
1357 {
1358 return( erosion( in, morphology::sphere( radius, in.reso1( ), in.reso2( ), in.reso3( ) ), f, thread_num ) );
1359 }
1360 }
1361
1362
1376 template < class Array, class Functor >
1377 inline bool dilation( Array &in, double radius, Functor f, typename Array::size_type thread_num )
1378 {
1379 if( in.depth( ) == 1 )
1380 {
1381 return( dilation( in, morphology::circle( radius, in.reso1( ), in.reso2( ) ), f, thread_num ) );
1382 }
1383 else
1384 {
1385 return( dilation( in, morphology::sphere( radius, in.reso1( ), in.reso2( ), in.reso3( ) ), f, thread_num ) );
1386 }
1387 }
1388
1389
1403 template < class Array, class Functor >
1404 inline bool opening( Array &in, double radius, Functor f, typename Array::size_type thread_num )
1405 {
1406 if( in.depth( ) == 1 )
1407 {
1408 return( opening( in, morphology::circle( radius, in.reso1( ), in.reso2( ) ), f, thread_num ) );
1409 }
1410 else
1411 {
1412 return( opening( in, morphology::sphere( radius, in.reso1( ), in.reso2( ), in.reso3( ) ), f, thread_num ) );
1413 }
1414 }
1415
1416
1430 template < class Array, class Functor >
1431 inline bool closing( Array &in, double radius, Functor f, typename Array::size_type thread_num )
1432 {
1433 if( in.depth( ) == 1 )
1434 {
1435 return( closing( in, morphology::circle( radius, in.reso1( ), in.reso2( ) ), f, thread_num ) );
1436 }
1437 else
1438 {
1439 return( closing( in, morphology::sphere( radius, in.reso1( ), in.reso2( ), in.reso3( ) ), f, thread_num ) );
1440 }
1441 }
1442
1443
1444
1457 template < class Array >
1458 inline bool erosion( Array &in, double radius, typename Array::size_type thread_num = 0 )
1459 {
1460 return( erosion( in, radius, __mist_dmy_callback__( ), thread_num ) );
1461 }
1462
1463
1476 template < class Array >
1477 inline bool dilation( Array &in, double radius, typename Array::size_type thread_num = 0 )
1478 {
1479 return( dilation( in, radius, __mist_dmy_callback__( ), thread_num ) );
1480 }
1481
1482
1495 template < class Array >
1496 inline bool opening( Array &in, double radius, typename Array::size_type thread_num = 0 )
1497 {
1498 return( opening( in, radius, __mist_dmy_callback__( ), thread_num ) );
1499 }
1500
1501
1514 template < class Array >
1515 inline bool closing( Array &in, double radius, typename Array::size_type thread_num = 0 )
1516 {
1517 return( closing( in, radius, __mist_dmy_callback__( ), thread_num ) );
1518 }
1519
1520
1522 // モルフォロジ演算グループの終わり
1523
1524
1525 // mist名前空間の終わり
1526 _MIST_END
1527
1528
1529 #endif // __INCLUDE_MIST_MORPHOLOGY__
1530