DOWNLOAD
package Utils; import ij.IJ;import ij.ImagePlus;import ij.gui.PolygonRoi;import ij.measure.Measurements;import ij.process.ImageProcessor; public class Convex_Hull_Plus implements Measurements { ImagePlus imp; int counter = 0; private PolygonRoi convexHullPolygonRoi = null; public void run(ImageProcessor ip) { this.imp = new ImagePlus("", ip); String myMode = "Convex Hull selection"; boolean white = true; int k = 0; int colour = 0; if (white) { colour = 255; } for(int j = 0; j < this.imp.getHeight(); ++j) { for(int i = 0; i < this.imp.getWidth(); ++i) { if (ip.getPixel(i, j) == colour) { ++this.counter; } } } int[] x = new int[this.counter + 1]; int[] y = new int[this.counter + 1]; for(int var74 = 0; var74 < this.imp.getHeight(); ++var74) { for(int i = 0; i < this.imp.getWidth(); ++i) { if (ip.getPixel(i, var74) == colour) { x[k] = i; y[k] = var74; ++k; } } } int n = this.counter; int min = 0; int ney = 0; double zxmi = 0.0; for(int i = 1; i < n; ++i) { if (y[i] < y[min]) { min = i; } } int temp = x[0]; x[0] = x[min]; x[min] = temp; temp = y[0]; y[0] = y[min]; y[min] = temp; min = 0; for(int var67 = 1; var67 < n; ++var67) { if (y[var67] == y[0]) { ++ney; if (x[var67] < x[min]) { min = var67; } } } temp = x[0]; x[0] = x[min]; x[min] = temp; temp = y[0]; y[0] = y[min]; y[min] = temp; ip.setColor(127); int px = x[0]; int py = y[0]; min = 0; int m = -1; x[n] = x[min]; y[n] = y[min]; double minangle; if (ney > 0) { minangle = -1.0; } else { minangle = 0.0; } while(min != n + 0) { temp = x[++m]; x[m] = x[min]; x[min] = temp; temp = y[m]; y[m] = y[min]; y[min] = temp; min = n; double v = minangle; minangle = 360.0; int h2 = 0; for(int var68 = m + 1; var68 < n + 1; ++var68) { int dx = x[var68] - x[m]; int ax = Math.abs(dx); int dy = y[var68] - y[m]; int ay = Math.abs(dy); double t; if (dx == 0 && dy == 0) { t = 0.0; } else { t = (double)dy / (double)(ax + ay); } if (dx < 0) { t = 2.0 - t; } else if (dy < 0) { t += 4.0; } double th = t * 90.0; if (th > v) { if (th < minangle) { min = var68; minangle = th; h2 = dx * dx + dy * dy; } else if (th == minangle) { int h = dx * dx + dy * dy; if (h > h2) { min = var68; h2 = h; } } } } if (myMode.equals("Draw Convex Hull") || myMode.equals("Draw both")) { ip.drawLine(px, py, x[min], y[min]); } px = x[min]; py = y[min]; zxmi += Math.sqrt((double)h2); } int[] hx = new int[++m]; int[] hy = new int[m]; for(int var69 = 0; var69 < m; ++var69) { hx[var69] = x[var69]; hy[var69] = y[var69]; } if (myMode.equals("Convex Hull selection")) { this.convexHullPolygonRoi = new PolygonRoi(hx, hy, hx.length, 2); this.imp.setRoi(this.convexHullPolygonRoi); } double[] d = new double[m * (m - 1) / 2]; int[] p1 = new int[m * (m - 1) / 2]; int[] p2 = new int[m * (m - 1) / 2]; k = 0; for(int var70 = 0; var70 < m - 1; ++var70) { for(int var75 = var70 + 1; var75 < m; ++var75) { d[k] = Math.sqrt(Math.pow((double)(hx[var70] - hx[var75]), 2.0) + Math.pow((double)(hy[var70] - hy[var75]), 2.0)); p1[k] = var70; p2[k] = var75; ++k; } } --k; boolean sw = true; while(sw) { sw = false; for(int var71 = 0; var71 < k - 1; ++var71) { if (d[var71] < d[var71 + 1]) { double tempd = d[var71]; d[var71] = d[var71 + 1]; d[var71 + 1] = tempd; temp = p1[var71]; p1[var71] = p1[var71 + 1]; p1[var71 + 1] = temp; temp = p2[var71]; p2[var71] = p2[var71 + 1]; p2[var71 + 1] = temp; sw = true; } } } double radius = d[0] / 2.0; double cx = (double)(hx[p1[0]] + hx[p2[0]]) / 2.0; double cy = (double)(hy[p1[0]] + hy[p2[0]]) / 2.0; int p3 = -1; double tt = radius; for(int var72 = 0; var72 < m; ++var72) { double tttemp = Math.sqrt(Math.pow((double)hx[var72] - cx, 2.0) + Math.pow((double)hy[var72] - cy, 2.0)); if (tttemp > tt) { tt = tttemp; p3 = var72; } } if (p3 > -1) { double[] op1 = new double[2]; double[] op2 = new double[2]; double[] op3 = new double[2]; double[] circ = new double[3]; double tD = Double.MAX_VALUE; int tp1 = 0; int tp2 = 0; int tp3 = 0; for(int var73 = 0; var73 < m - 2; ++var73) { for(int var76 = var73 + 1; var76 < m - 1; ++var76) { for(int var79 = var76 + 1; var79 < m; ++var79) { op1[0] = (double)hx[var73]; op1[1] = (double)hy[var73]; op2[0] = (double)hx[var76]; op2[1] = (double)hy[var76]; op3[0] = (double)hx[var79]; op3[1] = (double)hy[var79]; this.osculating(op1, op2, op3, circ); if (circ[2] > 0.0) { sw = true; for(int z = 0; z < m; ++z) { double tttemp = (double)((float)Math.sqrt(Math.pow((double)hx[z] - circ[0], 2.0) + Math.pow((double)hy[z] - circ[1], 2.0))); if (tttemp > circ[2]) { sw = false; break; } } if (sw && circ[2] < tD) { tp1 = var73; tp2 = var76; tp3 = var79; tD = circ[2]; } } } } } op1[0] = (double)hx[tp1]; op1[1] = (double)hy[tp1]; op2[0] = (double)hx[tp2]; op2[1] = (double)hy[tp2]; op3[0] = (double)hx[tp3]; op3[1] = (double)hy[tp3]; this.osculating(op1, op2, op3, circ); radius = circ[2]; if (myMode.equals("Minimal Bounding Circle selection") && circ[2] > 0.0) { IJ.makeOval( (int)Math.floor(circ[0] - circ[2] + 0.5), (int)Math.floor(circ[1] - circ[2] + 0.5), (int)Math.floor(radius * 2.0 + 0.5), (int)Math.floor(radius * 2.0 + 0.5) ); } if ((myMode.equals("Draw Minimal Bounding Circle") || myMode.equals("Draw both")) && circ[2] > 0.0) { IJ.makeOval( (int)Math.floor(circ[0] - circ[2] + 0.5), (int)Math.floor(circ[1] - circ[2] + 0.5), (int)Math.floor(radius * 2.0 + 0.5), (int)Math.floor(radius * 2.0 + 0.5) ); IJ.run("Unlock Image"); IJ.run("Draw"); } } else { if (myMode.equals("Minimal Bounding Circle selection")) { IJ.makeOval((int)Math.floor(cx - radius + 0.5), (int)Math.floor(cy - radius + 0.5), (int)Math.floor(d[0] + 0.5), (int)Math.floor(d[0] + 0.5)); } if (myMode.equals("Draw Minimal Bounding Circle") || myMode.equals("Draw both")) { IJ.makeOval((int)(cx - radius), (int)(cy - radius), (int)Math.floor(d[0] + 0.5), (int)Math.floor(d[0] + 0.5)); IJ.run("Unlock Image"); IJ.run("Draw"); } } } public PolygonRoi getConvexHullPolygonRoi() { return this.convexHullPolygonRoi; } void osculating(double[] pa, double[] pb, double[] pc, double[] centrad) { if ((pa[0] != pb[0] || pb[0] != pc[0]) && (pa[1] != pb[1] || pb[1] != pc[1])) { double a = pb[0] - pa[0]; double b = pb[1] - pa[1]; double c = pc[0] - pa[0]; double d = pc[1] - pa[1]; double e = a * (pa[0] + pb[0]) + b * (pa[1] + pb[1]); double f = c * (pa[0] + pc[0]) + d * (pa[1] + pc[1]); double g = 2.0 * (a * (pc[1] - pb[1]) - b * (pc[0] - pb[0])); if (g == 0.0) { centrad[0] = 0.0; centrad[1] = 0.0; centrad[2] = -1.0; } else { centrad[0] = (d * e - b * f) / g; centrad[1] = (a * f - c * e) / g; centrad[2] = (double)((float)Math.sqrt(Math.pow(pa[0] - centrad[0], 2.0) + Math.pow(pa[1] - centrad[1], 2.0))); } } else { centrad[0] = 0.0; centrad[1] = 0.0; centrad[2] = -1.0; } }}