Search in sources :

Example 21 with Point2

use of qupath.lib.geom.Point2 in project qupath by qupath.

the class ROIConverterIJ method getTransformedPoints.

/**
 * Convert a collection of points from a ROI into the coordinate space determined from the calibration information.
 *
 * @param points
 * @param xOrigin
 * @param yOrigin
 * @param downsampleFactor
 * @return float arrays, where result[0] gives the x coordinates and result[1] the y coordinates
 */
private static float[][] getTransformedPoints(Collection<Point2> points, double xOrigin, double yOrigin, double downsampleFactor) {
    float[] xPoints = new float[points.size()];
    float[] yPoints = new float[points.size()];
    int i = 0;
    for (Point2 p : points) {
        xPoints[i] = (float) convertXtoIJ(p.getX(), xOrigin, downsampleFactor);
        yPoints[i] = (float) convertYtoIJ(p.getY(), yOrigin, downsampleFactor);
        i++;
    }
    return new float[][] { xPoints, yPoints };
}
Also used : Point2(qupath.lib.geom.Point2)

Example 22 with Point2

use of qupath.lib.geom.Point2 in project qupath by qupath.

the class AbstractPathTool method setConstrainedAreaParent.

/**
 * Set the parent that may be used to constrain a new ROI, if possible.
 *
 * @param hierarchy object hierarchy containing potential constraining objects
 * @param xx x-coordinate in the image space of the starting point for the new object
 * @param yy y-coordinate in the image space of the starting point for the new object
 * @param exclusions objects not to consider (e.g. the new ROI being created)
 */
void setConstrainedAreaParent(final PathObjectHierarchy hierarchy, double xx, double yy, Collection<PathObject> exclusions) {
    if (!Platform.isFxApplicationThread())
        throw new IllegalStateException("Not on the FxApplication thread!");
    // Reset parent area & its descendant annotation areas
    constrainedParentGeometry = null;
    constrainedRemoveGeometries = null;
    // Identify the smallest area annotation that contains the specified point
    constrainedParentObject = getSelectableObjectList(xx, yy).stream().filter(p -> !p.isDetection() && p.hasROI() && p.getROI().isArea() && !exclusions.contains(p)).sorted(Comparator.comparing(p -> p.getROI().getArea())).findFirst().orElseGet(() -> null);
    // Check the parent is a valid potential parent
    if (constrainedParentObject == null || !(constrainedParentObject.hasROI() && constrainedParentObject.getROI().isArea())) {
        constrainedParentObject = hierarchy.getRootObject();
    }
    // Get the parent Geometry
    if (constrainedParentObject.hasROI() && constrainedParentObject.getROI().isArea())
        constrainedParentGeometry = constrainedParentObject.getROI().getGeometry();
    constrainedStartPoint = new Point2(xx, yy);
}
Also used : Point2(qupath.lib.geom.Point2)

Example 23 with Point2

use of qupath.lib.geom.Point2 in project qupath by qupath.

the class DensityMaps method findHotspots.

/**
 * Find hotspots in a density map.
 *
 * @param hierarchy hierarchy used to obtain selected objects and add hotspots
 * @param densityServer the density map to query
 * @param channel channel in which to find hotspots (usually 0)
 * @param nHotspots maximum number of hotspots to find per selected annotation
 * @param radius hotspot radius, in calibrated units
 * @param minCount minimum value required in the 'count' channel (the last channel)
 * @param hotspotClass the classification to apply to hotspots
 * @param deleteExisting optionally delete existing annotations identified as hotspots
 * @param peaksOnly optionally restrict hotspots to only include intensity peaks
 * @throws IOException
 */
public static void findHotspots(PathObjectHierarchy hierarchy, ImageServer<BufferedImage> densityServer, int channel, int nHotspots, double radius, double minCount, PathClass hotspotClass, boolean deleteExisting, boolean peaksOnly) throws IOException {
    if (nHotspots <= 0) {
        logger.warn("Number of hotspots requested is {}!", nHotspots);
        return;
    }
    logger.debug("Finding {} hotspots in {} for channel {}, radius {}", nHotspots, densityServer, channel, radius);
    Collection<PathObject> parents = new ArrayList<>(hierarchy.getSelectionModel().getSelectedObjects());
    if (parents.isEmpty())
        parents = Collections.singleton(hierarchy.getRootObject());
    double downsample = densityServer.getDownsampleForResolution(0);
    var toDelete = new HashSet<PathObject>();
    // Handle deleting existing hotspots
    if (deleteExisting) {
        toDelete.addAll(hierarchy.getAnnotationObjects().stream().filter(p -> p.getPathClass() == hotspotClass && p.isAnnotation() && p.getName() != null && p.getName().startsWith("Hotspot")).collect(Collectors.toList()));
    }
    // Convert radius to pixels
    double radiusPixels = radius / densityServer.getPixelCalibration().getAveragedPixelSize().doubleValue();
    try (@SuppressWarnings("unchecked") var scope = new PointerScope()) {
        for (var parent : parents) {
            ROI roi = parent.getROI();
            // We need a ROI to define the area of interest
            if (roi == null) {
                if (densityServer.nTimepoints() > 1 || densityServer.nZSlices() > 1) {
                    logger.warn("Hotspot detection without a parent object not supported for images with multiple z-slices/timepoints.");
                    logger.warn("I will apply detection to the first plane only. If you need hotspots elsewhere, create an annotation first and use it to define the ROI.");
                }
                roi = ROIs.createRectangleROI(0, 0, densityServer.getWidth(), densityServer.getHeight(), ImagePlane.getDefaultPlane());
            }
            // Erode the ROI & see if any hotspot could fit
            var roiEroded = RoiTools.buffer(roi, -radiusPixels);
            if (roiEroded.isEmpty() || roiEroded.getArea() == 0) {
                logger.warn("ROI is too small! Cannot detected hotspots with radius {} in {}", radius, parent);
                continue;
            }
            // Read the image
            var plane = roi.getImagePlane();
            RegionRequest request = RegionRequest.createInstance(densityServer.getPath(), downsample, 0, 0, densityServer.getWidth(), densityServer.getHeight(), plane.getZ(), plane.getT());
            var img = densityServer.readBufferedImage(request);
            // Create a mask
            var imgMask = BufferedImageTools.createROIMask(img.getWidth(), img.getHeight(), roiEroded, request);
            // Switch to OpenCV
            var mat = OpenCVTools.imageToMat(img);
            var matMask = OpenCVTools.imageToMat(imgMask);
            // Find hotspots
            var channels = OpenCVTools.splitChannels(mat);
            var density = channels.get(channel);
            if (minCount > 0) {
                var thresholdMask = opencv_core.greaterThan(channels.get(channels.size() - 1), minCount).asMat();
                opencv_core.bitwise_and(matMask, thresholdMask, matMask);
                thresholdMask.close();
            }
            // TODO: Limit to peaks
            if (peaksOnly) {
                var matMaxima = OpenCVTools.findRegionalMaxima(density);
                var matPeaks = OpenCVTools.shrinkLabels(matMaxima);
                matPeaks.put(opencv_core.greaterThan(matPeaks, 0));
                opencv_core.bitwise_and(matMask, matPeaks, matMask);
                matPeaks.close();
                matMaxima.close();
            }
            // Sort in descending order
            var maxima = new ArrayList<>(OpenCVTools.getMaskedPixels(density, matMask));
            Collections.sort(maxima, Comparator.comparingDouble((IndexedPixel p) -> p.getValue()).reversed());
            // Try to get as many maxima as we need
            // Impose minimum separation
            var points = maxima.stream().map(p -> new Point2(p.getX() * downsample, p.getY() * downsample)).collect(Collectors.toList());
            var hotspotCentroids = new ArrayList<Point2>();
            double distSqThreshold = radiusPixels * radiusPixels * 4;
            for (var p : points) {
                // Check not too close to an existing hotspot
                boolean skip = false;
                for (var p2 : hotspotCentroids) {
                    if (p.distanceSq(p2) < distSqThreshold) {
                        skip = true;
                        break;
                    }
                }
                if (!skip) {
                    hotspotCentroids.add(p);
                    if (hotspotCentroids.size() == nHotspots)
                        break;
                }
            }
            var hotspots = new ArrayList<PathObject>();
            int i = 0;
            for (var p : hotspotCentroids) {
                i++;
                var ellipse = ROIs.createEllipseROI(p.getX() - radiusPixels, p.getY() - radiusPixels, radiusPixels * 2, radiusPixels * 2, roi.getImagePlane());
                var hotspot = PathObjects.createAnnotationObject(ellipse, hotspotClass);
                hotspot.setName("Hotspot " + i);
                hotspots.add(hotspot);
            }
            if (hotspots.isEmpty())
                logger.warn("No hotspots found in {}", parent);
            else if (hotspots.size() < nHotspots) {
                logger.warn("Only {}/{} hotspots could be found in {}", hotspots.size(), nHotspots, parent);
            }
            parent.addPathObjects(hotspots);
        }
        hierarchy.fireHierarchyChangedEvent(DensityMaps.class);
        if (!toDelete.isEmpty())
            hierarchy.removeObjects(toDelete, true);
    }
}
Also used : CreateObjectOptions(qupath.opencv.ml.pixel.PixelClassifierTools.CreateObjectOptions) Arrays(java.util.Arrays) ImageServer(qupath.lib.images.servers.ImageServer) LoggerFactory(org.slf4j.LoggerFactory) ChannelType(qupath.lib.images.servers.ImageServerMetadata.ChannelType) Map(java.util.Map) PixelClassifierTools(qupath.opencv.ml.pixel.PixelClassifierTools) StandardPathClasses(qupath.lib.objects.classes.PathClassFactory.StandardPathClasses) BufferedImageTools(qupath.lib.awt.common.BufferedImageTools) Path(java.nio.file.Path) BufferedImage(java.awt.image.BufferedImage) PixelClassifiers(qupath.opencv.ml.pixel.PixelClassifiers) Collection(java.util.Collection) PathObjects(qupath.lib.objects.PathObjects) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) Objects(java.util.Objects) Project(qupath.lib.projects.Project) ImagePlane(qupath.lib.regions.ImagePlane) ColorModelBuilder(qupath.lib.analysis.heatmaps.ColorModels.ColorModelBuilder) org.bytedeco.opencv.global.opencv_core(org.bytedeco.opencv.global.opencv_core) GsonTools(qupath.lib.io.GsonTools) OpenCVTools(qupath.opencv.tools.OpenCVTools) PathClassFactory(qupath.lib.objects.classes.PathClassFactory) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) ROIs(qupath.lib.roi.ROIs) Point2(qupath.lib.geom.Point2) LinkedHashSet(java.util.LinkedHashSet) ImageData(qupath.lib.images.ImageData) IndexedPixel(qupath.opencv.tools.OpenCVTools.IndexedPixel) RoiTools(qupath.lib.roi.RoiTools) Logger(org.slf4j.Logger) Files(java.nio.file.Files) PointerScope(org.bytedeco.javacpp.PointerScope) RegionRequest(qupath.lib.regions.RegionRequest) PathClass(qupath.lib.objects.classes.PathClass) PixelClassifierMetadata(qupath.lib.classifiers.pixel.PixelClassifierMetadata) IOException(java.io.IOException) PathObjectTools(qupath.lib.objects.PathObjectTools) ROI(qupath.lib.roi.interfaces.ROI) PixelClassifier(qupath.lib.classifiers.pixel.PixelClassifier) ColorModel(java.awt.image.ColorModel) PixelCalibration(qupath.lib.images.servers.PixelCalibration) PathObjectPredicate(qupath.lib.objects.PathObjectPredicates.PathObjectPredicate) Comparator(java.util.Comparator) Collections(java.util.Collections) ImageServerMetadata(qupath.lib.images.servers.ImageServerMetadata) ArrayList(java.util.ArrayList) IndexedPixel(qupath.opencv.tools.OpenCVTools.IndexedPixel) PointerScope(org.bytedeco.javacpp.PointerScope) ROI(qupath.lib.roi.interfaces.ROI) PathObject(qupath.lib.objects.PathObject) Point2(qupath.lib.geom.Point2) RegionRequest(qupath.lib.regions.RegionRequest) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 24 with Point2

use of qupath.lib.geom.Point2 in project qupath by qupath.

the class PointsROI method recomputeBounds.

// @Deprecated
// public boolean startAdjusting(double x, double y, int modifiers) {
// Point2 pNearest = getNearest(x, y, PointsROI.getDefaultPointRadius());
// if (pNearest == null)
// return false;
// //		logger.info("STARTING: " + p);
// pointAdjusting = pNearest;
// pNearest.setLocation(x, y);
// isAdjusting = true;
// return true;
// }
// 
// @Override
// public void finishAdjusting(double x, double y, boolean shiftDown) {
// super.finishAdjusting(x, y, shiftDown);
// pointAdjusting = null;
// recomputeBounds();
// }
// 
// 
// @Override
// public void updateAdjustment(double x, double y, boolean shiftDown) {
// if (pointAdjusting != null) {
// pointAdjusting.setLocation(x, y);
// }
// }
protected void recomputeBounds() {
    if (points.isEmpty()) {
        resetBounds();
        return;
    }
    xMin = Double.POSITIVE_INFINITY;
    yMin = Double.POSITIVE_INFINITY;
    xMax = Double.NEGATIVE_INFINITY;
    yMax = Double.NEGATIVE_INFINITY;
    for (Point2 p : points) {
        updateBounds(p.getX(), p.getY());
    }
}
Also used : Point2(qupath.lib.geom.Point2)

Example 25 with Point2

use of qupath.lib.geom.Point2 in project qupath by qupath.

the class PointsROI method computeCentroid.

private void computeCentroid() {
    double xSum = 0;
    double ySum = 0;
    int n = points.size();
    for (Point2 p : points) {
        xSum += p.getX() / n;
        ySum += p.getY() / n;
    }
    xCentroid = xSum;
    yCentroid = ySum;
}
Also used : Point2(qupath.lib.geom.Point2)

Aggregations

Point2 (qupath.lib.geom.Point2)33 ArrayList (java.util.ArrayList)19 PathObject (qupath.lib.objects.PathObject)7 List (java.util.List)6 PointsROI (qupath.lib.roi.PointsROI)6 ROI (qupath.lib.roi.interfaces.ROI)6 HashMap (java.util.HashMap)5 ImagePlane (qupath.lib.regions.ImagePlane)5 Map (java.util.Map)4 PathClass (qupath.lib.objects.classes.PathClass)4 PathClassFactory (qupath.lib.objects.classes.PathClassFactory)4 ROIs (qupath.lib.roi.ROIs)4 PathIterator (java.awt.geom.PathIterator)3 IOException (java.io.IOException)3 Arrays (java.util.Arrays)3 HashSet (java.util.HashSet)3 Collectors (java.util.stream.Collectors)3 Test (org.junit.jupiter.api.Test)3 PathObjects (qupath.lib.objects.PathObjects)3 AlphaComposite (java.awt.AlphaComposite)2