|
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; |
@@ -449,122 +448,38 @@ public static < T extends RealType< T >> void erode( final RandomAccessible< T > |
449 | 448 | */ |
450 | 449 | public static < T extends Type< T > & Comparable< T > > void erode( final RandomAccessible< T > source, final IterableInterval< T > target, final Shape strel, final T maxVal, int numThreads ) |
451 | 450 | { |
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 | | - final Object tmp = maxVal; |
468 | | - if ( tmp instanceof BitType ) |
469 | | - { |
470 | | - /* |
471 | | - * Optimization for BitType |
472 | | - */ |
| 451 | + final RandomAccessible< Neighborhood< T >> neighborhoods = strel.neighborhoodsRandomAccessible( source ); |
| 452 | + Parallelization.runWithNumThreads( numThreads, () -> { |
| 453 | + IterableLoopBuilder.setImages( target, neighborhoods ).multithreaded().forEachChunk( chunk -> { |
| 454 | + chunk.forEachPixel( getErodeAction( maxVal ) ); |
| 455 | + return null; |
| 456 | + } ); |
| 457 | + } ); |
| 458 | + } |
473 | 459 |
|
474 | | - for ( int i = 0; i < threads.length; i++ ) |
475 | | - { |
476 | | - final Chunk chunk = chunks.get( i ); |
477 | | - threads[ i ] = new Thread( "Morphology erode thread " + i ) |
478 | | - { |
479 | | - @Override |
480 | | - public void run() |
| 460 | + private static < T extends Type< T > & Comparable< T > > BiConsumer< T, Neighborhood< T > > getErodeAction( T maxVal ) |
| 461 | + { |
| 462 | + if ( maxVal instanceof BitType ) |
| 463 | + return Cast.unchecked( ( BiConsumer< BitType, Neighborhood< BitType > > ) ( t, neighborhood ) -> { |
| 464 | + for ( BitType val1 : neighborhood ) |
| 465 | + if ( ! val1.get() ) |
481 | 466 | { |
482 | | - final RandomAccess< Neighborhood< T >> randomAccess = accessible.randomAccess( target ); |
483 | | - final Object tmp2 = target.cursor(); |
484 | | - @SuppressWarnings( "unchecked" ) |
485 | | - final Cursor< BitType > cursorTarget = ( Cursor< BitType > ) tmp2; |
486 | | - cursorTarget.jumpFwd( chunk.getStartPosition() ); |
487 | | - |
488 | | - for ( long steps = 0; steps < chunk.getLoopSize(); steps++ ) |
489 | | - { |
490 | | - cursorTarget.fwd(); |
491 | | - randomAccess.setPosition( cursorTarget ); |
492 | | - final Object tmp3 = randomAccess.get(); |
493 | | - @SuppressWarnings( "unchecked" ) |
494 | | - final Neighborhood< BitType > neighborhood = (net.imglib2.algorithm.neighborhood.Neighborhood< BitType > ) tmp3; |
495 | | - final Cursor< BitType > nc = neighborhood.cursor(); |
496 | | - |
497 | | - cursorTarget.get().set( true ); |
498 | | - while ( nc.hasNext() ) |
499 | | - { |
500 | | - nc.fwd(); |
501 | | - final BitType val = nc.get(); |
502 | | - if ( !val.get() ) |
503 | | - { |
504 | | - cursorTarget.get().set( false ); |
505 | | - break; |
506 | | - } |
507 | | - } |
508 | | - } |
509 | | - |
| 467 | + t.set( false ); |
| 468 | + return; |
510 | 469 | } |
511 | | - }; |
512 | | - } |
513 | | - } |
| 470 | + t.set( true ); |
| 471 | + } ); |
514 | 472 | else |
515 | 473 | { |
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 erode thread " + i ) |
524 | | - { |
525 | | - @Override |
526 | | - public void run() |
527 | | - { |
528 | | - final RandomAccess< Neighborhood< T >> randomAccess = accessible.randomAccess( target ); |
529 | | - final Cursor< T > cursorTarget = target.cursor(); |
530 | | - cursorTarget.jumpFwd( chunk.getStartPosition() ); |
531 | | - |
532 | | - final T max = MorphologyUtils.createVariable( source, target ); |
533 | | - for ( long steps = 0; steps < chunk.getLoopSize(); steps++ ) |
534 | | - { |
535 | | - cursorTarget.fwd(); |
536 | | - randomAccess.setPosition( cursorTarget ); |
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( maxVal ); |
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 | | - cursorTarget.get().set( max ); |
556 | | - } |
557 | | - |
558 | | - } |
559 | | - }; |
560 | | - } |
| 474 | + T min = maxVal.copy(); |
| 475 | + return ( t, neighborhood ) -> { |
| 476 | + min.set( maxVal ); |
| 477 | + for ( T val : neighborhood ) |
| 478 | + if ( val.compareTo( min ) < 0 ) |
| 479 | + min.set( val ); |
| 480 | + t.set( min ); |
| 481 | + }; |
561 | 482 | } |
562 | | - |
563 | | - /* |
564 | | - * Launch calculation |
565 | | - */ |
566 | | - |
567 | | - SimpleMultiThreading.startAndJoin( threads ); |
568 | 483 | } |
569 | 484 |
|
570 | 485 | /** |
|
0 commit comments