예제 #1
0
 /**
  * Calculates a 16-bit grayscale Euclidean Distance Map for a binary 8-bit image. Each foreground
  * (nonzero) pixel in the binary image is assigned a value equal to its distance from the nearest
  * background (zero) pixel, multiplied by EDM.ONE. For compatibility with previous versions of
  * ImageJ only.
  */
 public ShortProcessor make16bitEDM(ImageProcessor ip) {
   FloatProcessor floatEdm = makeFloatEDM(ip, 0, false);
   floatEdm.setMinAndMax(0, 65535. / ONE);
   return (ShortProcessor) floatEdm.convertToShort(true);
 }
  /**
   * Computes the geodesic distance function for each pixel in mask, using the given mask. Mask and
   * marker should be ImageProcessor the same size and containing float values. The function returns
   * a new Float processor the same size as the input, with values greater or equal to zero.
   */
  @Override
  public FloatProcessor geodesicDistanceMap(ImageProcessor marker, ImageProcessor mask) {
    // size of image
    width = mask.getWidth();
    height = mask.getHeight();

    // update mask
    this.maskProc = mask;

    // create new empty image, and fill it with black
    FloatProcessor result = new FloatProcessor(width, height);
    result.setValue(0);
    result.fill();

    // initialize empty image with either 0 (foreground) or Inf (background)
    array = result.getFloatArray();
    for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
        int val = marker.get(i, j) & 0x00ff;
        array[i][j] = val == 0 ? backgroundValue : 0;
      }
    }

    int iter = 0;
    do {
      modif = false;

      // forward iteration
      IJ.showStatus("Forward iteration " + iter);
      forwardIteration();

      // backward iteration
      IJ.showStatus("Backward iteration " + iter);
      backwardIteration();

      // Iterate while pixels have been modified
      iter++;
    } while (modif);

    // Normalize values by the first weight
    if (this.normalizeMap) {
      for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
          array[i][j] /= this.weights[0];
        }
      }
    }

    // Compute max value within the mask
    float maxVal = 0;
    for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
        if (maskProc.getPixel(i, j) != 0) maxVal = Math.max(maxVal, array[i][j]);
      }
    }

    // update and return resulting Image processor
    result.setFloatArray(array);
    result.setMinAndMax(0, maxVal);
    // Forces the display to non-inverted LUT
    if (result.isInvertedLut()) result.invertLut();
    return result;
  }
예제 #3
0
  /** 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