public void reconstructOffline(ImagePlus imagePlus) throws Exception {
   ImagePlusDataSink sink = new ImagePlusDataSink();
   configure();
   init();
   for (int i = 0; i < imagePlus.getStackSize(); i++) {
     backproject(ImageUtil.wrapImageProcessor(imagePlus.getStack().getProcessor(i + 1)), i);
   }
   waitForResult();
   if (Configuration.getGlobalConfiguration().getUseHounsfieldScaling()) applyHounsfieldScaling();
   int[] size = projectionVolume.getSize();
   System.out.println(size[0] + " " + size[1] + " " + size[2]);
   for (int k = 0; k < projectionVolume.getSize()[2]; k++) {
     FloatProcessor fl =
         new FloatProcessor(projectionVolume.getSize()[0], projectionVolume.getSize()[1]);
     for (int j = 0; j < projectionVolume.getSize()[1]; j++) {
       for (int i = 0; i < projectionVolume.getSize()[0]; i++) {
         fl.putPixelValue(i, j, projectionVolume.getAtIndex(i, j, k));
       }
     }
     sink.process(projectionVolume.getSubGrid(k), k);
   }
   sink.close();
   ImagePlus revan =
       ImageUtil.wrapGrid3D(sink.getResult(), "Reconstruction of " + imagePlus.getTitle());
   revan.setTitle(imagePlus.getTitle() + " reconstructed");
   revan.show();
   reset();
 }
Example #2
0
  /** Refine segmentation with ADD/SUB regions of interests */
  private synchronized void refine() {
    if (controlPanel.status != ControlJPanel.SEGMENTATED_STATUS) return;

    if (controlPanel.addJRadioButton.isSelected()) addRoi = imp.getRoi();
    else subRoi = imp.getRoi();

    if (null != addRoi) {
      final float alpha = controlPanel.addThreshold.getValue() / 100.0f;
      final Shape shape = ShapeRoiHelper.getShape(new ShapeRoi(addRoi));
      final AffineTransform trans = new AffineTransform();
      trans.translate(addRoi.getBounds().getX(), addRoi.getBounds().getY());
      final Area area = new Area(shape);
      area.transform(trans);
      siox.subpixelRefine(area, SioxSegmentator.ADD_EDGE, alpha, (float[]) confMatrix.getPixels());
    }
    if (null != subRoi) {
      final float alpha = controlPanel.subThreshold.getValue() / 100.0f;
      final Shape shape = ShapeRoiHelper.getShape(new ShapeRoi(subRoi));
      final AffineTransform trans = new AffineTransform();
      trans.translate(subRoi.getBounds().getX(), subRoi.getBounds().getY());
      final Area area = new Area(shape);
      area.transform(trans);
      siox.subpixelRefine(area, SioxSegmentator.SUB_EDGE, alpha, (float[]) confMatrix.getPixels());
    }

    updateResult();
  }
  private void raytrace(double energyEV, int numRays) {
    Grid2D grid = new Grid2D(600, 500);
    FloatProcessor imp;
    imp = new FloatProcessor(grid.getWidth(), grid.getHeight());
    imp.setPixels(grid.getBuffer());

    //		 SimpleVector startPosition = new SimpleVector(40,grid.getHeight()/2/scale, 0);
    SimpleVector startPosition = new SimpleVector(0, 0, 0);

    for (int i = 0; i < numRays; ++i) {
      followRay(startPosition.clone(), new SimpleVector(1, 0, 0), energyEV, imp, 0, 0);
    }
    imp.drawString(
        grid.getWidth() / scale + "cm",
        grid.getWidth() / 2 - 20,
        grid.getHeight() - 10,
        Color.WHITE);

    grid.show("Energy: " + energyEV + "eV, Material: " + material.getName());

    System.out.println(
        "Rejection sampling: average misses per draw: " + (float) sumMisses / (float) numDraws);

    numDraws = 0;
    sumMisses = 0;
  }
Example #4
0
 int[] smooth(int[] a, int n) {
   FloatProcessor fp = new FloatProcessor(n, 1);
   for (int i = 0; i < n; i++) fp.putPixelValue(i, 0, a[i]);
   GaussianBlur gb = new GaussianBlur();
   gb.blur1Direction(fp, 2.0, 0.01, true, 0);
   for (int i = 0; i < n; i++) a[i] = (int) Math.round(fp.getPixelValue(i, 0));
   return a;
 }
Example #5
0
 float[] smooth(float[] a, int n) {
   FloatProcessor fp = new FloatProcessor(n, 1);
   for (int i = 0; i < n; i++) fp.setf(i, 0, a[i]);
   GaussianBlur gb = new GaussianBlur();
   gb.blur1Direction(fp, 2.0, 0.01, true, 0);
   for (int i = 0; i < n; i++) a[i] = fp.getf(i, 0);
   return a;
 }
Example #6
0
  protected static final FloatProcessor scaleByte(final ByteProcessor bp) {
    final FloatProcessor fp = new FloatProcessor(bp.getWidth(), bp.getHeight());
    final byte[] bytes = (byte[]) bp.getPixels();
    final float[] floats = (float[]) fp.getPixels();
    for (int i = 0; i < bytes.length; ++i) floats[i] = (bytes[i] & 0xff) / 255.0f;

    return fp;
  }
Example #7
0
  public static double[] getPixels(ImagePlus imp, int[] slices, int[] frames, int[] channels) {

    ImagePlus subImp = AccessImage.getSubHyperStack(imp, slices, frames, channels);
    ImageStack imageStack = subImp.getImageStack();

    double[] pixels = new double[subImp.getWidth() * subImp.getHeight() * imageStack.getSize()];

    for (int i = 0; i < imageStack.getSize(); i++) {
      switch (subImp.getType()) {
        case ImagePlus.GRAY8:
          ByteProcessor byteProcessor = (ByteProcessor) imageStack.getProcessor(i + 1);
          for (int iX = 0; iX < subImp.getWidth(); iX++) {
            for (int iY = 0; iY < subImp.getHeight(); iY++) {
              pixels[i * subImp.getWidth() * subImp.getHeight() + iY * subImp.getWidth() + iX] =
                  (double) byteProcessor.getPixelValue(iX, iY);
            }
          }
          break;
        case ImagePlus.GRAY16:
          ShortProcessor shortProcessor = (ShortProcessor) imageStack.getProcessor(i + 1);
          for (int iX = 0; iX < subImp.getWidth(); iX++) {
            for (int iY = 0; iY < subImp.getHeight(); iY++) {
              pixels[i * subImp.getWidth() * subImp.getHeight() + iY * subImp.getWidth() + iX] =
                  (double) shortProcessor.getPixelValue(iX, iY);
            }
          }
          break;
        case ImagePlus.GRAY32:
          FloatProcessor floatProcessor = (FloatProcessor) imageStack.getProcessor(i + 1);
          for (int iX = 0; iX < subImp.getWidth(); iX++) {
            for (int iY = 0; iY < subImp.getHeight(); iY++) {
              pixels[i * subImp.getWidth() * subImp.getHeight() + iY * subImp.getWidth() + iX] =
                  (double) floatProcessor.getPixelValue(iX, iY);
            }
          }
          break;
        case ImagePlus.COLOR_RGB:
          ColorProcessor colorProcessor = (ColorProcessor) imageStack.getProcessor(i + 1);
          int nX = subImp.getWidth();
          int nY = subImp.getHeight();
          byte[] red = new byte[nX * nY];
          byte[] green = new byte[nX * nY];
          byte[] blue = new byte[nX * nY];
          colorProcessor.getRGB(red, green, blue);
          int r, g, b;

          for (int j = 0; j < nX * nY; j++) {
            r = red[j] << 16;
            g = green[j] << 8;
            b = blue[j] << 0;
            pixels[i * nX * nY + j] = (double) (r + g + b);
          }
          break;
      }
    }

    return (pixels);
  }
 /**
  * Creates a new FloatProcessor using the specified FloatProcessor. Set 'cm' to null to use the
  * default grayscale LUT.
  */
 public SerializableFloatProcessor(FloatProcessor floatProcessor) {
   floatProcessor = (FloatProcessor) floatProcessor.duplicate();
   this.width = floatProcessor.getWidth();
   this.height = floatProcessor.getHeight();
   this.pixels = (float[]) floatProcessor.getPixels();
   this.cm = floatProcessor.getColorModel();
   resetRoi();
   if (pixels != null) findMinAndMax();
 }
Example #9
0
  /** Performs actual projection using specified method. */
  public void doProjection() {
    if (imp == null) return;
    sliceCount = 0;
    if (method < AVG_METHOD || method > MEDIAN_METHOD) method = AVG_METHOD;
    for (int slice = startSlice; slice <= stopSlice; slice += increment) sliceCount++;
    if (method == MEDIAN_METHOD) {
      projImage = doMedianProjection();
      return;
    }

    // Create new float processor for projected pixels.
    FloatProcessor fp = new FloatProcessor(imp.getWidth(), imp.getHeight());
    ImageStack stack = imp.getStack();
    RayFunction rayFunc = getRayFunction(method, fp);
    if (IJ.debugMode == true) {
      IJ.log("\nProjecting stack from: " + startSlice + " to: " + stopSlice);
    }

    // Determine type of input image. Explicit determination of
    // processor type is required for subsequent pixel
    // manipulation.  This approach is more efficient than the
    // more general use of ImageProcessor's getPixelValue and
    // putPixel methods.
    int ptype;
    if (stack.getProcessor(1) instanceof ByteProcessor) ptype = BYTE_TYPE;
    else if (stack.getProcessor(1) instanceof ShortProcessor) ptype = SHORT_TYPE;
    else if (stack.getProcessor(1) instanceof FloatProcessor) ptype = FLOAT_TYPE;
    else {
      IJ.error("Z Project", "Non-RGB stack required");
      return;
    }

    // Do the projection.
    for (int n = startSlice; n <= stopSlice; n += increment) {
      IJ.showStatus("ZProjection " + color + ": " + n + "/" + stopSlice);
      IJ.showProgress(n - startSlice, stopSlice - startSlice);
      projectSlice(stack.getPixels(n), rayFunc, ptype);
    }

    // Finish up projection.
    if (method == SUM_METHOD) {
      fp.resetMinAndMax();
      projImage = new ImagePlus(makeTitle(), fp);
    } else if (method == SD_METHOD) {
      rayFunc.postProcess();
      fp.resetMinAndMax();
      projImage = new ImagePlus(makeTitle(), fp);
    } else {
      rayFunc.postProcess();
      projImage = makeOutputImage(imp, fp, ptype);
    }

    if (projImage == null) IJ.error("Z Project", "Error computing projection.");
  }
  /**
   * Retrieve float data of 32 bits images
   *
   * @param imp : image to analyze
   * @return float array with data for each pixel
   */
  public static float[] getFloatData(ImagePlus imp) {
    float[] imagefloat = null;
    for (int i = 0; i < imp.getStackSize(); i++) {
      FloatProcessor fp = (FloatProcessor) imp.getImageStack().getProcessor(i + 1).duplicate();
      if (i == 0) imagefloat = (float[]) fp.getPixels();
      else imagefloat = (float[]) ArrayUtils.addAll(imagefloat, (float[]) fp.getPixels());
      System.out.println("slice : " + (i + 1) + "/" + imp.getStackSize());
    }

    return imagefloat;
  }
Example #11
0
  /**
   * Convert VectorProcessor to an array of {@link FloatProcessor}'s.
   *
   * @return this VectorProcessor represented as an array of {@link FloatProcessor}'s
   * @see #toFloatStack()
   */
  public FloatProcessor[] toFloatProcessors() {
    final FloatProcessor[] r = new FloatProcessor[numberOfValues];
    for (int i = 0; i < numberOfValues; ++i) {
      final FloatProcessor fp = new FloatProcessor(width, height);
      final float[] values = (float[]) fp.getPixels();
      for (int j = 0; j < values.length; j++) {
        values[j] = pixels[j][i];
      }
      r[i] = fp;
    }

    return r;
  }
Example #12
0
  @Override
  public boolean run(JEXEntry optionalEntry) {
    if (imageData == null || !imageData.getTypeName().getType().equals(JEXData.IMAGE)) {
      return false;
    }

    // Run the function
    TreeMap<DimensionMap, String> images = ImageReader.readObjectToImagePathTable(imageData);
    TreeMap<DimensionMap, String> outputMap = new TreeMap<DimensionMap, String>();

    int count = 0;
    int total = images.size();
    for (DimensionMap dim : images.keySet()) {

      if (this.isCanceled()) {
        return false;
      }

      String path = images.get(dim);
      // File f = new File(path);

      // get the image
      ImagePlus im = new ImagePlus(path);
      ij.process.ImageProcessor imProc = im.getProcessor();
      if (imProc == null) continue;
      FloatProcessor imp =
          (FloatProcessor) im.getProcessor().convertToFloat(); // should be a float processor

      int newWidth = (int) (imp.getWidth() * scale);
      imp.setInterpolationMethod(ImageProcessor.BILINEAR);
      imp = (FloatProcessor) imp.resize(newWidth);

      ImagePlus toSave = FunctionUtility.makeImageToSave(imp, "false", bitDepth);
      String finalPath = JEXWriter.saveImage(toSave);

      outputMap.put(dim.copy(), finalPath);
      Logs.log("Finished processing " + count + " of " + total + ".", 1, this);
      count++;

      // Status bar
      int percentage = (int) (100 * ((double) count / (double) images.size()));
      JEXStatics.statusBar.setProgressPercentage(percentage);
    }

    // Set the outputs
    output = ImageWriter.makeImageStackFromPaths("temp", outputMap);
    output.setDataObjectInfo("Stack binned using binning function");

    // Return status
    return true;
  }
Example #13
0
  /**
   * Creates the Euclidian Distance Map of a (binary) byte image.
   *
   * @param ip The input image, not modified; must be a ByteProcessor.
   * @param backgroundValue Pixels in the input with this value are interpreted as background. Note:
   *     for pixel value 255, write either -1 or (byte)255.
   * @param edgesAreBackground Whether out-of-image pixels are considered background
   * @return The EDM, containing the distances to the nearest background pixel. Returns null if the
   *     thread is interrupted.
   */
  public FloatProcessor makeFloatEDM(
      ImageProcessor ip, int backgroundValue, boolean edgesAreBackground) {
    int width = ip.getWidth();
    int height = ip.getHeight();
    FloatProcessor fp = new FloatProcessor(width, height);
    byte[] bPixels = (byte[]) ip.getPixels();
    float[] fPixels = (float[]) fp.getPixels();
    final int progressInterval = 100;
    int nProgressUpdates =
        height
            / progressInterval; // how often the progress bar is updated when passing once through y
    // range
    double progressAddendum = (nProgressUpdates > 0) ? 0.5 / nProgressUpdates : 0;

    for (int i = 0; i < width * height; i++)
      if (bPixels[i] != backgroundValue) fPixels[i] = Float.MAX_VALUE;

    int[][] pointBufs =
        new int[2][width]; // two buffers for two passes; low short contains x, high short y
    int yDist = Integer.MAX_VALUE; // this value is used only if edges are not background
    // pass 1 & 2: increasing y
    for (int x = 0; x < width; x++) {
      pointBufs[0][x] = NO_POINT;
      pointBufs[1][x] = NO_POINT;
    }
    for (int y = 0; y < height; y++) {
      if (edgesAreBackground) yDist = y + 1; // distance to nearest background point (along y)
      edmLine(bPixels, fPixels, pointBufs, width, y * width, y, backgroundValue, yDist);
      if (y % progressInterval == 0) {
        if (Thread.currentThread().isInterrupted()) return null;
        addProgress(progressAddendum);
      }
    }
    // pass 3 & 4: decreasing y
    for (int x = 0; x < width; x++) {
      pointBufs[0][x] = NO_POINT;
      pointBufs[1][x] = NO_POINT;
    }
    for (int y = height - 1; y >= 0; y--) {
      if (edgesAreBackground) yDist = height - y;
      edmLine(bPixels, fPixels, pointBufs, width, y * width, y, backgroundValue, yDist);
      if (y % progressInterval == 0) {
        if (Thread.currentThread().isInterrupted()) return null;
        addProgress(progressAddendum);
      }
    }

    fp.sqrt();
    return fp;
  } // public FloatProcessor makeFloatEDM
Example #14
0
  void SMLblur1Direction(
      final FloatProcessor ippp,
      final double sigma,
      final double accuracy,
      final boolean xDirection,
      final int extraLines) {

    final float[] pixels = (float[]) ippp.getPixels();
    final int width = ippp.getWidth();
    final int height = ippp.getHeight();
    final int length =
        xDirection ? width : height; // number of points per line (line can be a row or column)
    final int pointInc =
        xDirection ? 1 : width; // increment of the pixels array index to the next poin a line
    final int lineInc =
        xDirection ? width : 1; // increment of the pixels array index to the next line
    final int lineFromA = 0 - extraLines; // the first line to process
    final int lineFrom;
    if (lineFromA < 0) lineFrom = 0;
    else lineFrom = lineFromA;
    final int lineToA = (xDirection ? height : width) + extraLines; // the last line+1 to process
    final int lineTo;
    if (lineToA > (xDirection ? height : width)) lineTo = (xDirection ? height : width);
    else lineTo = lineToA;
    final int writeFrom = 0; // first point of a line that needs to be written
    final int writeTo = xDirection ? width : height;

    final float[][] gaussKernel = lowpassGauss.makeGaussianKernel(sigma, accuracy, length);
    final int kRadius = gaussKernel[0].length; // Gaussian kernel radius after upscaling
    final int readFrom =
        (writeFrom - kRadius < 0)
            ? 0
            : writeFrom - kRadius; // not including broadening by downscale&upscale
    final int readTo = (writeTo + kRadius > length) ? length : writeTo + kRadius;
    final int newLength = length;

    final float[] cache1 =
        new float[newLength]; // holds data before convolution (after downscaling, if any)

    int pixel0 = 0;
    for (int line = lineFrom; line < lineTo; line++, pixel0 += lineInc) {
      int p = pixel0 + readFrom * pointInc;
      for (int i = readFrom; i < readTo; i++, p += pointInc) cache1[i] = pixels[p];
      SMLconvolveLine(
          cache1, pixels, gaussKernel, readFrom, readTo, writeFrom, writeTo, pixel0, pointInc);
    }

    return;
  }
Example #15
0
  /** Generate output image whose type is same as input image. */
  private ImagePlus makeOutputImage(ImagePlus imp, FloatProcessor fp, int ptype) {
    int width = imp.getWidth();
    int height = imp.getHeight();
    float[] pixels = (float[]) fp.getPixels();
    ImageProcessor oip = null;

    // Create output image consistent w/ type of input image.
    int size = pixels.length;
    switch (ptype) {
      case BYTE_TYPE:
        oip = imp.getProcessor().createProcessor(width, height);
        byte[] pixels8 = (byte[]) oip.getPixels();
        for (int i = 0; i < size; i++) pixels8[i] = (byte) pixels[i];
        break;
      case SHORT_TYPE:
        oip = imp.getProcessor().createProcessor(width, height);
        short[] pixels16 = (short[]) oip.getPixels();
        for (int i = 0; i < size; i++) pixels16[i] = (short) pixels[i];
        break;
      case FLOAT_TYPE:
        oip = new FloatProcessor(width, height, pixels, null);
        break;
    }

    // Adjust for display.
    // Calling this on non-ByteProcessors ensures image
    // processor is set up to correctly display image.
    oip.resetMinAndMax();

    // Create new image plus object. Don't use
    // ImagePlus.createImagePlus here because there may be
    // attributes of input image that are not appropriate for
    // projection.
    return new ImagePlus(makeTitle(), oip);
  }
Example #16
0
 // set values in floatEdm to zero if pixel in mask equals 'resetOnThis'
 private void resetMasked(FloatProcessor floatEdm, ImageProcessor mask, int resetOnThis) {
   int width = mask.getWidth();
   int height = mask.getHeight();
   byte[] mPixels = (byte[]) mask.getPixels();
   float[] fPixels = (float[]) floatEdm.getPixels();
   for (int i = 0; i < width * height; i++) if (mPixels[i] == resetOnThis) fPixels[i] = 0;
 }
Example #17
0
 public StandardDeviation(FloatProcessor fp, int num) {
   result = (float[]) fp.getPixels();
   len = result.length;
   this.num = num;
   sum = new double[len];
   sum2 = new double[len];
 }
Example #18
0
 /** Produce a binary image based on the current confidence matrix */
 private void createBinaryMask() {
   if (null != confMatrix) {
     final ByteProcessor result = (ByteProcessor) confMatrix.convertToByte(false);
     result.multiply(255);
     // Set background color based on the Process > Binary > Options
     if (!Prefs.blackBackground) result.invert();
     new ImagePlus("Mask", result).show();
   }
 }
Example #19
0
 // overwrite ip with floatEdm converted to bytes
 private void byteFromFloat(ImageProcessor ip, FloatProcessor floatEdm) {
   int width = ip.getWidth();
   int height = ip.getHeight();
   byte[] bPixels = (byte[]) ip.getPixels();
   float[] fPixels = (float[]) floatEdm.getPixels();
   for (int i = 0; i < width * height; i++) {
     float v = fPixels[i];
     bPixels[i] = v < 255f ? (byte) (v + 0.5) : (byte) 255;
   }
 }
  protected void copyProjectionViews() throws Exception {
    FloatProcessor currentProjection;
    for (int ip = 0; ip < nImages; ip++) {
      try {
        Grid2D projection = inputQueue.get(ip);
        currentProjection =
            new FloatProcessor(
                projection.getWidth(), projection.getHeight(), projection.getBuffer(), null);

        for (int iu = 0; iu <= maxU; iu++) {
          for (int iv = 0; iv <= maxV; iv++) {
            // there may be a problem
            projectionViews.setAtIndex(ip, iu, iv, currentProjection.getf(iu, iv));
          }
        }
      } catch (Exception e) {
        System.out.println("An error occured during copying projection views " + ip);
      }
    }
  }
Example #21
0
  public static ImagePlus asImagePlus(
      String title, double[] data, int width, int height, int nSlices, int nFrames, int nChannels) {
    ImageStack imageStack = new ImageStack(width, height);
    FloatProcessor ip = null;
    for (int i = 0; i < nSlices * nFrames * nChannels; i++) {
      ip = new FloatProcessor(width, height);
      for (int iX = 0; iX < width; iX++) {
        for (int iY = 0; iY < height; iY++) {
          ip.putPixelValue(iX, iY, data[i * height * width + iY * width + iX]);
        }
      }
      imageStack.addSlice(ip);
    }

    ImagePlus resImp = new ImagePlus(title, imageStack);
    resImp.setOpenAsHyperStack(true);
    resImp.setDimensions(nChannels, nSlices, nFrames);

    return resImp;
  }
Example #22
0
  /** Update the result overlay with the current matrix of confidence */
  private void updateResult() {
    imp.killRoi();
    roiOverlay.setRoi(null);

    ImageProcessor cp = confMatrix.convertToRGB();
    cp.multiply(1.0 / 255.0);
    cp.copyBits(ip, 0, 0, Blitter.MULTIPLY);

    resultOverlay.setImage(cp);

    imp.changes = true;
    imp.updateAndDraw();
  }
  private void followRay(
      SimpleVector pos,
      SimpleVector dir,
      double energyEV,
      FloatProcessor imp,
      int scatterCount,
      double totalDistance) {
    if (energyEV <= 1 || scatterCount > 20000) {
      System.out.println("energy low, times scattered: " + scatterCount);
      return;
    }
    // follow ray until next interaction point
    SimpleVector oldPos = pos.clone();
    double dist = sampler.getDistanceUntilNextInteractionCm(material, energyEV);
    pos.add(dir.multipliedBy(dist));
    pathlengths.add(dist);
    // draw the entire path
    // imp.drawLine((int)(scale*oldPos.getElement(0)), (int)(scale*oldPos.getElement(1)),
    // (int)(scale*pos.getElement(0)), (int)(scale*pos.getElement(1)));
    // draw interaction points only
    imp.drawDot((int) (scale * pos.getElement(0)), (int) (scale * pos.getElement(1)));

    // choose compton or photoelectric effect
    double photo =
        material.getAttenuation(energyEV / 1000, AttenuationType.PHOTOELECTRIC_ABSORPTION);
    double compton =
        material.getAttenuation(energyEV / 1000, AttenuationType.INCOHERENT_ATTENUATION);

    if (sampler.random() * (photo + compton) <= photo) {
      // photoelectric absorption
      energyEV = 0;
      // System.out.println("absorbed after " + scatterCount + " collisions");
      xs.add(pos.getElement(0));
      ys.add(pos.getElement(1));
      zs.add(pos.getElement(2));

      return;
    } else {
      // compton scattering

      energyEV = sampler.sampleComptonScattering(energyEV, dir);

      // send new ray
      followRay(pos, dir, energyEV, imp, scatterCount + 1, totalDistance + dist);
    }
  }
Example #24
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);
 }
Example #25
0
  public static ImagePlus subtract(ImagePlus a, ImagePlus b) {

    boolean silent = (IJ.getInstance() == null);

    int nX = a.getWidth();
    int nY = a.getHeight();
    int nSlices = a.getNSlices();
    int nFrames = a.getNFrames();
    int nChannels = a.getNChannels();

    if ((nX != b.getWidth())
        || (nY != b.getHeight())
        || (nSlices != b.getNSlices())
        || (nFrames != b.getNFrames())
        || (nChannels != b.getNChannels())) {
      if (silent) {
        System.out.println("Subtract: image dimensions do not match, return nothing.");
      } else {
        IJ.showMessage("Subtract: image dimensions do not match, return nothing.");
      }
    }

    ImageStack resIms = new ImageStack(nX, nY);
    FloatProcessor fp;
    ImageProcessor ip1, ip2;

    int total = nSlices * nFrames * nChannels;
    double prog = 0;

    if (silent) {
      System.out.println("SUBSTRACTING BACKGROUND");
    } else {
      IJ.showStatus("SUBSTRACTING BACKGROUND");
    }

    for (int i = 0; i < nChannels; i++) {
      for (int j = 0; j < nFrames; j++) {

        for (int k = 0; k < nSlices; k++) {
          if (silent) {
            FNTDprogress.updateProgress(prog / total);
          } else {
            IJ.showProgress(prog / total);
          }

          prog++;

          a.setPosition(i + 1, k + 1, j + 1);
          b.setPosition(i + 1, k + 1, j + 1);
          ip1 = a.getProcessor();
          ip2 = b.getProcessor();
          fp = new FloatProcessor(nX, nY);

          for (int m = 0; m < nX; m++) {
            for (int n = 0; n < nY; n++) {
              fp.putPixelValue(m, n, ip1.getPixelValue(m, n) - ip2.getPixelValue(m, n));
            }
          }
          resIms.addSlice(fp);
        }
      }
    }
    FNTDprogress.updateProgress(1);
    System.out.println("");

    ImagePlus resImp = new ImagePlus("Result of" + a.getTitle() + "-" + b.getTitle(), resIms);
    if (resIms.getSize() > 1) {
      resImp =
          HyperStackConverter.toHyperStack(
              resImp, nChannels, nSlices, nFrames, "xyztc", "grayscale");
    }
    return (resImp);
  }
  @Override
  public Grid2D applyToolToImage(Grid2D imageProcessor) {
    FloatProcessor imp = new FloatProcessor(imageProcessor.getWidth(), imageProcessor.getHeight());
    imp.setPixels(imageProcessor.getBuffer());

    if (!initBead) initializeBead();
    ImageProcessor imp1 = imp.duplicate(); // original

    double[][] beadMean3D = config.getBeadMeanPosition3D(); // [beadNo][x,y,z]
    double[] uv = new double[1];

    SimpleMatrix pMatrix = config.getGeometry().getProjectionMatrix(imageIndex).computeP();
    // [projection #][bead #][u, v, state[0: initial, 1: registered, 2: updated by hough searching]]
    double[][][] beadPosition2D = config.getBeadPosition2D();

    int noBeadRegistered = 0;

    double[][] xy1 = new double[WeightBearingBeadPositionBuilder.beadNo][2]; // original
    double[][] xy2 =
        new double[WeightBearingBeadPositionBuilder.beadNo]
            [2]; // warped	(mapped to the mean), control points, reference

    double[][] xy1_hat = new double[WeightBearingBeadPositionBuilder.beadNo][2]; // original
    double[][] xy2_hat = new double[WeightBearingBeadPositionBuilder.beadNo][2]; // original

    // double distanceReferenceToCurrentBead = 0;

    for (int i = WeightBearingBeadPositionBuilder.currentBeadNo; i >= 0; i--) {

      if (beadMean3D[i][0] != 0
          || beadMean3D[i][1] != 0
          || beadMean3D[i][2] != 0) { // assume bead 3d is registered.

        uv = compute2DCoordinates(beadMean3D[i], pMatrix);

        // find bead location if registered by txt: state 1
        if (beadPosition2D[imageIndex][i][2] == 1) {

          noBeadRegistered++;

          if (isDisplay) {
            imp1.setValue(2);
            imp1.drawLine(
                (int) Math.round(beadPosition2D[imageIndex][i][0] - 10),
                (int) Math.round(beadPosition2D[imageIndex][i][1] - 10),
                (int) Math.round(beadPosition2D[imageIndex][i][0] + 10),
                (int) Math.round(beadPosition2D[imageIndex][i][1] + 10));
            imp1.drawLine(
                (int) Math.round(beadPosition2D[imageIndex][i][0] - 10),
                (int) Math.round(beadPosition2D[imageIndex][i][1] + 10),
                (int) Math.round(beadPosition2D[imageIndex][i][0] + 10),
                (int) Math.round(beadPosition2D[imageIndex][i][1] - 10));
            imp1.drawString(
                "Bead " + i + " (state:" + (int) beadPosition2D[imageIndex][i][2] + ")",
                (int) beadPosition2D[imageIndex][i][0],
                (int) beadPosition2D[imageIndex][i][1] - 10);
          }

          xy1[noBeadRegistered - 1][0] = beadPosition2D[imageIndex][i][0];
          xy1[noBeadRegistered - 1][1] = beadPosition2D[imageIndex][i][1];

          xy2[noBeadRegistered - 1][0] = uv[0];
          xy2[noBeadRegistered - 1][1] = uv[1];

        } else if (imageIndex != 0
            && imageIndex != config.getGeometry().getNumProjectionMatrices() - 1) {

          if (beadPosition2D[imageIndex - 1][i][2] == 1
              && beadPosition2D[imageIndex + 1][i][2] == 1) {

            noBeadRegistered++;

            double xMean =
                (beadPosition2D[imageIndex - 1][i][0] + beadPosition2D[imageIndex - 1][i][0]) / 2;
            double yMean =
                (beadPosition2D[imageIndex + 1][i][1] + beadPosition2D[imageIndex + 1][i][1]) / 2;

            if (isDisplay) {
              imp1.setValue(2);
              imp1.drawLine(
                  (int) Math.round(xMean - 10),
                  (int) Math.round(yMean - 10),
                  (int) Math.round(xMean + 10),
                  (int) Math.round(yMean + 10));
              imp1.drawLine(
                  (int) Math.round(xMean - 10),
                  (int) Math.round(yMean + 10),
                  (int) Math.round(xMean + 10),
                  (int) Math.round(yMean - 10));
              imp1.drawString("Bead " + i + " (state:" + "M)", (int) xMean, (int) yMean - 10);
            }

            xy1[noBeadRegistered - 1][0] = xMean;
            xy1[noBeadRegistered - 1][1] = yMean;

            xy2[noBeadRegistered - 1][0] = uv[0];
            xy2[noBeadRegistered - 1][1] = uv[1];
          }
        }

        // mean projected bead
        //				imp1.drawLine((int) Math.round(uv[0]-10), (int) Math.round(uv[1]), (int)
        // Math.round(uv[0]+10), (int) Math.round(uv[1]));
        //				imp1.drawLine((int) Math.round(uv[0]), (int) Math.round(uv[1]-10), (int)
        // Math.round(uv[0]), (int) Math.round(uv[1]+10));
      }
    }

    if (isDisplay) {
      for (int x = 0; x < config.getGeometry().getDetectorWidth(); x += 50)
        imp1.drawLine(x, 0, x, config.getGeometry().getDetectorHeight());
      for (int y = 0; y < config.getGeometry().getDetectorHeight(); y += 50)
        imp1.drawLine(0, y, config.getGeometry().getDetectorWidth(), y);
    }

    if (isCornerIncluded) {
      xy1[noBeadRegistered + 0][0] = 0;
      xy1[noBeadRegistered + 0][1] = 0;
      xy2[noBeadRegistered + 0][0] = 0;
      xy2[noBeadRegistered + 0][1] = 0;

      xy1[noBeadRegistered + 1][0] = 0;
      xy1[noBeadRegistered + 1][1] = config.getGeometry().getDetectorHeight();
      xy2[noBeadRegistered + 1][0] = 0;
      xy2[noBeadRegistered + 1][1] = config.getGeometry().getDetectorHeight();

      xy1[noBeadRegistered + 2][0] = config.getGeometry().getDetectorWidth();
      xy1[noBeadRegistered + 2][1] = 0;
      xy2[noBeadRegistered + 2][0] = config.getGeometry().getDetectorWidth();
      xy2[noBeadRegistered + 2][1] = 0;

      xy1[noBeadRegistered + 3][0] = config.getGeometry().getDetectorWidth();
      xy1[noBeadRegistered + 3][1] = config.getGeometry().getDetectorHeight();
      xy2[noBeadRegistered + 3][0] = config.getGeometry().getDetectorWidth();
      xy2[noBeadRegistered + 3][1] = config.getGeometry().getDetectorHeight();

      noBeadRegistered = noBeadRegistered + 4;
    }

    boolean fScaling = true;

    double minX = Double.MAX_VALUE;
    double maxX = 0;
    double minY = Double.MAX_VALUE;
    double maxY = 0;
    double c = 0;
    if (fScaling) { // ----- scaling to reduce condition # of A matrix
      for (int i = 0; i < noBeadRegistered; i++) {
        minX = Math.min(minX, xy1[i][0]);
        maxX = Math.max(maxX, xy1[i][0]);
        minY = Math.min(minY, xy1[i][1]);
        maxY = Math.max(maxY, xy1[i][1]);
      }
      c = Math.max(maxX - minX, maxY - minY);

      for (int i = 0; i < noBeadRegistered; i++) {
        xy1_hat[i][0] = (xy1[i][0] - minX) / c;
        xy1_hat[i][1] = (xy1[i][1] - minY) / c;

        xy2_hat[i][0] = (xy2[i][0] - minX) / c;
        xy2_hat[i][1] = (xy2[i][1] - minY) / c;
      }
    } else {
      xy1_hat = xy1;
      xy2_hat = xy2;
    }

    ImageProcessor imp2 = imp1.duplicate(); // warped

    /*
     * A*x = b
     * Matrix A = (n + 3) * (n + 3);
     * n (noBeadRegistered + 4): # of control points + 4 corner points (assume corner points are static)
     */

    int n = noBeadRegistered + 3;

    SimpleMatrix A = new SimpleMatrix(n, n);
    SimpleVector x_x = new SimpleVector(n);
    SimpleVector x_y = new SimpleVector(n);
    SimpleVector b_x = new SimpleVector(n);
    SimpleVector b_y = new SimpleVector(n);

    double rij = 0;
    double valA = 0;
    double valb_x = 0;
    double valb_y = 0;

    // Matrix L formation
    // alpha: mean of distances between control points' xy-projections) is a constant only present
    // on the diagonal of K
    // lambda: TPS smoothing regularization coefficient

    double alpha = 0.0;
    double lambda = 1.6; // 1.6
    for (int i = 0; i < noBeadRegistered; i++) { // i= # of row
      for (int j = i; j < noBeadRegistered; j++) { // j= # of column
        alpha +=
            Math.sqrt(
                Math.pow(xy2_hat[i][0] - xy2_hat[j][0], 2)
                    + Math.pow(xy2_hat[i][1] - xy2_hat[j][1], 2));
      }
    }
    alpha = alpha / Math.pow(noBeadRegistered, 2);

    for (int i = 0; i < n; i++) { // i= # of row
      for (int j = i; j < n; j++) { // j= # of column
        if (i < 3 && j < 3) valA = 0;
        else if (i >= 3 && j >= 3 && i == j) {
          valA = Math.pow(alpha, 2) * lambda;
          // valA = lambda;
          if (imageIndex < 10)
            System.out.println("Regularization = " + valA + ", lambda= " + lambda);
        } else if (i == 0 && j >= 0) valA = 1;
        else if (i == 1 && j >= 3) valA = xy1_hat[j - 3][0];
        else if (i == 2 && j >= 3) valA = xy1_hat[j - 3][1];
        else {
          rij =
              Math.pow(xy1_hat[j - 3][0] - xy1_hat[i - 3][0], 2)
                  + Math.pow(xy1_hat[j - 3][1] - xy1_hat[i - 3][1], 2);
          if (rij == 0) valA = 0;
          else valA = rij * Math.log(rij);
        }

        A.setElementValue(i, j, valA);
        A.setElementValue(j, i, valA);
      }

      if (i < 3) {
        valb_x = 0;
        valb_y = 0;
      } else {
        //				valb_x = xy2_hat[i-3][0]-xy1_hat[i-3][0];
        //				valb_y = xy2_hat[i-3][1]-xy1_hat[i-3][1];
        valb_x = xy2[i - 3][0] - xy1[i - 3][0];
        valb_y = xy2[i - 3][1] - xy1[i - 3][1];
        //				if (imageIndex > 150 && imageIndex < 170)
        //					System.out.println("Idx" + imageIndex + ",Elevation" + (i-3) + ": " + valb_x + "---"
        // + valb_y);
      }

      b_x.setElementValue(i, valb_x);
      b_y.setElementValue(i, valb_y);
    }

    // System.out.println("A condition number=" + A.conditionNumber(MatrixNormType.MAT_NORM_L1));
    // System.out.println("A condition number=" + A.conditionNumber(MatrixNormType.MAT_NORM_LINF));

    x_x = Solvers.solveLinearSysytemOfEquations(A, b_x);
    x_y = Solvers.solveLinearSysytemOfEquations(A, b_y);

    if (fScaling) {
      // ----- pixel space coefficients a, b scaling back
      double tmpA0 =
          x_x.getElement(0) - x_x.getElement(1) * (minX / c) - x_x.getElement(2) * (minY / c);
      for (int j = 0; j < noBeadRegistered; j++) {
        tmpA0 -=
            Math.log(c)
                * 2
                * x_x.getElement(j + 3)
                * (Math.pow(xy1_hat[j][0], 2) + Math.pow(xy1_hat[j][1], 2));
      }
      x_x.setElementValue(0, tmpA0);
      tmpA0 = x_y.getElement(0) - x_y.getElement(1) * (minX / c) - x_y.getElement(2) * (minY / c);
      for (int j = 0; j < noBeadRegistered; j++) {
        tmpA0 -=
            Math.log(c)
                * 2
                * x_y.getElement(j + 3)
                * (Math.pow(xy1_hat[j][0], 2) + Math.pow(xy1_hat[j][1], 2));
      }
      x_y.setElementValue(0, tmpA0);

      x_x.setElementValue(1, x_x.getElement(1) / c);
      x_y.setElementValue(1, x_y.getElement(1) / c);
      x_x.setElementValue(2, x_x.getElement(2) / c);
      x_y.setElementValue(2, x_y.getElement(2) / c);

      for (int i = 3; i < n; i++) {
        x_x.setElementValue(i, x_x.getElement(i) / Math.pow(c, 2));
        x_y.setElementValue(i, x_y.getElement(i) / Math.pow(c, 2));
      }
      // ----- pixel space coefficients a, b scaling back end
    }

    double devU = 0;
    double devV = 0;
    // Do warping
    // if (imageIndex == 0) {
    for (int y = 0; y < config.getGeometry().getDetectorHeight(); y++) {
      // for (int y=252; y<253; y++) {
      for (int x = 0; x < config.getGeometry().getDetectorWidth(); x++) {
        // for (int x=606; x<607; x++) {
        devU = x_x.getElement(0) + x_x.getElement(1) * x + x_x.getElement(2) * y;
        devV = x_y.getElement(0) + x_y.getElement(1) * x + x_y.getElement(2) * y;
        for (int i = 0; i < noBeadRegistered; i++) {
          rij = Math.pow(xy1[i][0] - x, 2) + Math.pow(xy1[i][1] - y, 2);
          if (rij > 0) {
            devU += x_x.getElement(i + 3) * rij * Math.log(rij);
            devV += x_y.getElement(i + 3) * rij * Math.log(rij);
          }
        }

        //					devU = 0;
        //					devV = 0;

        imp2.setf(x, y, (float) imp1.getInterpolatedValue(x - devU, y - devV));

        // System.out.println("x, y=" + x + ", " + y + "\t" + devU + ", " + devV);
        // maxDevU = Math.max(maxDevU, devU);
        // maxDevV = Math.max(maxDevV, devV);
      }
    }

    // Error estimate after transformation
    //			for (int i=0; i<= WeightBearingBeadPositionBuilder.currentBeadNo; i++){
    //
    //				if (beadMean3D[i][0] != 0 || beadMean3D[i][1] != 0 || beadMean3D[i][2] != 0){ // assume
    // bead 3d is registered.
    //
    //					// find bead location if registered by txt: state 1
    //					if (beadPosition2D[imageIndex][i][2] == 1){
    //
    //						// Projected Reference
    //						uv = compute2DCoordinates(beadMean3D[i], pMatrix);
    //						double x = uv[0];
    //						double y = uv[1];
    //						// bead detected position in 2d
    //						// Transform to 2D coordinates, time variant position
    //						//beadPosition2D[imageIndex][i][0];
    //						//beadPosition2D[imageIndex][i][1];
    //
    //						devU = x_x.getElement(0) + x_x.getElement(1)*x + x_x.getElement(2)*y;
    //						devV = x_y.getElement(0) + x_y.getElement(1)*x + x_y.getElement(2)*y;
    //						for (int j=0; j<noBeadRegistered; j++){
    //							rij = Math.pow(xy1[j][0]-x, 2) + Math.pow(xy1[j][1]-y, 2);
    //							if (rij > 0) {
    //								devU += x_x.getElement(j+3)*rij*Math.log(rij);
    //								devV += x_y.getElement(j+3)*rij*Math.log(rij);
    //							}
    //						}
    //
    //						distanceReferenceToCurrentBead +=
    // Math.sqrt(Math.pow(uv[0]-(beadPosition2D[imageIndex][i][0]+devU),
    // 2)+Math.pow(uv[1]-(beadPosition2D[imageIndex][i][1]+devV), 2));
    //
    //					}
    //				}
    //			}
    //			System.out.println("Euclidean distance\t" + imageIndex + "\t" +
    // distanceReferenceToCurrentBead/noBeadRegistered);

    // }

    if (isDisplay) {
      for (int i = WeightBearingBeadPositionBuilder.currentBeadNo; i >= 0; i--) {

        if (beadMean3D[i][0] != 0
            || beadMean3D[i][1] != 0
            || beadMean3D[i][2] != 0) { // assume bead 3d is registered.

          uv = compute2DCoordinates(beadMean3D[i], pMatrix);

          imp2.setValue(2);
          // mean projected bead
          imp2.drawLine(
              (int) Math.round(uv[0] - 10),
              (int) Math.round(uv[1]),
              (int) Math.round(uv[0] + 10),
              (int) Math.round(uv[1]));
          imp2.drawLine(
              (int) Math.round(uv[0]),
              (int) Math.round(uv[1] - 10),
              (int) Math.round(uv[0]),
              (int) Math.round(uv[1] + 10));
        }
      }
    }
    Grid2D result = new Grid2D((float[]) imp2.getPixels(), imp2.getWidth(), imp2.getHeight());
    return result;
  }
  /**
   * Create ImagePlusExtended object from primary array (byte, short ....)
   *
   * @param title : title of the image
   * @param object : array
   * @param showImage : display image if true
   * @return ImagePlusExtended
   */
  public static ImagePlusExtended createImage(String title, Object object, boolean showImage) {
    ImagePlusExtended imp = null;
    int i = 0;
    if (object instanceof byte[][]) {
      byte[][] is = (byte[][]) object;
      int height = is.length;
      int width = is[0].length;
      ByteProcessor byteprocessor = new ByteProcessor(width, height);
      byte[] bp = (byte[]) byteprocessor.getPixels();
      int h = 0;
      while (h < height) {
        int w = 0;
        while (w < width) {
          bp[i] = is[h][w];
          w++;
          i++;
        }
        i = ++h * width;
      }
      imp = new ImagePlusExtended(title, byteprocessor);

    } else if (object instanceof short[][]) {
      short[][] is = (short[][]) object;
      int height = is.length;
      int width = is[0].length;
      ShortProcessor shortprocessor = new ShortProcessor(width, height);
      short[] sp = (short[]) shortprocessor.getPixels();
      int h = 0;
      while (h < height) {
        int w = 0;
        while (w < width) {
          sp[i] = is[h][w];
          w++;
          i++;
        }
        i = ++h * width;
      }
      imp = new ImagePlusExtended(title, shortprocessor);

    } else if (object instanceof int[][]) {
      int[][] is = (int[][]) object;
      int height = is.length;
      int width = is[0].length;
      ShortProcessor shortprocessor = new ShortProcessor(width, height);
      short[] sp = (short[]) shortprocessor.getPixels();
      int h = 0;
      while (h < height) {
        int w = 0;
        while (w < width) {
          sp[i] = (short) is[h][w];
          w++;
          i++;
        }
        i = ++h * width;
      }
      imp = new ImagePlusExtended(title, shortprocessor);
    } else if (object instanceof float[][]) {
      float[][] fs = (float[][]) object;
      int height = fs.length;
      int width = fs[0].length;
      FloatProcessor floatprocessor = new FloatProcessor(width, height);
      float[] fp = (float[]) floatprocessor.getPixels();
      int h = 0;
      while (h < height) {
        int w = 0;
        while (w < width) {
          fp[i] = fs[h][w];
          w++;
          i++;
        }
        i = ++h * width;
      }
      floatprocessor.resetMinAndMax();
      imp = new ImagePlusExtended(title, floatprocessor);

    } else if (object instanceof double[][]) {
      double[][] ds = (double[][]) object;
      int height = ds.length;
      int width = ds[0].length;
      FloatProcessor floatprocessor = new FloatProcessor(width, height);
      float[] fp = (float[]) floatprocessor.getPixels();
      int h = 0;
      while (h < height) {
        int w = 0;
        while (w < width) {
          fp[i] = (float) ds[h][w];
          w++;
          i++;
        }
        i = ++h * width;
      }
      floatprocessor.resetMinAndMax();
      imp = new ImagePlusExtended(title, floatprocessor);

    } else if (object instanceof byte[][][]) {
      byte[][][] is = (byte[][][]) object;
      int height = is.length;
      int width = is[0].length;
      int stackSize = is[0][0].length;
      ImageStack imagestack = new ImageStack(width, height);
      for (int sz = 0; sz < stackSize; sz++) {
        ByteProcessor byteprocessor = new ByteProcessor(width, height);
        byte[] bp = (byte[]) byteprocessor.getPixels();
        i = 0;
        int h = 0;
        while (h < height) {
          int w = 0;
          while (w < width) {
            bp[i] = is[h][w][sz];
            w++;
            i++;
          }
          i = ++h * width;
        }
        imagestack.addSlice("", byteprocessor);
      }
      imp = new ImagePlusExtended(title, imagestack);

    } else if (object instanceof short[][][]) {
      short[][][] is = (short[][][]) object;
      int height = is.length;
      int width = is[0].length;
      int stackSize = is[0][0].length;
      ImageStack imagestack = new ImageStack(width, height);
      for (int sz = 0; sz < stackSize; sz++) {
        ShortProcessor shortprocessor = new ShortProcessor(width, height);
        short[] sp = (short[]) shortprocessor.getPixels();
        i = 0;
        int h = 0;
        while (h < height) {
          int w = 0;
          while (w < width) {
            sp[i] = is[h][w][sz];
            w++;
            i++;
          }
          i = ++h * width;
        }
        imagestack.addSlice("", shortprocessor);
      }
      imp = new ImagePlusExtended(title, imagestack);

    } else if (object instanceof int[][][]) {
      int[][][] is = (int[][][]) object;
      int height = is.length;
      int width = is[0].length;
      int stackSize = is[0][0].length;
      ImageStack imagestack = new ImageStack(width, height);
      for (int sz = 0; sz < stackSize; sz++) {
        ShortProcessor shortprocessor = new ShortProcessor(width, height);
        short[] sp = (short[]) shortprocessor.getPixels();
        i = 0;
        int h = 0;
        while (h < height) {
          int w = 0;
          while (w < width) {
            sp[i] = (short) is[h][w][sz];
            w++;
            i++;
          }
          i = ++h * width;
        }
        if (sz == 0) shortprocessor.resetMinAndMax();
        imagestack.addSlice("", shortprocessor);
      }
      imp = new ImagePlusExtended(title, imagestack);

    } else if (object instanceof float[][][]) {
      float[][][] fs = (float[][][]) object;
      int height = fs.length;
      int width = fs[0].length;
      int stackSize = fs[0][0].length;
      ImageStack imagestack = new ImageStack(width, height);
      for (int sz = 0; sz < stackSize; sz++) {
        FloatProcessor floatprocessor = new FloatProcessor(width, height);
        float[] fp = (float[]) floatprocessor.getPixels();
        i = 0;
        int h = 0;
        while (h < height) {
          int w = 0;
          while (w < width) {
            fp[i] = fs[h][w][sz];
            w++;
            i++;
          }
          i = ++h * width;
        }
        if (sz == 0) floatprocessor.resetMinAndMax();
        imagestack.addSlice("", floatprocessor);
      }
      imp = new ImagePlusExtended(title, imagestack);

    } else if (object instanceof double[][][]) {
      double[][][] ds = (double[][][]) object;
      int height = ds.length;
      int width = ds[0].length;
      int stackSize = ds[0][0].length;
      ImageStack imagestack = new ImageStack(width, height);
      for (int sz = 0; sz < stackSize; sz++) {
        FloatProcessor floatprocessor = new FloatProcessor(width, height);
        float[] fp = (float[]) floatprocessor.getPixels();
        i = 0;
        int h = 0;
        while (h < height) {
          int w = 0;
          while (w < width) {
            fp[i] = (float) ds[h][w][sz];
            w++;
            i++;
          }
          i = ++h * width;
        }
        if (sz == 0) floatprocessor.resetMinAndMax();
        imagestack.addSlice("", floatprocessor);
      }
      imp = new ImagePlusExtended(title, imagestack);

    } else {
      System.out.println("MIJ Error message: Unknow type of images or volumes.");
      return null;
    }

    if (showImage) {
      imp.show();
      imp.updateAndDraw();
    }
    return imp;
  }
Example #28
0
  /**
   * Returns saturation corrected version of the input image. A simple, one-parametric
   * exponential-saturation function with characteristic saturation rate is used (see Greilich et
   * al., 2013; Klimpki et al., 2016)
   *
   * @param img Input image
   * @param dwell_time Pixel dwell time, unit has to match saturation_rate
   * @param saturation_rate Characteristic saturation rate, unit has to match dwell_time
   * @return
   */
  public static ImagePlus saturationCorrection(
      ImagePlus img, double dwell_time, double saturation_rate) {

    boolean silent = (IJ.getInstance() == null);

    int nX = img.getWidth();
    int nY = img.getHeight();
    int nSlices = img.getNSlices();
    int nFrames = img.getNFrames();
    int nChannels = img.getNChannels();

    ImageStack resIms = new ImageStack(nX, nY);
    FloatProcessor fp;
    ImageProcessor ip1;

    int total = nSlices * nFrames * nChannels;
    double prog = 0;

    if (silent) {
      System.out.println("SATURATION CORRECTION");
    } else {
      IJ.showStatus("SATURATION CORRECTION");
    }

    for (int i = 0; i < nChannels; i++) {
      for (int j = 0; j < nFrames; j++) {
        for (int k = 0; k < nSlices; k++) {
          if (silent) {
            FNTDprogress.updateProgress(prog / total);
          } else {
            IJ.showProgress(prog / total);
          }

          prog++;

          img.setPosition(i + 1, k + 1, j + 1);
          ip1 = img.getProcessor();
          fp = new FloatProcessor(nX, nY);

          double count_rate;

          for (int m = 0; m < nX; m++) {
            for (int n = 0; n < nY; n++) {
              count_rate = ip1.getPixelValue(m, n);
              count_rate = 1.0 - count_rate / (dwell_time * saturation_rate);
              count_rate = -1.0 * saturation_rate * dwell_time * log(count_rate);
              fp.putPixelValue(m, n, count_rate);
            }
          }
          resIms.addSlice(fp);
        }
      }
    }
    FNTDprogress.updateProgress(1);
    System.out.println("");

    ImagePlus resImp = new ImagePlus(img.getTitle() + " (sat. corrected)", resIms);
    if (resIms.getSize() > 1) {
      resImp =
          HyperStackConverter.toHyperStack(
              resImp, nChannels, nSlices, nFrames, "xyztc", "grayscale");
    }
    return (resImp);
  }
  /**
   * 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;
  }
Example #30
0
  /**
   * Returns image in units of adjusted count-rate (Klimpki et al., 2016), i.e. compensated for
   * laser power and dwell time. If requested, non-linearities in laser-power compensation are
   * considered.
   *
   * @param img Input image
   * @param dwell_time Pixel dwell time, unit will match rate (i.e. us --> MHz)
   * @param laser_power Percentage laser power,
   * @param laser_exponent Exponent of laser-power compensation non-linearity, referred to 10%
   *     percentage laser power. Equals 0.0 for perfect linearity
   * @return
   */
  public static ImagePlus getAdjustedCountrateImage(
      ImagePlus img, double dwell_time, double laser_power, double laser_exponent) {

    boolean silent = (IJ.getInstance() == null);

    int nX = img.getWidth();
    int nY = img.getHeight();
    int nSlices = img.getNSlices();
    int nFrames = img.getNFrames();
    int nChannels = img.getNChannels();

    ImageStack resIms = new ImageStack(nX, nY);
    FloatProcessor fp;
    ImageProcessor ip1;

    int total = nSlices * nFrames * nChannels;
    double prog = 0;

    if (silent) {
      System.out.println("DWELL-TIME/LASER-POWER COMPENSATION");
    } else {
      IJ.showStatus("DWELL-TIME/LASER-POWER COMPENSATION");
    }

    for (int i = 0; i < nChannels; i++) {
      for (int j = 0; j < nFrames; j++) {

        for (int k = 0; k < nSlices; k++) {
          if (silent) {
            FNTDprogress.updateProgress(prog / total);
          } else {
            IJ.showProgress(prog / total);
          }

          prog++;

          img.setPosition(i + 1, k + 1, j + 1);
          ip1 = img.getProcessor();
          fp = new FloatProcessor(nX, nY);

          double laser_factor = Math.pow(laser_power / 0.10, laser_exponent);

          for (int m = 0; m < nX; m++) {
            for (int n = 0; n < nY; n++) {
              fp.putPixelValue(
                  m, n, ip1.getPixelValue(m, n) * laser_factor / (laser_power * dwell_time));
            }
          }
          resIms.addSlice(fp);
        }
      }
    }
    FNTDprogress.updateProgress(1);
    System.out.println("");

    ImagePlus resImp = new ImagePlus(img.getTitle() + " (adj. count-rate)", resIms);
    if (resIms.getSize() > 1) {
      resImp =
          HyperStackConverter.toHyperStack(
              resImp, nChannels, nSlices, nFrames, "xyztc", "grayscale");
    }
    return (resImp);
  }