Exemplo n.º 1
0
 void setStackDisplayRange(ImagePlus imp) {
   ImageStack stack = imp.getStack();
   double min = Double.MAX_VALUE;
   double max = -Double.MAX_VALUE;
   int n = stack.getSize();
   for (int i = 1; i <= n; i++) {
     if (!silentMode) IJ.showStatus("Calculating stack min and max: " + i + "/" + n);
     ImageProcessor ip = stack.getProcessor(i);
     ip.resetMinAndMax();
     if (ip.getMin() < min) min = ip.getMin();
     if (ip.getMax() > max) max = ip.getMax();
   }
   imp.getProcessor().setMinAndMax(min, max);
   imp.updateAndDraw();
 }
Exemplo n.º 2
0
 /**
  * Updates this stack so its attributes, such as min, max, calibration table and color model, are
  * the same as 'ip'.
  */
 public void update(ImageProcessor ip) {
   if (ip != null) {
     min = ip.getMin();
     max = ip.getMax();
     cTable = ip.getCalibrationTable();
     cm = ip.getColorModel();
   }
 }
Exemplo n.º 3
0
 /** Adds the image in 'ip' to the end of the stack. */
 public void addSlice(String sliceLabel, ImageProcessor ip) {
   if (ip.getWidth() != width || ip.getHeight() != height)
     throw new IllegalArgumentException("Dimensions do not match");
   if (nSlices == 0) {
     cm = ip.getColorModel();
     min = ip.getMin();
     max = ip.getMax();
   }
   addSlice(sliceLabel, ip.getPixels());
 }
Exemplo n.º 4
0
 public void resetDisplayRanges() {
   int channels = getNChannels();
   if (lut == null) setupLuts(channels);
   ImageStack stack2 = getImageStack();
   if (lut == null
       || channels != lut.length
       || channels > stack2.getSize()
       || channels > MAX_CHANNELS) return;
   for (int i = 0; i < channels; ++i) {
     ImageProcessor ip2 = stack2.getProcessor(i + 1);
     ip2.resetMinAndMax();
     lut[i].min = ip2.getMin();
     lut[i].max = ip2.getMax();
   }
 }
Exemplo n.º 5
0
 /** Opens a stack of images. */
 ImagePlus openStack(ColorModel cm, boolean show) {
   ImageStack stack = new ImageStack(fi.width, fi.height, cm);
   long skip = fi.getOffset();
   Object pixels;
   try {
     ImageReader reader = new ImageReader(fi);
     InputStream is = createInputStream(fi);
     if (is == null) return null;
     IJ.resetEscape();
     for (int i = 1; i <= fi.nImages; i++) {
       if (!silentMode) IJ.showStatus("Reading: " + i + "/" + fi.nImages);
       if (IJ.escapePressed()) {
         IJ.beep();
         IJ.showProgress(1.0);
         silentMode = false;
         return null;
       }
       pixels = reader.readPixels(is, skip);
       if (pixels == null) break;
       stack.addSlice(null, pixels);
       skip = fi.gapBetweenImages;
       if (!silentMode) IJ.showProgress(i, fi.nImages);
     }
     is.close();
   } catch (Exception e) {
     IJ.log("" + e);
   } catch (OutOfMemoryError e) {
     IJ.outOfMemory(fi.fileName);
     stack.trim();
   }
   if (!silentMode) IJ.showProgress(1.0);
   if (stack.getSize() == 0) return null;
   if (fi.sliceLabels != null && fi.sliceLabels.length <= stack.getSize()) {
     for (int i = 0; i < fi.sliceLabels.length; i++) stack.setSliceLabel(fi.sliceLabels[i], i + 1);
   }
   ImagePlus imp = new ImagePlus(fi.fileName, stack);
   if (fi.info != null) imp.setProperty("Info", fi.info);
   if (show) imp.show();
   imp.setFileInfo(fi);
   setCalibration(imp);
   ImageProcessor ip = imp.getProcessor();
   if (ip.getMin() == ip.getMax()) // find stack min and max if first slice is blank
   setStackDisplayRange(imp);
   if (!silentMode) IJ.showProgress(1.0);
   silentMode = false;
   return imp;
 }
Exemplo n.º 6
0
  /**
   * Read VoxelMatrix file
   *
   * @param path input file name with path
   * @return read image or null if error
   */
  public static ImagePlus read(String path) {
    if (null == path) return null;

    ImagePlus imp = new ImagePlus();

    try {
      // create file input & data input stream
      FileInputStream fis = new FileInputStream(path);
      DataInputStream dis = new DataInputStream(fis);

      int size1, size2, size3;
      size1 = reverse(dis.readInt()); // 0
      size2 = reverse(dis.readInt()); // 0
      size3 = reverse(dis.readInt()); // 0

      // Distinguish between versions: previous versions of VM files used 3 values
      if (size1 > 0 && size2 > 0 && size3 > 0) {
        // old version type = int;
        imp = readOldFormat(path, dis, size1, size2, size3);
        fis.close();
        dis.close();
        if (size3 > 1) {
          imp.setSlice(size3 / 2);
          ImageProcessor ip = imp.getProcessor();
          ip.resetMinAndMax();
          imp.setDisplayRange(ip.getMin(), ip.getMax());
        }
      } else {
        imp = openNewFormat(path, dis);
        fis.close();
        dis.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
    return imp;
  }
Exemplo n.º 7
0
  void setCalibration(ImagePlus imp) {
    if (fi.fileType == FileInfo.GRAY16_SIGNED) {
      if (IJ.debugMode) IJ.log("16-bit signed");
      double[] coeff = new double[2];
      coeff[0] = -32768.0;
      coeff[1] = 1.0;
      imp.getLocalCalibration().setFunction(Calibration.STRAIGHT_LINE, coeff, "gray value");
    }

    Properties props = decodeDescriptionString(fi);
    Calibration cal = imp.getCalibration();
    boolean calibrated = false;
    if (fi.pixelWidth > 0.0 && fi.unit != null) {
      cal.pixelWidth = fi.pixelWidth;
      cal.pixelHeight = fi.pixelHeight;
      cal.pixelDepth = fi.pixelDepth;
      cal.setUnit(fi.unit);
      calibrated = true;
    }

    if (fi.valueUnit != null) {
      int f = fi.calibrationFunction;
      if ((f >= Calibration.STRAIGHT_LINE && f <= Calibration.RODBARD2 && fi.coefficients != null)
          || f == Calibration.UNCALIBRATED_OD) {
        boolean zeroClip = props != null && props.getProperty("zeroclip", "false").equals("true");
        cal.setFunction(f, fi.coefficients, fi.valueUnit, zeroClip);
        calibrated = true;
      }
    }

    if (calibrated) checkForCalibrationConflict(imp, cal);

    if (fi.frameInterval != 0.0) cal.frameInterval = fi.frameInterval;

    if (props == null) return;

    cal.xOrigin = getDouble(props, "xorigin");
    cal.yOrigin = getDouble(props, "yorigin");
    cal.zOrigin = getDouble(props, "zorigin");
    cal.info = props.getProperty("info");

    cal.fps = getDouble(props, "fps");
    cal.loop = getBoolean(props, "loop");
    cal.frameInterval = getDouble(props, "finterval");
    cal.setTimeUnit(props.getProperty("tunit", "sec"));

    double displayMin = getDouble(props, "min");
    double displayMax = getDouble(props, "max");
    if (!(displayMin == 0.0 && displayMax == 0.0)) {
      int type = imp.getType();
      ImageProcessor ip = imp.getProcessor();
      if (type == ImagePlus.GRAY8 || type == ImagePlus.COLOR_256)
        ip.setMinAndMax(displayMin, displayMax);
      else if (type == ImagePlus.GRAY16 || type == ImagePlus.GRAY32) {
        if (ip.getMin() != displayMin || ip.getMax() != displayMax)
          ip.setMinAndMax(displayMin, displayMax);
      }
    }

    int stackSize = imp.getStackSize();
    if (stackSize > 1) {
      int channels = (int) getDouble(props, "channels");
      int slices = (int) getDouble(props, "slices");
      int frames = (int) getDouble(props, "frames");
      if (channels == 0) channels = 1;
      if (slices == 0) slices = 1;
      if (frames == 0) frames = 1;
      // IJ.log("setCalibration: "+channels+"  "+slices+"  "+frames);
      if (channels * slices * frames == stackSize) {
        imp.setDimensions(channels, slices, frames);
        if (getBoolean(props, "hyperstack")) imp.setOpenAsHyperStack(true);
      }
    }
  }
Exemplo n.º 8
0
  String getInfo(ImagePlus imp, ImageProcessor ip) {
    String s = new String("\n");
    s += "Title: " + imp.getTitle() + "\n";
    Calibration cal = imp.getCalibration();
    int stackSize = imp.getStackSize();
    int channels = imp.getNChannels();
    int slices = imp.getNSlices();
    int frames = imp.getNFrames();
    int digits = imp.getBitDepth() == 32 ? 4 : 0;
    if (cal.scaled()) {
      String unit = cal.getUnit();
      String units = cal.getUnits();
      s +=
          "Width:  "
              + IJ.d2s(imp.getWidth() * cal.pixelWidth, 2)
              + " "
              + units
              + " ("
              + imp.getWidth()
              + ")\n";
      s +=
          "Height:  "
              + IJ.d2s(imp.getHeight() * cal.pixelHeight, 2)
              + " "
              + units
              + " ("
              + imp.getHeight()
              + ")\n";
      if (slices > 1)
        s += "Depth:  " + IJ.d2s(slices * cal.pixelDepth, 2) + " " + units + " (" + slices + ")\n";
      double xResolution = 1.0 / cal.pixelWidth;
      double yResolution = 1.0 / cal.pixelHeight;
      int places = Tools.getDecimalPlaces(xResolution, yResolution);
      if (xResolution == yResolution)
        s += "Resolution:  " + IJ.d2s(xResolution, places) + " pixels per " + unit + "\n";
      else {
        s += "X Resolution:  " + IJ.d2s(xResolution, places) + " pixels per " + unit + "\n";
        s += "Y Resolution:  " + IJ.d2s(yResolution, places) + " pixels per " + unit + "\n";
      }
    } else {
      s += "Width:  " + imp.getWidth() + " pixels\n";
      s += "Height:  " + imp.getHeight() + " pixels\n";
      if (stackSize > 1) s += "Depth:  " + slices + " pixels\n";
    }
    if (stackSize > 1)
      s +=
          "Voxel size: "
              + d2s(cal.pixelWidth)
              + "x"
              + d2s(cal.pixelHeight)
              + "x"
              + d2s(cal.pixelDepth)
              + " "
              + cal.getUnit()
              + "\n";
    else
      s +=
          "Pixel size: "
              + d2s(cal.pixelWidth)
              + "x"
              + d2s(cal.pixelHeight)
              + " "
              + cal.getUnit()
              + "\n";

    s += "ID: " + imp.getID() + "\n";
    String zOrigin = stackSize > 1 || cal.zOrigin != 0.0 ? "," + d2s(cal.zOrigin) : "";
    s += "Coordinate origin:  " + d2s(cal.xOrigin) + "," + d2s(cal.yOrigin) + zOrigin + "\n";
    int type = imp.getType();
    switch (type) {
      case ImagePlus.GRAY8:
        s += "Bits per pixel: 8 ";
        String lut = "LUT";
        if (imp.getProcessor().isColorLut()) lut = "color " + lut;
        else lut = "grayscale " + lut;
        if (imp.isInvertedLut()) lut = "inverting " + lut;
        s += "(" + lut + ")\n";
        if (imp.getNChannels() > 1) s += displayRanges(imp);
        else s += "Display range: " + (int) ip.getMin() + "-" + (int) ip.getMax() + "\n";
        break;
      case ImagePlus.GRAY16:
      case ImagePlus.GRAY32:
        if (type == ImagePlus.GRAY16) {
          String sign = cal.isSigned16Bit() ? "signed" : "unsigned";
          s += "Bits per pixel: 16 (" + sign + ")\n";
        } else s += "Bits per pixel: 32 (float)\n";
        if (imp.getNChannels() > 1) s += displayRanges(imp);
        else {
          s += "Display range: ";
          double min = ip.getMin();
          double max = ip.getMax();
          if (cal.calibrated()) {
            min = cal.getCValue((int) min);
            max = cal.getCValue((int) max);
          }
          s += IJ.d2s(min, digits) + " - " + IJ.d2s(max, digits) + "\n";
        }
        break;
      case ImagePlus.COLOR_256:
        s += "Bits per pixel: 8 (color LUT)\n";
        break;
      case ImagePlus.COLOR_RGB:
        s += "Bits per pixel: 32 (RGB)\n";
        break;
    }
    double interval = cal.frameInterval;
    double fps = cal.fps;
    if (stackSize > 1) {
      ImageStack stack = imp.getStack();
      int slice = imp.getCurrentSlice();
      String number = slice + "/" + stackSize;
      String label = stack.getShortSliceLabel(slice);
      if (label != null && label.length() > 0) label = " (" + label + ")";
      else label = "";
      if (interval > 0.0 || fps != 0.0) {
        s += "Frame: " + number + label + "\n";
        if (fps != 0.0) {
          String sRate =
              Math.abs(fps - Math.round(fps)) < 0.00001 ? IJ.d2s(fps, 0) : IJ.d2s(fps, 5);
          s += "Frame rate: " + sRate + " fps\n";
        }
        if (interval != 0.0)
          s +=
              "Frame interval: "
                  + ((int) interval == interval ? IJ.d2s(interval, 0) : IJ.d2s(interval, 5))
                  + " "
                  + cal.getTimeUnit()
                  + "\n";
      } else s += "Image: " + number + label + "\n";
      if (imp.isHyperStack()) {
        if (channels > 1) s += "  Channel: " + imp.getChannel() + "/" + channels + "\n";
        if (slices > 1) s += "  Slice: " + imp.getSlice() + "/" + slices + "\n";
        if (frames > 1) s += "  Frame: " + imp.getFrame() + "/" + frames + "\n";
      }
      if (imp.isComposite()) {
        if (!imp.isHyperStack() && channels > 1) s += "  Channels: " + channels + "\n";
        String mode = ((CompositeImage) imp).getModeAsString();
        s += "  Composite mode: \"" + mode + "\"\n";
      }
    }

    if (ip.getMinThreshold() == ImageProcessor.NO_THRESHOLD) s += "No Threshold\n";
    else {
      double lower = ip.getMinThreshold();
      double upper = ip.getMaxThreshold();
      int dp = digits;
      if (cal.calibrated()) {
        lower = cal.getCValue((int) lower);
        upper = cal.getCValue((int) upper);
        dp = cal.isSigned16Bit() ? 0 : 4;
      }
      s += "Threshold: " + IJ.d2s(lower, dp) + "-" + IJ.d2s(upper, dp) + "\n";
    }
    ImageCanvas ic = imp.getCanvas();
    double mag = ic != null ? ic.getMagnification() : 1.0;
    if (mag != 1.0) s += "Magnification: " + IJ.d2s(mag, 2) + "\n";

    if (cal.calibrated()) {
      s += " \n";
      int curveFit = cal.getFunction();
      s += "Calibration Function: ";
      if (curveFit == Calibration.UNCALIBRATED_OD) s += "Uncalibrated OD\n";
      else if (curveFit == Calibration.CUSTOM) s += "Custom lookup table\n";
      else s += CurveFitter.fList[curveFit] + "\n";
      double[] c = cal.getCoefficients();
      if (c != null) {
        s += "  a: " + IJ.d2s(c[0], 6) + "\n";
        s += "  b: " + IJ.d2s(c[1], 6) + "\n";
        if (c.length >= 3) s += "  c: " + IJ.d2s(c[2], 6) + "\n";
        if (c.length >= 4) s += "  c: " + IJ.d2s(c[3], 6) + "\n";
        if (c.length >= 5) s += "  c: " + IJ.d2s(c[4], 6) + "\n";
      }
      s += "  Unit: \"" + cal.getValueUnit() + "\"\n";
    } else s += "Uncalibrated\n";

    FileInfo fi = imp.getOriginalFileInfo();
    if (fi != null) {
      if (fi.url != null && !fi.url.equals("")) s += "URL: " + fi.url + "\n";
      else if (fi.directory != null && fi.fileName != null)
        s += "Path: " + fi.directory + fi.fileName + "\n";
    }

    ImageWindow win = imp.getWindow();
    if (win != null) {
      Point loc = win.getLocation();
      Dimension screen = IJ.getScreenSize();
      s +=
          "Screen location: "
              + loc.x
              + ","
              + loc.y
              + " ("
              + screen.width
              + "x"
              + screen.height
              + ")\n";
    }

    Overlay overlay = imp.getOverlay();
    if (overlay != null) {
      String hidden = imp.getHideOverlay() ? " (hidden)" : " ";
      int n = overlay.size();
      String elements = n == 1 ? " element" : " elements";
      s += "Overlay: " + n + elements + (imp.getHideOverlay() ? " (hidden)" : "") + "\n";
    } else s += "No Overlay\n";

    Roi roi = imp.getRoi();
    if (roi == null) {
      if (cal.calibrated()) s += " \n";
      s += "No Selection\n";
    } else if (roi instanceof EllipseRoi) {
      s += "\nElliptical Selection\n";
      double[] p = ((EllipseRoi) roi).getParams();
      double dx = p[2] - p[0];
      double dy = p[3] - p[1];
      double major = Math.sqrt(dx * dx + dy * dy);
      s += "  Major: " + IJ.d2s(major, 2) + "\n";
      s += "  Minor: " + IJ.d2s(major * p[4], 2) + "\n";
      s += "  X1: " + IJ.d2s(p[0], 2) + "\n";
      s += "  Y1: " + IJ.d2s(p[1], 2) + "\n";
      s += "  X2: " + IJ.d2s(p[2], 2) + "\n";
      s += "  Y2: " + IJ.d2s(p[3], 2) + "\n";
      s += "  Aspect ratio: " + IJ.d2s(p[4], 2) + "\n";
    } else {
      s += " \n";
      s += roi.getTypeAsString() + " Selection";
      String points = null;
      if (roi instanceof PointRoi) {
        int npoints = ((PolygonRoi) roi).getNCoordinates();
        String suffix = npoints > 1 ? "s)" : ")";
        points = " (" + npoints + " point" + suffix;
      }
      String name = roi.getName();
      if (name != null) {
        s += " (\"" + name + "\")";
        if (points != null) s += "\n " + points;
      } else if (points != null) s += points;
      s += "\n";
      Rectangle r = roi.getBounds();
      if (roi instanceof Line) {
        Line line = (Line) roi;
        s += "  X1: " + IJ.d2s(line.x1d * cal.pixelWidth) + "\n";
        s += "  Y1: " + IJ.d2s(yy(line.y1d, imp) * cal.pixelHeight) + "\n";
        s += "  X2: " + IJ.d2s(line.x2d * cal.pixelWidth) + "\n";
        s += "  Y2: " + IJ.d2s(yy(line.y2d, imp) * cal.pixelHeight) + "\n";
      } else if (cal.scaled()) {
        s += "  X: " + IJ.d2s(cal.getX(r.x)) + " (" + r.x + ")\n";
        s += "  Y: " + IJ.d2s(cal.getY(r.y, imp.getHeight())) + " (" + r.y + ")\n";
        s += "  Width: " + IJ.d2s(r.width * cal.pixelWidth) + " (" + r.width + ")\n";
        s += "  Height: " + IJ.d2s(r.height * cal.pixelHeight) + " (" + r.height + ")\n";
      } else {
        s += "  X: " + r.x + "\n";
        s += "  Y: " + yy(r.y, imp) + "\n";
        s += "  Width: " + r.width + "\n";
        s += "  Height: " + r.height + "\n";
      }
    }

    return s;
  }
Exemplo n.º 9
0
  static ImagePlus openNewFormat(String path, DataInputStream dis) throws IOException {
    // ImagePlus imp;
    // New version of VM using 12 parameter fields
    int version = reverse(dis.readInt());
    int type = reverse(dis.readInt());
    int size1 = reverse(dis.readInt());
    int size2 = reverse(dis.readInt());
    int size3 = reverse(dis.readInt());
    ImageStack stack = new ImageStack(size1, size2);

    int voxelUnit = reverse(dis.readInt());
    float voxelWidth = Float.intBitsToFloat(reverse(dis.readInt()));
    float voxelHeight = Float.intBitsToFloat(reverse(dis.readInt()));
    float voxelDepth = Float.intBitsToFloat(reverse(dis.readInt()));

    final int numPixels = size1 * size2;
    final int bufferSize = 4 * numPixels;

    final byte[] buffer = new byte[bufferSize];

    // write pixels
    for (int z = 0; z < size3; ++z) {

      final float[][] pixels = new float[size1][size2];

      int n = dis.read(buffer, 0, bufferSize);

      for (int j = 0; j < bufferSize; j += 4) {
        int tmp =
            (int)
                (((buffer[j + 3] & 0xff) << 24)
                    | ((buffer[j + 2] & 0xff) << 16)
                    | ((buffer[j + 1] & 0xff) << 8)
                    | (buffer[j] & 0xff));

        int currentPos = j / 4;
        int y = currentPos / size2;
        int x = currentPos % size2;

        if (type == 5) pixels[y][x] = Float.intBitsToFloat(tmp); // float type
        else if (type == 2) pixels[y][x] = (float) tmp; // int type
      }
      final FloatProcessor fp = new FloatProcessor(pixels);
      stack.addSlice(fp);
    }

    ImagePlus imp = new ImagePlus(path, stack);

    if (size3 > 1) {
      imp.setSlice(size3 / 2);
      ImageProcessor ip = imp.getProcessor();
      ip.resetMinAndMax();
      imp.setDisplayRange(ip.getMin(), ip.getMax());
    }

    Calibration calibration = new Calibration();
    String unit = intToUnitString(voxelUnit);
    calibration.setXUnit(unit);
    calibration.setYUnit(unit);
    calibration.setZUnit(unit);
    calibration.pixelWidth = voxelWidth;
    calibration.pixelHeight = voxelHeight;
    calibration.pixelDepth = voxelDepth;
    imp.setCalibration(calibration);

    return imp;
  }
Exemplo n.º 10
0
  /**
   * Calculate the Rand index stats between to 3D clusters, as described by William M. Rand
   * \cite{Rand71}, but pruning out the zero component of the ground truth, which leads to an
   * asymmetric index. The input images must be 16-bit. Note: this method is based on the N^2
   * normalization.
   *
   * <p>BibTeX:
   *
   * <pre>
   * &#64;article{Rand71,
   *   author    = {William M. Rand},
   *   title     = {Objective criteria for the evaluation of clustering methods},
   *   journal   = {Journal of the American Statistical Association},
   *   year      = {1971},
   *   volume    = {66},
   *   number    = {336},
   *   pages     = {846--850},
   *   doi       = {10.2307/2284239)
   * }
   * </pre>
   *
   * @param segA ground truth, 3D segmented image (objects are labeled with different numbers)
   * @param segB prediction, 3D segmented image (objects are labeled with different numbers)
   * @return [ precision, recall, Rand index with n^2 normalization ]
   */
  public static double[] adaptedRandIndexStats3DN2(ImagePlus segA, ImagePlus segB) {
    if (segA.getImageStack().getProcessor(1) instanceof ShortProcessor == false
        || segB.getImageStack().getProcessor(1) instanceof ShortProcessor == false) return null;

    // IJ.log( "Calculating adapted Rand index stats...");

    int nSlices = segA.getImageStackSize();

    int nLabelsA = 0;
    int nLabelsB = 0;

    // Calculate larger IDs of both clusters
    for (int slice = 1; slice <= nSlices; slice++) {
      ImageProcessor gt = segA.getImageStack().getProcessor(slice);
      gt.resetMinAndMax();
      if (nLabelsA < gt.getMax()) nLabelsA = (int) gt.getMax();
      ImageProcessor proposal = segB.getImageStack().getProcessor(slice);
      proposal.resetMinAndMax();
      if (nLabelsB < proposal.getMax()) nLabelsB = (int) proposal.getMax();
    }

    // Form the contingency matrix
    long[][] pij = new long[nLabelsA + 1][nLabelsB + 1];

    double n = segA.getImageStackSize() * segA.getWidth() * segA.getHeight();

    for (int slice = 1; slice <= nSlices; slice++) {
      // IJ.log(" Processing slice " + slice +"...");

      ShortProcessor cluster1 = (ShortProcessor) segA.getImageStack().getProcessor(slice);
      ShortProcessor cluster2 = (ShortProcessor) segB.getImageStack().getProcessor(slice);

      final short[] pixels1 = (short[]) cluster1.getPixels();
      final short[] pixels2 = (short[]) cluster2.getPixels();

      double nPixels = pixels1.length;

      for (int i = 0; i < nPixels; i++) pij[pixels1[i] & 0xffff][pixels2[i] & 0xffff]++;
    }

    // sum of squares of sums of rows
    // (skip background objects in the first cluster)
    double[] ai = new double[pij.length];
    for (int i = 1; i < pij.length; i++)
      for (int j = 0; j < pij[0].length; j++) {
        ai[i] += pij[i][j];
      }

    // sum of squares of sums of columns
    // (prune out the zero component in the labeling (un-assigned "out" space))
    double[] bj = new double[pij[0].length];
    for (int j = 1; j < pij[0].length; j++)
      for (int i = 1; i < pij.length; i++) {
        bj[j] += pij[i][j];
      }

    double[] pi0 = new double[pij.length];
    double aux = 0;
    for (int i = 1; i < pij.length; i++) {
      pi0[i] = pij[i][0];
      aux += pi0[i];
    }

    double sumA = 0;
    for (int i = 0; i < ai.length; i++) sumA += ai[i] * ai[i];

    double sumB = 0;
    for (int j = 0; j < bj.length; j++) sumB += bj[j] * bj[j];

    sumB += aux / n;

    double sumAB = 0;
    for (int i = 1; i < pij.length; i++)
      for (int j = 1; j < pij[0].length; j++) sumAB += pij[i][j] * pij[i][j];

    sumAB += aux / n;

    // return precision, recall and Rand index value
    return new double[] {sumAB / sumB, sumAB / sumA, 1.0 - (sumA + sumB - 2.0 * sumAB) / (n * n)};
  }
Exemplo n.º 11
0
  /**
   * Calculate the Rand index between to 3D clusters, as described by William M. Rand \cite{Rand71},
   * but pruning out the zero component of the ground truth, which leads to an asymmetric index. The
   * input images must be 16-bit. Note: this method is based on the N_choose_2 normalization.
   *
   * <p>BibTeX:
   *
   * <pre>
   * &#64;article{Rand71,
   *   author    = {William M. Rand},
   *   title     = {Objective criteria for the evaluation of clustering methods},
   *   journal   = {Journal of the American Statistical Association},
   *   year      = {1971},
   *   volume    = {66},
   *   number    = {336},
   *   pages     = {846--850},
   *   doi       = {10.2307/2284239)
   * }
   * </pre>
   *
   * @param originalLabels ground truth, 3D segmented image (objects are labeled with different
   *     numbers)
   * @param proposedLabels prediction, 3D segmented image (objects are labeled with different
   *     numbers)
   * @return adapted Rand index value and prediction statistics
   */
  public static ClassificationStatistics adaptedRandIndexStats3D(
      ImagePlus originalLabels, ImagePlus proposedLabels) {
    if (originalLabels.getImageStack().getProcessor(1) instanceof ShortProcessor == false
        || proposedLabels.getImageStack().getProcessor(1) instanceof ShortProcessor == false)
      return null;

    // IJ.log( "Calculating adapted Rand index stats...");

    int nSlices = originalLabels.getImageStackSize();

    int maxIDGroundTruth = 0;
    int maxIDProposal = 0;

    // Calculate larger IDs of both clusters
    for (int slice = 1; slice <= nSlices; slice++) {
      ImageProcessor gt = originalLabels.getImageStack().getProcessor(slice);
      gt.resetMinAndMax();
      if (maxIDGroundTruth < gt.getMax()) maxIDGroundTruth = (int) gt.getMax();
      ImageProcessor proposal = proposedLabels.getImageStack().getProcessor(slice);
      proposal.resetMinAndMax();
      if (maxIDProposal < proposal.getMax()) maxIDProposal = (int) proposal.getMax();
    }

    double agreements = 0;

    // Form the contingency matrix
    long[][] cont = new long[maxIDGroundTruth + 1][maxIDProposal + 1];
    double[] ni = new double[cont.length];
    double[] nj = new double[cont[0].length];

    // number of pixels that are "in" (not background) in
    // cluster number 1 (ground truth)
    double n = 0;

    for (int slice = 1; slice <= nSlices; slice++) {
      // IJ.log(" Processing slice " + slice +"...");

      ShortProcessor cluster1 = (ShortProcessor) originalLabels.getImageStack().getProcessor(slice);
      ShortProcessor cluster2 = (ShortProcessor) proposedLabels.getImageStack().getProcessor(slice);

      final short[] pixels1 = (short[]) cluster1.getPixels();
      final short[] pixels2 = (short[]) cluster2.getPixels();

      double nPixels = pixels1.length;

      for (int i = 0; i < nPixels; i++) {
        cont[pixels1[i] & 0xffff][pixels2[i] & 0xffff]++;
        if (pixels1[i] > 0) n++;
      }
    }
    // sum of squares of sums of rows
    // (skip background objects in the first cluster)

    for (int i = 1; i < cont.length; i++)
      for (int j = 0; j < cont[0].length; j++) {
        ni[i] += cont[i][j];
      }

    // sum of squares of sums of columns
    // (prune out the zero component in the labeling (un-assigned "out" space))
    for (int j = 1; j < cont[0].length; j++)
      for (int i = 1; i < cont.length; i++) {
        nj[j] += cont[i][j];
      }

    // true positives - type (i): objects in the pair are placed in the
    // same class in cluster1 and in the same class in claster2
    // (prune out the zero component in the labeling (un-assigned "out" space))
    double truePositives = 0;
    for (int j = 1; j < cont[0].length; j++)
      for (int i = 1; i < cont.length; i++)
        truePositives += cont[i][j] * (cont[i][j] - 1.0); // / 2.0;

    // total number of pairs (after pruning background pixels
    // of the ground truth)
    double nPairsTotal = n * (n - 1.0); // / 2.0 ;

    // total number of positive samples in ground truth
    double nPosTrue = 0;
    for (int k = 0; k < ni.length; k++) nPosTrue += ni[k] * (ni[k] - 1.0); // /2.0;

    // number of pairs actually classified as positive (in the prediction)
    double nPosActual = 0;
    for (int k = 0; k < nj.length; k++) nPosActual += nj[k] * (nj[k] - 1.0); // /2.0;	

    // true negatives - type (ii): objects in the pair are placed in different
    // classes in cluster1 and in different classes in claster2
    // trueNegatives = 	nNegTrue - falsePositives = (nPairsTotal - nPosTrue) - (nPosActual -
    // truePositives)
    double trueNegatives = nPairsTotal + truePositives - nPosTrue - nPosActual;

    // IJ.log("  agreements = " + (truePositives + trueNegatives) );

    agreements += truePositives + trueNegatives; // number of agreements

    double falsePositives = nPosActual - truePositives;
    double nNegActual = nPairsTotal - nPosActual;
    double falseNegatives = nNegActual - trueNegatives;

    truePositives /= 2.0;
    trueNegatives /= 2.0;
    falsePositives /= 2.0;
    falseNegatives /= 2.0;

    // agreements /= 2.0;
    // nPairsTotal /= 2.0;

    double randIndex = agreements / nPairsTotal;

    return new ClassificationStatistics(
        truePositives, trueNegatives, falsePositives, falseNegatives, randIndex);
  }
Exemplo n.º 12
0
  public synchronized void updateImage() {
    int imageSize = width * height;
    int nChannels = getNChannels();
    int redValue, greenValue, blueValue;
    int ch = getChannel();

    // IJ.log("updateImage: "+ch+"/"+nChannels+" "+currentSlice+" "+currentFrame);
    if (ch > nChannels) ch = nChannels;
    boolean newChannel = false;
    if (ch - 1 != currentChannel) {
      previousChannel = currentChannel;
      currentChannel = ch - 1;
      newChannel = true;
    }

    ImageProcessor ip = getProcessor();
    if (mode != COMPOSITE) {
      if (newChannel) {
        setupLuts(nChannels);
        LUT cm = lut[currentChannel];
        if (mode == COLOR) ip.setColorModel(cm);
        if (!(cm.min == 0.0 && cm.max == 0.0)) ip.setMinAndMax(cm.min, cm.max);
        if (!IJ.isMacro()) ContrastAdjuster.update();
        for (int i = 0; i < MAX_CHANNELS; i++) active[i] = i == currentChannel ? true : false;
        Channels.updateChannels();
      }
      if (ip != null) img = ip.createImage();
      return;
    }

    if (nChannels == 1) {
      cip = null;
      rgbPixels = null;
      awtImage = null;
      if (ip != null) img = ip.createImage();
      return;
    }

    if (cip == null
        || cip[0].getWidth() != width
        || cip[0].getHeight() != height
        || getBitDepth() != bitDepth) {
      setup(nChannels, getImageStack());
      rgbPixels = null;
      rgbSampleModel = null;
      if (currentChannel >= nChannels) {
        setSlice(1);
        currentChannel = 0;
        newChannel = true;
      }
      bitDepth = getBitDepth();
    }

    if (newChannel) {
      getProcessor().setMinAndMax(cip[currentChannel].getMin(), cip[currentChannel].getMax());
      if (!IJ.isMacro()) ContrastAdjuster.update();
    }
    // IJ.log(nChannels+" "+ch+" "+currentChannel+"  "+newChannel);

    if (getSlice() != currentSlice || getFrame() != currentFrame) {
      currentSlice = getSlice();
      currentFrame = getFrame();
      int position = getStackIndex(1, currentSlice, currentFrame);
      if (cip == null) return;
      for (int i = 0; i < nChannels; ++i)
        cip[i].setPixels(getImageStack().getProcessor(position + i).getPixels());
    }

    if (rgbPixels == null) {
      rgbPixels = new int[imageSize];
      newPixels = true;
      imageSource = null;
      rgbRaster = null;
      rgbImage = null;
    }
    cip[currentChannel].setMinAndMax(ip.getMin(), ip.getMax());
    if (singleChannel && nChannels <= 3) {
      switch (currentChannel) {
        case 0:
          cip[0].updateComposite(rgbPixels, 1);
          break;
        case 1:
          cip[1].updateComposite(rgbPixels, 2);
          break;
        case 2:
          cip[2].updateComposite(rgbPixels, 3);
          break;
      }
    } else {
      if (cip == null) return;
      if (syncChannels) {
        ImageProcessor ip2 = getProcessor();
        double min = ip2.getMin(), max = ip2.getMax();
        for (int i = 0; i < nChannels; i++) {
          cip[i].setMinAndMax(min, max);
          lut[i].min = min;
          lut[i].max = max;
        }
        syncChannels = false;
      }
      if (active[0]) cip[0].updateComposite(rgbPixels, 4);
      else {
        for (int i = 1; i < imageSize; i++) rgbPixels[i] = 0;
      }
      if (cip == null || nChannels > cip.length) return;
      for (int i = 1; i < nChannels; i++) if (active[i]) cip[i].updateComposite(rgbPixels, 5);
    }
    if (IJ.isJava16()) createBufferedImage();
    else createImage();
    if (img == null && awtImage != null) img = awtImage;
    singleChannel = false;
  }