|
34 | 34 | package net.imglib2.algorithm.morphology; |
35 | 35 |
|
36 | 36 | import java.util.List; |
37 | | -import java.util.Vector; |
| 37 | +import java.util.function.BiConsumer; |
38 | 38 |
|
39 | | -import net.imglib2.Cursor; |
40 | 39 | import net.imglib2.FinalDimensions; |
41 | 40 | import net.imglib2.Interval; |
42 | 41 | import net.imglib2.IterableInterval; |
43 | | -import net.imglib2.RandomAccess; |
44 | 42 | import net.imglib2.RandomAccessible; |
45 | 43 | import net.imglib2.RandomAccessibleInterval; |
| 44 | +import net.imglib2.loops.IterableLoopBuilder; |
46 | 45 | import net.imglib2.algorithm.neighborhood.Neighborhood; |
47 | 46 | import net.imglib2.algorithm.neighborhood.Shape; |
48 | 47 | import net.imglib2.img.Img; |
49 | 48 | import net.imglib2.img.ImgFactory; |
50 | | -import net.imglib2.multithreading.Chunk; |
51 | | -import net.imglib2.multithreading.SimpleMultiThreading; |
| 49 | +import net.imglib2.parallel.Parallelization; |
52 | 50 | import net.imglib2.type.Type; |
53 | 51 | import net.imglib2.type.logic.BitType; |
54 | 52 | import net.imglib2.type.numeric.RealType; |
| 53 | +import net.imglib2.util.Cast; |
55 | 54 | import net.imglib2.util.Util; |
56 | 55 | import net.imglib2.view.ExtendedRandomAccessibleInterval; |
57 | 56 | import net.imglib2.view.IntervalView; |
58 | 57 | import net.imglib2.view.Views; |
59 | 58 |
|
60 | 59 | public class Dilation |
61 | 60 | { |
| 61 | + |
62 | 62 | /** |
63 | 63 | * Performs the dilation morphological operation, on a {@link RealType} |
64 | 64 | * {@link Img} using a list of {@link Shape}s as a flat structuring element. |
@@ -449,122 +449,38 @@ public static < T extends RealType< T >> void dilate( final RandomAccessible< T |
449 | 449 | */ |
450 | 450 | public static < T extends Type< T > & Comparable< T > > void dilate( final RandomAccessible< T > source, final IterableInterval< T > target, final Shape strel, final T minVal, int numThreads ) |
451 | 451 | { |
452 | | - numThreads = Math.max( 1, numThreads ); |
453 | | - |
454 | | - /* |
455 | | - * Prepare iteration. |
456 | | - */ |
457 | | - |
458 | | - final RandomAccessible< Neighborhood< T >> accessible = strel.neighborhoodsRandomAccessible( source ); |
459 | | - |
460 | | - /* |
461 | | - * Multithread |
462 | | - */ |
463 | | - |
464 | | - final Vector< Chunk > chunks = SimpleMultiThreading.divideIntoChunks( target.size(), numThreads ); |
465 | | - final Thread[] threads = SimpleMultiThreading.newThreads( numThreads ); |
466 | | - |
467 | | - |
468 | | - final Object tmp = minVal; |
469 | | - if ( tmp instanceof BitType ) |
470 | | - { |
471 | | - /* |
472 | | - * Optimization for BitType |
473 | | - */ |
| 452 | + final RandomAccessible< Neighborhood< T > > neighborhoods = strel.neighborhoodsRandomAccessible( source ); |
| 453 | + Parallelization.runWithNumThreads( numThreads, () -> { |
| 454 | + IterableLoopBuilder.setImages( target, neighborhoods ).multithreaded().forEachChunk( chunk -> { |
| 455 | + chunk.forEachPixel( getDilateAction( minVal ) ); |
| 456 | + return null; |
| 457 | + } ); |
| 458 | + } ); |
| 459 | + } |
474 | 460 |
|
475 | | - for ( int i = 0; i < threads.length; i++ ) |
476 | | - { |
477 | | - final Chunk chunk = chunks.get( i ); |
478 | | - threads[ i ] = new Thread( "Morphology dilate thread " + i ) |
479 | | - { |
480 | | - @Override |
481 | | - public void run() |
| 461 | + private static < T extends Type< T > & Comparable< T > > BiConsumer< T, Neighborhood< T > > getDilateAction( T minVal ) |
| 462 | + { |
| 463 | + if ( minVal instanceof BitType ) |
| 464 | + return Cast.unchecked( (BiConsumer< BitType, Neighborhood< BitType > > ) ( t, neighborhood ) -> { |
| 465 | + for ( BitType val1 : neighborhood ) |
| 466 | + if ( val1.get() ) |
482 | 467 | { |
483 | | - final RandomAccess< Neighborhood< T >> randomAccess = accessible.randomAccess( target ); |
484 | | - final Object tmp2 = target.cursor(); |
485 | | - @SuppressWarnings( "unchecked" ) |
486 | | - final Cursor< BitType > cursorDilated = ( Cursor< BitType > ) tmp2; |
487 | | - cursorDilated.jumpFwd( chunk.getStartPosition() ); |
488 | | - |
489 | | - for ( long steps = 0; steps < chunk.getLoopSize(); steps++ ) |
490 | | - { |
491 | | - cursorDilated.fwd(); |
492 | | - randomAccess.setPosition( cursorDilated ); |
493 | | - final Neighborhood< T > neighborhood = randomAccess.get(); |
494 | | - final Object tmp3 = neighborhood.cursor(); |
495 | | - @SuppressWarnings( "unchecked" ) |
496 | | - final Cursor< BitType > nc = ( Cursor< BitType > ) tmp3; |
497 | | - |
498 | | - while ( nc.hasNext() ) |
499 | | - { |
500 | | - nc.fwd(); |
501 | | - final BitType val = nc.get(); |
502 | | - if ( val.get() ) |
503 | | - { |
504 | | - cursorDilated.get().set( true ); |
505 | | - break; |
506 | | - } |
507 | | - } |
508 | | - } |
509 | | - |
| 468 | + t.set( true ); |
| 469 | + return; |
510 | 470 | } |
511 | | - }; |
512 | | - } |
513 | | - } |
| 471 | + t.set( false ); |
| 472 | + } ); |
514 | 473 | else |
515 | 474 | { |
516 | | - /* |
517 | | - * All other comparable type. |
518 | | - */ |
519 | | - |
520 | | - for ( int i = 0; i < threads.length; i++ ) |
521 | | - { |
522 | | - final Chunk chunk = chunks.get( i ); |
523 | | - threads[ i ] = new Thread( "Morphology dilate thread " + i ) |
524 | | - { |
525 | | - @Override |
526 | | - public void run() |
527 | | - { |
528 | | - final RandomAccess< Neighborhood< T >> randomAccess = accessible.randomAccess( target ); |
529 | | - final Cursor< T > cursorDilated = target.cursor(); |
530 | | - cursorDilated.jumpFwd( chunk.getStartPosition() ); |
531 | | - |
532 | | - final T max = MorphologyUtils.createVariable( source, target ); |
533 | | - for ( long steps = 0; steps < chunk.getLoopSize(); steps++ ) |
534 | | - { |
535 | | - cursorDilated.fwd(); |
536 | | - randomAccess.setPosition( cursorDilated ); |
537 | | - final Neighborhood< T > neighborhood = randomAccess.get(); |
538 | | - final Cursor< T > nc = neighborhood.cursor(); |
539 | | - |
540 | | - /* |
541 | | - * Look for max in the neighborhood. |
542 | | - */ |
543 | | - |
544 | | - max.set( minVal ); |
545 | | - while ( nc.hasNext() ) |
546 | | - { |
547 | | - nc.fwd(); |
548 | | - final T val = nc.get(); |
549 | | - // We need only Comparable to do this: |
550 | | - if ( val.compareTo( max ) > 0 ) |
551 | | - { |
552 | | - max.set( val ); |
553 | | - } |
554 | | - } |
555 | | - cursorDilated.get().set( max ); |
556 | | - } |
557 | | - |
558 | | - } |
559 | | - }; |
560 | | - } |
| 475 | + T max = minVal.copy(); |
| 476 | + return ( t, neighborhood ) -> { |
| 477 | + max.set( minVal ); |
| 478 | + for ( T val : neighborhood ) |
| 479 | + if ( val.compareTo( max ) > 0 ) |
| 480 | + max.set( val ); |
| 481 | + t.set( max ); |
| 482 | + }; |
561 | 483 | } |
562 | | - |
563 | | - /* |
564 | | - * Launch calculation |
565 | | - */ |
566 | | - |
567 | | - SimpleMultiThreading.startAndJoin( threads ); |
568 | 484 | } |
569 | 485 |
|
570 | 486 | /** |
|
0 commit comments