Search in sources :

Example 61 with Nullable

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

the class FindFociOptimiser_PlugIn method showResult.

@Nullable
private static AssignedPoint[] showResult(ImagePlus imp, ImagePlus mask, Parameters parameters, boolean showScoreImages, int matchSearchMethod, double matchSearchDistance) {
    if (imp == null) {
        return null;
    }
    // Clone the input image to allow display of the peaks on the original
    final ImagePlus clone = cloneImage(imp, imp.getTitle() + " clone");
    clone.show();
    final FindFociProcessorOptions processorOptions = parameters.processorOptions.copy();
    processorOptions.setMaskMethod(MaskMethod.PEAKS_ABOVE_SADDLE);
    final FindFociOptions options = new FindFociOptions(true);
    options.setOption(OutputOption.ROI_SELECTION, true);
    options.setOption(OutputOption.MASK_ROI_SELECTION, true);
    final FindFoci_PlugIn ff = new FindFoci_PlugIn();
    ff.exec(clone, mask, processorOptions, options, true);
    // Add 3D support here by getting the results from the results table
    final List<FindFociResult> results = FindFoci_PlugIn.getLastResults();
    final AssignedPoint[] predictedPoints = extractedPredictedPoints(results);
    maskImage(clone, mask);
    if (showScoreImages) {
        final AssignedPoint[] actualPoints = extractRoiPoints(imp, mask);
        final List<Coordinate> truePositives = new LinkedList<>();
        final List<Coordinate> falsePositives = new LinkedList<>();
        final List<Coordinate> falseNegatives = new LinkedList<>();
        final double distanceThreshold = getDistanceThreshold(imp, matchSearchMethod, matchSearchDistance);
        final ToDoubleBiFunction<Coordinate, Coordinate> distanceFunction = CoordinateUtils.getSquaredDistanceFunction(imp.getCalibration(), is3D(actualPoints));
        MatchCalculator.analyseResultsCoordinates(actualPoints, predictedPoints, distanceThreshold, truePositives, falsePositives, falseNegatives, null, distanceFunction);
        // Show image with TP, FP and FN. Use an overlay to support 3D images
        final ImagePlus tpImp = cloneImage(imp, mask, imp.getTitle() + " TP");
        tpImp.setOverlay(createOverlay(truePositives, imp));
        tpImp.show();
        final ImagePlus fpImp = cloneImage(imp, mask, imp.getTitle() + " FP");
        fpImp.setOverlay(createOverlay(falsePositives, imp));
        fpImp.show();
        final ImagePlus fnImp = cloneImage(imp, mask, imp.getTitle() + " FN");
        fnImp.setOverlay(createOverlay(falseNegatives, imp));
        fnImp.show();
    } else {
        // Leaving old results would be confusing so close them
        closeImage(imp.getTitle() + " TP");
        closeImage(imp.getTitle() + " FP");
        closeImage(imp.getTitle() + " FN");
    }
    return predictedPoints;
}
Also used : ImagePlus(ij.ImagePlus) LinkedList(java.util.LinkedList) Coordinate(uk.ac.sussex.gdsc.core.match.Coordinate) Nullable(uk.ac.sussex.gdsc.core.annotation.Nullable)

Example 62 with Nullable

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

the class FindFociBaseProcessor method extractMask.

/**
 * Extract the mask image.
 *
 * @param mask the mask
 * @return The mask image array
 */
@Nullable
private int[] extractMask(ImagePlus mask) {
    if (mask == null) {
        return null;
    }
    // Check sizes in X & Y
    if (mask.getWidth() != maxx || mask.getHeight() != maxy || (mask.getNSlices() != maxz && mask.getNSlices() != 1)) {
        return null;
    }
    final int maxx_maxy = maxx * maxy;
    final int[] image;
    if (mask.getNSlices() == 1) {
        // Extract a single plane
        final ImageProcessor ipMask = mask.getProcessor();
        image = new int[maxx_maxy];
        for (int i = maxx_maxy; i-- > 0; ) {
            image[i] = ipMask.get(i);
        }
    } else {
        final int maxx_maxy_maxz = maxx * maxy * maxz;
        // If the same stack size then process through the image
        final ImageStack stack = mask.getStack();
        final int c = mask.getChannel();
        final int f = mask.getFrame();
        image = new int[maxx_maxy_maxz];
        for (int slice = 1; slice <= mask.getNSlices(); slice++) {
            final int stackIndex = mask.getStackIndex(c, slice, f);
            final ImageProcessor ipMask = stack.getProcessor(stackIndex);
            int index = maxx_maxy * slice;
            for (int i = maxx_maxy; i-- > 0; ) {
                index--;
                image[index] = ipMask.get(i);
            }
        }
    }
    return image;
}
Also used : ImageProcessor(ij.process.ImageProcessor) ImageStack(ij.ImageStack) Nullable(uk.ac.sussex.gdsc.core.annotation.Nullable)

Example 63 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 64 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 65 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)

Aggregations

Nullable (uk.ac.sussex.gdsc.core.annotation.Nullable)83 Point (java.awt.Point)16 LinkedList (java.util.LinkedList)12 ArrayList (java.util.ArrayList)11 Rectangle (java.awt.Rectangle)9 ConvergenceException (org.apache.commons.math3.exception.ConvergenceException)8 TooManyIterationsException (org.apache.commons.math3.exception.TooManyIterationsException)8 FractionalAssignment (uk.ac.sussex.gdsc.core.match.FractionalAssignment)8 DirectFilter (uk.ac.sussex.gdsc.smlm.results.filter.DirectFilter)8 IDirectFilter (uk.ac.sussex.gdsc.smlm.results.filter.IDirectFilter)8 ImagePlus (ij.ImagePlus)7 FloatProcessor (ij.process.FloatProcessor)7 Plot (ij.gui.Plot)6 ConcurrentRuntimeException (org.apache.commons.lang3.concurrent.ConcurrentRuntimeException)6 HistogramPlot (uk.ac.sussex.gdsc.core.ij.HistogramPlot)6 ExtendedGenericDialog (uk.ac.sussex.gdsc.core.ij.gui.ExtendedGenericDialog)6 MultiPathFilter (uk.ac.sussex.gdsc.smlm.results.filter.MultiPathFilter)6 PeakFractionalAssignment (uk.ac.sussex.gdsc.smlm.results.filter.PeakFractionalAssignment)6 ImageProcessor (ij.process.ImageProcessor)5 LeastSquaresBuilder (org.apache.commons.math3.fitting.leastsquares.LeastSquaresBuilder)5