Search in sources :

Example 11 with MeasurementList

use of qupath.lib.measurements.MeasurementList in project qupath by qupath.

the class SubcellularDetection method processObject.

/**
 * Initial version of subcellular detection processing.
 *
 * @param pathObject
 * @param params
 * @param imageWrapper
 * @return
 * @throws InterruptedException
 * @throws IOException
 */
static boolean processObject(final PathObject pathObject, final ParameterList params, final ImageWrapper imageWrapper) throws InterruptedException, IOException {
    // Get the base classification for the object as it currently stands
    PathClass baseClass = PathClassTools.getNonIntensityAncestorClass(pathObject.getPathClass());
    // Variable to hold estimated spot count
    double estimatedSpots;
    // We assume that after this processing, any previous sub-cellular objects should be removed
    pathObject.clearPathObjects();
    // Ensure we have no existing subcellular detection measurements - if we do, remove them
    String[] existingMeasurements = pathObject.getMeasurementList().getMeasurementNames().stream().filter(n -> n.startsWith("Subcellular:")).toArray(n -> new String[n]);
    if (existingMeasurements.length > 0) {
        pathObject.getMeasurementList().removeMeasurements(existingMeasurements);
        pathObject.getMeasurementList().close();
    }
    // // If we're part of a TMA core, request the whole core...
    // if (pathObject.getParent() instanceof TMACoreObject && pathObject.getParent().hasROI()) {
    // regionStore.getImage(server, RegionRequest.createInstance(server.getPath(), 1, pathObject.getParent().getROI()), 25, true);
    // }
    ROI pathROI = pathObject.getROI();
    if (pathROI == null || pathROI.isEmpty())
        return false;
    // double downsample = 0.5;
    double downsample = 1;
    // Determine spot size
    ImageServer<BufferedImage> server = imageWrapper.getServer();
    PixelCalibration cal = server.getPixelCalibration();
    double minSpotArea, maxSpotArea, singleSpotArea;
    double pixelWidth, pixelHeight;
    if (cal.hasPixelSizeMicrons()) {
        double spotSizeMicrons = params.getDoubleParameterValue("spotSizeMicrons");
        double minSpotSizeMicrons = params.getDoubleParameterValue("minSpotSizeMicrons");
        double maxSpotSizeMicrons = params.getDoubleParameterValue("maxSpotSizeMicrons");
        pixelWidth = cal.getPixelWidthMicrons() * downsample;
        pixelHeight = cal.getPixelHeightMicrons() * downsample;
        singleSpotArea = spotSizeMicrons / (pixelWidth * pixelHeight);
        minSpotArea = minSpotSizeMicrons / (pixelWidth * pixelHeight);
        maxSpotArea = maxSpotSizeMicrons / (pixelWidth * pixelHeight);
    } else {
        singleSpotArea = params.getDoubleParameterValue("spotSizePixels");
        minSpotArea = params.getDoubleParameterValue("minSpotSizePixels");
        maxSpotArea = params.getDoubleParameterValue("maxSpotSizePixels");
        pixelWidth = downsample;
        pixelHeight = downsample;
    }
    boolean includeClusters = Boolean.TRUE.equals(params.getBooleanParameterValue("includeClusters"));
    boolean doSmoothing = Boolean.TRUE.equals(params.getBooleanParameterValue("doSmoothing"));
    boolean splitByIntensity = Boolean.TRUE.equals(params.getBooleanParameterValue("splitByIntensity"));
    boolean splitByShape = Boolean.TRUE.equals(params.getBooleanParameterValue("splitByShape"));
    // Get region to request - give a pixel as border
    int xStart = (int) Math.max(0, pathROI.getBoundsX() - 1);
    int yStart = (int) Math.max(0, pathROI.getBoundsY() - 1);
    int width = (int) Math.min(server.getWidth() - 1, pathROI.getBoundsX() + pathROI.getBoundsWidth() + 1.5) - xStart;
    int height = (int) Math.min(server.getHeight() - 1, pathROI.getBoundsY() + pathROI.getBoundsHeight() + 1.5) - yStart;
    if (width <= 0 || height <= 0) {
        logger.error("Negative ROI size for {}", pathROI);
        pathObject.setPathClass(baseClass);
        return false;
    }
    int z = pathROI.getZ();
    int t = pathROI.getT();
    // Don't associate with channel
    int c = -1;
    RegionRequest region = RegionRequest.createInstance(server.getPath(), 1.0, xStart, yStart, width, height, z, t);
    // Mask to indicate pixels within the cell
    byte[] cellMask = null;
    for (String channelName : imageWrapper.getChannelNames(true, true)) {
        double detectionThreshold = params.getDoubleParameterValue("detection[" + channelName + "]");
        if (Double.isNaN(detectionThreshold) || detectionThreshold < 0)
            continue;
        // // TODO: Consider whether to use channel numbers for non-brightfield images
        // if (!imageWrapper.imageData.isBrightfield())
        // c++;
        SimpleImage img = imageWrapper.getRegion(region, channelName);
        // Get an ImageJ-friendly calibration for ROI conversion
        Calibration calIJ = new Calibration();
        calIJ.xOrigin = -xStart / downsample;
        calIJ.yOrigin = -yStart / downsample;
        // Create a cell mask
        if (cellMask == null) {
            BufferedImage imgMask = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
            Graphics2D g2d = imgMask.createGraphics();
            if (downsample != 1)
                g2d.scale(1.0 / downsample, 1.0 / downsample);
            g2d.translate(-xStart, -yStart);
            Shape shape = RoiTools.getShape(pathROI);
            g2d.setColor(Color.WHITE);
            g2d.fill(shape);
            g2d.dispose();
            cellMask = (byte[]) ((DataBufferByte) imgMask.getRaster().getDataBuffer()).getData(0);
        }
        // Get a buffer containing the image pixels
        int w = img.getWidth();
        int h = img.getHeight();
        // Identify (& try to separate) spots
        // Mask out non-cell areas as we go
        FloatProcessor fpDetection = new FloatProcessor(w, h);
        if (doSmoothing) {
            for (int i = 0; i < w * h; i++) fpDetection.setf(i, img.getValue(i % w, i / w));
            fpDetection.smooth();
            for (int i = 0; i < w * h; i++) {
                if (cellMask[i] == (byte) 0)
                    fpDetection.setf(i, 0f);
            }
        } else {
            for (int i = 0; i < w * h; i++) {
                if (cellMask[i] == (byte) 0)
                    fpDetection.setf(i, 0f);
                else
                    fpDetection.setf(i, img.getValue(i % w, i / w));
            }
        }
        ByteProcessor bpSpots;
        if (splitByIntensity)
            bpSpots = new MaximumFinder().findMaxima(fpDetection, detectionThreshold / 10.0, detectionThreshold, MaximumFinder.SEGMENTED, false, false);
        else
            bpSpots = SimpleThresholding.thresholdAboveEquals(fpDetection, (float) detectionThreshold);
        if (splitByShape) {
            new EDM().toWatershed(bpSpots);
        }
        // Loop through spot ROIs & make a decision
        bpSpots.setThreshold(1, ImageProcessor.NO_THRESHOLD, ImageProcessor.NO_LUT_UPDATE);
        List<PolygonRoi> possibleSpotRois = RoiLabeling.getFilledPolygonROIs(bpSpots, Wand.FOUR_CONNECTED);
        List<PathObject> spotObjects = new ArrayList<>();
        List<PathObject> clusterObjects = new ArrayList<>();
        estimatedSpots = 0;
        for (PolygonRoi spotRoi : possibleSpotRois) {
            fpDetection.setRoi(spotRoi);
            ImageStatistics stats = fpDetection.getStatistics();
            // In v0.2
            // ImagePlane plane = ImagePlane.getPlaneWithChannel(spotRoi.getCPosition(), spotRoi.getZPosition(), spotRoi.getTPosition());
            // In v0.3
            ImagePlane plane = ImagePlane.getPlaneWithChannel(c, z, t);
            PathObject spotOrCluster = null;
            if (stats.pixelCount >= minSpotArea && stats.pixelCount <= maxSpotArea) {
                ROI roi = IJTools.convertToROI(spotRoi, calIJ, downsample, plane);
                // cluster = new SubcellularObject(roi, 1);
                spotOrCluster = createSubcellularObject(roi, 1);
                estimatedSpots += 1;
            } else if (includeClusters && stats.pixelCount >= minSpotArea) {
                // Add a cluster
                ROI roi = IJTools.convertToROI(spotRoi, calIJ, downsample, plane);
                double nSpots = stats.pixelCount / singleSpotArea;
                estimatedSpots += nSpots;
                // cluster = new SubcellularObject(roi, nSpots);
                spotOrCluster = createSubcellularObject(roi, nSpots);
            }
            if (spotOrCluster != null) {
                boolean isCluster = spotOrCluster.getMeasurementList().getMeasurementValue("Num spots") > 1;
                int rgb = imageWrapper.getChannelColor(channelName);
                rgb = isCluster ? ColorTools.makeScaledRGB(rgb, 0.5) : ColorTools.makeScaledRGB(rgb, 1.5);
                PathClass pathClass = PathClassFactory.getDerivedPathClass(spotOrCluster.getPathClass(), channelName + " object", rgb);
                spotOrCluster.setPathClass(pathClass);
                spotOrCluster.getMeasurementList().putMeasurement("Subcellular cluster: " + channelName + ": Area", stats.pixelCount * pixelWidth * pixelHeight);
                spotOrCluster.getMeasurementList().putMeasurement("Subcellular cluster: " + channelName + ": Mean channel intensity", stats.mean);
                // cluster.getMeasurementList().putMeasurement("Subcellular cluster: " + channelName +  ": Max channel intensity", stats.max);
                spotOrCluster.getMeasurementList().close();
                if (isCluster)
                    clusterObjects.add(spotOrCluster);
                else
                    spotObjects.add(spotOrCluster);
            }
        }
        // Add measurements
        MeasurementList measurementList = pathObject.getMeasurementList();
        measurementList.putMeasurement("Subcellular: " + channelName + ": Num spots estimated", estimatedSpots);
        measurementList.putMeasurement("Subcellular: " + channelName + ": Num single spots", spotObjects.size());
        measurementList.putMeasurement("Subcellular: " + channelName + ": Num clusters", clusterObjects.size());
        // Add spots
        pathObject.addPathObjects(spotObjects);
        pathObject.addPathObjects(clusterObjects);
    }
    return true;
}
Also used : Color(java.awt.Color) RoiLabeling(qupath.imagej.processing.RoiLabeling) ImageServer(qupath.lib.images.servers.ImageServer) ByteProcessor(ij.process.ByteProcessor) ImageProcessor(ij.process.ImageProcessor) IJTools(qupath.imagej.tools.IJTools) LoggerFactory(org.slf4j.LoggerFactory) DataBufferByte(java.awt.image.DataBufferByte) Wand(ij.gui.Wand) ParameterList(qupath.lib.plugins.parameters.ParameterList) ImageStatistics(ij.process.ImageStatistics) Map(java.util.Map) PluginRunner(qupath.lib.plugins.PluginRunner) Shape(java.awt.Shape) MeasurementListType(qupath.lib.measurements.MeasurementList.MeasurementListType) ColorTools(qupath.lib.common.ColorTools) BufferedImage(java.awt.image.BufferedImage) Collection(java.util.Collection) PathObjects(qupath.lib.objects.PathObjects) Collectors(java.util.stream.Collectors) EDM(ij.plugin.filter.EDM) StainVector(qupath.lib.color.StainVector) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathDetectionObject(qupath.lib.objects.PathDetectionObject) PathObject(qupath.lib.objects.PathObject) List(java.util.List) SimpleThresholding(qupath.imagej.processing.SimpleThresholding) ImagePlane(qupath.lib.regions.ImagePlane) AbstractInteractivePlugin(qupath.lib.plugins.AbstractInteractivePlugin) PathCellObject(qupath.lib.objects.PathCellObject) ColorTransformer(qupath.lib.color.ColorTransformer) PathClassTools(qupath.lib.objects.classes.PathClassTools) PolygonRoi(ij.gui.PolygonRoi) HashMap(java.util.HashMap) PathClassFactory(qupath.lib.objects.classes.PathClassFactory) ArrayList(java.util.ArrayList) MeasurementList(qupath.lib.measurements.MeasurementList) ColorDeconvolutionStains(qupath.lib.color.ColorDeconvolutionStains) Graphics2D(java.awt.Graphics2D) MeasurementListFactory(qupath.lib.measurements.MeasurementListFactory) ImageData(qupath.lib.images.ImageData) RoiTools(qupath.lib.roi.RoiTools) Logger(org.slf4j.Logger) GeneralTools(qupath.lib.common.GeneralTools) RegionRequest(qupath.lib.regions.RegionRequest) Calibration(ij.measure.Calibration) SimpleImage(qupath.lib.analysis.images.SimpleImage) ColorTransformMethod(qupath.lib.color.ColorTransformer.ColorTransformMethod) PathClass(qupath.lib.objects.classes.PathClass) IOException(java.io.IOException) TMACoreObject(qupath.lib.objects.TMACoreObject) PathObjectTools(qupath.lib.objects.PathObjectTools) ROI(qupath.lib.roi.interfaces.ROI) FloatProcessor(ij.process.FloatProcessor) PixelCalibration(qupath.lib.images.servers.PixelCalibration) MaximumFinder(ij.plugin.filter.MaximumFinder) SimpleImages(qupath.lib.analysis.images.SimpleImages) ByteProcessor(ij.process.ByteProcessor) Shape(java.awt.Shape) MeasurementList(qupath.lib.measurements.MeasurementList) MaximumFinder(ij.plugin.filter.MaximumFinder) ArrayList(java.util.ArrayList) DataBufferByte(java.awt.image.DataBufferByte) BufferedImage(java.awt.image.BufferedImage) EDM(ij.plugin.filter.EDM) PathClass(qupath.lib.objects.classes.PathClass) PolygonRoi(ij.gui.PolygonRoi) ImagePlane(qupath.lib.regions.ImagePlane) FloatProcessor(ij.process.FloatProcessor) PixelCalibration(qupath.lib.images.servers.PixelCalibration) Calibration(ij.measure.Calibration) PixelCalibration(qupath.lib.images.servers.PixelCalibration) ROI(qupath.lib.roi.interfaces.ROI) Graphics2D(java.awt.Graphics2D) PathObject(qupath.lib.objects.PathObject) ImageStatistics(ij.process.ImageStatistics) SimpleImage(qupath.lib.analysis.images.SimpleImage) RegionRequest(qupath.lib.regions.RegionRequest)

Example 12 with MeasurementList

use of qupath.lib.measurements.MeasurementList in project qupath by qupath.

the class QuPath_Send_Overlay_to_QuPath method createObjectsFromROIs.

/**
 * Turn an array of ImageJ ROIs into a list of QuPath PathObjects, optionally adding measurements as well.
 *
 * @param imp
 * @param rois
 * @param downsample
 * @param asDetection
 * @param includeMeasurements
 * @param plane
 * @return
 * @since v0.4.0
 */
public static List<PathObject> createObjectsFromROIs(final ImagePlus imp, final Collection<? extends Roi> rois, final double downsample, final boolean asDetection, final boolean includeMeasurements, final ImagePlane plane) {
    List<PathObject> pathObjects = new ArrayList<>();
    ResultsTable rt = new ResultsTable();
    Analyzer analyzer = imp == null ? null : new Analyzer(imp, Analyzer.getMeasurements(), rt);
    String[] headings = null;
    Calibration cal = imp == null ? null : imp.getCalibration();
    var xOrigin = cal == null ? 0 : cal.xOrigin;
    var yOrigin = cal == null ? 0 : cal.yOrigin;
    for (Roi roi : rois) {
        PathObject pathObject;
        if (asDetection && !(roi instanceof PointRoi))
            pathObject = IJTools.convertToDetection(roi, xOrigin, yOrigin, downsample, plane);
        else
            pathObject = IJTools.convertToAnnotation(roi, xOrigin, yOrigin, downsample, plane);
        if (pathObject == null)
            IJ.log("Sorry, I couldn't convert " + roi + " to a valid QuPath object");
        else {
            // Make measurements
            if (includeMeasurements && imp != null) {
                ImageProcessor ip = imp.getProcessor();
                ip.setRoi(roi);
                ImageStatistics stats = ImageStatistics.getStatistics(ip, Analyzer.getMeasurements(), imp.getCalibration());
                analyzer.saveResults(stats, roi);
                // Get measurements from table and append
                if (headings == null)
                    headings = rt.getHeadings();
                int row = rt.getCounter() - 1;
                MeasurementList ml = pathObject.getMeasurementList();
                for (String h : headings) {
                    if ("Label".equals(h))
                        continue;
                    ml.putMeasurement(h, rt.getValue(h, row));
                }
                ml.close();
            }
            pathObjects.add(pathObject);
        }
    }
    return pathObjects;
}
Also used : MeasurementList(qupath.lib.measurements.MeasurementList) ArrayList(java.util.ArrayList) Calibration(ij.measure.Calibration) Analyzer(ij.plugin.filter.Analyzer) PointRoi(ij.gui.PointRoi) Roi(ij.gui.Roi) ImageProcessor(ij.process.ImageProcessor) PathObject(qupath.lib.objects.PathObject) ImageStatistics(ij.process.ImageStatistics) ResultsTable(ij.measure.ResultsTable) PointRoi(ij.gui.PointRoi)

Example 13 with MeasurementList

use of qupath.lib.measurements.MeasurementList in project qupath by qupath.

the class PixelClassificationMeasurementManager method updateMeasurements.

private synchronized MeasurementList updateMeasurements(Map<Integer, PathClass> classificationLabels, long[] counts, double pixelArea, String pixelAreaUnits) {
    long total = counts == null ? 0L : GeneralTools.sum(counts);
    Collection<PathClass> pathClasses = new LinkedHashSet<>(classificationLabels.values());
    boolean addNames = measurementNames == null;
    List<String> tempList = null;
    int nMeasurements = pathClasses.size() * 2;
    if (!isMulticlass)
        nMeasurements += 2;
    if (addNames) {
        tempList = new ArrayList<>();
        measurementNames = Collections.unmodifiableList(tempList);
    } else
        nMeasurements = measurementNames.size();
    MeasurementList measurementList = MeasurementListFactory.createMeasurementList(nMeasurements, MeasurementListType.DOUBLE);
    Set<PathClass> ignored = pathClasses.stream().filter(p -> p == null || PathClassTools.isIgnoredClass(p)).collect(Collectors.toSet());
    // Calculate totals for all non-ignored classes
    Map<PathClass, Long> pathClassTotals = new LinkedHashMap<>();
    long totalWithoutIgnored = 0L;
    if (counts != null) {
        for (var entry : classificationLabels.entrySet()) {
            PathClass pathClass = entry.getValue();
            // Skip background channels
            if (pathClass == null || ignored.contains(pathClass))
                continue;
            int c = entry.getKey();
            long temp = counts == null || c >= counts.length ? 0L : counts[c];
            totalWithoutIgnored += temp;
            pathClassTotals.put(pathClass, pathClassTotals.getOrDefault(pathClass, 0L) + temp);
        }
    } else {
        for (var pathClass : pathClasses) if (pathClass != null && !ignored.contains(pathClass))
            pathClassTotals.put(pathClass, 0L);
    }
    // Add measurements for classes
    for (var entry : pathClassTotals.entrySet()) {
        var pathClass = entry.getKey();
        String name = pathClass.toString();
        String namePercentage = name + " %";
        String nameArea = name + " area " + pixelAreaUnits;
        if (tempList != null) {
            if (pathClassTotals.size() > 1)
                tempList.add(namePercentage);
            tempList.add(nameArea);
        }
        if (counts != null) {
            long count = entry.getValue();
            if (pathClassTotals.size() > 1)
                measurementList.putMeasurement(namePercentage, (double) count / totalWithoutIgnored * 100.0);
            if (!Double.isNaN(pixelArea)) {
                measurementList.putMeasurement(nameArea, count * pixelArea);
            }
        }
    }
    // Add total area (useful as a check)
    String nameArea = "Total annotated area " + pixelAreaUnits;
    String nameAreaWithoutIgnored = "Total quantified area " + pixelAreaUnits;
    if (counts != null && !Double.isNaN(pixelArea)) {
        if (tempList != null) {
            tempList.add(nameArea);
            tempList.add(nameAreaWithoutIgnored);
        }
        measurementList.putMeasurement(nameArea, totalWithoutIgnored * pixelArea);
        measurementList.putMeasurement(nameAreaWithoutIgnored, total * pixelArea);
    }
    measurementList.close();
    return measurementList;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Color(java.awt.Color) ImageServer(qupath.lib.images.servers.ImageServer) PathClassTools(qupath.lib.objects.classes.PathClassTools) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) MeasurementList(qupath.lib.measurements.MeasurementList) LinkedHashMap(java.util.LinkedHashMap) ROIs(qupath.lib.roi.ROIs) ChannelType(qupath.lib.images.servers.ImageServerMetadata.ChannelType) Graphics2D(java.awt.Graphics2D) Map(java.util.Map) TileRequest(qupath.lib.images.servers.TileRequest) BufferedImageTools(qupath.lib.awt.common.BufferedImageTools) MeasurementListFactory(qupath.lib.measurements.MeasurementListFactory) LinkedHashSet(java.util.LinkedHashSet) WeakHashMap(java.util.WeakHashMap) Shape(java.awt.Shape) MeasurementListType(qupath.lib.measurements.MeasurementList.MeasurementListType) RoiTools(qupath.lib.roi.RoiTools) Logger(org.slf4j.Logger) BufferedImage(java.awt.image.BufferedImage) GeneralTools(qupath.lib.common.GeneralTools) RegionRequest(qupath.lib.regions.RegionRequest) Collection(java.util.Collection) PathClass(qupath.lib.objects.classes.PathClass) Set(java.util.Set) IOException(java.io.IOException) Collectors(java.util.stream.Collectors) PathObject(qupath.lib.objects.PathObject) ROI(qupath.lib.roi.interfaces.ROI) List(java.util.List) PixelCalibration(qupath.lib.images.servers.PixelCalibration) ImagePlane(qupath.lib.regions.ImagePlane) BasicStroke(java.awt.BasicStroke) WritableRaster(java.awt.image.WritableRaster) Collections(java.util.Collections) ImageServerMetadata(qupath.lib.images.servers.ImageServerMetadata) DataBuffer(java.awt.image.DataBuffer) MeasurementList(qupath.lib.measurements.MeasurementList) LinkedHashMap(java.util.LinkedHashMap) PathClass(qupath.lib.objects.classes.PathClass)

Example 14 with MeasurementList

use of qupath.lib.measurements.MeasurementList in project qupath by qupath.

the class OpenCvClassifier method updateClassifier.

@Override
public boolean updateClassifier(final Map<PathClass, List<PathObject>> map, final List<String> measurements, Normalization normalization) {
    // There is a chance we don't need to retrain... to find out, cache the most important current variables
    boolean maybeSameClassifier = isValid() && this.normalization == normalization && !classifierOptionsChanged() && this.measurements.equals(measurements) && pathClasses.size() == map.size() && map.keySet().containsAll(pathClasses);
    float[] arrayTrainingPrevious = arrayTraining;
    int[] arrayResponsesPrevious = arrayResponses;
    pathClasses = new ArrayList<>(map.keySet());
    Collections.sort(pathClasses);
    int n = 0;
    for (Map.Entry<PathClass, List<PathObject>> entry : map.entrySet()) {
        n += entry.getValue().size();
    }
    // Compute running statistics for normalization
    HashMap<String, RunningStatistics> statsMap = new LinkedHashMap<>();
    for (String m : measurements) statsMap.put(m, new RunningStatistics());
    this.measurements.clear();
    this.measurements.addAll(measurements);
    int nMeasurements = measurements.size();
    arrayTraining = new float[n * nMeasurements];
    arrayResponses = new int[n];
    int row = 0;
    int nnan = 0;
    for (PathClass pathClass : pathClasses) {
        List<PathObject> list = map.get(pathClass);
        int classIndex = pathClasses.indexOf(pathClass);
        for (int i = 0; i < list.size(); i++) {
            MeasurementList measurementList = list.get(i).getMeasurementList();
            int col = 0;
            for (String m : measurements) {
                double value = measurementList.getMeasurementValue(m);
                if (Double.isNaN(value))
                    nnan++;
                else
                    statsMap.get(m).addValue(value);
                arrayTraining[row * nMeasurements + col] = (float) value;
                col++;
            }
            arrayResponses[row] = classIndex;
            row++;
        }
    }
    // Normalise, if required
    if (normalization != null && normalization != Normalization.NONE) {
        logger.debug("Training classifier with normalization: {}", normalization);
        int numMeasurements = measurements.size();
        normOffset = new double[numMeasurements];
        normScale = new double[numMeasurements];
        for (int i = 0; i < numMeasurements; i++) {
            RunningStatistics stats = statsMap.get(measurements.get(i));
            if (normalization == Normalization.MEAN_VARIANCE) {
                normOffset[i] = -stats.getMean();
                if (stats.getStdDev() > 0)
                    normScale[i] = 1.0 / stats.getStdDev();
            } else if (normalization == Normalization.MIN_MAX) {
                normOffset[i] = -stats.getMin();
                if (stats.getRange() > 0)
                    normScale[i] = 1.0 / (stats.getMax() - stats.getMin());
                else
                    normScale[i] = 1.0;
            }
        }
        // Apply normalisation
        for (int i = 0; i < arrayTraining.length; i++) {
            int k = i % numMeasurements;
            arrayTraining[i] = (float) ((arrayTraining[i] + normOffset[k]) * normScale[k]);
        }
        this.normalization = normalization;
    } else {
        logger.debug("Training classifier without normalization");
        normScale = null;
        normOffset = null;
        this.normalization = Normalization.NONE;
    }
    // Record that we have NaNs
    if (nnan > 0)
        logger.debug("Number of NaNs in training set: " + nnan);
    // Having got this far, check to see whether we really do need to retrain
    if (maybeSameClassifier) {
        if (Arrays.equals(arrayTrainingPrevious, arrayTraining) && Arrays.equals(arrayResponsesPrevious, arrayResponses)) {
            logger.info("Classifier already trained with the same samples - existing classifier will be used");
            return false;
        }
    }
    createAndTrainClassifier();
    timestamp = System.currentTimeMillis();
    this.measurements = new ArrayList<>(measurements);
    return true;
}
Also used : MeasurementList(qupath.lib.measurements.MeasurementList) RunningStatistics(qupath.lib.analysis.stats.RunningStatistics) LinkedHashMap(java.util.LinkedHashMap) PathClass(qupath.lib.objects.classes.PathClass) PathObject(qupath.lib.objects.PathObject) ArrayList(java.util.ArrayList) MeasurementList(qupath.lib.measurements.MeasurementList) ParameterList(qupath.lib.plugins.parameters.ParameterList) List(java.util.List) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 15 with MeasurementList

use of qupath.lib.measurements.MeasurementList in project qupath by qupath.

the class OpenCvClassifier method classifyPathObjects.

@Override
public int classifyPathObjects(Collection<PathObject> pathObjects) {
    int counter = 0;
    float[] array = new float[measurements.size()];
    Mat samples = new Mat(1, array.length, CV_32FC1);
    FloatBuffer bufferSamples = samples.createBuffer();
    Mat results = new Mat();
    for (PathObject pathObject : pathObjects) {
        MeasurementList measurementList = pathObject.getMeasurementList();
        int idx = 0;
        for (String m : measurements) {
            double value = measurementList.getMeasurementValue(m);
            if (normScale != null && normOffset != null)
                value = (value + normOffset[idx]) * normScale[idx];
            array[idx] = (float) value;
            idx++;
        }
        // FloatIndexer indexerSamples = samples.createIndexer();
        // indexerSamples.put(0L, 0L, array);
        bufferSamples.clear();
        bufferSamples.put(array);
        try {
            setPredictedClass(classifier, pathClasses, samples, results, pathObject);
        // float prediction = classifier.predict(samples);
        // 
        // //				float prediction2 = classifier.predict(samples, results, StatModel.RAW_OUTPUT);
        // float prediction2 = classifier.predict(samples, results, StatModel.RAW_OUTPUT);
        // 
        // pathObject.setPathClass(pathClasses.get((int)prediction), prediction2);
        } catch (Exception e) {
            pathObject.setPathClass(null);
            logger.trace("Error with samples: {}", samples);
        // e.printStackTrace();
        }
        // TODO: See if this can be created outside the loop & reused... appears to work, but docs say release should be called
        // indexerSamples.release();
        // }
        counter++;
    }
    samples.close();
    results.close();
    return counter;
}
Also used : PathObject(qupath.lib.objects.PathObject) MeasurementList(qupath.lib.measurements.MeasurementList) FloatBuffer(java.nio.FloatBuffer) IOException(java.io.IOException)

Aggregations

MeasurementList (qupath.lib.measurements.MeasurementList)24 PathObject (qupath.lib.objects.PathObject)12 ArrayList (java.util.ArrayList)9 ROI (qupath.lib.roi.interfaces.ROI)9 BufferedImage (java.awt.image.BufferedImage)6 RegionRequest (qupath.lib.regions.RegionRequest)6 List (java.util.List)5 PixelCalibration (qupath.lib.images.servers.PixelCalibration)5 IOException (java.io.IOException)4 HashMap (java.util.HashMap)4 TMACoreObject (qupath.lib.objects.TMACoreObject)4 PathClass (qupath.lib.objects.classes.PathClass)4 LinkedHashSet (java.util.LinkedHashSet)3 Map (java.util.Map)3 SimpleModifiableImage (qupath.lib.analysis.images.SimpleModifiableImage)3 ImmutableDimension (qupath.lib.geom.ImmutableDimension)3 PathCellObject (qupath.lib.objects.PathCellObject)3 ParameterList (qupath.lib.plugins.parameters.ParameterList)3 Calibration (ij.measure.Calibration)2 ImageProcessor (ij.process.ImageProcessor)2