@Test public final void testErosionCubicMeshC6() { ImageStack mask = createCubicMeshImage(); invertGray8Stack(mask); ImageStack marker = ImageStack.create(20, 20, 20, 8); marker.setVoxel(5, 5, 5, 255); invertGray8Stack(marker); GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8(); algo.setReconstructionType(GeodesicReconstructionType.BY_EROSION); algo.setConnectivity(6); ImageStack result = algo.applyTo(marker, mask); assertEquals(0, result.getVoxel(5, 15, 5), .01); assertEquals(255, result.getVoxel(0, 0, 0), .01); int sizeX = mask.getWidth(); int sizeY = mask.getHeight(); int sizeZ = mask.getSize(); for (int z = 0; z < sizeZ; z++) { for (int y = 0; y < sizeY; y++) { for (int x = 0; x < sizeX; x++) { assertEquals(result.getVoxel(x, y, z), mask.getVoxel(x, y, z), .01); } } } }
/** * Creates an image of cube edges, similar to this: * * <p>*---------* ** ** * * * * *********** * | * | * | *------|--* | / | * |/ |* *********** * * <p>Typical planes are as follow: z = 0 z=1,2,3 z = 4 X * * * * . . . . . * * * * * . . . . * . * . . . . * . . . * . . . . * . . . . . * . . . * . . . . * . . . . . * . . . * Z . . . * * . . . * * * . . . * * * <p>(reconstruction starts from the X, and terminates at the Z) */ private ImageStack createThinCubicMeshImage() { int sizeX = 5; int sizeY = 5; int sizeZ = 5; int bitDepth = 8; // create empty stack ImageStack stack = ImageStack.create(sizeX, sizeY, sizeZ, bitDepth); // First, the edges in the x direction for (int x = 0; x < 5; x++) { stack.setVoxel(x, 0, 0, 255); stack.setVoxel(x, 0, 4, 255); } // then, the edges in the y direction for (int y = 0; y < 5; y++) { stack.setVoxel(4, y, 0, 255); stack.setVoxel(0, y, 4, 255); stack.setVoxel(4, y, 4, 255); } // Finally, the edges in the z direction for (int z = 0; z < 5; z++) { stack.setVoxel(0, 4, z, 255); stack.setVoxel(4, 4, z, 255); } return stack; }
@Test public final void testDilationCochleaVolumeC6() { String fileName = getClass().getResource("/files/bat-cochlea-volume.tif").getFile(); ImagePlus imagePlus = IJ.openImage(fileName); assertNotNull(imagePlus); assertTrue(imagePlus.getStackSize() > 0); ImageStack mask = imagePlus.getStack(); // Ensure regularity of the mask mask = Morphology.opening(mask, CubeStrel.fromRadius(1)); int width = mask.getWidth(); int height = mask.getHeight(); int depth = mask.getSize(); int bitDepth = mask.getBitDepth(); ImageStack marker = ImageStack.create(width, height, depth, bitDepth); marker.setVoxel(20, 80, 50, 255); GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8(); algo.setConnectivity(6); algo.verbose = false; ImageStack result = algo.applyTo(marker, mask); for (int z = 0; z < depth; z++) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { assertEquals(result.getVoxel(x, y, z), mask.getVoxel(x, y, z), .01); } } } }
@Test public final void testDilationHilbertCurveC26() { String fileName = getClass().getResource("/files/hilbert3d.tif").getFile(); ImagePlus imagePlus = IJ.openImage(fileName); assertNotNull(imagePlus); assertTrue(imagePlus.getStackSize() > 0); ImageStack mask = imagePlus.getStack(); int width = mask.getWidth(); int height = mask.getHeight(); int depth = mask.getSize(); int bitDepth = mask.getBitDepth(); ImageStack marker = ImageStack.create(width, height, depth, bitDepth); marker.setVoxel(3, 0, 0, 255); GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8(); algo.setConnectivity(26); algo.verbose = false; ImageStack result = algo.applyTo(marker, mask); for (int z = 0; z < depth; z++) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { assertEquals(result.getVoxel(x, y, z), mask.getVoxel(x, y, z), .01); } } } }
@Test public final void testApplyTo() { GeodesicReconstructionByDilation3DGray8 algo = new GeodesicReconstructionByDilation3DGray8(); String fileName = getClass().getResource("/files/bat-cochlea-volume.tif").getFile(); ImagePlus imagePlus = IJ.openImage(fileName); assertNotNull(imagePlus); assertTrue(imagePlus.getStackSize() > 0); ImageStack mask = imagePlus.getStack(); int width = mask.getWidth(); int height = mask.getHeight(); int depth = mask.getSize(); int bitDepth = mask.getBitDepth(); ImageStack marker = ImageStack.create(width, height, depth, bitDepth); marker.setVoxel(20, 80, 50, 255); ImageStack result = algo.applyTo(marker, mask); for (int z = 0; z < depth; z++) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { assertEquals(result.getVoxel(x, y, z), mask.getVoxel(x, y, z), .01); } } } }
/** * Resizes the current array to the given dimensions. * * @param input the array to resize * @param lenX the desired length in x-direction (with, horizontal length) * @param lenY the desired length in y-direction (height, vertical length) * @return a new 2d float array with the specified dimensions, and values interpolated from the * input array. */ public static float[][] resize(float[][] input, int lenX, int lenY) { float[] linearized = linearize2DArray(input); ImageStack is = ImageStack.create(input.length, input[0].length, 1, 32); is.setPixels(linearized, 1); ImageProcessor ip = new ImagePlus("", is).getProcessor(); ip.setInterpolationMethod(ImageProcessor.BICUBIC); float[] resized = (float[]) ip.resize(lenX, lenY).getPixels(); return linearizedArrayTo2D(resized, lenX, lenY); }
@Test public final void testDilationThinCubicMeshC26() { ImageStack mask = createThinCubicMeshImage(); ImageStack marker = ImageStack.create(5, 5, 5, 8); marker.setVoxel(0, 0, 0, 255); GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8(); algo.setConnectivity(26); ImageStack result = algo.applyTo(marker, mask); assertEquals(255, result.getVoxel(0, 4, 0), .01); }
private ImageStack loadImages() { String fileNameNumberRef = new String(); String fileNameNumberCorr = new String(); if (numOfIteration < 9) { fileNameNumberRef = "000" + numOfIteration; fileNameNumberCorr = "000" + (numOfIteration + 1); } if (numOfIteration == 9) { fileNameNumberRef = "0009"; fileNameNumberCorr = "0010"; } if (numOfIteration >= 10 && numOfIteration < 99) { fileNameNumberRef = "00" + numOfIteration; fileNameNumberCorr = "00" + (numOfIteration + 1); } if (numOfIteration == 99) { fileNameNumberRef = "0099"; fileNameNumberCorr = "0100"; } if (numOfIteration >= 100 && numOfIteration < 999) { fileNameNumberRef = "0" + numOfIteration; fileNameNumberCorr = "0" + (numOfIteration + 1); } if (numOfIteration == 999) { fileNameNumberRef = "0999"; fileNameNumberCorr = "1000"; } if (numOfIteration >= 1000) { fileNameNumberRef = String.valueOf(numOfIteration); fileNameNumberCorr = String.valueOf(numOfIteration + 1); } ImagePlus ref = new ImagePlus(dir + name + fileNameNumberRef + format); ImagePlus corr = new ImagePlus(dir + name + (fileNameNumberCorr) + format); ImageStack tmp = ImageStack.create(ref.getWidth(), ref.getHeight(), 2, ref.getBitDepth()); tmp.setPixels(ref.getProcessor().getPixels(), 1); tmp.setPixels(corr.getProcessor().getPixels(), 2); return tmp; }
/** * Combination of {@link ImageJInterpolation#crop(float[][], float, float, float, float)} and * {@link ImageJInterpolation#resize(float[][], int, int)}. Crops and resizes the input array into * a new output array. * * @param input the array to work on * @param lenX the desired length in x-direction (with, horizontal length) * @param lenY the desired length in y-direction (height, vertical length) * @param minX the lower index in x-direction * @param minY the lower index in y-direction * @param maxX the higher index in x-direction * @param maxY the higher index in y-direction * @return a new cropped and resized version of the input array */ public static float[][] cropAndResize( float[][] input, int lenX, int lenY, float minX, float minY, float maxX, float maxY) { float[] linearized = linearize2DArray(input); ImageStack is = ImageStack.create(input[0].length, input.length, 1, 32); is.setPixels(linearized, 1); ImageProcessor ip = new ImagePlus("", is).getProcessor(); ip.setInterpolationMethod(ImageProcessor.BICUBIC); ip.setRoi((int) minX, (int) minY, (int) Math.ceil(maxX - minX), (int) Math.ceil(maxY - minY)); float[] resized = (float[]) ip.crop().resize(lenX, lenY).getPixels(); return linearizedArrayTo2D(resized, lenX, lenY); }
private ImageStack createCubicMeshImage() { int sizeX = 20; int sizeY = 20; int sizeZ = 20; int bitDepth = 8; // create empty stack ImageStack stack = ImageStack.create(sizeX, sizeY, sizeZ, bitDepth); // number of voxels between edges and 'tube' borders int gap = 2; // First, the edges in the x direction for (int z = 5 - gap - 1; z <= 5 + gap + 1; z++) { for (int y = 5 - gap - 1; y <= 5 + gap + 1; y++) { for (int x = 5 - gap - 1; x <= 15 + gap + 1; x++) { stack.setVoxel(x, y, z, 255); stack.setVoxel(x, y, z + 10, 255); } } } // then, the edges in the y direction for (int z = 5 - gap - 1; z <= 5 + gap + 1; z++) { for (int x = 5 - gap - 1; x <= 5 + gap + 1; x++) { for (int y = 5 - gap - 1; y <= 15 + gap + 1; y++) { stack.setVoxel(x + 10, y, z, 255); stack.setVoxel(x, y, z + 10, 255); stack.setVoxel(x + 10, y, z + 10, 255); } } } // Finally, the edges in the z direction for (int y = 5 - gap - 1; y <= 5 + gap + 1; y++) { for (int x = 5 - gap - 1; x <= 5 + gap + 1; x++) { for (int z = 5 - gap - 1; z <= 15 + gap + 1; z++) { stack.setVoxel(x, y + 10, z, 255); stack.setVoxel(x + 10, y + 10, z, 255); } } } return stack; }
@Test public final void testDilationCubicHollowMesh() { ImageStack mask = createCubicHollowMeshImage(); ImageStack marker = ImageStack.create(20, 20, 20, 8); for (int z = 0; z < 20; z++) { for (int y = 0; y < 20; y++) { for (int x = 0; x < 20; x++) { marker.setVoxel(x, y, z, 255); } } } marker.setVoxel(5, 5, 5, 0); GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8(); ImageStack result = algo.applyTo(marker, mask); assertEquals(0, result.getVoxel(5, 15, 5), .01); assertStackEquals(mask, result); }
@Test public final void testErosionCochleaVolumeC26() { String fileName = getClass().getResource("/files/bat-cochlea-volume.tif").getFile(); ImagePlus imagePlus = IJ.openImage(fileName); assertNotNull(imagePlus); assertTrue(imagePlus.getStackSize() > 0); ImageStack mask = imagePlus.getStack(); // Ensure regularity of the mask mask = Morphology.opening(mask, CubeStrel.fromRadius(1)); invertGray8Stack(mask); int width = mask.getWidth(); int height = mask.getHeight(); int depth = mask.getSize(); int bitDepth = mask.getBitDepth(); ImageStack marker = ImageStack.create(width, height, depth, bitDepth); marker.setVoxel(20, 80, 50, 255); invertGray8Stack(marker); GeodesicReconstruction3DHybrid0Gray8 algo = new GeodesicReconstruction3DHybrid0Gray8(GeodesicReconstructionType.BY_EROSION); algo.setConnectivity(26); ImageStack result = algo.applyTo(marker, mask); for (int z = 0; z < depth; z++) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (Math.abs(result.getVoxel(x, y, z) - mask.getVoxel(x, y, z)) > .1) { System.out.println("x=" + x + " y=" + y + " z=" + z); System.out.println(" mask = " + (int) mask.getVoxel(x, y, z)); System.out.println(" res = " + (int) result.getVoxel(x, y, z)); assertTrue(false); } } } } }
/** Creates a 3D image containing thin cube mesh. */ private ImageStack createCubeGraphImage() { int sizeX = 11; int sizeY = 11; int sizeZ = 11; int bitDepth = 8; // create empty stack ImageStack stack = ImageStack.create(sizeX, sizeY, sizeZ, bitDepth); // coordinates of the cube edges int x1 = 1; int x2 = 9; int y1 = 1; int y2 = 9; int z1 = 1; int z2 = 9; // First, the edges in the x direction for (int x = x1; x <= x2; x++) { stack.setVoxel(x, y1, z1, 255); stack.setVoxel(x, y1, z2, 255); } // then, the edges in the y direction for (int y = y1; y <= y2; y++) { stack.setVoxel(x2, y, z1, 255); stack.setVoxel(x1, y, z2, 255); stack.setVoxel(x2, y, z2, 255); } // Finally, the edges in the z direction for (int z = z1; z <= z2; z++) { stack.setVoxel(x1, y2, z, 255); stack.setVoxel(x2, y2, z, 255); } return stack; }