Skip to content

Commit 17ccca3

Browse files
committed
Add MapNeighborhoodNativeTypeExtended
This Op provides the same interface as all the other MapNeighborhood Ops and therefore makes the optimized implementation of MapNeighborhood for NativeType (namely `MapNeighborhoodNativeType`) available for implicit optimization of depending algorithms.
1 parent 26df6e3 commit 17ccca3

File tree

5 files changed

+108
-36
lines changed

5 files changed

+108
-36
lines changed

src/main/java/net/imagej/ops/AbstractOpEnvironment.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@
5454
import net.imglib2.IterableInterval;
5555
import net.imglib2.RandomAccessible;
5656
import net.imglib2.RandomAccessibleInterval;
57+
import net.imglib2.algorithm.neighborhood.RectangleShape;
5758
import net.imglib2.algorithm.neighborhood.Shape;
5859
import net.imglib2.img.array.ArrayImg;
60+
import net.imglib2.outofbounds.OutOfBoundsFactory;
5961
import net.imglib2.type.NativeType;
6062
import net.imglib2.type.Type;
6163
import net.imglib2.type.numeric.RealType;
@@ -534,6 +536,32 @@ public <I, O> RandomAccessibleInterval<O> map(
534536
return result;
535537
}
536538

539+
@Override
540+
public <I extends NativeType<I>, O extends NativeType<O>> ArrayImg<O, ?> map(
541+
ArrayImg<O, ?> out, ArrayImg<I, ?> in, ComputerOp<Iterable<I>, O> op,
542+
RectangleShape shape)
543+
{
544+
@SuppressWarnings("unchecked")
545+
final ArrayImg<O, ?> result =
546+
(ArrayImg<O, ?>) run(
547+
net.imagej.ops.map.neighborhood.array.MapNeighborhoodNativeTypeExtended.class,
548+
out, in, op, shape);
549+
return result;
550+
}
551+
552+
@Override
553+
public <I extends NativeType<I>, O extends NativeType<O>> ArrayImg<O, ?> map(
554+
ArrayImg<O, ?> out, ArrayImg<I, ?> in, ComputerOp<Iterable<I>, O> op,
555+
RectangleShape shape, OutOfBoundsFactory<I, ?> oobFactory)
556+
{
557+
@SuppressWarnings("unchecked")
558+
final ArrayImg<O, ?> result =
559+
(ArrayImg<O, ?>) run(
560+
net.imagej.ops.map.neighborhood.array.MapNeighborhoodNativeTypeExtended.class,
561+
out, in, op, shape, oobFactory);
562+
return result;
563+
}
564+
537565
@Override
538566
public <A, B> Iterable<B> map(final Iterable<B> out, final Iterable<A> in,
539567
final ComputerOp<A, B> op)

src/main/java/net/imagej/ops/OpEnvironment.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,22 @@ <I, O> RandomAccessibleInterval<O> map(RandomAccessibleInterval<O> out,
417417
ArrayImg<O, ?> out, ArrayImg<I, ?> in, ComputerOp<Iterable<I>, O> op,
418418
Integer span);
419419

420+
/** Executes the "map" operation on the given arguments. */
421+
@OpMethod(
422+
op = net.imagej.ops.map.neighborhood.array.MapNeighborhoodNativeTypeExtended.class)
423+
public
424+
<I extends NativeType<I>, O extends NativeType<O>> ArrayImg<O, ?> map(
425+
ArrayImg<O, ?> out, ArrayImg<I, ?> in, ComputerOp<Iterable<I>, O> op,
426+
RectangleShape shape);
427+
428+
/** Executes the "map" operation on the given arguments. */
429+
@OpMethod(
430+
op = net.imagej.ops.map.neighborhood.array.MapNeighborhoodNativeTypeExtended.class)
431+
public
432+
<I extends NativeType<I>, O extends NativeType<O>> ArrayImg<O, ?> map(
433+
ArrayImg<O, ?> out, ArrayImg<I, ?> in, ComputerOp<Iterable<I>, O> op,
434+
RectangleShape shape, OutOfBoundsFactory<I, ?> oobFactory);
435+
420436
/** Executes the "map" operation on the given arguments. */
421437
@OpMethod(op = net.imagej.ops.map.MapIterableToIterable.class)
422438
<A, B> Iterable<B> map(Iterable<B> out, Iterable<A> in, ComputerOp<A, B> op);

src/main/java/net/imagej/ops/map/neighborhood/array/MapNeighborhoodNativeType.java

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import net.imagej.ops.Op;
77
import net.imagej.ops.Ops;
88
import net.imagej.ops.map.AbstractMapComputer;
9+
import net.imglib2.IterableInterval;
910
import net.imglib2.img.Img;
1011
import net.imglib2.img.array.ArrayImg;
1112
import net.imglib2.type.NativeType;
@@ -31,29 +32,40 @@
3132
@Plugin(type = Op.class, name = Ops.Map.NAME,
3233
priority = Priority.LOW_PRIORITY + 10)
3334
public class MapNeighborhoodNativeType<I extends NativeType<I>, O extends NativeType<O>>
34-
extends AbstractMapComputer<Iterable<I>, O, ArrayImg<I, ?>, ArrayImg<O, ?>>
35+
extends AbstractMapComputer<Iterable<I>, O, IterableInterval<I>, IterableInterval<O>>
3536
implements Contingent
3637
{
3738

3839
@Parameter
3940
private int span;
40-
41+
4142
@Override
42-
public void compute(final ArrayImg<I, ?> input, final ArrayImg<O, ?> output) {
43+
public void compute(final IterableInterval<I> input, final IterableInterval<O> output) {
4344
final I in = input.firstElement();
4445
final O out = output.firstElement();
4546

4647
final int width = (int) input.dimension(0);
47-
final int height = (int) input.dimension(1);
48-
final int depth = Math.max(0, (int) input.dimension(2));
48+
final int height = (input.numDimensions() > 1) ? (int) input.dimension(1) : 1;
49+
final int depth = (input.numDimensions() > 2) ? (int) input.dimension(2) : 1;
50+
51+
final int minX = (int) input.min(0);
52+
final int minY = (input.numDimensions() > 1) ? (int) input.min(1) : 0;
53+
final int minZ = (input.numDimensions() > 2) ? (int) input.min(2) : 0;
54+
55+
final int maxX = (int) input.max(0);
56+
final int maxY = (input.numDimensions() > 1) ? (int) input.max(1) : 0;
57+
final int maxZ = (input.numDimensions() > 2) ? (int) input.max(2) : 0;
4958

59+
final int skipX = width - (maxX - minX + 1);
60+
final int skipY = height - (maxY - minY + 1);
61+
5062
final ComputerOp<Iterable<I>, O> op = getOp();
5163

52-
int index;
64+
int index = minX + minY * width + minZ * height * width;
5365

54-
for (int z = 0; z < depth; ++z) {
55-
for (int y = 0; y < height; ++y) {
56-
for (int x = 0; x < width; ++x) {
66+
for (int z = minZ; z <= maxZ; ++z) {
67+
for (int y = minY; y <= maxY; ++y) {
68+
for (int x = minX; x <= maxX; ++x) {
5769
// save the current index, since it will be changed by the
5870
// NeighborhoodIterable. Increment to save doing that later.
5971
index = in.getIndex() + 1;
@@ -67,7 +79,11 @@ public void compute(final ArrayImg<I, ?> input, final ArrayImg<O, ?> output) {
6779
in.updateIndex(index);
6880
out.incIndex();
6981
}
82+
in.incIndex(skipX);
83+
out.incIndex(skipX);
7084
}
85+
in.incIndex(skipY);
86+
out.incIndex(skipY);
7187
}
7288
}
7389

src/main/java/net/imagej/ops/map/neighborhood/array/MapNeighborhoodNativeTypeExtended.java

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
import net.imagej.ops.map.AbstractMapComputer;
1212
import net.imagej.ops.map.neighborhood.MapNeighborhood;
1313
import net.imglib2.FinalInterval;
14-
import net.imglib2.algorithm.neighborhood.CenteredRectangleShape;
15-
import net.imglib2.algorithm.neighborhood.Neighborhood;
14+
import net.imglib2.algorithm.neighborhood.RectangleShape;
1615
import net.imglib2.img.array.ArrayImg;
1716
import net.imglib2.outofbounds.OutOfBoundsFactory;
1817
import net.imglib2.type.NativeType;
@@ -54,17 +53,15 @@ public class MapNeighborhoodNativeTypeExtended<I extends NativeType<I>, O extend
5453
protected LogService log;
5554

5655
@Parameter
57-
private CenteredRectangleShape shape;
56+
private RectangleShape shape;
5857

5958
@Parameter(required = false)
6059
private OutOfBoundsFactory<I, I> oobFactory;
6160

6261
@Override
6362
public void compute(final ArrayImg<I, ?> input, final ArrayImg<O, ?> output) {
6463
// all dimensions are equal as ensured in conforms() */
65-
final int span =
66-
(int) ((shape.neighborhoodsRandomAccessible(input).randomAccess().get()
67-
.dimension(0) - 1) / 2);
64+
final int span = shape.getSpan();
6865

6966
final int numDimensions = input.numDimensions();
7067

@@ -93,7 +90,7 @@ public void compute(final ArrayImg<I, ?> input, final ArrayImg<O, ?> output) {
9390
/* left */
9491
new FinalInterval(new long[] { 0 }, new long[] { span }),
9592
/* right */
96-
new FinalInterval(new long[] { dim0 - span }, new long[] { span }) };
93+
new FinalInterval(new long[] { dim0 - span }, new long[] { dim0 - 1 }) };
9794
/* center */
9895
center = new FinalInterval(new long[] { span + 1 }, new long[] { max0 });
9996
}
@@ -121,7 +118,7 @@ else if (numDimensions == 2) {
121118
max1 });
122119
}
123120
else {
124-
// numDimensions == 3, guranteed by conforms()
121+
// numDimensions == 3, guaranteed by conforms()
125122

126123
final long dim1 = input.dimension(1);
127124
final long dim2 = input.dimension(2);
@@ -165,10 +162,17 @@ else if (numDimensions == 2) {
165162

166163
@Override
167164
public void run() {
168-
ops.run(MapNeighborhood.class, Views.interval(output, interval),
169-
Views.interval(input, interval), getOp(), shape, oobFactory);
165+
if (oobFactory == null) {
166+
ops.run(MapNeighborhood.class, Views.interval(output, interval), Views
167+
.interval(input, interval), getOp(), shape);
168+
}
169+
else {
170+
ops.run(MapNeighborhood.class, Views.interval(output, interval), Views
171+
.interval(input, interval), getOp(), shape, oobFactory);
172+
}
170173
}
171174
}));
175+
172176
}
173177

174178
final FinalInterval finalCenter = center;
@@ -199,23 +203,8 @@ public void run() {
199203

200204
@Override
201205
public boolean conforms() {
202-
if (!(getInput().numDimensions() > 0 || getInput().numDimensions() <= 3)) {
203-
return false;
204-
}
205-
206-
/* all dimensions of the neighborhood have to be equal to be able to use
207-
MapNeighborhoodNativeType */
208-
Neighborhood<I> neighborhood =
209-
shape.neighborhoodsRandomAccessible(getInput()).randomAccess().get();
210-
final long dimension0 = neighborhood.dimension(0);
211-
212-
for (int i = 1; i < neighborhood.numDimensions(); ++i) {
213-
if (dimension0 != neighborhood.dimension(i)) {
214-
return false;
215-
}
216-
}
217-
218-
return true;
206+
return getInput().numDimensions() > 0 && getInput().numDimensions() <= 3 &&
207+
!shape.isSkippingCenter();
219208
}
220209

221210
// --- Cancelable methods ---

src/test/java/net/imagej/ops/map/neighborhood/MapNeighborhoodTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import net.imagej.ops.AbstractOpTest;
88
import net.imagej.ops.Op;
99
import net.imagej.ops.map.neighborhood.array.MapNeighborhoodNativeType;
10+
import net.imagej.ops.map.neighborhood.array.MapNeighborhoodNativeTypeExtended;
1011
import net.imagej.ops.map.neighborhood.array.MapNeighborhoodWithCenterNativeType;
1112
import net.imglib2.algorithm.neighborhood.RectangleShape;
1213
import net.imglib2.img.Img;
@@ -135,6 +136,28 @@ public void testMapNeighborhoodsArrayImage1D() {
135136
assertEquals("Index " + index + ": ", expected[index++], t.get());
136137
}
137138
}
139+
140+
/**
141+
* TODO
142+
*
143+
* @see MapNeighborhoodNativeTypeExtended
144+
*/
145+
@Test
146+
public void testMapNeighborhoodsArrayImageAlias() {
147+
in = generateByteTestImg(true, 7);
148+
out = generateByteTestImg(false, 7);
149+
150+
final Op functional =
151+
ops.op(MapNeighborhoodNativeTypeExtended.class, out, in,
152+
new CountNeighbors(), new RectangleShape(1, false));
153+
functional.run();
154+
155+
int index = 0;
156+
for (ByteType t : out) {
157+
assertEquals("Index " + index, 3, t.get());
158+
index ++;
159+
}
160+
}
138161

139162
/**
140163
* Test if every neighborhood pixel of the 3D image was really accessed during

0 commit comments

Comments
 (0)