use of net.imglib2.roi.labeling.ImgLabeling in project imagej-ops by imagej.
the class CreateLabelingTest method testImageDimensions.
@Test
public void testImageDimensions() {
final Random randomGenerator = new Random();
for (int i = 0; i < TEST_SIZE; i++) {
// between 2 and 5 dimensions
final long[] dim = new long[randomGenerator.nextInt(4) + 2];
// between 2 and 10 pixels per dimensions
for (int j = 0; j < dim.length; j++) {
dim[j] = randomGenerator.nextInt(9) + 2;
}
// create imglabeling
@SuppressWarnings("unchecked") final ImgLabeling<String, ?> img = (ImgLabeling<String, ?>) ops.run(DefaultCreateImgLabeling.class, dim);
assertArrayEquals("Labeling Dimensions:", dim, Intervals.dimensionsAsLongArray(img));
}
}
use of net.imglib2.roi.labeling.ImgLabeling in project imagej-ops by imagej.
the class WatershedBinarySingleSigmaTest method test.
@SuppressWarnings("unchecked")
@Test
public void test() {
// load test image
Img<FloatType> watershedTestImg = openFloatImg(WatershedTest.class, "watershed_test_image.png");
// threshold it
RandomAccessibleInterval<BitType> thresholdedImg = ops.create().img(watershedTestImg, new BitType());
ops.threshold().apply(Views.flatIterable(thresholdedImg), Views.flatIterable(watershedTestImg), new FloatType(1));
// compute inverted distance transform and smooth it with gaussian
// filtering
final RandomAccessibleInterval<FloatType> distMap = ops.image().distancetransform(thresholdedImg);
final RandomAccessibleInterval<FloatType> invertedDistMap = ops.create().img(distMap, new FloatType());
ops.image().invert(Views.iterable(invertedDistMap), Views.iterable(distMap));
double sigma = 3.0;
final RandomAccessibleInterval<FloatType> gauss = ops.filter().gauss(invertedDistMap, sigma);
// run randomly only one configuration to save execution time
int nextInt = new Random().nextInt(3);
if (nextInt == 0) {
// compute result
final ImgLabeling<Integer, IntType> out1 = (ImgLabeling<Integer, IntType>) ops.run(WatershedBinarySingleSigma.class, null, thresholdedImg, true, false, sigma, thresholdedImg);
final ImgLabeling<Integer, IntType> expOut1 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, gauss, true, false, thresholdedImg);
assertResults(expOut1, out1);
final ImgLabeling<Integer, IntType> out2 = (ImgLabeling<Integer, IntType>) ops.run(WatershedBinarySingleSigma.class, null, thresholdedImg, true, false, sigma);
final ImgLabeling<Integer, IntType> expOut2 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, gauss, true, false);
assertResults(expOut2, out2);
} else if (nextInt == 1) {
// compute result
final ImgLabeling<Integer, IntType> out1 = (ImgLabeling<Integer, IntType>) ops.run(WatershedBinarySingleSigma.class, null, thresholdedImg, true, true, sigma, thresholdedImg);
final ImgLabeling<Integer, IntType> expOut1 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, gauss, true, true, thresholdedImg);
assertResults(expOut1, out1);
final ImgLabeling<Integer, IntType> out2 = (ImgLabeling<Integer, IntType>) ops.run(WatershedBinarySingleSigma.class, null, thresholdedImg, true, true, sigma);
final ImgLabeling<Integer, IntType> expOut2 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, gauss, true, true);
assertResults(expOut2, out2);
} else {
// compute result
final ImgLabeling<Integer, IntType> out1 = (ImgLabeling<Integer, IntType>) ops.run(WatershedBinarySingleSigma.class, null, thresholdedImg, false, true, sigma, thresholdedImg);
final ImgLabeling<Integer, IntType> expOut1 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, gauss, false, true, thresholdedImg);
assertResults(expOut1, out1);
final ImgLabeling<Integer, IntType> out2 = (ImgLabeling<Integer, IntType>) ops.run(WatershedBinarySingleSigma.class, null, thresholdedImg, false, true, sigma);
final ImgLabeling<Integer, IntType> expOut2 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, gauss, false, true);
assertResults(expOut2, out2);
}
}
use of net.imglib2.roi.labeling.ImgLabeling in project imagej-ops by imagej.
the class WatershedSeededTest method testWithoutMask.
@SuppressWarnings("unchecked")
private void testWithoutMask(final RandomAccessibleInterval<FloatType> in, final ImgLabeling<Integer, IntType> seeds) {
// create mask which is 1 everywhere
long[] dims = new long[in.numDimensions()];
in.dimensions(dims);
Img<BitType> mask = ArrayImgs.bits(dims);
for (BitType b : mask) {
b.setOne();
}
/*
* use 8-connected neighborhood
*/
// compute result without watersheds
ImgLabeling<Integer, IntType> out = (ImgLabeling<Integer, IntType>) ops.run(WatershedSeeded.class, null, in, seeds, true, false);
assertResults(in, out, seeds, mask, false, false);
// compute result with watersheds
ImgLabeling<Integer, IntType> out2 = (ImgLabeling<Integer, IntType>) ops.run(WatershedSeeded.class, null, in, seeds, true, true);
assertResults(in, out2, seeds, mask, true, false);
/*
* use 4-connected neighborhood
*/
// compute result without watersheds
ImgLabeling<Integer, IntType> out3 = (ImgLabeling<Integer, IntType>) ops.run(WatershedSeeded.class, null, in, seeds, false, false);
assertResults(in, out3, seeds, mask, false, false);
// compute result with watersheds
ImgLabeling<Integer, IntType> out4 = (ImgLabeling<Integer, IntType>) ops.run(WatershedSeeded.class, null, in, seeds, false, true);
assertResults(in, out4, seeds, mask, true, false);
}
use of net.imglib2.roi.labeling.ImgLabeling in project imagej-ops by imagej.
the class WatershedTest method testWithMask.
@SuppressWarnings("unchecked")
private void testWithMask(final RandomAccessibleInterval<FloatType> in) {
// create mask which is 1 everywhere
long[] dims = new long[in.numDimensions()];
in.dimensions(dims);
Img<BitType> mask = ArrayImgs.bits(dims);
RandomAccess<BitType> raMask = mask.randomAccess();
for (BitType b : mask) {
b.setZero();
}
for (int x = 0; x < dims[0] / 2; x++) {
for (int y = 0; y < dims[1] / 2; y++) {
raMask.setPosition(new int[] { x, y });
raMask.get().setOne();
}
}
/*
* use 8-connected neighborhood
*/
// compute result without watersheds
ImgLabeling<Integer, IntType> out = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, in, true, false, mask);
assertResults(in, out, mask, true, false, true);
// compute result with watersheds
ImgLabeling<Integer, IntType> out2 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, in, true, true, mask);
assertResults(in, out2, mask, true, true, true);
/*
* use 4-connected neighborhood
*/
// compute result without watersheds
ImgLabeling<Integer, IntType> out3 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, in, false, false, mask);
assertResults(in, out3, mask, false, false, true);
// compute result with watersheds
ImgLabeling<Integer, IntType> out4 = (ImgLabeling<Integer, IntType>) ops.run(Watershed.class, null, in, false, true, mask);
assertResults(in, out4, mask, false, true, true);
}
use of net.imglib2.roi.labeling.ImgLabeling in project imagej-ops by imagej.
the class Watershed method compute.
@Override
public void compute(final RandomAccessibleInterval<T> in, final ImgLabeling<Integer, IntType> out) {
final RandomAccess<T> raIn = in.randomAccess();
RandomAccess<B> raMask = null;
if (mask != null) {
raMask = mask.randomAccess();
}
// stores the size of each dimension
final long[] dimensSizes = new long[in.numDimensions()];
in.dimensions(dimensSizes);
// calculates the number of points in the n-d space
long numPixels = Intervals.numElements(in);
// the pixels indices are stored in an array, which is sorted depending
// on the pixel values
final List<Long> imiList = new ArrayList<>();
if (mask != null) {
final Cursor<Void> c = Regions.iterable(mask).localizingCursor();
while (c.hasNext()) {
c.next();
imiList.add(IntervalIndexer.positionToIndex(c, in));
}
} else {
for (long i = 0; i < numPixels; i++) {
imiList.add(i);
}
}
final Long[] imi = imiList.toArray(new Long[imiList.size()]);
/*
* Sort the pixels of imi in the increasing order of their grey value
* (only the pixel indices are stored)
*/
Arrays.sort(imi, new Comparator<Long>() {
@Override
public int compare(final Long o1, final Long o2) {
IntervalIndexer.indexToPosition(o1, in, raIn);
final T value = raIn.get().copy();
IntervalIndexer.indexToPosition(o2, in, raIn);
return value.compareTo(raIn.get());
}
});
// lab and dist store the values calculated after each phase
final RandomAccessibleInterval<IntType> lab = ops().create().img(in, new IntType());
// extend border to be able to do a quick check, if a voxel is inside
final ExtendedRandomAccessibleInterval<IntType, RandomAccessibleInterval<IntType>> labExt = Views.extendBorder(lab);
final OutOfBounds<IntType> raLab = labExt.randomAccess();
final RandomAccessibleInterval<IntType> dist = ops().create().img(in, new IntType());
final RandomAccess<IntType> raDist = dist.randomAccess();
// initial values
for (final IntType pixel : Views.flatIterable(lab)) {
pixel.set(INIT);
}
int current_label = 0;
int current_dist;
final ArrayList<Long> fifo = new ArrayList<>();
// RandomAccess for Neighborhoods
final Shape shape;
if (useEightConnectivity) {
shape = new RectangleShape(1, true);
} else {
shape = new DiamondShape(1);
}
final RandomAccessible<Neighborhood<T>> neighborhoods = shape.neighborhoodsRandomAccessible(in);
final RandomAccess<Neighborhood<T>> raNeighbor = neighborhoods.randomAccess();
/*
* Start flooding
*/
for (int j = 0; j < imi.length; j++) {
IntervalIndexer.indexToPosition(imi[j], in, raIn);
final T actualH = raIn.get().copy();
int i = j;
while (actualH.compareTo(raIn.get()) == 0) {
final long p = imi[i];
IntervalIndexer.indexToPosition(p, in, raIn);
raLab.setPosition(raIn);
raLab.get().set(MASK);
raNeighbor.setPosition(raIn);
final Cursor<T> neighborHood = raNeighbor.get().cursor();
while (neighborHood.hasNext()) {
neighborHood.fwd();
raLab.setPosition(neighborHood);
if (!raLab.isOutOfBounds()) {
final int f = raLab.get().get();
if ((f > 0) || (f == WSHED)) {
raDist.setPosition(raIn);
raDist.get().set(1);
fifo.add(p);
break;
}
}
}
i++;
if (i == imi.length) {
break;
}
IntervalIndexer.indexToPosition(imi[i], in, raIn);
}
current_dist = 1;
// add fictitious pixel
fifo.add(-1l);
while (true) {
long p = fifo.remove(0);
if (p == -1) {
if (fifo.isEmpty()) {
break;
}
fifo.add(-1l);
current_dist++;
p = fifo.remove(0);
}
IntervalIndexer.indexToPosition(p, in, raNeighbor);
final Cursor<T> neighborHood = raNeighbor.get().cursor();
raLab.setPosition(raNeighbor);
int labp = raLab.get().get();
final long[] posNeighbor = new long[neighborHood.numDimensions()];
while (neighborHood.hasNext()) {
neighborHood.fwd();
neighborHood.localize(posNeighbor);
raLab.setPosition(posNeighbor);
if (!raLab.isOutOfBounds()) {
raDist.setPosition(posNeighbor);
final int labq = raLab.get().get();
final int distq = raDist.get().get();
if ((distq < current_dist) && ((labq > 0) || (labq == WSHED))) {
// the watersheds
if (labq > 0) {
if ((labp == MASK) || (labp == WSHED)) {
labp = labq;
} else {
if (labp != labq) {
labp = WSHED;
}
}
} else {
if (labp == MASK) {
labp = WSHED;
}
}
raLab.setPosition(raNeighbor);
raLab.get().set(labp);
} else {
if ((labq == MASK) && (distq == 0)) {
raDist.setPosition(posNeighbor);
raDist.get().set(current_dist + 1);
fifo.add(IntervalIndexer.positionToIndex(posNeighbor, dimensSizes));
}
}
}
}
}
// checks if new minima have been discovered
IntervalIndexer.indexToPosition(imi[j], in, raIn);
i = j;
while (actualH.compareTo(raIn.get()) == 0) {
final long p = imi[i];
IntervalIndexer.indexToPosition(p, dist, raDist);
// the distance associated with p is reseted to 0
raDist.get().set(0);
raLab.setPosition(raDist);
if (raLab.get().get() == MASK) {
current_label++;
fifo.add(p);
raLab.get().set(current_label);
while (!fifo.isEmpty()) {
final long q = fifo.remove(0);
IntervalIndexer.indexToPosition(q, in, raNeighbor);
final Cursor<T> neighborHood = raNeighbor.get().cursor();
final long[] posNeighbor = new long[neighborHood.numDimensions()];
while (neighborHood.hasNext()) {
neighborHood.fwd();
neighborHood.localize(posNeighbor);
raLab.setPosition(posNeighbor);
if (!raLab.isOutOfBounds()) {
final long r = IntervalIndexer.positionToIndex(posNeighbor, dimensSizes);
if (raLab.get().get() == MASK) {
fifo.add(r);
raLab.get().set(current_label);
}
}
}
}
}
i++;
if (i == imi.length) {
break;
}
IntervalIndexer.indexToPosition(imi[i], in, raIn);
}
j = i - 1;
}
/*
* Draw output and remove as the case may be the watersheds
*/
final Cursor<LabelingType<Integer>> cursorOut = out.cursor();
while (cursorOut.hasNext()) {
cursorOut.fwd();
boolean maskValue = true;
if (mask != null) {
raMask.setPosition(cursorOut);
if (!raMask.get().get()) {
maskValue = false;
}
}
raLab.setPosition(cursorOut);
if (!maskValue) {
cursorOut.get().clear();
} else {
if (!drawWatersheds && raLab.get().get() == WSHED) {
raNeighbor.setPosition(cursorOut);
final Cursor<T> neighborHood = raNeighbor.get().cursor();
int newLab = WSHED;
while (neighborHood.hasNext()) {
neighborHood.fwd();
raLab.setPosition(neighborHood);
if (!raLab.isOutOfBounds()) {
newLab = raLab.get().get();
if (newLab > WSHED) {
break;
}
}
}
if (newLab == WSHED) {
cursorOut.get().clear();
} else {
cursorOut.get().add(newLab);
}
} else {
cursorOut.get().add(raLab.get().get());
}
}
}
/*
* Merge already present labels before calculation of watershed
*/
if (out() != null) {
final Cursor<LabelingType<Integer>> cursor = out().cursor();
final RandomAccess<LabelingType<Integer>> raOut = out.randomAccess();
while (cursor.hasNext()) {
cursor.fwd();
raOut.setPosition(cursor);
final List<Integer> labels = new ArrayList<>();
cursor.get().iterator().forEachRemaining(labels::add);
raOut.get().addAll(labels);
}
}
}
Aggregations