/** * Do watershed segmentation based on the EDM of the foreground objects (nonzero pixels) in an * 8-bit image. Particles are segmented by their shape; segmentation lines added are background * pixels (value = 0); */ public void toWatershed(ImageProcessor ip) { FloatProcessor floatEdm = makeFloatEDM(ip, 0, false); ByteProcessor maxIp = maxFinder.findMaxima( floatEdm, MAXFINDER_TOLERANCE, ImageProcessor.NO_THRESHOLD, MaximumFinder.SEGMENTED, false, true); if (maxIp != null) ip.copyBits(maxIp, 0, 0, Blitter.AND); }
/** * Called by the PlugInFilterRunner after setup. Asks the user in case of a stack and prepares a * separate ouptut stack if required */ public int showDialog(ImagePlus imp, String command, PlugInFilterRunner pfr) { this.pfr = pfr; int width = imp.getWidth(); int height = imp.getHeight(); // ask whether to process all slices of stack & prepare stack // (if required) for writing into it in parallel threads flags = IJ.setupDialog(imp, flags); if ((flags & DOES_STACKS) != 0 && outImageType != BYTE_OVERWRITE) { outStack = new ImageStack(width, height, imp.getStackSize()); maxFinder.setNPasses(imp.getStackSize()); } return flags; } // public int showDialog
/** * Prepare the progress bar. Without calling it or if nPasses=0, no progress bar will be shown. * * @param nPasses Number of images that this EDM will process. */ public void setNPasses(int nPasses) { this.nPasses = nPasses; progressDone = 0; if (USES_MAX_FINDER[processType]) maxFinder.setNPasses(nPasses); }
/** Called by the PlugInFilterRunner to process the image or one frame of a stack */ public void run(ImageProcessor ip) { if (interrupted) return; int width = ip.getWidth(); int height = ip.getHeight(); int backgroundValue = (processType == VORONOI) ? (background255 ? 0 : (byte) 255) : // Voronoi needs EDM of the background (background255 ? (byte) 255 : 0); // all others do EDM of the foreground if (USES_WATERSHED[processType]) nPasses = 0; // watershed has its own progress bar FloatProcessor floatEdm = makeFloatEDM(ip, backgroundValue, false); ByteProcessor maxIp = null; if (USES_MAX_FINDER[processType]) { if (processType == VORONOI) floatEdm.multiply(-1); // Voronoi starts from minima of EDM int maxOutputType = USES_WATERSHED[processType] ? MaximumFinder.SEGMENTED : MaximumFinder.SINGLE_POINTS; boolean isEDM = processType != VORONOI; maxIp = maxFinder.findMaxima( floatEdm, MAXFINDER_TOLERANCE, ImageProcessor.NO_THRESHOLD, maxOutputType, false, isEDM); if (maxIp == null) { // segmentation cancelled by user? interrupted = true; return; } else if (processType != WATERSHED) { if (processType == VORONOI) floatEdm.multiply(-1); resetMasked(floatEdm, maxIp, processType == VORONOI ? -1 : 0); } } ImageProcessor outIp = null; if (processType == WATERSHED) { if (background255) maxIp.invert(); ip.copyBits(maxIp, 0, 0, Blitter.COPY); ip.setBinaryThreshold(); } else switch (outImageType) { // for all these, output contains the values of the EDM case FLOAT: outIp = floatEdm; break; case SHORT: floatEdm.setMinAndMax(0., 65535.); outIp = floatEdm.convertToShort(true); break; case BYTE: floatEdm.setMinAndMax(0., 255.); outIp = floatEdm.convertToByte(true); break; case BYTE_OVERWRITE: ip.setPixels(0, floatEdm); if (floatEdm.getMax() > 255.) ip.resetMinAndMax(); // otherwise we have max of floatEdm } if (outImageType != BYTE_OVERWRITE) { // new output image if (outStack == null) { outImp = new ImagePlus(TITLE_PREFIX[processType] + imp.getShortTitle(), outIp); } else outStack.setPixels(outIp.getPixels(), pfr.getSliceNumber()); } } // public void run