void createMaskFromThreshold(ImagePlus imp) { ImageProcessor ip = imp.getProcessor(); if (ip.getMinThreshold() == ImageProcessor.NO_THRESHOLD) { IJ.error("Create Mask", "Area selection or thresholded image required"); return; } double t1 = ip.getMinThreshold(); double t2 = ip.getMaxThreshold(); IJ.run("Duplicate...", "title=mask"); ImagePlus imp2 = WindowManager.getCurrentImage(); ImageProcessor ip2 = imp2.getProcessor(); ip2.setThreshold(t1, t2, ImageProcessor.NO_LUT_UPDATE); IJ.run("Convert to Mask"); }
void createMask(ImagePlus imp) { Roi roi = imp.getRoi(); boolean useInvertingLut = Prefs.useInvertingLut; Prefs.useInvertingLut = false; if (roi == null || !(roi.isArea() || roi.getType() == Roi.POINT)) { createMaskFromThreshold(imp); Prefs.useInvertingLut = useInvertingLut; return; } ImagePlus maskImp = null; Frame frame = WindowManager.getFrame("Mask"); if (frame != null && (frame instanceof ImageWindow)) maskImp = ((ImageWindow) frame).getImagePlus(); if (maskImp == null) { ImageProcessor ip = new ByteProcessor(imp.getWidth(), imp.getHeight()); if (!Prefs.blackBackground) ip.invertLut(); maskImp = new ImagePlus("Mask", ip); maskImp.show(); } ImageProcessor ip = maskImp.getProcessor(); ip.setRoi(roi); ip.setValue(255); ip.fill(ip.getMask()); maskImp.updateAndDraw(); Prefs.useInvertingLut = useInvertingLut; }
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; imp.killRoi(); imp.setRoi(new EllipseRoi(x1, y1, x2, y2, aspectRatio)); }
void setHistogram(ImagePlus imp, int j) { ImageProcessor ip = imp.getProcessor(); ImageStatistics stats = ImageStatistics.getStatistics(ip, AREA + MODE, null); int maxCount2 = 0; histogram = stats.histogram; for (int i = 0; i < stats.nBins; i++) if ((histogram[i] > maxCount2) && (i != stats.mode)) maxCount2 = histogram[i]; hmax = stats.maxCount; if ((hmax > (maxCount2 * 1.5)) && (maxCount2 != 0)) { // GL 1.5 was 2 hmax = (int) (maxCount2 * 1.1); // GL 1.1 was 1.5 histogram[stats.mode] = hmax; } os = null; ColorModel cm = ip.getColorModel(); if (!(cm instanceof IndexColorModel)) return; IndexColorModel icm = (IndexColorModel) cm; int mapSize = icm.getMapSize(); if (mapSize != 256) return; byte[] r = new byte[256]; byte[] g = new byte[256]; byte[] b = new byte[256]; icm.getReds(r); icm.getGreens(g); icm.getBlues(b); hColors = new Color[256]; if (isRGB) { if (j == 0) { for (int i = 0; i < 256; i++) hColors[i] = new Color(i & 255, 0 & 255, 0 & 255); } else if (j == 1) { for (int i = 0; i < 256; i++) hColors[i] = new Color(0 & 255, i & 255, 0 & 255); } else if (j == 2) { for (int i = 0; i < 256; i++) hColors[i] = new Color(0 & 255, 0 & 255, i & 255); } } else { if (j == 0) { for (int i = 0; i < 256; i++) hColors[i] = new Color(r[i] & 255, g[i] & 255, b[i] & 255); } else if (j == 1) { for (int i = 0; i < 256; i++) // hColors[i] = new Color(127-i/2&255, 127+i/2&255, 127-i/2&255); hColors[i] = new Color(192 - i / 4 & 255, 192 + i / 4 & 255, 192 - i / 4 & 255); } else if (j == 2) { for (int i = 0; i < 256; i++) hColors[i] = new Color(i & 255, i & 255, 0 & 255); } } }
void createSelectionFromMask(ImagePlus imp) { ImageProcessor ip = imp.getProcessor(); if (ip.getMinThreshold() != ImageProcessor.NO_THRESHOLD) { IJ.runPlugIn("ij.plugin.filter.ThresholdToSelection", ""); return; } if (!ip.isBinary()) { IJ.error( "Create Selection", "This command creates a composite selection from\n" + "a mask (8-bit binary image with white background)\n" + "or from an image that has been thresholded using\n" + "the Image>Adjust>Threshold tool. The current\n" + "image is not a mask and has not been thresholded."); return; } int threshold = ip.isInvertedLut() ? 255 : 0; ip.setThreshold(threshold, threshold, ImageProcessor.NO_LUT_UPDATE); IJ.runPlugIn("ij.plugin.filter.ThresholdToSelection", ""); }
void createMask(ImagePlus imp) { Roi roi = imp.getRoi(); boolean useInvertingLut = Prefs.useInvertingLut; Prefs.useInvertingLut = false; boolean selectAll = roi != null && roi.getType() == Roi.RECTANGLE && roi.getBounds().width == imp.getWidth() && roi.getBounds().height == imp.getHeight() && imp.isThreshold(); if (roi == null || !(roi.isArea() || roi.getType() == Roi.POINT) || selectAll) { createMaskFromThreshold(imp); Prefs.useInvertingLut = useInvertingLut; return; } ImagePlus maskImp = null; Frame frame = WindowManager.getFrame("Mask"); if (frame != null && (frame instanceof ImageWindow)) maskImp = ((ImageWindow) frame).getImagePlus(); if (maskImp == null) { ImageProcessor ip = new ByteProcessor(imp.getWidth(), imp.getHeight()); if (!Prefs.blackBackground) ip.invertLut(); maskImp = new ImagePlus("Mask", ip); maskImp.show(); } ImageProcessor ip = maskImp.getProcessor(); ip.setRoi(roi); ip.setValue(255); ip.fill(ip.getMask()); Calibration cal = imp.getCalibration(); if (cal.scaled()) { Calibration cal2 = maskImp.getCalibration(); cal2.pixelWidth = cal.pixelWidth; cal2.pixelHeight = cal.pixelHeight; cal2.setUnit(cal.getUnit()); } maskImp.updateAndRepaintWindow(); Prefs.useInvertingLut = useInvertingLut; }
/* 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 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.killRoi(); int d = (int) Math.round(2.0 * r); IJ.makeOval( (int) Math.round(stats.xCentroid - r), (int) Math.round(stats.yCentroid - r), d, d); 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; imp.killRoi(); IJ.makeOval( (int) Math.round(CenterX - radius), (int) Math.round(CenterY - radius), (int) Math.round(2 * radius), (int) Math.round(2 * radius)); }
private void makeBand(ImagePlus imp) { Roi roi = imp.getRoi(); if (roi == null) { noRoi("Make Band"); return; } if (!roi.isArea()) { IJ.error("Make Band", "Area selection required"); return; } Calibration cal = imp.getCalibration(); double pixels = bandSize; double size = pixels * cal.pixelWidth; int decimalPlaces = 0; if ((int) size != size) decimalPlaces = 2; GenericDialog gd = new GenericDialog("Make Band"); gd.addNumericField("Band Size:", size, decimalPlaces, 4, cal.getUnits()); gd.showDialog(); if (gd.wasCanceled()) return; size = gd.getNextNumber(); if (Double.isNaN(size)) { IJ.error("Make Band", "invalid number"); return; } int n = (int) Math.round(size / cal.pixelWidth); if (n > 255) { IJ.error("Make Band", "Cannot make bands wider that 255 pixels"); return; } int width = imp.getWidth(); int height = imp.getHeight(); Rectangle r = roi.getBounds(); ImageProcessor ip = roi.getMask(); if (ip == null) { ip = new ByteProcessor(r.width, r.height); ip.invert(); } ImageProcessor mask = new ByteProcessor(width, height); mask.insert(ip, r.x, r.y); ImagePlus edm = new ImagePlus("mask", mask); boolean saveBlackBackground = Prefs.blackBackground; Prefs.blackBackground = false; IJ.run(edm, "Distance Map", ""); Prefs.blackBackground = saveBlackBackground; ip = edm.getProcessor(); ip.setThreshold(0, n, ImageProcessor.NO_LUT_UPDATE); int xx = -1, yy = -1; for (int x = r.x; x < r.x + r.width; x++) { for (int y = r.y; y < r.y + r.height; y++) { if (ip.getPixel(x, y) < n) { xx = x; yy = y; break; } } if (xx >= 0 || yy >= 0) break; } int count = IJ.doWand(edm, xx, yy, 0, null); if (count <= 0) { IJ.error("Make Band", "Unable to make band"); return; } ShapeRoi roi2 = new ShapeRoi(edm.getRoi()); if (!(roi instanceof ShapeRoi)) roi = new ShapeRoi(roi); ShapeRoi roi1 = (ShapeRoi) roi; roi2 = roi2.not(roi1); imp.setRoi(roi2); bandSize = n; }
ImageProcessor setup(ImagePlus imp) { ImageProcessor ip; int type = imp.getType(); if (type != ImagePlus.COLOR_RGB) return null; ip = imp.getProcessor(); int id = imp.getID(); int slice = imp.getCurrentSlice(); if ((id != previousImageID) | (slice != previousSlice) | (flag)) { flag = false; // if true, flags a change from HSB to RGB or viceversa numSlices = imp.getStackSize(); stack = imp.getStack(); width = stack.getWidth(); height = stack.getHeight(); numPixels = width * height; hSource = new byte[numPixels]; sSource = new byte[numPixels]; bSource = new byte[numPixels]; // restore = (int[])ip.getPixelsCopy(); //This runs into trouble sometimes, so do it the // long way: int[] temp = (int[]) ip.getPixels(); restore = new int[numPixels]; for (int i = 0; i < numPixels; i++) restore[i] = temp[i]; fillMask = new int[numPixels]; // Get hsb or rgb from image. ColorProcessor cp = (ColorProcessor) ip; IJ.showStatus("Gathering data"); if (isRGB) cp.getRGB(hSource, sSource, bSource); else cp.getHSB(hSource, sSource, bSource); IJ.showStatus("done"); // Create a spectrum ColorModel for the Hue histogram plot. Color c; byte[] reds = new byte[256]; byte[] greens = new byte[256]; byte[] blues = new byte[256]; for (int i = 0; i < 256; i++) { c = Color.getHSBColor(i / 255f, 1f, 1f); reds[i] = (byte) c.getRed(); greens[i] = (byte) c.getGreen(); blues[i] = (byte) c.getBlue(); } ColorModel cm = new IndexColorModel(8, 256, reds, greens, blues); // Make an image with just the hue from the RGB image and the spectrum LUT. // This is just for a hue histogram for the plot. Do not show it. // ByteProcessor bpHue = new ByteProcessor(width,height,h,cm); ByteProcessor bpHue = new ByteProcessor(width, height, hSource, cm); ImagePlus impHue = new ImagePlus("Hue", bpHue); // impHue.show(); ByteProcessor bpSat = new ByteProcessor(width, height, sSource, cm); ImagePlus impSat = new ImagePlus("Sat", bpSat); // impSat.show(); ByteProcessor bpBri = new ByteProcessor(width, height, bSource, cm); ImagePlus impBri = new ImagePlus("Bri", bpBri); // impBri.show(); plot.setHistogram(impHue, 0); splot.setHistogram(impSat, 1); bplot.setHistogram(impBri, 2); updateLabels(); updatePlot(); updateScrollBars(); imp.updateAndDraw(); } previousImageID = id; previousSlice = slice; return ip; }