Skip to content

Commit d5e11c4

Browse files
authored
Merge pull request #109 from imglib/distance-tform-arrayOob-fix
fix/test: DistanceTransform array out of bounds exception
2 parents d6bb3ae + e6a50a2 commit d5e11c4

File tree

3 files changed

+382
-7
lines changed

3 files changed

+382
-7
lines changed

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

+204-7
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,9 @@ public static < T extends RealType< T >, U extends RealType< U >, V extends Real
355355
final int nTasks,
356356
final double... weights ) throws InterruptedException, ExecutionException
357357
{
358-
359358
final boolean isIsotropic = weights.length <= 1;
360-
final double[] w = weights.length == source.numDimensions() ? weights : DoubleStream.generate( () -> weights.length == 0 ? 1.0 : weights[ 0 ] ).limit( source.numDimensions() ).toArray();
359+
final double[] w = weights.length == source.numDimensions() ? weights
360+
: DoubleStream.generate(() -> weights.length == 0 ? 1.0 : weights[0]).limit(source.numDimensions()).toArray();
361361

362362
switch ( distanceType )
363363
{
@@ -1105,6 +1105,19 @@ private static < T extends RealType< T >, U extends RealType< U > > void transfo
11051105
final RandomAccessibleInterval< U > target,
11061106
final Distance d,
11071107
final int dim )
1108+
{
1109+
final long size = target.dimension( dim );
1110+
if( size > Integer.MAX_VALUE )
1111+
transformAlongDimensionComposite(source, target, d, dim);
1112+
else
1113+
transformAlongDimensionPrimitive(source, target, d, dim);
1114+
}
1115+
1116+
private static < T extends RealType< T >, U extends RealType< U > > void transformAlongDimensionComposite(
1117+
final RandomAccessible< T > source,
1118+
final RandomAccessibleInterval< U > target,
1119+
final Distance d,
1120+
final int dim )
11081121
{
11091122
final int lastDim = target.numDimensions() - 1;
11101123
final long size = target.dimension( dim );
@@ -1129,6 +1142,35 @@ private static < T extends RealType< T >, U extends RealType< U > > void transfo
11291142
}
11301143
}
11311144

1145+
private static < T extends RealType< T >, U extends RealType< U > > void transformAlongDimensionPrimitive(
1146+
final RandomAccessible< T > source,
1147+
final RandomAccessibleInterval< U > target,
1148+
final Distance d,
1149+
final int dim )
1150+
{
1151+
final int lastDim = target.numDimensions() - 1;
1152+
final long size = target.dimension( dim );
1153+
final RealComposite< DoubleType > tmp = Views.collapseReal( createAppropriateOneDimensionalImage( size, new DoubleType() ) ).randomAccess().get();
1154+
1155+
// do not permute if we already work on last dimension
1156+
final Cursor< RealComposite< T > > s = Views.flatIterable( Views.collapseReal( dim == lastDim ? Views.interval( source, target ) : Views.permute( Views.interval( source, target ), dim, lastDim ) ) ).cursor();
1157+
final Cursor< RealComposite< U > > t = Views.flatIterable( Views.collapseReal( dim == lastDim ? target : Views.permute( target, dim, lastDim ) ) ).cursor();
1158+
1159+
final long[] lowerBoundDistanceIndex = new long[(int)size];
1160+
final double[] envelopeIntersectLocation = new double[(int)size + 1];
1161+
1162+
while ( s.hasNext() )
1163+
{
1164+
final RealComposite< T > sourceComp = s.next();
1165+
final RealComposite< U > targetComp = t.next();
1166+
for ( long i = 0; i < size; ++i )
1167+
{
1168+
tmp.get( i ).set( sourceComp.get( i ).getRealDouble() );
1169+
}
1170+
transformSingleColumnPrimitive( tmp, targetComp, lowerBoundDistanceIndex, envelopeIntersectLocation, d, dim, size );
1171+
}
1172+
}
1173+
11321174
private static < T extends RealType< T >, U extends RealType< U > > void transformAlongDimensionParallel(
11331175
final RandomAccessible< T > source,
11341176
final RandomAccessibleInterval< U > target,
@@ -1167,6 +1209,53 @@ private static < T extends RealType< T >, U extends RealType< U > > void transfo
11671209
invokeAllAndWait( es, tasks );
11681210
}
11691211

1212+
private static < T extends RealType< T >, U extends RealType< U > > void transformSingleColumnPrimitive(
1213+
final RealComposite< T > source,
1214+
final RealComposite< U > target,
1215+
final long[] lowerBoundDistanceIndex,
1216+
final double[] envelopeIntersectLocation,
1217+
final Distance d,
1218+
final int dim,
1219+
final long size )
1220+
{
1221+
int k = 0;
1222+
1223+
lowerBoundDistanceIndex[0] = 0;
1224+
envelopeIntersectLocation[0] = Double.NEGATIVE_INFINITY;
1225+
envelopeIntersectLocation[1] = Double.POSITIVE_INFINITY;
1226+
for ( long position = 1; position < size; ++position )
1227+
{
1228+
long envelopeIndexAtK = lowerBoundDistanceIndex[k];
1229+
final double sourceAtPosition = source.get( position ).getRealDouble();
1230+
double s = d.intersect( envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), position, sourceAtPosition, dim );
1231+
1232+
for ( double envelopeValueAtK = envelopeIntersectLocation[k]; s <= envelopeValueAtK && k >= 1; envelopeValueAtK = envelopeIntersectLocation[k] )
1233+
{
1234+
--k;
1235+
envelopeIndexAtK = lowerBoundDistanceIndex[k];
1236+
s = d.intersect( envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), position, sourceAtPosition, dim );
1237+
}
1238+
++k;
1239+
lowerBoundDistanceIndex[k] = position;
1240+
envelopeIntersectLocation[k] = s;
1241+
envelopeIntersectLocation[k + 1] = Double.POSITIVE_INFINITY;
1242+
}
1243+
1244+
k = 0;
1245+
1246+
for ( long position = 0; position < size; ++position )
1247+
{
1248+
while ( envelopeIntersectLocation[ k + 1 ] < position )
1249+
{
1250+
++k;
1251+
}
1252+
final long envelopeIndexAtK = lowerBoundDistanceIndex[k];
1253+
// copy necessary because of the following line, access to source
1254+
// after write to source -> source and target cannot be the same
1255+
target.get( position ).setReal( d.evaluate( position, envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), dim ) );
1256+
}
1257+
}
1258+
11701259
private static < T extends RealType< T >, U extends RealType< U > > void transformSingleColumn(
11711260
final RealComposite< T > source,
11721261
final RealComposite< U > target,
@@ -1187,7 +1276,7 @@ private static < T extends RealType< T >, U extends RealType< U > > void transfo
11871276
final double sourceAtPosition = source.get( position ).getRealDouble();
11881277
double s = d.intersect( envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), position, sourceAtPosition, dim );
11891278

1190-
for ( double envelopeValueAtK = envelopeIntersectLocation.get( k ).get(); s <= envelopeValueAtK; envelopeValueAtK = envelopeIntersectLocation.get( k ).get() )
1279+
for ( double envelopeValueAtK = envelopeIntersectLocation.get( k ).get(); s <= envelopeValueAtK && k >= 1; envelopeValueAtK = envelopeIntersectLocation.get( k ).get() )
11911280
{
11921281
--k;
11931282
envelopeIndexAtK = lowerBoundDistanceIndex.get( k ).get();
@@ -1212,7 +1301,6 @@ private static < T extends RealType< T >, U extends RealType< U > > void transfo
12121301
// after write to source -> source and target cannot be the same
12131302
target.get( position ).setReal( d.evaluate( position, envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), dim ) );
12141303
}
1215-
12161304
}
12171305

12181306
private static < T extends RealType< T >, U extends RealType< U > > void transformL1AlongDimension(
@@ -1725,6 +1813,21 @@ private static < T extends RealType< T >, U extends RealType< U >, L extends Int
17251813
final RandomAccessible< M > labelTarget,
17261814
final Distance d,
17271815
final int dim )
1816+
{
1817+
final long size = target.dimension( dim );
1818+
if( size > Integer.MAX_VALUE )
1819+
transformAlongDimensionPropagateLabelsComposite(source, target, labelSource, labelTarget, d, dim);
1820+
else
1821+
transformAlongDimensionPropagateLabelsPrimitive(source, target, labelSource, labelTarget, d, dim);
1822+
}
1823+
1824+
private static < T extends RealType< T >, U extends RealType< U >, L extends IntegerType< L >, M extends IntegerType< M > > void transformAlongDimensionPropagateLabelsComposite(
1825+
final RandomAccessible< T > source,
1826+
final RandomAccessibleInterval< U > target,
1827+
final RandomAccessible< L > labelSource,
1828+
final RandomAccessible< M > labelTarget,
1829+
final Distance d,
1830+
final int dim )
17281831
{
17291832
final int lastDim = target.numDimensions() - 1;
17301833
final long size = target.dimension( dim );
@@ -1759,11 +1862,11 @@ private static < T extends RealType< T >, U extends RealType< U >, L extends Int
17591862
tmp.get( i ).set( sourceComp.get( i ).getRealDouble() );
17601863
tmpLabel.get( i ).setInteger( labelComp.get( i ).getIntegerLong() );
17611864
}
1762-
transformSingleColumnPropagateLabels( tmp, targetComp, tmpLabel, labelTargetComp, lowerBoundDistanceIndex, envelopeIntersectLocation, d, dim, size );
1865+
transformSingleColumnPropagateLabelsComposite( tmp, targetComp, tmpLabel, labelTargetComp, lowerBoundDistanceIndex, envelopeIntersectLocation, d, dim, size );
17631866
}
17641867
}
17651868

1766-
private static < T extends RealType< T >, U extends RealType< U >, L extends IntegerType<L>, M extends IntegerType<M> > void transformSingleColumnPropagateLabels(
1869+
private static < T extends RealType< T >, U extends RealType< U >, L extends IntegerType<L>, M extends IntegerType<M> > void transformSingleColumnPropagateLabelsComposite(
17671870
final RealComposite< T > source,
17681871
final RealComposite< U > target,
17691872
final RealComposite< L > labelsSource,
@@ -1785,7 +1888,7 @@ private static < T extends RealType< T >, U extends RealType< U >, L extends Int
17851888
final double sourceAtPosition = source.get( position ).getRealDouble();
17861889
double s = d.intersect( envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), position, sourceAtPosition, dim );
17871890

1788-
for ( double envelopeValueAtK = envelopeIntersectLocation.get( k ).get(); s <= envelopeValueAtK; envelopeValueAtK = envelopeIntersectLocation.get( k ).get() )
1891+
for ( double envelopeValueAtK = envelopeIntersectLocation.get( k ).get(); s <= envelopeValueAtK && k >= 1; envelopeValueAtK = envelopeIntersectLocation.get( k ).get() )
17891892
{
17901893
--k;
17911894
envelopeIndexAtK = lowerBoundDistanceIndex.get( k ).get();
@@ -1813,6 +1916,100 @@ private static < T extends RealType< T >, U extends RealType< U >, L extends Int
18131916

18141917
}
18151918

1919+
private static < T extends RealType< T >, U extends RealType< U >, L extends IntegerType< L >, M extends IntegerType< M > > void transformAlongDimensionPropagateLabelsPrimitive(
1920+
final RandomAccessible< T > source,
1921+
final RandomAccessibleInterval< U > target,
1922+
final RandomAccessible< L > labelSource,
1923+
final RandomAccessible< M > labelTarget,
1924+
final Distance d,
1925+
final int dim )
1926+
{
1927+
final int lastDim = target.numDimensions() - 1;
1928+
final int size = (int)target.dimension( dim );
1929+
1930+
final Img< DoubleType > tmpImg = createAppropriateOneDimensionalImage( size, new DoubleType() );
1931+
final RealComposite< DoubleType > tmp = Views.collapseReal( tmpImg ).randomAccess().get();
1932+
1933+
final Img< L > tmpLabelImg = Util.getSuitableImgFactory( tmpImg, labelSource.getType() ).create( tmpImg );
1934+
final RealComposite< L > tmpLabel = Views.collapseReal( tmpLabelImg ).randomAccess().get();
1935+
1936+
// do not permute if we already work on last dimension
1937+
final Cursor< RealComposite< T > > s = Views.flatIterable( Views.collapseReal( dim == lastDim ? Views.interval( source, target ) : Views.permute( Views.interval( source, target ), dim, lastDim ) ) ).cursor();
1938+
final Cursor< RealComposite< U > > t = Views.flatIterable( Views.collapseReal( dim == lastDim ? target : Views.permute( target, dim, lastDim ) ) ).cursor();
1939+
1940+
final Cursor< RealComposite< L > > ls = Views.flatIterable(
1941+
Views.collapseReal( dim == lastDim ? Views.interval( labelSource, target ) : Views.permute( Views.interval( labelSource, target ), dim, lastDim ) ) ).cursor();
1942+
1943+
final Cursor< RealComposite< M > > lt = Views.flatIterable(
1944+
Views.collapseReal( dim == lastDim ? Views.interval( labelTarget, target ) : Views.permute( Views.interval( labelTarget, target ), dim, lastDim ) ) ).cursor();
1945+
1946+
final long[] lowerBoundDistanceIndex = new long[size];
1947+
final double[] envelopeIntersectLocation = new double[size+1];
1948+
1949+
while ( s.hasNext() )
1950+
{
1951+
final RealComposite< T > sourceComp = s.next();
1952+
final RealComposite< U > targetComp = t.next();
1953+
final RealComposite< L > labelComp = ls.next();
1954+
final RealComposite< M > labelTargetComp = lt.next();
1955+
for ( long i = 0; i < size; ++i )
1956+
{
1957+
tmp.get( i ).set( sourceComp.get( i ).getRealDouble() );
1958+
tmpLabel.get( i ).setInteger( labelComp.get( i ).getIntegerLong() );
1959+
}
1960+
transformSingleColumnPropagateLabelsPrimitive( tmp, targetComp, tmpLabel, labelTargetComp, lowerBoundDistanceIndex, envelopeIntersectLocation, d, dim, size );
1961+
}
1962+
}
1963+
1964+
private static < T extends RealType< T >, U extends RealType< U >, L extends IntegerType<L>, M extends IntegerType<M> > void transformSingleColumnPropagateLabelsPrimitive(
1965+
final RealComposite< T > source,
1966+
final RealComposite< U > target,
1967+
final RealComposite< L > labelsSource,
1968+
final RealComposite< M > labelsResult,
1969+
final long[] lowerBoundDistanceIndex,
1970+
final double[] envelopeIntersectLocation,
1971+
final Distance d,
1972+
final int dim,
1973+
final long size )
1974+
{
1975+
int k = 0;
1976+
1977+
lowerBoundDistanceIndex[0] = 0;
1978+
envelopeIntersectLocation[0] = Double.NEGATIVE_INFINITY;
1979+
envelopeIntersectLocation[1] = Double.POSITIVE_INFINITY;
1980+
for ( long position = 1; position < size; ++position )
1981+
{
1982+
long envelopeIndexAtK = lowerBoundDistanceIndex[k];
1983+
final double sourceAtPosition = source.get( position ).getRealDouble();
1984+
double s = d.intersect( envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), position, sourceAtPosition, dim );
1985+
1986+
for ( double envelopeValueAtK = envelopeIntersectLocation[k]; s <= envelopeValueAtK && k >= 1; envelopeValueAtK = envelopeIntersectLocation[k] )
1987+
{
1988+
--k;
1989+
envelopeIndexAtK = lowerBoundDistanceIndex[k];
1990+
s = d.intersect( envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), position, sourceAtPosition, dim );
1991+
}
1992+
++k;
1993+
lowerBoundDistanceIndex[k] = position;
1994+
envelopeIntersectLocation[k] = s;
1995+
envelopeIntersectLocation[k + 1] = Double.POSITIVE_INFINITY;
1996+
}
1997+
1998+
k = 0;
1999+
for ( long position = 0; position < size; ++position )
2000+
{
2001+
while ( envelopeIntersectLocation[ k + 1 ] < position )
2002+
{
2003+
++k;
2004+
}
2005+
final long envelopeIndexAtK = lowerBoundDistanceIndex[k];
2006+
// copy necessary because of the following line, access to source
2007+
// after write to source -> source and target cannot be the same
2008+
target.get( position ).setReal( d.evaluate( position, envelopeIndexAtK, source.get( envelopeIndexAtK ).getRealDouble(), dim ) );
2009+
labelsResult.get( position ).setInteger( labelsSource.get( envelopeIndexAtK ).getIntegerLong() );
2010+
}
2011+
}
2012+
18162013
private static < T extends RealType< T >, U extends RealType< U >, L extends IntegerType< L >, M extends IntegerType< M > > void transformAlongDimensionPropagateLabelsParallel(
18172014
final RandomAccessible< T > source,
18182015
final RandomAccessibleInterval< U > target,

0 commit comments

Comments
 (0)