Skip to content

Commit 2b71c6d

Browse files
stelfrichhanslovsky
authored andcommitted
Add getStructuringElementBoundingBox() for Shapes (#27)
* Shape(s): add getStructuringElementBoundingBox() * Shape: add documentation * Shape: add def getStructuringElementBoundingBox() Thanks @stelfrich
1 parent 5420e63 commit 2b71c6d

18 files changed

+349
-0
lines changed

src/main/java/net/imglib2/algorithm/neighborhood/CenteredRectangleShape.java

+14
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import net.imglib2.RandomAccessibleInterval;
4141
import net.imglib2.algorithm.neighborhood.RectangleShape.NeighborhoodsAccessible;
4242
import net.imglib2.algorithm.neighborhood.RectangleShape.NeighborhoodsIterableInterval;
43+
import net.imglib2.util.Intervals;
4344
import net.imglib2.util.Util;
4445

4546
/**
@@ -152,4 +153,17 @@ private Interval createSpan()
152153
}
153154
return new FinalInterval( min, max );
154155
}
156+
157+
@Override
158+
public Interval getStructuringElementBoundingBox(final int numDimensions) {
159+
final long[] a = new long[numDimensions];
160+
final long[] b = new long[numDimensions];
161+
162+
for (int i = 0; i < numDimensions; ++i) {
163+
a[i] = span[i] * -1;
164+
b[i] = span[i];
165+
}
166+
167+
return Intervals.union(new FinalInterval(a, a), new FinalInterval(b, b));
168+
}
155169
}

src/main/java/net/imglib2/algorithm/neighborhood/DiamondShape.java

+13
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
*/
3434
package net.imglib2.algorithm.neighborhood;
3535

36+
import java.util.Arrays;
3637
import java.util.Iterator;
3738

3839
import net.imglib2.AbstractEuclideanSpace;
3940
import net.imglib2.AbstractInterval;
4041
import net.imglib2.Cursor;
42+
import net.imglib2.FinalInterval;
4143
import net.imglib2.FlatIterationOrder;
4244
import net.imglib2.Interval;
4345
import net.imglib2.IterableInterval;
@@ -203,4 +205,15 @@ public int numDimensions()
203205
}
204206

205207
}
208+
209+
@Override
210+
public Interval getStructuringElementBoundingBox(final int numDimensions) {
211+
final long[] min = new long[numDimensions];
212+
Arrays.fill(min, -getRadius());
213+
214+
final long[] max = new long[numDimensions];
215+
Arrays.fill(max, getRadius());
216+
217+
return new FinalInterval(min, max);
218+
}
206219
}

src/main/java/net/imglib2/algorithm/neighborhood/DiamondTipsShape.java

+13
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
*/
3434
package net.imglib2.algorithm.neighborhood;
3535

36+
import java.util.Arrays;
3637
import java.util.Iterator;
3738

3839
import net.imglib2.AbstractEuclideanSpace;
3940
import net.imglib2.AbstractInterval;
4041
import net.imglib2.Cursor;
42+
import net.imglib2.FinalInterval;
4143
import net.imglib2.FlatIterationOrder;
4244
import net.imglib2.Interval;
4345
import net.imglib2.IterableInterval;
@@ -205,4 +207,15 @@ public int numDimensions()
205207
}
206208

207209
}
210+
211+
@Override
212+
public Interval getStructuringElementBoundingBox(final int numDimensions) {
213+
final long[] min = new long[numDimensions];
214+
Arrays.fill(min, -getRadius());
215+
216+
final long[] max = new long[numDimensions];
217+
Arrays.fill(max, getRadius());
218+
219+
return new FinalInterval(min, max);
220+
}
208221
}

src/main/java/net/imglib2/algorithm/neighborhood/HorizontalLineShape.java

+14
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@
3838
import net.imglib2.AbstractEuclideanSpace;
3939
import net.imglib2.AbstractInterval;
4040
import net.imglib2.Cursor;
41+
import net.imglib2.FinalInterval;
4142
import net.imglib2.FlatIterationOrder;
4243
import net.imglib2.Interval;
4344
import net.imglib2.IterableInterval;
4445
import net.imglib2.RandomAccess;
4546
import net.imglib2.RandomAccessible;
4647
import net.imglib2.RandomAccessibleInterval;
48+
import net.imglib2.util.Intervals;
4749

4850
/**
4951
* A {@link Shape} representing finite, centered, symmetric lines, that are
@@ -243,4 +245,16 @@ public int numDimensions()
243245
}
244246

245247
}
248+
249+
@Override
250+
public Interval getStructuringElementBoundingBox(final int numDimensions) {
251+
final long[] a = new long[numDimensions];
252+
final long[] b = new long[numDimensions];
253+
254+
a[dim] = -span;
255+
b[dim] = span;
256+
257+
return Intervals.union(new FinalInterval(a, a), new FinalInterval(b, b));
258+
}
259+
246260
}

src/main/java/net/imglib2/algorithm/neighborhood/HyperSphereShape.java

+13
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@
3434

3535
package net.imglib2.algorithm.neighborhood;
3636

37+
import java.util.Arrays;
3738
import java.util.Iterator;
3839

3940
import net.imglib2.AbstractEuclideanSpace;
4041
import net.imglib2.AbstractInterval;
4142
import net.imglib2.Cursor;
43+
import net.imglib2.FinalInterval;
4244
import net.imglib2.FlatIterationOrder;
4345
import net.imglib2.Interval;
4446
import net.imglib2.IterableInterval;
@@ -187,4 +189,15 @@ public RandomAccess< Neighborhood< T >> randomAccess( final Interval interval )
187189
return new HyperSphereNeighborhoodRandomAccess< T >( source, radius, factory, interval );
188190
}
189191
}
192+
193+
@Override
194+
public Interval getStructuringElementBoundingBox(final int numDimensions) {
195+
final long[] min = new long[numDimensions];
196+
Arrays.fill(min, -getRadius());
197+
198+
final long[] max = new long[numDimensions];
199+
Arrays.fill(max, getRadius());
200+
201+
return new FinalInterval(min, max);
202+
}
190203
}

src/main/java/net/imglib2/algorithm/neighborhood/PairOfPointsShape.java

+12
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,20 @@
3333
*/
3434
package net.imglib2.algorithm.neighborhood;
3535

36+
import java.util.Arrays;
3637
import java.util.Iterator;
3738

3839
import net.imglib2.AbstractEuclideanSpace;
3940
import net.imglib2.AbstractInterval;
4041
import net.imglib2.Cursor;
42+
import net.imglib2.FinalInterval;
4143
import net.imglib2.FlatIterationOrder;
4244
import net.imglib2.Interval;
4345
import net.imglib2.IterableInterval;
4446
import net.imglib2.RandomAccess;
4547
import net.imglib2.RandomAccessible;
4648
import net.imglib2.RandomAccessibleInterval;
49+
import net.imglib2.util.Intervals;
4750
import net.imglib2.util.Util;
4851

4952
/**
@@ -201,4 +204,13 @@ public int numDimensions()
201204
}
202205
}
203206

207+
@Override
208+
public Interval getStructuringElementBoundingBox(final int numDimensions) {
209+
final long[] zeroMin = new long[numDimensions];
210+
Arrays.fill(zeroMin, 0);
211+
212+
return Intervals.union(new FinalInterval(zeroMin, zeroMin),
213+
new FinalInterval(offset, offset));
214+
}
215+
204216
}

src/main/java/net/imglib2/algorithm/neighborhood/PeriodicLineShape.java

+15
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@
3838
import net.imglib2.AbstractEuclideanSpace;
3939
import net.imglib2.AbstractInterval;
4040
import net.imglib2.Cursor;
41+
import net.imglib2.FinalInterval;
4142
import net.imglib2.FlatIterationOrder;
4243
import net.imglib2.Interval;
4344
import net.imglib2.IterableInterval;
4445
import net.imglib2.RandomAccess;
4546
import net.imglib2.RandomAccessible;
4647
import net.imglib2.RandomAccessibleInterval;
48+
import net.imglib2.util.Intervals;
4749
import net.imglib2.util.Util;
4850

4951
/**
@@ -243,4 +245,17 @@ public int numDimensions()
243245
}
244246
}
245247

248+
@Override
249+
public Interval getStructuringElementBoundingBox(final int numDimensions) {
250+
final long[] a = new long[numDimensions];
251+
final long[] b = new long[numDimensions];
252+
253+
for (int i = 0; i < numDimensions; ++i) {
254+
a[i] = increments[i] * -getSpan();
255+
b[i] = increments[i] * getSpan();
256+
}
257+
258+
return Intervals.union(new FinalInterval(a, a), new FinalInterval(b, b));
259+
}
260+
246261
}

src/main/java/net/imglib2/algorithm/neighborhood/RectangleShape.java

+13
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
package net.imglib2.algorithm.neighborhood;
3636

37+
import java.util.Arrays;
3738
import java.util.Iterator;
3839

3940
import net.imglib2.AbstractEuclideanSpace;
@@ -224,4 +225,16 @@ public RandomAccess< Neighborhood< T >> randomAccess( final Interval interval )
224225
return new RectangleNeighborhoodRandomAccess< T >( source, span, factory, interval );
225226
}
226227
}
228+
229+
@Override
230+
public Interval getStructuringElementBoundingBox( final int numDimensions )
231+
{
232+
final long[] min = new long[ numDimensions ];
233+
Arrays.fill( min, -getSpan() );
234+
235+
final long[] max = new long[ numDimensions ];
236+
Arrays.fill( max, getSpan() );
237+
238+
return new FinalInterval( min, max );
239+
}
227240
}

src/main/java/net/imglib2/algorithm/neighborhood/Shape.java

+45
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,17 @@
3434

3535
package net.imglib2.algorithm.neighborhood;
3636

37+
import java.util.stream.LongStream;
38+
3739
import net.imglib2.Cursor;
40+
import net.imglib2.FinalInterval;
41+
import net.imglib2.Interval;
3842
import net.imglib2.IterableInterval;
3943
import net.imglib2.RandomAccess;
4044
import net.imglib2.RandomAccessible;
4145
import net.imglib2.RandomAccessibleInterval;
4246
import net.imglib2.Sampler;
47+
import net.imglib2.util.ConstantUtils;
4348

4449
/**
4550
* A factory for Accessibles on {@link Neighborhood Neighborhoods}.
@@ -48,6 +53,46 @@
4853
*/
4954
public interface Shape
5055
{
56+
57+
/**
58+
* Get the bounding box for a {@link Shape} with {@code numDimensions}
59+
* dimensions.
60+
* <p>
61+
* Providing {@code numDimensions} is required since the input from which
62+
* {@link Neighborhood neighborhoods} are generated is not known yet. The
63+
* bounding box is described by an {@link Interval} with the center of the
64+
* bounding box located at zero.
65+
* </p>
66+
* <p>
67+
* The values of this bounding box should only be used to determine the extent
68+
* of the {@link Shape}, ignoring the absolute {@link Interval#min(int) min}
69+
* and {@link Interval#max(int) max} values.
70+
* </p>
71+
*
72+
* @param numDimensions dimensions of the {@link Shape}
73+
* @return an {@link Interval} that describes the bounding box of a
74+
* {@link Shape}
75+
*/
76+
public default Interval getStructuringElementBoundingBox( final int numDimensions )
77+
{
78+
final RandomAccessible< Object > accessible = ConstantUtils.constantRandomAccessible( null, numDimensions );
79+
final RandomAccess< Neighborhood< Object > > access = neighborhoodsRandomAccessible( accessible ).randomAccess();
80+
access.setPosition( new long[ numDimensions ] );
81+
final long[] min = LongStream.generate( () -> Long.MAX_VALUE ).limit( numDimensions ).toArray();
82+
final long[] max = LongStream.generate( () -> Long.MIN_VALUE ).limit( numDimensions ).toArray();
83+
for ( final Cursor< Object > cursor = access.get().localizingCursor(); cursor.hasNext(); )
84+
{
85+
cursor.fwd();
86+
for ( int d = 0; d < numDimensions; ++d )
87+
{
88+
final long pos = cursor.getLongPosition( d );
89+
min[ d ] = Math.min( pos, min[ d ] );
90+
max[ d ] = Math.max( pos, max[ d ] );
91+
}
92+
}
93+
return new FinalInterval( min, max );
94+
}
95+
5196
/**
5297
* Get an {@link IterableInterval} that contains all {@link Neighborhood
5398
* Neighborhoods} of the source image.

src/test/java/net/imglib2/algorithm/neighborhood/CenteredRectangleShapeTest.java

+15
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,15 @@
3333
*/
3434
package net.imglib2.algorithm.neighborhood;
3535

36+
import static org.junit.Assert.assertTrue;
37+
38+
import net.imglib2.FinalInterval;
39+
import net.imglib2.Interval;
3640
import net.imglib2.algorithm.neighborhood.CenteredRectangleShape;
3741
import net.imglib2.algorithm.neighborhood.Shape;
42+
import net.imglib2.util.Intervals;
43+
44+
import org.junit.Test;
3845

3946
public class CenteredRectangleShapeTest extends AbstractShapeTest
4047
{
@@ -57,4 +64,12 @@ protected boolean isInside( final long[] pos, final long[] center )
5764
return true;
5865

5966
}
67+
68+
@Test
69+
public void testStructuringElementBoundingBox() {
70+
Interval boundingBox = shape.getStructuringElementBoundingBox(img
71+
.numDimensions());
72+
assertTrue(Intervals.equals(boundingBox, new FinalInterval(new long[] { -2,
73+
-3, -1 }, new long[] { 2, 3, 1 })));
74+
}
6075
}

src/test/java/net/imglib2/algorithm/neighborhood/DiamondShapeTest.java

+14
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,15 @@
3333
*/
3434
package net.imglib2.algorithm.neighborhood;
3535

36+
import static org.junit.Assert.assertTrue;
37+
38+
import net.imglib2.FinalInterval;
39+
import net.imglib2.Interval;
3640
import net.imglib2.algorithm.neighborhood.DiamondShape;
3741
import net.imglib2.algorithm.neighborhood.Shape;
42+
import net.imglib2.util.Intervals;
43+
44+
import org.junit.Test;
3845

3946
public class DiamondShapeTest extends AbstractShapeTest
4047
{
@@ -58,4 +65,11 @@ protected boolean isInside( final long[] pos, final long[] center )
5865
return cityblock <= RADIUS;
5966
}
6067

68+
@Test
69+
public void testStructuringElementBoundingBox() {
70+
Interval boundingBox = shape.getStructuringElementBoundingBox(img
71+
.numDimensions());
72+
assertTrue(Intervals.equals(boundingBox, new FinalInterval(new long[] { -3,
73+
-3, -3 }, new long[] { 3, 3, 3 })));
74+
}
6175
}

src/test/java/net/imglib2/algorithm/neighborhood/DiamondTipsShapeTest.java

+15
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,15 @@
3333
*/
3434
package net.imglib2.algorithm.neighborhood;
3535

36+
import static org.junit.Assert.assertTrue;
37+
38+
import net.imglib2.FinalInterval;
39+
import net.imglib2.Interval;
3640
import net.imglib2.algorithm.neighborhood.DiamondTipsShape;
3741
import net.imglib2.algorithm.neighborhood.Shape;
42+
import net.imglib2.util.Intervals;
43+
44+
import org.junit.Test;
3845

3946
public class DiamondTipsShapeTest extends AbstractShapeTest
4047
{
@@ -72,4 +79,12 @@ protected boolean isInside( final long[] pos, final long[] center )
7279
}
7380
return false;
7481
}
82+
83+
@Test
84+
public void testStructuringElementBoundingBox() {
85+
Interval boundingBox = shape.getStructuringElementBoundingBox(img
86+
.numDimensions());
87+
assertTrue(Intervals.equals(boundingBox, new FinalInterval(new long[] { -3,
88+
-3, -3 }, new long[] { 3, 3, 3 })));
89+
}
7590
}

0 commit comments

Comments
 (0)