Beispiel #1
0
 void createEllipse(ImagePlus imp) {
   IJ.showStatus("Fitting ellipse");
   Roi roi = imp.getRoi();
   if (roi == null) {
     noRoi("Fit Ellipse");
     return;
   }
   if (roi.isLine()) {
     IJ.error("Fit Ellipse", "\"Fit Ellipse\" does not work with line selections");
     return;
   }
   ImageProcessor ip = imp.getProcessor();
   ip.setRoi(roi);
   int options = Measurements.CENTROID + Measurements.ELLIPSE;
   ImageStatistics stats = ImageStatistics.getStatistics(ip, options, null);
   double dx = stats.major * Math.cos(stats.angle / 180.0 * Math.PI) / 2.0;
   double dy = -stats.major * Math.sin(stats.angle / 180.0 * Math.PI) / 2.0;
   double x1 = stats.xCentroid - dx;
   double x2 = stats.xCentroid + dx;
   double y1 = stats.yCentroid - dy;
   double y2 = stats.yCentroid + dy;
   double aspectRatio = stats.minor / stats.major;
   Undo.setup(Undo.ROI, imp);
   imp.deleteRoi();
   Roi roi2 = new EllipseRoi(x1, y1, x2, y2, aspectRatio);
   transferProperties(roi, roi2);
   imp.setRoi(roi2);
 }
Beispiel #2
0
 public void run(String arg) {
   imp = WindowManager.getCurrentImage();
   if (arg.equals("add")) {
     addToRoiManager(imp);
     return;
   }
   if (imp == null) {
     IJ.noImage();
     return;
   }
   if (arg.equals("all")) imp.setRoi(0, 0, imp.getWidth(), imp.getHeight());
   else if (arg.equals("none")) imp.deleteRoi();
   else if (arg.equals("restore")) imp.restoreRoi();
   else if (arg.equals("spline")) fitSpline();
   else if (arg.equals("interpolate")) interpolate();
   else if (arg.equals("circle")) fitCircle(imp);
   else if (arg.equals("ellipse")) createEllipse(imp);
   else if (arg.equals("hull")) convexHull(imp);
   else if (arg.equals("mask")) createMask(imp);
   else if (arg.equals("from")) createSelectionFromMask(imp);
   else if (arg.equals("inverse")) invert(imp);
   else if (arg.equals("toarea")) lineToArea(imp);
   else if (arg.equals("toline")) areaToLine(imp);
   else if (arg.equals("properties")) {
     setProperties("Properties ", imp.getRoi());
     imp.draw();
   } else if (arg.equals("band")) makeBand(imp);
   else if (arg.equals("tobox")) toBoundingBox(imp);
   else if (arg.equals("rotate")) rotate(imp);
   else if (arg.equals("enlarge")) enlarge(imp);
 }
Beispiel #3
0
 void scale(ImageProcessor ip) {
   if (newWindow) {
     Rectangle r = ip.getRoi();
     ImagePlus imp2 = imp.createImagePlus();
     imp2.setProcessor(title, ip.resize(newWidth, newHeight, averageWhenDownsizing));
     Calibration cal = imp2.getCalibration();
     if (cal.scaled()) {
       cal.pixelWidth *= 1.0 / xscale;
       cal.pixelHeight *= 1.0 / yscale;
     }
     imp2.show();
     imp.trimProcessor();
     imp2.trimProcessor();
     imp2.changes = true;
   } else {
     if (processStack && imp.getStackSize() > 1) {
       Undo.reset();
       StackProcessor sp = new StackProcessor(imp.getStack(), ip);
       sp.scale(xscale, yscale, bgValue);
     } else {
       ip.snapshot();
       Undo.setup(Undo.FILTER, imp);
       ip.setSnapshotCopyMode(true);
       ip.scale(xscale, yscale);
       ip.setSnapshotCopyMode(false);
     }
     imp.deleteRoi();
     imp.updateAndDraw();
     imp.changes = true;
   }
 }
Beispiel #4
0
 /**
  * Creates a dialog box, allowing the user to enter the requested width, height, x & y
  * coordinates, slice number for a Region Of Interest, option for oval, and option for whether x &
  * y coordinates to be centered.
  */
 void showDialog() {
   Calibration cal = imp.getCalibration();
   int digits = 0;
   if (scaledUnits && cal.scaled()) digits = 2;
   Roi roi = imp.getRoi();
   if (roi == null) drawRoi();
   GenericDialog gd = new GenericDialog("Specify");
   gd.addNumericField("Width:", width, digits);
   gd.addNumericField("Height:", height, digits);
   gd.addNumericField("X coordinate:", xRoi, digits);
   gd.addNumericField("Y coordinate:", yRoi, digits);
   if (stackSize > 1) gd.addNumericField("Slice:", iSlice, 0);
   gd.addCheckbox("Oval", oval);
   gd.addCheckbox("Constrain square/circle", square);
   gd.addCheckbox("Centered", centered);
   if (cal.scaled()) {
     boolean unitsMatch = cal.getXUnit().equals(cal.getYUnit());
     String units = unitsMatch ? cal.getUnits() : cal.getXUnit() + " x " + cal.getYUnit();
     gd.addCheckbox("Scaled units (" + units + ")", scaledUnits);
   }
   fields = gd.getNumericFields();
   gd.addDialogListener(this);
   gd.showDialog();
   if (gd.wasCanceled()) {
     if (roi == null) imp.deleteRoi();
     else // *ALWAYS* restore initial ROI when cancelled
     imp.setRoi(roi);
   }
 }
Beispiel #5
0
 void toBoundingBox(ImagePlus imp) {
   Roi roi = imp.getRoi();
   if (roi == null) {
     noRoi("To Bounding Box");
     return;
   }
   Undo.setup(Undo.ROI, imp);
   Rectangle r = roi.getBounds();
   imp.deleteRoi();
   Roi roi2 = new Roi(r.x, r.y, r.width, r.height);
   transferProperties(roi, roi2);
   imp.setRoi(roi2);
 }
Beispiel #6
0
 private boolean deleteOverlayRoi(ImagePlus imp) {
   if (imp == null) return false;
   Overlay overlay = null;
   ImageCanvas ic = imp.getCanvas();
   if (ic != null) overlay = ic.getShowAllList();
   if (overlay == null) overlay = imp.getOverlay();
   if (overlay == null) return false;
   Roi roi = imp.getRoi();
   for (int i = 0; i < overlay.size(); i++) {
     Roi roi2 = overlay.get(i);
     if (roi2 == roi) {
       overlay.remove(i);
       imp.deleteRoi();
       ic = imp.getCanvas();
       if (ic != null) ic.roiManagerSelect(roi, true);
       return true;
     }
   }
   return false;
 }
Beispiel #7
0
 public void run(String arg) {
   imp = IJ.getImage();
   Roi roi = imp.getRoi();
   if (roi != null && !roi.isArea()) imp.deleteRoi(); // ignore any line selection
   ImageProcessor ip = imp.getProcessor();
   if (!showDialog(ip)) return;
   if (newDepth > 0 && newDepth != oldDepth) {
     newWindow = true;
     processStack = true;
   }
   if ((ip.getWidth() > 1 && ip.getHeight() > 1) || newWindow)
     ip.setInterpolationMethod(interpolationMethod);
   else ip.setInterpolationMethod(ImageProcessor.NONE);
   ip.setBackgroundValue(bgValue);
   imp.startTiming();
   try {
     if (newWindow && imp.getStackSize() > 1 && processStack) createNewStack(imp, ip);
     else scale(ip);
   } catch (OutOfMemoryError o) {
     IJ.outOfMemory("Scale");
   }
   IJ.showProgress(1.0);
 }
Beispiel #8
0
  /*
  if selection is closed shape, create a circle with the same area and centroid, otherwise use<br>
  the Pratt method to fit a circle to the points that define the line or multi-point selection.<br>
  Reference: Pratt V., Direct least-squares fitting of algebraic surfaces", Computer Graphics, Vol. 21, pages 145-152 (1987).<br>
  Original code: Nikolai Chernov's MATLAB script for Newton-based Pratt fit.<br>
  (http://www.math.uab.edu/~chernov/cl/MATLABcircle.html)<br>
  Java version: https://github.com/mdoube/BoneJ/blob/master/src/org/doube/geometry/FitCircle.java<br>
  Authors: Nikolai Chernov, Michael Doube, Ved Sharma
  */
  void fitCircle(ImagePlus imp) {
    Roi roi = imp.getRoi();
    if (roi == null) {
      noRoi("Fit Circle");
      return;
    }

    if (roi.isArea()) { // create circle with the same area and centroid
      Undo.setup(Undo.ROI, imp);
      ImageProcessor ip = imp.getProcessor();
      ip.setRoi(roi);
      ImageStatistics stats =
          ImageStatistics.getStatistics(ip, Measurements.AREA + Measurements.CENTROID, null);
      double r = Math.sqrt(stats.pixelCount / Math.PI);
      imp.deleteRoi();
      int d = (int) Math.round(2.0 * r);
      Roi roi2 =
          new OvalRoi(
              (int) Math.round(stats.xCentroid - r), (int) Math.round(stats.yCentroid - r), d, d);
      transferProperties(roi, roi2);
      imp.setRoi(roi2);
      return;
    }

    Polygon poly = roi.getPolygon();
    int n = poly.npoints;
    int[] x = poly.xpoints;
    int[] y = poly.ypoints;
    if (n < 3) {
      IJ.error("Fit Circle", "At least 3 points are required to fit a circle.");
      return;
    }

    // calculate point centroid
    double sumx = 0, sumy = 0;
    for (int i = 0; i < n; i++) {
      sumx = sumx + poly.xpoints[i];
      sumy = sumy + poly.ypoints[i];
    }
    double meanx = sumx / n;
    double meany = sumy / n;

    // calculate moments
    double[] X = new double[n], Y = new double[n];
    double Mxx = 0, Myy = 0, Mxy = 0, Mxz = 0, Myz = 0, Mzz = 0;
    for (int i = 0; i < n; i++) {
      X[i] = x[i] - meanx;
      Y[i] = y[i] - meany;
      double Zi = X[i] * X[i] + Y[i] * Y[i];
      Mxy = Mxy + X[i] * Y[i];
      Mxx = Mxx + X[i] * X[i];
      Myy = Myy + Y[i] * Y[i];
      Mxz = Mxz + X[i] * Zi;
      Myz = Myz + Y[i] * Zi;
      Mzz = Mzz + Zi * Zi;
    }
    Mxx = Mxx / n;
    Myy = Myy / n;
    Mxy = Mxy / n;
    Mxz = Mxz / n;
    Myz = Myz / n;
    Mzz = Mzz / n;

    // calculate the coefficients of the characteristic polynomial
    double Mz = Mxx + Myy;
    double Cov_xy = Mxx * Myy - Mxy * Mxy;
    double Mxz2 = Mxz * Mxz;
    double Myz2 = Myz * Myz;
    double A2 = 4 * Cov_xy - 3 * Mz * Mz - Mzz;
    double A1 = Mzz * Mz + 4 * Cov_xy * Mz - Mxz2 - Myz2 - Mz * Mz * Mz;
    double A0 = Mxz2 * Myy + Myz2 * Mxx - Mzz * Cov_xy - 2 * Mxz * Myz * Mxy + Mz * Mz * Cov_xy;
    double A22 = A2 + A2;
    double epsilon = 1e-12;
    double ynew = 1e+20;
    int IterMax = 20;
    double xnew = 0;
    int iterations = 0;

    // Newton's method starting at x=0
    for (int iter = 1; iter <= IterMax; iter++) {
      iterations = iter;
      double yold = ynew;
      ynew = A0 + xnew * (A1 + xnew * (A2 + 4. * xnew * xnew));
      if (Math.abs(ynew) > Math.abs(yold)) {
        if (IJ.debugMode) IJ.log("Fit Circle: wrong direction: |ynew| > |yold|");
        xnew = 0;
        break;
      }
      double Dy = A1 + xnew * (A22 + 16 * xnew * xnew);
      double xold = xnew;
      xnew = xold - ynew / Dy;
      if (Math.abs((xnew - xold) / xnew) < epsilon) break;
      if (iter >= IterMax) {
        if (IJ.debugMode) IJ.log("Fit Circle: will not converge");
        xnew = 0;
      }
      if (xnew < 0) {
        if (IJ.debugMode) IJ.log("Fit Circle: negative root:  x = " + xnew);
        xnew = 0;
      }
    }
    if (IJ.debugMode)
      IJ.log("Fit Circle: n=" + n + ", xnew=" + IJ.d2s(xnew, 2) + ", iterations=" + iterations);

    // calculate the circle parameters
    double DET = xnew * xnew - xnew * Mz + Cov_xy;
    double CenterX = (Mxz * (Myy - xnew) - Myz * Mxy) / (2 * DET);
    double CenterY = (Myz * (Mxx - xnew) - Mxz * Mxy) / (2 * DET);
    double radius = Math.sqrt(CenterX * CenterX + CenterY * CenterY + Mz + 2 * xnew);
    if (Double.isNaN(radius)) {
      IJ.error("Fit Circle", "Points are collinear.");
      return;
    }
    CenterX = CenterX + meanx;
    CenterY = CenterY + meany;
    Undo.setup(Undo.ROI, imp);
    imp.deleteRoi();
    IJ.makeOval(
        (int) Math.round(CenterX - radius),
        (int) Math.round(CenterY - radius),
        (int) Math.round(2 * radius),
        (int) Math.round(2 * radius));
  }