Skip to content

Commit e3d30cf

Browse files
committed
Change Thresholder implementation to multi-threaded LoopBuilder
This simplifies the existing implementation while staying backwards compatible. The code adds a new method: Thresholder.threshold( source, threshold, above ) That is multi-threaded according to the Parallelization context.
1 parent 7d6d6ca commit e3d30cf

File tree

1 file changed

+34
-94
lines changed

1 file changed

+34
-94
lines changed

src/main/java/net/imglib2/algorithm/binary/Thresholder.java

Lines changed: 34 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,12 @@
3333
*/
3434
package net.imglib2.algorithm.binary;
3535

36-
import java.util.Vector;
36+
import java.util.function.BiConsumer;
3737

38-
import net.imglib2.Cursor;
39-
import net.imglib2.RandomAccess;
40-
import net.imglib2.converter.Converter;
41-
import net.imglib2.exception.IncompatibleTypeException;
4238
import net.imglib2.img.Img;
4339
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;
4642
import net.imglib2.type.Type;
4743
import net.imglib2.type.logic.BitType;
4844

@@ -73,95 +69,39 @@ public class Thresholder
7369
*/
7470
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 )
7571
{
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+
}
10875

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+
}
15698

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 );
165105
}
166106

167107
}

0 commit comments

Comments
 (0)