Search in sources :

Example 46 with Nullable

use of uk.ac.sussex.gdsc.core.annotation.Nullable in project gdsc by aherbert.

the class AutoThreshold_PlugIn method exec.

/**
 * Execute the plugin functionality.
 *
 * @param imp the image
 * @param method the method
 * @param noWhite the no white
 * @param noBlack the no black
 * @param doIwhite flag to set the foreground as white
 * @param doIset flag to set the threshold on the image
 * @param doIlog flag to log the threshold
 * @param doIstackHistogram flag to use the stack histogram
 * @return an Object[] array with the threshold and the ImagePlus. Does NOT show the new, image;
 *         just returns it.
 */
@Nullable
public Object[] exec(ImagePlus imp, AutoThreshold.Method method, boolean noWhite, boolean noBlack, boolean doIwhite, boolean doIset, boolean doIlog, boolean doIstackHistogram) {
    // 0 - Check validity of parameters
    if (null == imp) {
        return null;
    }
    final int currentSlice = imp.getCurrentSlice();
    ImageProcessor ip = imp.getProcessor();
    final int xe = ip.getWidth();
    final int ye = ip.getHeight();
    int foreColour = 0;
    int backColour = imp.getBitDepth() == 8 ? 255 : 65535;
    if (doIwhite) {
        foreColour = backColour;
        backColour = 0;
    }
    final int[] data = ip.getHistogram();
    IJ.showStatus("Thresholding...");
    // 1 Do it
    if (imp.getStackSize() == 1) {
        ip.snapshot();
        Undo.setup(Undo.FILTER, imp);
    } else if (doIstackHistogram) {
        // get the stack histogram into the data[] array
        for (int i = 1; i <= imp.getStackSize(); i++) {
            // Ignore the slice that has already been included
            if (i == currentSlice) {
                continue;
            }
            imp.setSliceWithoutUpdate(i);
            ip = imp.getProcessor();
            final int[] temp = ip.getHistogram();
            for (int j = 0; j < data.length; j++) {
                data[j] += temp[j];
            }
        }
        imp.setSliceWithoutUpdate(currentSlice);
    }
    if (noBlack) {
        data[0] = 0;
    }
    if (noWhite) {
        data[data.length - 1] = 0;
    }
    final int threshold = AutoThreshold.getThreshold(method, data);
    // show threshold in log window if required
    if (doIlog) {
        IJ.log(method + ": " + threshold);
    }
    if (threshold > -1) {
        // threshold it
        if (doIset) {
            if (doIwhite) {
                imp.getProcessor().setThreshold(threshold + 1.0, data.length - 1.0, ImageProcessor.RED_LUT);
            } else {
                imp.getProcessor().setThreshold(0, threshold, ImageProcessor.RED_LUT);
            }
        } else {
            // Reset display range otherwise we can never set the threshold
            imp.setDisplayRange(0, Math.max(backColour, foreColour));
            if (doIstackHistogram) {
                for (int j = 1; j <= imp.getStackSize(); j++) {
                    imp.setSliceWithoutUpdate(j);
                    ip = imp.getProcessor();
                    for (int y = 0; y < ye; y++) {
                        for (int x = 0; x < xe; x++) {
                            if (ip.getPixel(x, y) > threshold) {
                                ip.putPixel(x, y, foreColour);
                            } else {
                                ip.putPixel(x, y, backColour);
                            }
                        }
                    }
                }
                // threshold all of them
                imp.setSliceWithoutUpdate(currentSlice);
            } else {
                for (int y = 0; y < ye; y++) {
                    for (int x = 0; x < xe; x++) {
                        if (ip.getPixel(x, y) > threshold) {
                            ip.putPixel(x, y, foreColour);
                        } else {
                            ip.putPixel(x, y, backColour);
                        }
                    }
                }
            }
            imp.getProcessor().setThreshold(data.length - 1.0, data.length - 1.0, ImageProcessor.NO_LUT_UPDATE);
        }
    }
    imp.updateAndDraw();
    // 2 - Return the threshold and the image
    return new Object[] { threshold, imp };
}
Also used : ImageProcessor(ij.process.ImageProcessor) Nullable(uk.ac.sussex.gdsc.core.annotation.Nullable)

Example 47 with Nullable

use of uk.ac.sussex.gdsc.core.annotation.Nullable in project gdsc by aherbert.

the class CellOutliner_PlugIn method findCells.

@Nullable
private PolygonRoi[] findCells(ImageProcessor inputProcessor) {
    // Limit processing to where it is needed
    final Rectangle bounds = createBounds(inputProcessor, xpoints, ypoints, getCellRange());
    ImageProcessor ip = inputProcessor.duplicate();
    ip.setRoi(bounds);
    ip = ip.crop();
    if (kernels == null) {
        kernels = createKernels();
        convolved = null;
    }
    if (convolved == null) {
        convolved = convolveImage(ip, kernels);
    // showConvolvedImages(convolved)
    }
    if (ImageJUtils.isInterrupted()) {
        return null;
    }
    FloatProcessor combinedIp = null;
    Blitter blitter = null;
    ImagePlus combinedImp = null;
    if (debug) {
        combinedIp = new FloatProcessor(ip.getWidth(), ip.getHeight());
        blitter = new FloatBlitter(combinedIp);
        combinedImp = displayImage(combinedIp, "Combined edge projection");
    }
    final PolygonRoi[] cells = new PolygonRoi[xpoints.length];
    if (!this.buildMaskOutput) {
        IJ.showStatus("Finding cells ...");
    }
    // Process each point
    for (int n = 0; n < xpoints.length; n++) {
        if (!this.buildMaskOutput) {
            IJ.showProgress(n, xpoints.length);
        }
        final int cx = xpoints[n] - bounds.x;
        final int cy = ypoints[n] - bounds.y;
        // Restrict bounds using the cell radius and tolerance
        final Rectangle pointBounds = createBounds(ip, cx, cy, cx, cy, getCellRange());
        // Calculate the angle
        final FloatProcessor angle = createAngleProcessor(cx, cy, pointBounds);
        if (ImageJUtils.isInterrupted()) {
            return null;
        }
        final FloatProcessor edgeProjection = computeEdgeProjection(convolved, pointBounds, angle);
        // Initialise the edge as a circle.
        PolygonRoi cell = null;
        double[] params = { cx - pointBounds.x, cy - pointBounds.y, settings.cellRadius, settings.cellRadius, settings.cellRadius, 0 };
        final double range = settings.cellRadius * 0.9;
        // Iterate to find the best cell outline
        boolean returnEllipticalFit = settings.ellipticalFit;
        for (int iter = 0; iter < settings.iterations; iter++) {
            // Use the current elliptical edge to define the weights for the edge projection
            final FloatProcessor weights = createWeightMap(pointBounds, params, range);
            if (ImageJUtils.isInterrupted() || weights == null) {
                return null;
            }
            if (debug) {
                displayImage(weights, "Weight map");
            }
            final FloatProcessor weightedEdgeProjection = applyWeights(edgeProjection, weights);
            if (debug) {
                blitter.copyBits(weightedEdgeProjection, pointBounds.x, pointBounds.y, Blitter.ADD);
                combinedIp.resetMinAndMax();
                combinedImp.updateAndDraw();
                displayImage(weightedEdgeProjection, "Weighted edge projection");
            }
            cell = findPolygonalCell((int) Math.round(params[0]), (int) Math.round(params[1]), weightedEdgeProjection, angle);
            // weights
            final FloatProcessor weightMap = weightedEdgeProjection;
            final double[] newParams = fitPolygonalCell(cell, params, weightMap);
            if (newParams == null) {
                returnEllipticalFit = false;
                break;
            }
            // Set the parameters for the weight map
            params = newParams;
        }
        assert cell != null : "No cell";
        // Return either the fitted elliptical cell or the last polygon outline
        if (returnEllipticalFit) {
            final EllipticalCell e = new EllipticalCell();
            final FloatPolygon ellipse = e.drawEllipse(params);
            cell = new PolygonRoi(ellipse.xpoints, ellipse.ypoints, ellipse.npoints, Roi.POLYGON);
        }
        PolygonRoi finalCell = cell;
        if (settings.dilate > 0) {
            // Dilate the cell and then trace the new outline
            final ByteProcessor bp = new ByteProcessor(pointBounds.width, pointBounds.height);
            bp.setColor(CELL & 0xff);
            bp.draw(cell);
            for (int i = 0; i < settings.dilate; i++) {
                dilate(bp);
            }
            cell = traceOutline(bp);
            if (cell != null) {
                finalCell = cell;
            }
        }
        final Rectangle pos = finalCell.getBounds();
        // Does not work in IJ 1.46+
        // finalCell.setLocation(pos.x + bounds.x + pointBounds.x, pos.y + bounds.y + pointBounds.y)
        // Create a new Polygon with the correct coordinates. This is required since IJ 1.46
        // since setting the location is not passed through when drawing an overlay
        final int[] xCoords = finalCell.getXCoordinates();
        final int[] yCoords = finalCell.getYCoordinates();
        final int npoints = finalCell.getNCoordinates();
        for (int i = 0; i < npoints; i++) {
            xCoords[i] += pos.x + bounds.x + pointBounds.x;
            yCoords[i] += pos.y + bounds.y + pointBounds.y;
        }
        finalCell = new PolygonRoi(xCoords, yCoords, npoints, Roi.POLYGON);
        cells[n] = finalCell;
    }
    return cells;
}
Also used : ByteProcessor(ij.process.ByteProcessor) FloatProcessor(ij.process.FloatProcessor) Rectangle(java.awt.Rectangle) Blitter(ij.process.Blitter) FloatBlitter(ij.process.FloatBlitter) ImagePlus(ij.ImagePlus) Point(java.awt.Point) ImageProcessor(ij.process.ImageProcessor) FloatBlitter(ij.process.FloatBlitter) PolygonRoi(ij.gui.PolygonRoi) FloatPolygon(ij.process.FloatPolygon) Nullable(uk.ac.sussex.gdsc.core.annotation.Nullable)

Example 48 with Nullable

use of uk.ac.sussex.gdsc.core.annotation.Nullable in project gdsc by aherbert.

the class CellOutliner_PlugIn method fitPolygonalCell.

/**
 * Find an ellipse that optimises the fit to the polygon detected edges.
 *
 * @param roi the roi
 * @param params the params
 * @param weightMap the weight map
 * @return the ellipse parameters
 */
@Nullable
private double[] fitPolygonalCell(PolygonRoi roi, double[] params, FloatProcessor weightMap) {
    // Get an estimate of the starting parameters using the current polygon
    final double[] startPoint = estimateStartPoint(roi, weightMap.getWidth(), weightMap.getHeight());
    final int maxEval = 2000;
    final DifferentiableEllipticalFitFunction func = new DifferentiableEllipticalFitFunction(roi, weightMap);
    final double relativeThreshold = 100 * Precision.EPSILON;
    final double absoluteThreshold = 100 * Precision.SAFE_MIN;
    final ConvergenceChecker<PointVectorValuePair> checker = new SimplePointChecker<>(relativeThreshold, absoluteThreshold);
    final double initialStepBoundFactor = 10;
    final double costRelativeTolerance = 1e-10;
    final double parRelativeTolerance = 1e-10;
    final double orthoTolerance = 1e-10;
    final double threshold = Precision.SAFE_MIN;
    final LevenbergMarquardtOptimizer optimiser = new LevenbergMarquardtOptimizer(initialStepBoundFactor, costRelativeTolerance, parRelativeTolerance, orthoTolerance, threshold);
    try {
        // @formatter:off
        final LeastSquaresProblem problem = new LeastSquaresBuilder().maxEvaluations(Integer.MAX_VALUE).maxIterations(maxEval).start(startPoint).target(func.calculateTarget()).weight(new DiagonalMatrix(func.calculateWeights())).model(func, func::jacobian).checkerPair(checker).build();
        // @formatter:on
        final Optimum solution = optimiser.optimize(problem);
        if (debug) {
            IJ.log(String.format("Eval = %d (Iter = %d), RMS = %f", solution.getEvaluations(), solution.getIterations(), solution.getRMS()));
        }
        return solution.getPoint().toArray();
    } catch (final Exception ex) {
        IJ.log("Failed to find an elliptical solution, defaulting to polygon: " + ex.getMessage());
    }
    return null;
}
Also used : Point(java.awt.Point) LeastSquaresBuilder(org.apache.commons.math3.fitting.leastsquares.LeastSquaresBuilder) Optimum(org.apache.commons.math3.fitting.leastsquares.LeastSquaresOptimizer.Optimum) PointVectorValuePair(org.apache.commons.math3.optim.PointVectorValuePair) LevenbergMarquardtOptimizer(org.apache.commons.math3.fitting.leastsquares.LevenbergMarquardtOptimizer) DiagonalMatrix(org.apache.commons.math3.linear.DiagonalMatrix) LeastSquaresProblem(org.apache.commons.math3.fitting.leastsquares.LeastSquaresProblem) SimplePointChecker(org.apache.commons.math3.optim.SimplePointChecker) Nullable(uk.ac.sussex.gdsc.core.annotation.Nullable)

Example 49 with Nullable

use of uk.ac.sussex.gdsc.core.annotation.Nullable in project gdsc by aherbert.

the class GaussianFit_PlugIn method fit.

/**
 * Fit the data using a 2D Gaussian.
 *
 * <p>Returns null if fitting failed.
 *
 * @param data the data
 * @param width the width
 * @param height the height
 * @return The fitted Gaussian parameters (Background, Amplitude, x0, x1, s)
 */
@Nullable
public double[] fit(float[] data, int width, int height) {
    SimpleArrayUtils.hasData2D(width, height, data);
    try {
        // Use reflection to allow building without the SMLM plugins on the classpath
        final Class c = Class.forName(GAUSSIAN_FIT_CLASS, true, this.getClass().getClassLoader());
        final Method m = c.getDeclaredMethod("fit", float[].class, int.class, int.class);
        return (double[]) m.invoke(c.newInstance(), data, width, height);
    } catch (final ExceptionInInitializerError | RuntimeException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException ex) {
        Logger.getLogger(getClass().getName()).log(Level.WARNING, () -> "Fitting failed: " + ex.getMessage());
        return null;
    }
}
Also used : Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) Nullable(uk.ac.sussex.gdsc.core.annotation.Nullable)

Aggregations

Nullable (uk.ac.sussex.gdsc.core.annotation.Nullable)49 Point (java.awt.Point)10 ArrayList (java.util.ArrayList)8 LinkedList (java.util.LinkedList)6 ImagePlus (ij.ImagePlus)5 Rectangle (java.awt.Rectangle)5 FloatProcessor (ij.process.FloatProcessor)4 ImageProcessor (ij.process.ImageProcessor)4 ConvergenceException (org.apache.commons.math3.exception.ConvergenceException)4 TooManyIterationsException (org.apache.commons.math3.exception.TooManyIterationsException)4 FractionalAssignment (uk.ac.sussex.gdsc.core.match.FractionalAssignment)4 DirectFilter (uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter)4 IDirectFilter (uk.ac.sussex.gdsc.smlm.results.filter.IDirectFilter)4 Plot (ij.gui.Plot)3 File (java.io.File)3 ConcurrentRuntimeException (org.apache.commons.lang3.concurrent.ConcurrentRuntimeException)3 LeastSquaresBuilder (org.apache.commons.math3.fitting.leastsquares.LeastSquaresBuilder)3 Optimum (org.apache.commons.math3.fitting.leastsquares.LeastSquaresOptimizer.Optimum)3 LeastSquaresProblem (org.apache.commons.math3.fitting.leastsquares.LeastSquaresProblem)3 LevenbergMarquardtOptimizer (org.apache.commons.math3.fitting.leastsquares.LevenbergMarquardtOptimizer)3