Skip to content

Commit 106b628

Browse files
authored
Merge pull request #36 from scijava/imagej/imagej-ops2/real-transform
RealTransform
2 parents f1fa478 + 8be030c commit 106b628

File tree

6 files changed

+181
-1
lines changed

6 files changed

+181
-1
lines changed

imagej/imagej-ops2/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
requires ojalgo;
168168
requires jama;
169169
requires mines.jtk;
170+
requires net.imglib2.realtransform;
170171

171172
provides org.scijava.types.TypeExtractor with
172173
net.imagej.ops2.types.ImgFactoryTypeExtractor,
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* #%L
3+
* ImageJ software for multidimensional image processing and analysis.
4+
* %%
5+
* Copyright (C) 2014 - 2018 ImageJ developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
30+
package net.imagej.ops2.transform;
31+
32+
import org.scijava.function.Functions;
33+
import org.scijava.ops.spi.Optional;
34+
35+
import net.imglib2.FinalInterval;
36+
import net.imglib2.Interval;
37+
import net.imglib2.RandomAccessible;
38+
import net.imglib2.RandomAccessibleInterval;
39+
import net.imglib2.interpolation.InterpolatorFactory;
40+
import net.imglib2.interpolation.randomaccess.LanczosInterpolatorFactory;
41+
import net.imglib2.realtransform.InvertibleRealTransform;
42+
import net.imglib2.realtransform.RealViews;
43+
import net.imglib2.type.numeric.NumericType;
44+
import net.imglib2.type.numeric.RealType;
45+
import net.imglib2.view.Views;
46+
47+
/**
48+
* Applies an Affine transform to a {@link RandomAccessibleInterval}
49+
*
50+
* @author Brian Northan (True North Intelligent Algorithms)
51+
* @author Martin Horn (University of Konstanz)
52+
* @author Stefan Helfrich (University of Konstanz)
53+
* @implNote op names="transform.realTransform", priority="101.0"
54+
*/
55+
public class DefaultTransformView<T extends NumericType<T> & RealType<T>>
56+
implements
57+
Functions.Arity4<RandomAccessibleInterval<T>, InvertibleRealTransform, Interval, InterpolatorFactory<T, RandomAccessible<T>>, RandomAccessibleInterval<T>>
58+
{
59+
60+
/**
61+
* TODO: declare {@code outputInterval}, {@code interpolator} as optional once
62+
* <a href=https://github.com/scijava/incubator/pull/32>this issue</a> has
63+
* been resolved. Until then, this op <b>must</b> be called as a
64+
* {@link Functions.Arity4}
65+
*
66+
* @param input the input
67+
* @param transform the transform to apply
68+
* @param outputInterval the output interval
69+
* @param interpolator the {@link InterpolatorFactory} delegated to for
70+
* interpolation
71+
* @return the output
72+
*/
73+
@Override
74+
public RandomAccessibleInterval<T> apply( //
75+
RandomAccessibleInterval<T> input, //
76+
InvertibleRealTransform transform, //
77+
@Optional Interval outputInterval, //
78+
@Optional InterpolatorFactory<T, RandomAccessible<T>> interpolator //
79+
) {
80+
if (outputInterval == null) {
81+
outputInterval = new FinalInterval(input);
82+
}
83+
84+
if (interpolator == null) {
85+
interpolator = new LanczosInterpolatorFactory<>();
86+
}
87+
88+
var extended = Views.extendZero(input);
89+
var interpolated = Views.interpolate(extended, interpolator);
90+
var transformed = RealViews.transformReal(interpolated, transform);
91+
var rasterized = Views.raster(transformed);
92+
return Views.interval(rasterized, outputInterval);
93+
}
94+
95+
}

imagej/imagej-ops2/src/test/java/net/imagej/ops2/OpRegressionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class OpRegressionTest extends AbstractOpTest {
3939

4040
@Test
4141
public void opDiscoveryRegressionIT() {
42-
long expected = 1457;
42+
long expected = 1460;
4343
long actual = StreamSupport.stream(ops.infos().spliterator(), false).count();
4444
assertEquals(expected, actual);
4545
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*-
2+
* #%L
3+
* ImageJ software for multidimensional image processing and analysis.
4+
* %%
5+
* Copyright (C) 2014 - 2018 ImageJ developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
modification, are permitted provided that the following conditions are met:
9+
1. Redistributions of source code must retain the above copyright notice,
10+
this list of conditions and the following disclaimer.
11+
2. Redistributions in binary form must reproduce the above copyright notice,
12+
this list of conditions and the following disclaimer in the documentation
13+
and/or other materials provided with the distribution.
14+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
18+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24+
POSSIBILITY OF SUCH DAMAGE.
25+
* #L%
26+
*/
27+
28+
package net.imagej.ops2.transform.realTransform;
29+
30+
import static org.junit.jupiter.api.Assertions.assertEquals;
31+
32+
import org.junit.jupiter.api.Test;
33+
import org.scijava.types.Nil;
34+
35+
import net.imagej.ops2.AbstractOpTest;
36+
import net.imglib2.Cursor;
37+
import net.imglib2.RandomAccess;
38+
import net.imglib2.RandomAccessibleInterval;
39+
import net.imglib2.img.Img;
40+
import net.imglib2.realtransform.AffineTransform2D;
41+
import net.imglib2.type.numeric.integer.UnsignedByteType;
42+
import net.imglib2.view.Views;
43+
44+
public class RealTransformTest extends AbstractOpTest {
45+
46+
@Test
47+
public void regressionTest() {
48+
49+
final Img<UnsignedByteType> image = openRelativeUnsignedByteImg(getClass(),
50+
"lowresbridge.tif");
51+
final Img<UnsignedByteType> expectedOutput = openRelativeUnsignedByteImg(
52+
getClass(), "rotatedscaledcenter.tif");
53+
54+
final AffineTransform2D transform = new AffineTransform2D();
55+
56+
double translation = ((double) image.dimension(0) / 2);
57+
transform.translate(-translation, -translation);
58+
transform.rotate(1);
59+
transform.scale(0.5);
60+
transform.translate(translation, translation);
61+
62+
var outType = new Nil<RandomAccessibleInterval<UnsignedByteType>>() {};
63+
var actualOutput = ops.op("transform.realTransform").arity2() //
64+
.input(image, transform) //
65+
.outType(outType) //
66+
.apply();
67+
68+
// compare the output image data to that stored in the file.
69+
final Cursor<UnsignedByteType> cursor = Views.iterable(actualOutput)
70+
.localizingCursor();
71+
final RandomAccess<UnsignedByteType> actualRA = actualOutput.randomAccess();
72+
final RandomAccess<UnsignedByteType> expectedRA = expectedOutput
73+
.randomAccess();
74+
75+
while (cursor.hasNext()) {
76+
cursor.fwd();
77+
actualRA.setPosition(cursor);
78+
expectedRA.setPosition(cursor);
79+
assertEquals(expectedRA.get().get(), actualRA.get().get(), 0);
80+
}
81+
82+
}
83+
84+
}
Binary file not shown.

0 commit comments

Comments
 (0)