/** * Checks if the two input 3D images have the same data type * * @param image1 * the first image * @param image2 * the second image * @return true if both images have the same data type, given by the bit * depth. */ public static final boolean isSameType(ImageStack image1, ImageStack image2) { return image1.getBitDepth() == image2.getBitDepth(); }
/** * Determine max possible value from bit depth. * 8 bits -> 255 * 16 bits -> 65535 * 32 bits -> Float.MAX_VALUE */ private static final double getMaxPossibleValue(ImageStack stack) { double maxVal = 255; int bitDepth = stack.getBitDepth(); if (bitDepth == 16) { maxVal = 65535; } else if (bitDepth == 32) { maxVal = Float.MAX_VALUE; } return maxVal; }
@Override public void inPlaceDilation(ImageStack stack) { // If size is one, there is no need to compute if (length <= 1) { return; } if (stack.getBitDepth() == 8) inPlaceDilationGray8(stack); else inPlaceDilationFloat(stack); }
@Override public void inPlaceErosion(ImageStack stack) { // If size is one, there is no need to compute if (length <= 1) { return; } if (stack.getBitDepth() == 8) inPlaceErosionGray8(stack); else inPlaceErosionFloat(stack); }
/** * Update result image using pixels in the upper left neighborhood, using * the 26-adjacency. */ private void backwardDilationC26() { switch(this.result.getBitDepth()) { case 8: backwardDilationC26Gray8(); break; default: backwardDilationC26Generic(); break; } }
/** * Update result image using pixels in the upper left neighborhood, using * the 26-adjacency. */ private void backwardDilationC26( ImageStack binaryMask ) { switch(this.result.getBitDepth()) { case 8: backwardDilationC26Gray8( binaryMask ); break; default: backwardDilationC26Generic( binaryMask ); break; } }
public float[] getVoxels(int x0, int y0, int z0, int w, int h, int d, float[] voxels, int channel) { if (getBitDepth()!=24) return getVoxels(x0, y0, z0, w, h, d, voxels); boolean inBounds = x0>=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; if (voxels==null || voxels.length!=w*h*d) voxels = new float[w*h*d]; int i = 0; for (int z=z0; z<z0+d; z++) { int[] ints = (int[])stack[z]; for (int y=y0; y<y0+h; y++) { for (int x=x0; x<x0+w; x++) { int value = inBounds?ints[y*width+x]&0xffffffff:(int)getVoxel(x, y, z); switch (channel) { case 0: value=(value&0xff0000)>>16; break; case 1: value=(value&0xff00)>>8; break; case 2: value=value&0xff;; break; } voxels[i++] = (float)value; } } } return voxels; }
public ShortStackWrapper(ImageStack stack) { // Check type if (stack.getBitDepth() != 16) { throw new IllegalArgumentException("Requires a 16-bits stack"); } // store stack size this.sizeX = stack.getWidth(); this.sizeY = stack.getHeight(); this.sizeZ = stack.getSize(); // Convert slices type this.slices = new short[sizeZ][]; Object[] array = stack.getImageArray(); for (int i = 0; i < sizeZ; i++) { slices[i] = (short[]) array[i]; } }
public ByteStackWrapper(ImageStack stack) { // Check type if (stack.getBitDepth() != 8) { throw new IllegalArgumentException("Requires a 8-bits stack"); } // store stack size this.sizeX = stack.getWidth(); this.sizeY = stack.getHeight(); this.sizeZ = stack.getSize(); // Convert slices type this.slices = new byte[sizeZ][]; Object[] array = stack.getImageArray(); for (int i = 0; i < sizeZ; i++) { slices[i] = (byte[]) array[i]; } }
/** * Update result image using pixels in the upper left neighborhood, using * the 26-adjacency. */ private void forwardDilationC26() { switch(this.result.getBitDepth()) { case 8: forwardDilationC26Gray8(); break; case 16: forwardDilationC26Gray16(); break; case 32: forwardDilationC26Float(); break; } }
/** * Update result image using pixels in the upper left neighborhood, using * the 26-adjacency. */ private void forwardDilationC26( ImageStack binaryMask ) { switch(this.result.getBitDepth()) { case 8: forwardDilationC26Gray8( binaryMask ); break; case 16: forwardDilationC26Gray16( binaryMask ); break; case 32: forwardDilationC26Float( binaryMask ); break; } }
public FloatStackWrapper(ImageStack stack) { // Check type if (stack.getBitDepth() != 32) { throw new IllegalArgumentException("Requires a 32-bits stack"); } // store stack size this.sizeX = stack.getWidth(); this.sizeY = stack.getHeight(); this.sizeZ = stack.getSize(); // Convert slices type this.slices = new float[sizeZ][]; Object[] array = stack.getImageArray(); for (int i = 0; i < sizeZ; i++) { slices[i] = (float[]) array[i]; } }
/** Replaces the ImageProcessor with the one specified and updates the display. With stacks, the ImageProcessor must be the same type as other images in the stack and it must be the same width and height. Set 'title' to null to leave the title unchanged. */ public void setProcessor(String title, ImageProcessor ip) { if (ip==null || ip.getPixels()==null) throw new IllegalArgumentException("ip null or ip.getPixels() null"); if (getStackSize()>1) { if (ip.getWidth()!=width || ip.getHeight()!=height) throw new IllegalArgumentException("Wrong dimensions for this stack"); int stackBitDepth = stack!=null?stack.getBitDepth():0; if (stackBitDepth>0 && getBitDepth()!=stackBitDepth) throw new IllegalArgumentException("Wrong type for this stack"); } else { setStackNull(); setCurrentSlice(1); } setProcessor2(title, ip, null); }
/** Replaces the ImageProcessor with the one specified and updates the display. With stacks, the ImageProcessor must be the same type as other images in the stack and it must be the same width and height. Set 'title' to null to leave the title unchanged. */ public void setProcessor(String title, ImageProcessor ip) { if (ip==null || ip.getPixels()==null) throw new IllegalArgumentException("ip null or ip.getPixels() null"); if (getStackSize()>1) { if (ip.getWidth()!=width || ip.getHeight()!=height) throw new IllegalArgumentException("Wrong dimensions for this stack"); int stackBitDepth = stack!=null?stack.getBitDepth():0; if (stackBitDepth>0 && getBitDepth()!=stackBitDepth) throw new IllegalArgumentException("Wrong type for this stack"); } else { setStackNull(); setCurrentSlice(1); } setProcessor2(title, ip, null); }
private static void blurZ(ImageStack stack, double sigmaZ) { GaussianBlur gb = new GaussianBlur(); double accuracy = (stack.getBitDepth()==8||stack.getBitDepth()==24)?0.002:0.0002; int w=stack.getWidth(), h=stack.getHeight(), d=stack.getSize(); float[] zpixels = null; FloatProcessor fp =null; IJ.showStatus("Z blurring"); gb.showProgress(false); int channels = stack.getProcessor(1).getNChannels(); for (int y=0; y<h; y++) { IJ.showProgress(y, h-1); for (int channel=0; channel<channels; channel++) { zpixels = stack.getVoxels(0, y, 0, w, 1, d, zpixels, channel); if (fp==null) fp = new FloatProcessor(w, d, zpixels); //if (y==h/2) new ImagePlus("before-"+h/2, fp.duplicate()).show(); gb.blur1Direction(fp, sigmaZ, accuracy, false, 0); stack.setVoxels(0, y, 0, w, 1, d, zpixels, channel); } } IJ.showStatus(""); }
private static void blurZ(ImageStack stack, double sigmaZ) { GaussianBlur gb = new GaussianBlur(); double accuracy = (stack.getBitDepth()==8||stack.getBitDepth()==24)?0.002:0.0002; int w=stack.getWidth(), h=stack.getHeight(), d=stack.getSize(); float[] zpixels = null; FloatProcessor fp =null; IJ.showStatus("Z blurring"); gb.showProgress(false); int channels = stack.getProcessor(1).getNChannels(); for (int y=0; y<h; y++) { IJ.showProgress(y, h-1); for (int channel=0; channel<channels; channel++) { zpixels = stack.getVoxels(0, y, 0, w, 1, d, zpixels, channel); if (fp==null) fp = new FloatProcessor(w, d, zpixels); //if (y==h/2) new ImagePlus("before-"+h/2, fp.duplicate()).show(); gb.blur1Direction(fp, sigmaZ, accuracy, false, 0); stack.setVoxels(0, y, 0, w, 1, d, zpixels, channel); } } IJ.showStatus(""); }
/** * Default settings are 4 connectivity, 16 bits image. */ @Test public void testFloodFillComponentsLabeling_Default() { ImageStack image = createNineCubesImage(); FloodFillComponentsLabeling3D algo = new FloodFillComponentsLabeling3D(); ImageStack result = algo.computeLabels(image); assertEquals(16, result.getBitDepth()); assertEquals(9, result.getVoxel(7, 7, 7), .1); }
/** * Using 6 connectivity should result in nine connected components. */ @Test public void testFloodFillComponentsLabeling_C6_Byte() { ImageStack image = createNineCubesImage(); FloodFillComponentsLabeling3D algo = new FloodFillComponentsLabeling3D(6, 8); ImageStack result = algo.computeLabels(image); assertEquals(8, result.getBitDepth()); assertEquals(9, result.getVoxel(7, 7, 7), .1); }
/** * Using 26 connectivity should result in one connected component. */ @Test public void testFloodFillComponentsLabeling_C26_Short() { ImageStack image = createNineCubesImage(); FloodFillComponentsLabeling3D algo = new FloodFillComponentsLabeling3D(26, 16); ImageStack result = algo.computeLabels(image); assertEquals(16, result.getBitDepth()); assertEquals(1, result.getVoxel(7, 7, 7), .1); }
@Test public void testDistanceMap() { // create 3D image containing a cube ImageStack image = ImageStack.create(20, 20, 20, 8); for (int z = 2; z < 19; z++) { for (int y = 2; y < 19; y++) { for (int x = 2; x < 19; x++) { image.setVoxel(x, y, z, 255); } } } float[] weights = ChamferWeights3D.WEIGHTS_3_4_5_7.getFloatWeights(); DistanceTransform3D algo = new DistanceTransform3D4WeightsFloat(weights, true); ImageStack result = algo.distanceMap(image); assertEquals(32, result.getBitDepth()); double middle = result.getVoxel(10, 10, 10); assertEquals(9, middle, .1); }