Skip to content

Commit 8e9047e

Browse files
committed
1 parent 741ea2b commit 8e9047e

File tree

4 files changed

+201
-0
lines changed

4 files changed

+201
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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.realTransform;
31+
32+
import net.imglib2.FinalInterval;
33+
import net.imglib2.Interval;
34+
import net.imglib2.RandomAccessible;
35+
import net.imglib2.RandomAccessibleInterval;
36+
import net.imglib2.interpolation.InterpolatorFactory;
37+
import net.imglib2.interpolation.randomaccess.LanczosInterpolatorFactory;
38+
import net.imglib2.realtransform.InvertibleRealTransform;
39+
import net.imglib2.realtransform.RealViews;
40+
import net.imglib2.type.numeric.NumericType;
41+
import net.imglib2.type.numeric.RealType;
42+
import net.imglib2.view.IntervalView;
43+
import net.imglib2.view.Views;
44+
45+
import org.scijava.Priority;
46+
import org.scijava.ops.core.Op;
47+
import org.scijava.ops.function.Functions;
48+
import org.scijava.param.Parameter;
49+
import org.scijava.plugin.Plugin;
50+
import org.scijava.struct.ItemIO;
51+
52+
/**
53+
* Applies an Affine transform to a {@link RandomAccessibleInterval}
54+
*
55+
* @author Brian Northan (True North Intelligent Algorithms)
56+
* @author Martin Horn (University of Konstanz)
57+
* @author Stefan Helfrich (University of Konstanz)
58+
*/
59+
@Plugin(type = Op.class, name = "transform.realTransform",
60+
priority = Priority.HIGH + 1)
61+
@Parameter(key = "input")
62+
@Parameter(key = "transform")
63+
@Parameter(key = "outputInterval")
64+
@Parameter(key = "interpolator")
65+
@Parameter(key = "output", itemIO = ItemIO.OUTPUT)
66+
public class DefaultTransformView<T extends NumericType<T> & RealType<T>>
67+
implements
68+
Functions.Arity4<RandomAccessibleInterval<T>, InvertibleRealTransform, Interval, InterpolatorFactory<T, RandomAccessible<T>>, RandomAccessibleInterval<T>>
69+
{
70+
71+
/**
72+
* TODO: declare {@code outputInterval}, {@code interpolator} as optional once
73+
* <a href=https://github.com/scijava/incubator/pull/32>this issue</a> has
74+
* been resolved. Until then, this op <b>must</b> be called as a
75+
* {@link org.scijava.ops.function.Functions.Arity4}
76+
*
77+
* @param input the input
78+
* @param transform the transform to apply
79+
* @param outputInterval the output interval
80+
* @param interpolator the {@link InterpolatorFactory} delegated to for
81+
* interpolation
82+
* @return the output
83+
*/
84+
@Override
85+
public RandomAccessibleInterval<T> apply(RandomAccessibleInterval<T> input,
86+
InvertibleRealTransform transform, Interval outputInterval,
87+
InterpolatorFactory<T, RandomAccessible<T>> interpolator)
88+
{
89+
if (outputInterval == null) {
90+
outputInterval = new FinalInterval(input);
91+
}
92+
93+
if (interpolator == null) {
94+
interpolator = new LanczosInterpolatorFactory<>();
95+
}
96+
97+
final IntervalView<T> interval = Views.interval(Views.raster(RealViews
98+
.transformReal(Views.interpolate(Views.extendZero(input), interpolator),
99+
transform)), outputInterval);
100+
101+
return interval;
102+
}
103+
104+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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.Assert.assertEquals;
31+
32+
import net.imagej.ops2.AbstractOpTest;
33+
import net.imglib2.Cursor;
34+
import net.imglib2.Interval;
35+
import net.imglib2.RandomAccess;
36+
import net.imglib2.RandomAccessible;
37+
import net.imglib2.RandomAccessibleInterval;
38+
import net.imglib2.img.Img;
39+
import net.imglib2.interpolation.InterpolatorFactory;
40+
import net.imglib2.realtransform.AffineTransform2D;
41+
import net.imglib2.realtransform.InvertibleRealTransform;
42+
import net.imglib2.type.numeric.integer.UnsignedByteType;
43+
import net.imglib2.view.Views;
44+
45+
import org.junit.jupiter.api.Test;
46+
47+
import org.scijava.ops.function.Functions;
48+
import org.scijava.types.Nil;
49+
50+
public class RealTransformTest extends AbstractOpTest {
51+
52+
@Test
53+
public void regressionTest() throws Exception {
54+
55+
final Img<UnsignedByteType> image = openUnsignedByteType(getClass(),
56+
"lowresbridge.tif");
57+
final Img<UnsignedByteType> expectedOutput = openUnsignedByteType(
58+
getClass(), "rotatedscaledcenter.tif");
59+
60+
final AffineTransform2D transform = new AffineTransform2D();
61+
62+
transform.translate(-image.dimension(0) / 2, -image.dimension(0) / 2);
63+
transform.rotate(1);
64+
transform.scale(0.5);
65+
transform.translate(image.dimension(0) / 2, image.dimension(0) / 2);
66+
67+
// TODO: make the op call simpler once incubator PR 32 has been merged
68+
Nil<RandomAccessibleInterval<UnsignedByteType>> imgNil = new Nil<>() {};
69+
Nil<InvertibleRealTransform> transformNil = Nil.of(
70+
InvertibleRealTransform.class);
71+
Nil<Interval> intervalNil = Nil.of(Interval.class);
72+
Nil<InterpolatorFactory<UnsignedByteType, RandomAccessible<UnsignedByteType>>> factoryNil =
73+
new Nil<>()
74+
{};
75+
final Functions.Arity4<RandomAccessibleInterval<UnsignedByteType>, InvertibleRealTransform, Interval, InterpolatorFactory<UnsignedByteType, RandomAccessible<UnsignedByteType>>, RandomAccessibleInterval<UnsignedByteType>> f =
76+
ops.op("transform.realTransform").inType(imgNil, transformNil,
77+
intervalNil, factoryNil).outType(imgNil).function();
78+
final RandomAccessibleInterval<UnsignedByteType> actualOutput = f.apply(
79+
image, transform, null, null);
80+
81+
// compare the output image data to that stored in the file.
82+
final Cursor<UnsignedByteType> cursor = Views.iterable(actualOutput)
83+
.localizingCursor();
84+
final RandomAccess<UnsignedByteType> actualRA = actualOutput.randomAccess();
85+
final RandomAccess<UnsignedByteType> expectedRA = expectedOutput
86+
.randomAccess();
87+
88+
while (cursor.hasNext()) {
89+
cursor.fwd();
90+
actualRA.setPosition(cursor);
91+
expectedRA.setPosition(cursor);
92+
assertEquals(expectedRA.get().get(), actualRA.get().get(), 0);
93+
}
94+
95+
}
96+
97+
}

0 commit comments

Comments
 (0)