Search in sources :

Example 1 with RandomAccessible

use of net.imglib2.RandomAccessible in project imagej-ops by imagej.

the class AbstractThin method compute.

@Override
public void compute(final RandomAccessibleInterval<BitType> input, final RandomAccessibleInterval<BitType> output) {
    // Create a new image as a buffer to store the thinning image in each
    // iteration.
    // This image and output are swapped each iteration since we need to work on
    // the image
    // without changing it.
    final Img<BitType> buffer = ops().create().img(input, new BitType());
    final IterableInterval<BitType> it1 = Views.iterable(buffer);
    final IterableInterval<BitType> it2 = Views.iterable(output);
    // Extend the buffer in order to be able to iterate care-free later.
    final RandomAccessible<BitType> ra1 = Views.extendBorder(buffer);
    final RandomAccessible<BitType> ra2 = Views.extendBorder(output);
    // Used only in first iteration.
    RandomAccessible<BitType> currRa = Views.extendBorder(input);
    // Create cursors.
    final Cursor<BitType> firstCursor = it1.localizingCursor();
    Cursor<BitType> currentCursor = Views.iterable(input).localizingCursor();
    final Cursor<BitType> secondCursor = it2.localizingCursor();
    // Create pointers to the current and next cursor and set them to Buffer and
    // output respectively.
    Cursor<BitType> nextCursor;
    nextCursor = secondCursor;
    // The main loop.
    boolean changes = true;
    int i = 0;
    // Until no more changes, do:
    while (changes) {
        changes = false;
        // defined by the strategies).
        for (int j = 0; j < m_strategy.getIterationsPerCycle(); ++j) {
            // For each pixel in the image.
            while (currentCursor.hasNext()) {
                // Move both cursors
                currentCursor.fwd();
                nextCursor.fwd();
                // Get the position of the current cursor.
                final long[] coordinates = new long[currentCursor.numDimensions()];
                currentCursor.localize(coordinates);
                // Copy the value of the image currently operated upon.
                final boolean curr = currentCursor.get().get();
                nextCursor.get().set(curr);
                // Only foreground pixels may be thinned
                if (curr) {
                    // Ask the strategy whether to flip the foreground pixel or not.
                    final boolean flip = m_strategy.removePixel(coordinates, currRa, j);
                    // If yes - change and keep track of the change.
                    if (flip) {
                        nextCursor.get().set(false);
                        changes = true;
                    }
                }
            }
            // One step of the cycle is finished, notify the strategy.
            m_strategy.afterCycle();
            // Reset the cursors to the beginning and assign pointers for the next
            // iteration.
            currentCursor.reset();
            nextCursor.reset();
            // Keep track of the most recent image. Needed for output.
            if (currRa == ra2) {
                currRa = ra1;
                currentCursor = firstCursor;
                nextCursor = secondCursor;
            } else {
                currRa = ra2;
                currentCursor = secondCursor;
                nextCursor = firstCursor;
            }
            // Keep track of iterations.
            ++i;
        }
    }
    // ra2. Copy it to output.
    if (i % 2 == 0) {
        // Ra1 points to img1, ra2 points to output.
        copy(buffer, output);
    }
}
Also used : BitType(net.imglib2.type.logic.BitType)

Example 2 with RandomAccessible

use of net.imglib2.RandomAccessible in project imagej-ops by imagej.

the class HistogramOfOrientedGradients2D method compute.

@SuppressWarnings("unchecked")
@Override
public void compute(RandomAccessibleInterval<T> in, RandomAccessibleInterval<T> out) {
    final RandomAccessible<FloatType> convertedIn = Converters.convert(Views.extendMirrorDouble(in), converterToFloat, new FloatType());
    // compute partial derivative for each dimension
    RandomAccessibleInterval<FloatType> derivative0 = createImgOp.calculate();
    RandomAccessibleInterval<FloatType> derivative1 = createImgOp.calculate();
    // case of grayscale image
    if (in.numDimensions() == 2) {
        PartialDerivative.gradientCentralDifference(convertedIn, derivative0, 0);
        PartialDerivative.gradientCentralDifference(convertedIn, derivative1, 1);
    } else // case of color image
    {
        List<RandomAccessibleInterval<FloatType>> listDerivs0 = new ArrayList<>();
        List<RandomAccessibleInterval<FloatType>> listDerivs1 = new ArrayList<>();
        for (int i = 0; i < in.dimension(2); i++) {
            final RandomAccessibleInterval<FloatType> deriv0 = createImgOp.calculate();
            final RandomAccessibleInterval<FloatType> deriv1 = createImgOp.calculate();
            PartialDerivative.gradientCentralDifference(Views.interval(convertedIn, new long[] { 0, 0, i }, new long[] { in.max(0), in.max(1), i }), deriv0, 0);
            PartialDerivative.gradientCentralDifference(Views.interval(convertedIn, new long[] { 0, 0, i }, new long[] { in.max(0), in.max(1), i }), deriv1, 1);
            listDerivs0.add(deriv0);
            listDerivs1.add(deriv1);
        }
        derivative0 = Converters.convert(Views.collapse(Views.stack(listDerivs0)), converterGetMax, new FloatType());
        derivative1 = Converters.convert(Views.collapse(Views.stack(listDerivs1)), converterGetMax, new FloatType());
    }
    final RandomAccessibleInterval<FloatType> finalderivative0 = derivative0;
    final RandomAccessibleInterval<FloatType> finalderivative1 = derivative1;
    // compute angles and magnitudes
    final RandomAccessibleInterval<FloatType> angles = createImgOp.calculate();
    final RandomAccessibleInterval<FloatType> magnitudes = createImgOp.calculate();
    final CursorBasedChunk chunkable = new CursorBasedChunk() {

        @Override
        public void execute(int startIndex, int stepSize, int numSteps) {
            final Cursor<FloatType> cursorAngles = Views.flatIterable(angles).localizingCursor();
            final Cursor<FloatType> cursorMagnitudes = Views.flatIterable(magnitudes).localizingCursor();
            final Cursor<FloatType> cursorDerivative0 = Views.flatIterable(finalderivative0).localizingCursor();
            final Cursor<FloatType> cursorDerivative1 = Views.flatIterable(finalderivative1).localizingCursor();
            setToStart(cursorAngles, startIndex);
            setToStart(cursorMagnitudes, startIndex);
            setToStart(cursorDerivative0, startIndex);
            setToStart(cursorDerivative1, startIndex);
            for (int i = 0; i < numSteps; i++) {
                final float x = cursorDerivative0.get().getRealFloat();
                final float y = cursorDerivative1.get().getRealFloat();
                cursorAngles.get().setReal(getAngle(x, y));
                cursorMagnitudes.get().setReal(getMagnitude(x, y));
                cursorAngles.jumpFwd(stepSize);
                cursorMagnitudes.jumpFwd(stepSize);
                cursorDerivative0.jumpFwd(stepSize);
                cursorDerivative1.jumpFwd(stepSize);
            }
        }
    };
    ops().thread().chunker(chunkable, Views.flatIterable(magnitudes).size());
    // stores each Thread to execute
    final List<Callable<Void>> listCallables = new ArrayList<>();
    // compute descriptor (default 3x3, i.e. 9 channels: one channel for
    // each bin)
    final RectangleShape shape = new RectangleShape(spanOfNeighborhood, false);
    final NeighborhoodsAccessible<FloatType> neighborHood = shape.neighborhoodsRandomAccessible(angles);
    for (int i = 0; i < in.dimension(0); i++) {
        listCallables.add(new ComputeDescriptor(Views.interval(convertedIn, in), i, angles.randomAccess(), magnitudes.randomAccess(), (RandomAccess<FloatType>) out.randomAccess(), neighborHood.randomAccess()));
    }
    try {
        es.invokeAll(listCallables);
    } catch (final InterruptedException e) {
        throw new RuntimeException(e);
    }
    listCallables.clear();
}
Also used : CursorBasedChunk(net.imagej.ops.thread.chunker.CursorBasedChunk) ArrayList(java.util.ArrayList) RandomAccess(net.imglib2.RandomAccess) Callable(java.util.concurrent.Callable) FloatType(net.imglib2.type.numeric.real.FloatType) RectangleShape(net.imglib2.algorithm.neighborhood.RectangleShape) RandomAccessibleInterval(net.imglib2.RandomAccessibleInterval)

Example 3 with RandomAccessible

use of net.imglib2.RandomAccessible in project imagej-ops by imagej.

the class PartialDerivativeRAI method initialize.

@SuppressWarnings("unchecked")
@Override
public void initialize() {
    RandomAccessibleInterval<T> kernel = ops().create().kernelSobel(Util.getTypeFromInterval(in()));
    RandomAccessibleInterval<T> kernelA = Views.hyperSlice(Views.hyperSlice(kernel, 3, 0), 2, 0);
    RandomAccessibleInterval<T> kernelB = Views.hyperSlice(Views.hyperSlice(kernel, 3, 0), 2, 1);
    // add dimensions to kernel to rotate properly
    if (in().numDimensions() > 2) {
        RandomAccessible<T> expandedKernelA = Views.addDimension(kernelA);
        RandomAccessible<T> expandedKernelB = Views.addDimension(kernelB);
        for (int i = 0; i < in().numDimensions() - 3; i++) {
            expandedKernelA = Views.addDimension(expandedKernelA);
            expandedKernelB = Views.addDimension(expandedKernelB);
        }
        long[] dims = new long[in().numDimensions()];
        for (int j = 0; j < in().numDimensions(); j++) {
            dims[j] = 1;
        }
        dims[0] = 3;
        Interval kernelInterval = new FinalInterval(dims);
        kernelA = Views.interval(expandedKernelA, kernelInterval);
        kernelB = Views.interval(expandedKernelB, kernelInterval);
    }
    long[] dims = new long[in().numDimensions()];
    if (dimension == 0) {
        // FIXME hack
        kernelBConvolveOp = RAIs.computer(ops(), Ops.Filter.Convolve.class, in(), new Object[] { kernelB });
    } else {
        // rotate kernel B to dimension
        for (int j = 0; j < in().numDimensions(); j++) {
            if (j == dimension) {
                dims[j] = 3;
            } else {
                dims[j] = 1;
            }
        }
        Img<DoubleType> kernelInterval = ops().create().img(dims);
        RandomAccessibleInterval<T> rotatedKernelB = kernelB;
        for (int i = 0; i < dimension; i++) {
            rotatedKernelB = Views.rotate(rotatedKernelB, i, i + 1);
        }
        rotatedKernelB = Views.interval(rotatedKernelB, kernelInterval);
        kernelBConvolveOp = RAIs.computer(ops(), Ops.Filter.Convolve.class, in(), new Object[] { rotatedKernelB });
    }
    dims = null;
    // rotate kernel A to all other dimensions
    kernelAConvolveOps = new UnaryComputerOp[in().numDimensions()];
    if (dimension != 0) {
        kernelAConvolveOps[0] = RAIs.computer(ops(), Ops.Filter.Convolve.class, in(), new Object[] { kernelA });
    }
    RandomAccessibleInterval<T> rotatedKernelA = kernelA;
    for (int i = 1; i < in().numDimensions(); i++) {
        if (i != dimension) {
            dims = new long[in().numDimensions()];
            for (int j = 0; j < in().numDimensions(); j++) {
                if (i == j) {
                    dims[j] = 3;
                } else {
                    dims[j] = 1;
                }
            }
            Img<DoubleType> kernelInterval = ops().create().img(dims);
            for (int j = 0; j < i; j++) {
                rotatedKernelA = Views.rotate(rotatedKernelA, j, j + 1);
            }
            kernelAConvolveOps[i] = RAIs.computer(ops(), Ops.Filter.Convolve.class, in(), new Object[] { Views.interval(rotatedKernelA, kernelInterval) });
            rotatedKernelA = kernelA;
        }
    }
    addOp = RAIs.binaryComputer(ops(), Ops.Math.Add.class, in(), in());
    createRAI = RAIs.function(ops(), Ops.Create.Img.class, in());
}
Also used : Img(net.imglib2.img.Img) Ops(net.imagej.ops.Ops) DoubleType(net.imglib2.type.numeric.real.DoubleType) FinalInterval(net.imglib2.FinalInterval) RandomAccessibleInterval(net.imglib2.RandomAccessibleInterval) Interval(net.imglib2.Interval) FinalInterval(net.imglib2.FinalInterval)

Example 4 with RandomAccessible

use of net.imglib2.RandomAccessible in project imagej-ops by imagej.

the class ConvolveNaiveC method compute.

@Override
public void compute(final RandomAccessible<I> input, final RandomAccessibleInterval<O> output) {
    // TODO: try a decomposition of the kernel into n 1-dim kernels
    final long[] min = new long[input.numDimensions()];
    final long[] max = new long[input.numDimensions()];
    for (int d = 0; d < kernel.numDimensions(); d++) {
        min[d] = -kernel.dimension(d);
        max[d] = kernel.dimension(d) + output.dimension(d);
    }
    final RandomAccess<I> inRA = input.randomAccess(new FinalInterval(min, max));
    final Cursor<K> kernelC = Views.iterable(kernel).localizingCursor();
    final Cursor<O> outC = Views.iterable(output).localizingCursor();
    final long[] pos = new long[input.numDimensions()];
    final long[] kernelRadius = new long[kernel.numDimensions()];
    for (int i = 0; i < kernelRadius.length; i++) {
        kernelRadius[i] = kernel.dimension(i) / 2;
    }
    float val;
    while (outC.hasNext()) {
        // image
        outC.fwd();
        outC.localize(pos);
        // kernel inlined version of the method convolve
        val = 0;
        inRA.setPosition(pos);
        kernelC.reset();
        while (kernelC.hasNext()) {
            kernelC.fwd();
            for (int i = 0; i < kernelRadius.length; i++) {
                // dimension can have zero extension e.g. vertical 1d kernel
                if (kernelRadius[i] > 0) {
                    inRA.setPosition(pos[i] + kernelC.getLongPosition(i) - kernelRadius[i], i);
                }
            }
            val += inRA.get().getRealDouble() * kernelC.get().getRealDouble();
        }
        outC.get().setReal(val);
    }
}
Also used : FinalInterval(net.imglib2.FinalInterval)

Example 5 with RandomAccessible

use of net.imglib2.RandomAccessible in project imagej-ops by imagej.

the class HyperSliceViewTest method defaultHyperSliceTest.

@Test
public void defaultHyperSliceTest() {
    final Img<DoubleType> img = new ArrayImgFactory<DoubleType>().create(new int[] { 10, 10, 10 }, new DoubleType());
    final MixedTransformView<DoubleType> il2 = Views.hyperSlice((RandomAccessible<DoubleType>) img, 1, 8);
    final MixedTransformView<DoubleType> opr = ops.transform().hyperSliceView(deinterval(img), 1, 8);
    for (int i = 0; i < il2.getTransformToSource().getMatrix().length; i++) {
        for (int j = 0; j < il2.getTransformToSource().getMatrix()[i].length; j++) {
            assertEquals(il2.getTransformToSource().getMatrix()[i][j], opr.getTransformToSource().getMatrix()[i][j], 1e-10);
        }
    }
}
Also used : DoubleType(net.imglib2.type.numeric.real.DoubleType) AbstractOpTest(net.imagej.ops.AbstractOpTest) Test(org.junit.Test)

Aggregations

AbstractOpTest (net.imagej.ops.AbstractOpTest)12 DoubleType (net.imglib2.type.numeric.real.DoubleType)12 Test (org.junit.Test)12 RandomAccessibleInterval (net.imglib2.RandomAccessibleInterval)5 ArrayList (java.util.ArrayList)3 Interval (net.imglib2.Interval)3 RectangleShape (net.imglib2.algorithm.neighborhood.RectangleShape)3 Random (java.util.Random)2 Ops (net.imagej.ops.Ops)2 FinalInterval (net.imglib2.FinalInterval)2 Point (net.imglib2.Point)2 RandomAccess (net.imglib2.RandomAccess)2 RandomAccessible (net.imglib2.RandomAccessible)2 DiamondShape (net.imglib2.algorithm.neighborhood.DiamondShape)2 Neighborhood (net.imglib2.algorithm.neighborhood.Neighborhood)2 Shape (net.imglib2.algorithm.neighborhood.Shape)2 LabelingType (net.imglib2.roi.labeling.LabelingType)2 BitType (net.imglib2.type.logic.BitType)2 IntType (net.imglib2.type.numeric.integer.IntType)2 FloatType (net.imglib2.type.numeric.real.FloatType)2