Skip to content

Commit bb1c0db

Browse files
committed
Add binary distance transform convenience methods
As suggested in #69
1 parent 8d7c1da commit bb1c0db

File tree

2 files changed

+451
-5
lines changed

2 files changed

+451
-5
lines changed

src/main/java/net/imglib2/algorithm/morphology/distance/DistanceTransform.java

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,20 @@
4949
import net.imglib2.Interval;
5050
import net.imglib2.RandomAccessible;
5151
import net.imglib2.RandomAccessibleInterval;
52+
import net.imglib2.converter.Converter;
53+
import net.imglib2.converter.Converters;
5254
import net.imglib2.img.Img;
5355
import net.imglib2.img.array.ArrayImg;
5456
import net.imglib2.img.array.ArrayImgFactory;
5557
import net.imglib2.img.cell.CellImg;
5658
import net.imglib2.img.cell.CellImgFactory;
59+
import net.imglib2.type.BooleanType;
5760
import net.imglib2.type.NativeType;
5861
import net.imglib2.type.numeric.RealType;
5962
import net.imglib2.type.numeric.integer.LongType;
6063
import net.imglib2.type.numeric.real.DoubleType;
6164
import net.imglib2.util.Intervals;
65+
import net.imglib2.util.Util;
6266
import net.imglib2.util.ValuePair;
6367
import net.imglib2.view.Views;
6468
import net.imglib2.view.composite.RealComposite;
@@ -530,6 +534,280 @@ public static < T extends RealType< T >, U extends RealType< U >, V extends Real
530534
}
531535
}
532536

537+
/**
538+
* Create binary distance transform on source using squared Euclidian (L2)
539+
* or L1 distance. Intermediate results will be stored in target
540+
* ({@link DoubleType} recommended). The distance can be weighted
541+
* (individually for each dimension, if desired) against the image values
542+
* via the weights parameter.
543+
*
544+
* @param source
545+
* Input function on which distance transform should be computed.
546+
* @param target
547+
* Intermediate and final results of distance transform.
548+
* @param distanceType
549+
* Defines distance to be used: squared Euclidian or L1
550+
* @param weights
551+
* Individual weights for each dimension, balancing image values
552+
* and distance (when using squared Euclidian distance, weights
553+
* should be squared, too).
554+
*/
555+
public static < B extends BooleanType< B >, U extends RealType< U > > void binaryTransform(
556+
final RandomAccessible< B > source,
557+
final RandomAccessibleInterval< U > target,
558+
final DISTANCE_TYPE distanceType,
559+
final double... weights )
560+
{
561+
binaryTransform( source, target, target, distanceType, weights );
562+
}
563+
564+
/**
565+
* Create binary distance transform on source using squared Euclidian (L2)
566+
* or L1 distance. Intermediate results will be stored in target
567+
* ({@link DoubleType} recommended). The distance can be weighted
568+
* (individually for each dimension, if desired) against the image values
569+
* via the weights parameter.
570+
*
571+
* @param source
572+
* Input function on which distance transform should be computed.
573+
* @param target
574+
* Intermediate and final results of distance transform.
575+
* @param distanceType
576+
* Defines distance to be used: squared Euclidian or L1
577+
* @param es
578+
* {@link ExecutorService} for parallel execution.
579+
* @param nTasks
580+
* Number of tasks/parallelism
581+
* @param weights
582+
* Individual weights for each dimension, balancing image values
583+
* and distance (when using squared Euclidian distance, weights
584+
* should be squared, too).
585+
* @throws InterruptedException
586+
* @throws ExecutionException
587+
*/
588+
public static < B extends BooleanType< B >, U extends RealType< U > > void binaryTransform(
589+
final RandomAccessible< B > source,
590+
final RandomAccessibleInterval< U > target,
591+
final DISTANCE_TYPE distanceType,
592+
final ExecutorService es,
593+
final int nTasks,
594+
final double... weights ) throws InterruptedException, ExecutionException
595+
{
596+
binaryTransform( source, target, target, distanceType, es, nTasks, weights );
597+
}
598+
599+
/**
600+
* Create binary distance transform on source using squared Euclidian (L2)
601+
* or L1 distance. Intermediate results will be stored in tmp
602+
* ({@link DoubleType} recommended). The output will be written into target.
603+
* The distance can be weighted (individually for each dimension, if
604+
* desired) against the image values via the weights parameter.
605+
*
606+
* @param source
607+
* Input function on which distance transform should be computed.
608+
* @param tmp
609+
* Storage for intermediate results.
610+
* @param target
611+
* Final result of distance transform.
612+
* @param distanceType
613+
* Defines distance to be used: squared Euclidian or L1
614+
* @param weights
615+
* Individual weights for each dimension, balancing image values
616+
* and distance (when using squared Euclidian distance, weights
617+
* should be squared, too).
618+
*/
619+
public static < B extends BooleanType< B >, U extends RealType< U >, V extends RealType< V > > void binaryTransform(
620+
final RandomAccessible< B > source,
621+
final RandomAccessibleInterval< U > tmp,
622+
final RandomAccessibleInterval< V > target,
623+
final DISTANCE_TYPE distanceType,
624+
final double... weights )
625+
{
626+
627+
final U maxVal = Util.getTypeFromInterval( tmp ).createVariable();
628+
maxVal.setReal( maxVal.getMaxValue() );
629+
final Converter< B, U > converter = new BinaryMaskToCost<>( maxVal );
630+
final RandomAccessible< U > converted = Converters.convert( source, converter, maxVal.createVariable() );
631+
transform( converted, tmp, target, distanceType, weights );
632+
}
633+
634+
/**
635+
* Create binary distance transform on source using squared Euclidian (L2)
636+
* or L1 distance. Intermediate results will be stored in tmp
637+
* ({@link DoubleType} recommended). The output will be written into target.
638+
* The distance can be weighted (individually for each dimension, if
639+
* desired) against the image values via the weights parameter.
640+
*
641+
* @param source
642+
* Input function on which distance transform should be computed.
643+
* @param tmp
644+
* Storage for intermediate results.
645+
* @param target
646+
* Final result of distance transform.
647+
* @param distanceType
648+
* Defines distance to be used: squared Euclidian or L1
649+
* @param es
650+
* {@link ExecutorService} for parallel execution.
651+
* @param nTasks
652+
* Number of tasks/parallelism
653+
* @param weights
654+
* Individual weights for each dimension, balancing image values
655+
* and distance (when using squared Euclidian distance, weights
656+
* should be squared, too).
657+
* @throws InterruptedException
658+
* @throws ExecutionException
659+
*/
660+
public static < B extends BooleanType< B >, U extends RealType< U >, V extends RealType< V > > void binaryTransform(
661+
final RandomAccessible< B > source,
662+
final RandomAccessibleInterval< U > tmp,
663+
final RandomAccessibleInterval< V > target,
664+
final DISTANCE_TYPE distanceType,
665+
final ExecutorService es,
666+
final int nTasks,
667+
final double... weights ) throws InterruptedException, ExecutionException
668+
{
669+
final U maxVal = Util.getTypeFromInterval( tmp ).createVariable();
670+
maxVal.setReal( maxVal.getMaxValue() );
671+
final Converter< B, U > converter = new BinaryMaskToCost<>( maxVal );
672+
final RandomAccessible< U > converted = Converters.convert( source, converter, maxVal.createVariable() );
673+
transform( converted, tmp, target, distanceType, es, nTasks, weights );
674+
}
675+
676+
/**
677+
* Create binary distance transform on source using arbitrary
678+
* {@link Distance} d. Intermediate and final results will be stored in
679+
* source ({@link DoubleType} recommended).
680+
*
681+
* @param source
682+
* Input function on which distance transform should be computed.
683+
* @param d
684+
* {@link Distance} between two points.
685+
* @param es
686+
* {@link ExecutorService} for parallel execution.
687+
* @param nTasks
688+
* Number of tasks/parallelism
689+
* @throws InterruptedException
690+
* @throws ExecutionException
691+
*/
692+
public static < B extends BooleanType< B > > void binaryTransform(
693+
final RandomAccessibleInterval< B > source,
694+
final Distance d,
695+
final ExecutorService es,
696+
final int nTasks ) throws InterruptedException, ExecutionException
697+
{
698+
binaryTransform( source, source, d, es, nTasks );
699+
}
700+
701+
/**
702+
* Create binary distance transform on source using arbitrary
703+
* {@link Distance} d. Intermediate and final results will be stored in
704+
* target ({@link DoubleType} recommended).
705+
*
706+
* @param source
707+
* Input function on which distance transform should be computed.
708+
* @param target
709+
* Final result of distance transform.
710+
* @param d
711+
* {@link Distance} between two points.
712+
*/
713+
public static < B extends BooleanType< B >, U extends RealType< U > > void binaryTransform(
714+
final RandomAccessible< B > source,
715+
final RandomAccessibleInterval< U > target,
716+
final Distance d )
717+
{
718+
binaryTransform( source, target, target, d );
719+
}
720+
721+
/**
722+
* Create binary distance transform on source using arbitrary
723+
* {@link Distance} d. Intermediate and final results will be stored in
724+
* target ({@link DoubleType} recommended).
725+
*
726+
* @param source
727+
* Input function on which distance transform should be computed.
728+
* @param target
729+
* Final result of distance transform.
730+
* @param d
731+
* {@link Distance} between two points.
732+
* @param es
733+
* {@link ExecutorService} for parallel execution.
734+
* @param nTasks
735+
* Number of tasks/parallelism
736+
*/
737+
public static < B extends BooleanType< B >, U extends RealType< U > > void binaryTransform(
738+
final RandomAccessible< B > source,
739+
final RandomAccessibleInterval< U > target,
740+
final Distance d,
741+
final ExecutorService es,
742+
final int nTasks ) throws InterruptedException, ExecutionException
743+
{
744+
binaryTransform( source, target, target, d, es, nTasks );
745+
}
746+
747+
/**
748+
* Create binary distance transform on source using arbitrary
749+
* {@link Distance} d. Intermediate results will be stored in tmp
750+
* ({@link DoubleType} recommended). The output will be written into target.
751+
*
752+
* @param source
753+
* Input function on which distance transform should be computed.
754+
* @param tmp
755+
* Storage for intermediate results.
756+
* @param target
757+
* Final result of distance transform.
758+
* @param d
759+
* {@link Distance} between two points.
760+
*/
761+
public static < B extends BooleanType< B >, U extends RealType< U >, V extends RealType< V > > void binaryTransform(
762+
final RandomAccessible< B > source,
763+
final RandomAccessibleInterval< U > tmp,
764+
final RandomAccessibleInterval< V > target,
765+
final Distance d )
766+
{
767+
final U maxVal = Util.getTypeFromInterval( tmp ).createVariable();
768+
maxVal.setReal( maxVal.getMaxValue() );
769+
final Converter< B, U > converter = new BinaryMaskToCost<>( maxVal );
770+
final RandomAccessible< U > converted = Converters.convert( source, converter, maxVal.createVariable() );
771+
transform( converted, tmp, target, d );
772+
}
773+
774+
/**
775+
* Create
776+
* <a href="http://www.theoryofcomputing.org/articles/v008a019/">distance
777+
* transforms of sampled functions</a> on source using arbitrary
778+
* {@link Distance} d. Intermediate results will be stored in tmp
779+
* ({@link DoubleType} recommended). The output will be written into target.
780+
*
781+
* @param source
782+
* Input function on which distance transform should be computed.
783+
* @param tmp
784+
* Storage for intermediate results.
785+
* @param target
786+
* Final result of distance transform.
787+
* @param d
788+
* {@link Distance} between two points.
789+
* @param es
790+
* {@link ExecutorService} for parallel execution.
791+
* @param nTasks
792+
* Number of tasks/parallelism
793+
* @throws InterruptedException
794+
* @throws ExecutionException
795+
*/
796+
public static < B extends BooleanType< B >, U extends RealType< U >, V extends RealType< V > > void binaryTransform(
797+
final RandomAccessible< B > source,
798+
final RandomAccessibleInterval< U > tmp,
799+
final RandomAccessibleInterval< V > target,
800+
final Distance d,
801+
final ExecutorService es,
802+
final int nTasks ) throws InterruptedException, ExecutionException
803+
{
804+
final U maxVal = Util.getTypeFromInterval( tmp ).createVariable();
805+
maxVal.setReal( maxVal.getMaxValue() );
806+
final Converter< B, U > converter = new BinaryMaskToCost<>( maxVal );
807+
final RandomAccessible< U > converted = Converters.convert( source, converter, maxVal.createVariable() );
808+
transform( converted, tmp, target, d, es, nTasks );
809+
}
810+
533811
/**
534812
* Create
535813
* <a href="http://www.theoryofcomputing.org/articles/v008a019/">distance
@@ -884,4 +1162,26 @@ public static int getLargestDimension( final Interval interval )
8841162
return IntStream.range( 0, interval.numDimensions() ).mapToObj( i -> new ValuePair<>( i, interval.dimension( i ) ) ).max( ( p1, p2 ) -> Long.compare( p1.getB(), p2.getB() ) ).get().getA();
8851163
}
8861164

1165+
private static class BinaryMaskToCost< B extends BooleanType< B >, R extends RealType< R > > implements Converter< B, R >
1166+
{
1167+
1168+
private final R maxValForR;
1169+
1170+
private final R zero;
1171+
1172+
public BinaryMaskToCost( final R maxValForR )
1173+
{
1174+
this.maxValForR = maxValForR;
1175+
this.zero = maxValForR.createVariable();
1176+
zero.setZero();
1177+
}
1178+
1179+
@Override
1180+
public void convert( final B input, final R output )
1181+
{
1182+
output.set( input.get() ? zero : maxValForR );
1183+
}
1184+
1185+
}
1186+
8871187
}

0 commit comments

Comments
 (0)