Skip to content

Commit 67a5c21

Browse files
committed
WIP Lucas Kanade registration
1 parent c56e709 commit 67a5c21

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*-
2+
* #%L
3+
* Image processing operations for SciJava Ops.
4+
* %%
5+
* Copyright (C) 2014 - 2025 SciJava 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 org.scijava.ops.image.registration;
31+
32+
import net.imglib2.RandomAccessibleInterval;
33+
import net.imglib2.type.numeric.RealType;
34+
35+
import org.scijava.function.Computers;
36+
import org.scijava.ops.spi.Nullable;
37+
import org.scijava.ops.spi.OpDependency;
38+
39+
import java.util.ArrayList;
40+
import java.util.function.BiFunction;
41+
42+
/**
43+
* @author Edward Evans
44+
* @param <I> input type
45+
* @param <O> output type
46+
* @implNote op names='registration.lucasKanade', priority='100.'
47+
*/
48+
49+
// TODO: write missing scaleView op
50+
// TODO: export 'u' and 'v' optical flow array, can be used for segmentation
51+
// TODO: consider making this Op a function and not a computer?
52+
53+
public class LucasKanadeRegistration<I extends RealType<I>> implements
54+
Computers.Arity7<RandomAccessibleInterval<I>, Integer, Integer, Float, Float, Boolean, Boolean, RandomAccessibeInteger<O>>
55+
{
56+
@OpDependency(name = "transform.scaleView")
57+
private BiFunction<RandomAccessibleInterval<I>, double[], RandomAccessibleInterval<I>> scaleOp;
58+
59+
/**
60+
* Lucas-Kanade image registration. This Op utilizes Lucas-Kanade's method of
61+
* optical flow to register an image stack.
62+
*
63+
* @param image input 3D (X, Y, Time) image
64+
* @param pyramidLevel maximum pyramid level to use
65+
* @param iterations number of iterations to perform
66+
* @param updateCoefficient template update coefficient
67+
* @param errorTolerance error tolerance
68+
* @param useAffine use the affine method, if false use transform
69+
* @param logTransform boolean to set log transform
70+
* @param output the output image
71+
*/
72+
73+
@Override
74+
public void compute(final RandomAccessibleInterval<I> image,
75+
final Integer pyramidLevel, final Integer iterations,
76+
final Float updateCoefficient, final Float errorTolerance,
77+
final Boolean useAfffine, final Boolean logTransform,
78+
RandomAccessibleInterval<O> output)
79+
{
80+
// ensure images are 3D only
81+
if (!(image.numDimensions() == 3)) {
82+
throw new IllegalArgumentException(
83+
"Input image must be 3D (X, Y, Time).");
84+
85+
// construct pyramid
86+
long[] dims = image.dimensionsAsLongArray()
87+
var pyramid = createScalePyramid(pyramidLevel, dims)
88+
}
89+
}
90+
91+
/**
92+
* Creates a scale pyramid with the specified level.
93+
*
94+
* @param image input image
95+
* @param level number of pyramid levels to create
96+
* @param shape shape of the input image
97+
* @return the scale pyramid as a list
98+
*/
99+
private ArrayList<RandomAccessibleInterval<I>> createScalePyramid(final RandomAccessibleInterval<I> image,
100+
final Integer level, final long[] shape)
101+
{
102+
var pyramid = new ArrayList<RandomAccessibleInterval<I>>();
103+
double divFactor = 2.0;
104+
double[] scaleFactors = {0.0, 0.0, 1.0};
105+
for (int i = 0; i < level; i++;) {
106+
// compute scale factor, only scale X and Y
107+
scaleFactors[0] = 1.0 / divFactor;
108+
scaleFactors[1] = 1.0 / divFactor;
109+
// scale image and add to the pyramid
110+
pyramid.add(scaleOp.apply(image, scaleFactors));
111+
// increment division scale factor
112+
divFactor *= 2;
113+
114+
return pyramid
115+
}
116+
}

0 commit comments

Comments
 (0)