imglib / imglib2-algorithm

Image processing algorithms for ImgLib2
http://imglib2.net/
Other
22 stars 20 forks source link

feat: add RadialKDTreeInterpolatorFactory #99

Closed bogovicj closed 6 months ago

bogovicj commented 6 months ago

This PR adds an interpolator for KDTrees that takes a custom function of the (squared) radius to produce a RealRandomAccessible. This is code I've used for some years and thought I'd finally push somewhere more common.

// the parameters to build a RadialKDTreeInterpolatorFactory
double maxRadius;
DoubleUnaryOperator squaredRadiusFunction;

RadialKDTreeInterpolatorFactory<FloatType> interp = new RadialKDTreeInterpolatorFactory<>(squaredRadiusFunction, maxRadius, new FloatType());

KDTree tree;
RealRandomAccessible<FloatType> image = Views.interpolate(tree, interp);

The full working demo below produces this output:

Screenshot from 2024-03-08 15-08-58

// generate points
int N = 12; // number of points
final double bigCircleRadius = 10;
final double angleDelta = 2 * Math.PI / N;
final List<RealPoint> pts = DoubleStream.iterate(0.0, x -> x + angleDelta).limit(N).mapToObj(tht -> {
    return new RealPoint(
            bigCircleRadius * Math.cos(tht),
            bigCircleRadius * Math.sin(tht));
}).collect(Collectors.toList());    

// generate values
final FloatType one = new FloatType(1f);
final ArrayList<FloatType> vals = new ArrayList<>();
IntStream.range(0, pts.size()).forEach( x -> { vals.add(one); });

// build a tree
final KDTree<FloatType> tree = new KDTree<>(vals, pts);

// a function of the squared radius for each rendered point
final double value = 2.0;
final double maxRadius = 2.0;
final double maxSqrRadius = maxRadius*maxRadius;
final DoubleUnaryOperator squaredRadiusFunction = r2 -> value * (1 - (r2 / maxSqrRadius));

// create an image from the points and the radial function
final RealRandomAccessible<FloatType> image = Views.interpolate(
        tree, 
        new RadialKDTreeInterpolatorFactory<>(squaredRadiusFunction, maxRadius, new FloatType()));

// show the image
BdvStackSource<FloatType> bdv = BdvFunctions.show( 
        image, 
        Intervals.createMinSize(-20,-20, 40, 40),
        "rendered points",
        BdvOptions.options().is2D());

bdv.setDisplayRange(0, 2);
bogovicj commented 6 months ago

talked to @axtimwalde - this make make more sense in imglib2 core. I'll close this and move it there shortly