|
33 | 33 | */ |
34 | 34 | package net.imglib2.algorithm.binary; |
35 | 35 |
|
36 | | -import java.util.Vector; |
| 36 | +import java.util.function.BiConsumer; |
37 | 37 |
|
38 | | -import net.imglib2.Cursor; |
39 | | -import net.imglib2.RandomAccess; |
40 | | -import net.imglib2.converter.Converter; |
41 | | -import net.imglib2.exception.IncompatibleTypeException; |
42 | 38 | import net.imglib2.img.Img; |
43 | 39 | import net.imglib2.img.ImgFactory; |
44 | | -import net.imglib2.multithreading.Chunk; |
45 | | -import net.imglib2.multithreading.SimpleMultiThreading; |
| 40 | +import net.imglib2.loops.LoopBuilder; |
| 41 | +import net.imglib2.parallel.Parallelization; |
46 | 42 | import net.imglib2.type.Type; |
47 | 43 | import net.imglib2.type.logic.BitType; |
48 | 44 |
|
@@ -73,95 +69,39 @@ public class Thresholder |
73 | 69 | */ |
74 | 70 | public static final < T extends Type< T > & Comparable< T >> Img< BitType > threshold( final Img< T > source, final T threshold, final boolean above, final int numThreads ) |
75 | 71 | { |
76 | | - final ImgFactory< T > factory = source.factory(); |
77 | | - try |
78 | | - { |
79 | | - final ImgFactory< BitType > bitFactory = factory.imgFactory( new BitType() ); |
80 | | - final Img< BitType > target = bitFactory.create( source ); |
81 | | - |
82 | | - final Converter< T, BitType > converter; |
83 | | - if ( above ) |
84 | | - { |
85 | | - converter = new Converter< T, BitType >() |
86 | | - { |
87 | | - @Override |
88 | | - public void convert( final T input, final BitType output ) |
89 | | - { |
90 | | - output.set( input.compareTo( threshold ) > 0 ); |
91 | | - } |
92 | | - }; |
93 | | - } |
94 | | - else |
95 | | - { |
96 | | - converter = new Converter< T, BitType >() |
97 | | - { |
98 | | - @Override |
99 | | - public void convert( final T input, final BitType output ) |
100 | | - { |
101 | | - output.set( input.compareTo( threshold ) < 0 ); |
102 | | - } |
103 | | - }; |
104 | | - } |
105 | | - |
106 | | - final Vector< Chunk > chunks = SimpleMultiThreading.divideIntoChunks( target.size(), numThreads ); |
107 | | - final Thread[] threads = SimpleMultiThreading.newThreads( numThreads ); |
| 72 | + return Parallelization.runWithNumThreads( numThreads, |
| 73 | + () -> threshold( source, threshold, above ) ); |
| 74 | + } |
108 | 75 |
|
109 | | - if ( target.iterationOrder().equals( source.iterationOrder() ) ) |
110 | | - { |
111 | | - for ( int i = 0; i < threads.length; i++ ) |
112 | | - { |
113 | | - final Chunk chunk = chunks.get( i ); |
114 | | - threads[ i ] = new Thread( "Thresholder thread " + i ) |
115 | | - { |
116 | | - @Override |
117 | | - public void run() |
118 | | - { |
119 | | - final Cursor< BitType > cursorTarget = target.cursor(); |
120 | | - cursorTarget.jumpFwd( chunk.getStartPosition() ); |
121 | | - final Cursor< T > cursorSource = source.cursor(); |
122 | | - cursorSource.jumpFwd( chunk.getStartPosition() ); |
123 | | - for ( long steps = 0; steps < chunk.getLoopSize(); steps++ ) |
124 | | - { |
125 | | - cursorTarget.fwd(); |
126 | | - cursorSource.fwd(); |
127 | | - converter.convert( cursorSource.get(), cursorTarget.get() ); |
128 | | - } |
129 | | - } |
130 | | - }; |
131 | | - } |
132 | | - } |
133 | | - else |
134 | | - { |
135 | | - for ( int i = 0; i < threads.length; i++ ) |
136 | | - { |
137 | | - final Chunk chunk = chunks.get( i ); |
138 | | - threads[ i ] = new Thread( "Thresholder thread " + i ) |
139 | | - { |
140 | | - @Override |
141 | | - public void run() |
142 | | - { |
143 | | - final Cursor< BitType > cursorTarget = target.cursor(); |
144 | | - cursorTarget.jumpFwd( chunk.getStartPosition() ); |
145 | | - final RandomAccess< T > ra = source.randomAccess( target ); |
146 | | - for ( long steps = 0; steps < chunk.getLoopSize(); steps++ ) |
147 | | - { |
148 | | - cursorTarget.fwd(); |
149 | | - ra.setPosition( cursorTarget ); |
150 | | - converter.convert( ra.get(), cursorTarget.get() ); |
151 | | - } |
152 | | - } |
153 | | - }; |
154 | | - } |
155 | | - } |
| 76 | + /** |
| 77 | + * Returns a new boolean {@link Img} generated by thresholding the values of |
| 78 | + * the source image. |
| 79 | + * |
| 80 | + * @param source |
| 81 | + * the image to threshold. |
| 82 | + * @param threshold |
| 83 | + * the threshold. |
| 84 | + * @param above |
| 85 | + * if {@code true}, the target value will be true for source |
| 86 | + * values above the threshold, {@code false} otherwise. |
| 87 | + * @return a new {@link Img} of type {@link BitType} and of same dimension |
| 88 | + * that the source image. |
| 89 | + */ |
| 90 | + public static < T extends Type< T > & Comparable< T > > Img< BitType > threshold( Img< T > source, T threshold, boolean above ) |
| 91 | + { |
| 92 | + final ImgFactory< BitType > factory = source.factory().imgFactory( new BitType() ); |
| 93 | + final Img< BitType > target = factory.create( source ); |
| 94 | + final BiConsumer< T, BitType > converter = getThresholdConverter( threshold, above ); |
| 95 | + LoopBuilder.setImages( source, target ).multiThreaded().forEachPixel( converter ); |
| 96 | + return target; |
| 97 | + } |
156 | 98 |
|
157 | | - SimpleMultiThreading.startAndJoin( threads ); |
158 | | - return target; |
159 | | - } |
160 | | - catch ( final IncompatibleTypeException e ) |
161 | | - { |
162 | | - e.printStackTrace(); |
163 | | - return null; |
164 | | - } |
| 99 | + private static < T extends Type< T > & Comparable< T > > BiConsumer< T, BitType > getThresholdConverter( T threshold, boolean above ) |
| 100 | + { |
| 101 | + if ( above ) |
| 102 | + return ( input, output ) -> output.set( input.compareTo( threshold ) > 0 ); |
| 103 | + else |
| 104 | + return ( input, output ) -> output.set( input.compareTo( threshold ) < 0 ); |
165 | 105 | } |
166 | 106 |
|
167 | 107 | } |
0 commit comments