Search in sources :

Example 11 with Point2

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

the class WindingTest method getWindingNumber.

public static int getWindingNumber(final List<Point2> points, final double x, final double y) {
    if (points.size() <= 2)
        return 0;
    int nPoints = points.size();
    int wn = 0;
    for (int i = 0; i < nPoints; i++) {
        Point2 p = points.get(i);
        Point2 p2 = points.get((i + 1) % nPoints);
        if (p.getY() <= y) {
            // start y <= P.y
            if (// an upward crossing
            p2.getY() > y)
                if (// P left of  edge
                isLeft(p.getX(), p.getY(), p2.getX(), p2.getY(), x, y) > 0)
                    // have  a valid up intersect
                    wn++;
        } else {
            // start y > P.y (no test needed)
            if (// a downward crossing
            p2.getY() <= y)
                if (// P right of  edge
                isLeft(p.getX(), p.getY(), p2.getX(), p2.getY(), x, y) < 0)
                    // have  a valid down intersect
                    wn--;
        }
    }
    return wn;
}
Also used : Point2(qupath.lib.geom.Point2)

Example 12 with Point2

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

the class WindingTest method getWindingNumber.

public static int getWindingNumber(final Vertices vertices, final double x, final double y) {
    if (vertices.size() <= 2)
        return 0;
    int nPoints = vertices.size();
    int wn = 0;
    for (int i = 0; i < nPoints; i++) {
        Point2 p = vertices.get(i);
        Point2 p2 = vertices.get((i + 1) % nPoints);
        if (p.getY() <= y) {
            // start y <= P.y
            if (// an upward crossing
            p2.getY() > y)
                if (// P left of  edge
                isLeft(p.getX(), p.getY(), p2.getX(), p2.getY(), x, y) > 0)
                    // have  a valid up intersect
                    wn++;
        } else {
            // start y > P.y (no test needed)
            if (// a downward crossing
            p2.getY() <= y)
                if (// P right of  edge
                isLeft(p.getX(), p.getY(), p2.getX(), p2.getY(), x, y) < 0)
                    // have  a valid down intersect
                    wn--;
        }
    }
    return wn;
}
Also used : Point2(qupath.lib.geom.Point2)

Example 13 with Point2

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

the class ShapeSimplifier method smoothPoints.

/**
 * Apply a simple 3-point moving average to a list of points.
 *
 * @param points
 * @return
 */
public static List<Point2> smoothPoints(List<Point2> points) {
    List<Point2> points2 = new ArrayList<>(points.size());
    for (int i = 0; i < points.size(); i++) {
        Point2 p1 = points.get((i + points.size() - 1) % points.size());
        Point2 p2 = points.get(i);
        Point2 p3 = points.get((i + 1) % points.size());
        points2.add(new Point2((p1.getX() + p2.getX() + p3.getX()) / 3, (p1.getY() + p2.getY() + p3.getY()) / 3));
    }
    return points2;
}
Also used : Point2(qupath.lib.geom.Point2) ArrayList(java.util.ArrayList)

Example 14 with Point2

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

the class PathClassificationLabellingHelper method getClassificationMap.

/**
 * Get a map of training data, based on the child objects of some classified annotations.
 *
 * @param hierarchy the hierarchy containing all the objects and annotations.
 * @param pointsOnly if true, only Point annotations will be used for training.
 *
 * @return
 */
public static Map<PathClass, List<PathObject>> getClassificationMap(final PathObjectHierarchy hierarchy, final boolean pointsOnly) {
    Map<PathClass, List<PathObject>> classifications = new TreeMap<>();
    // Get the annotations & filter out those that are useful
    List<PathObject> annotations = new ArrayList<>(getAnnotations(hierarchy));
    Iterator<PathObject> iter = annotations.iterator();
    while (iter.hasNext()) {
        PathObject pathObject = iter.next();
        // We need a PathClass, and may need to only include points
        if (pathObject.getPathClass() == null || pathObject.getPathClass() == PathClassFactory.getPathClass(StandardPathClasses.REGION) || (pointsOnly && !PathObjectTools.hasPointROI(pathObject)))
            iter.remove();
        else
            classifications.put(pathObject.getPathClass(), new ArrayList<>());
    }
    // from the hierarchy
    if (annotations.size() > 1) {
        annotations.sort(new Comparator<PathObject>() {

            @Override
            public int compare(PathObject o1, PathObject o2) {
                PathAnnotationObject p1 = (PathAnnotationObject) o1;
                PathAnnotationObject p2 = (PathAnnotationObject) o2;
                int comp = 0;
                if (p1.hasROI()) {
                    if (p2.hasROI()) {
                        comp = Double.compare(p1.getROI().getCentroidY(), p2.getROI().getCentroidY());
                        if (comp == 0)
                            comp = Double.compare(p1.getROI().getCentroidX(), p2.getROI().getCentroidX());
                        if (comp == 0)
                            comp = p1.getROI().toString().compareTo(p2.getROI().toString());
                    }
                }
                if (comp == 0)
                    return Integer.compare(o1.hashCode(), o2.hashCode());
                else
                    return comp;
            }
        });
    }
    // StringBuilder sb = new StringBuilder("DETECTIONS:\t");
    for (PathObject pathObject : annotations) {
        PathClass pathClass = pathObject.getPathClass();
        List<PathObject> list = classifications.get(pathClass);
        // sb.append(list.size() + ", ");
        if (PathObjectTools.hasPointROI(pathObject)) {
            for (Point2 p : ((PointsROI) pathObject.getROI()).getAllPoints()) {
                // TODO: Pay attention to z & t position!
                Collection<PathObject> pathObjectsTemp = PathObjectTools.getObjectsForLocation(hierarchy, p.getX(), p.getY(), 0, 0, -1);
                pathObjectsTemp = PathObjectTools.getObjectsOfClass(pathObjectsTemp, PathDetectionObject.class);
                // Clumsy way to avoid duplicates...
                list.removeAll(pathObjectsTemp);
                list.addAll(pathObjectsTemp);
            }
        } else
            list.addAll(hierarchy.getObjectsForROI(PathDetectionObject.class, pathObject.getROI()));
    }
    for (Entry<PathClass, List<PathObject>> entry : classifications.entrySet()) {
        logger.info(entry.getKey() + ": " + entry.getValue().size());
    }
    return classifications;
}
Also used : PathDetectionObject(qupath.lib.objects.PathDetectionObject) ArrayList(java.util.ArrayList) PointsROI(qupath.lib.roi.PointsROI) TreeMap(java.util.TreeMap) PathClass(qupath.lib.objects.classes.PathClass) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) Point2(qupath.lib.geom.Point2) ArrayList(java.util.ArrayList) List(java.util.List)

Example 15 with Point2

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

the class PixelClassificationOverlay method paintOverlay.

@Override
public void paintOverlay(Graphics2D g2d, ImageRegion imageRegion, double downsampleFactor, ImageData<BufferedImage> imageData, boolean paintCompletely) {
    // For now, bind the display to the display of detections
    if (!showOverlay.get())
        return;
    if (imageData == null)
        return;
    // ImageServer<BufferedImage> server = imageData.getServer();
    var server = getPixelClassificationServer(imageData);
    if (server == null)
        return;
    // Show classified tiles. Without this, opacity can make it hard to see which regions have been processed.
    // Note that if the alpha value is too large, tile boundaries can appear at some viewing magnifications (previous default was 32)
    var colorComplete = imageData.getImageType() == ImageData.ImageType.FLUORESCENCE ? ColorToolsAwt.getCachedColor(255, 255, 255, 1) : ColorToolsAwt.getCachedColor(0, 0, 0, 1);
    // Get the displayed clip bounds for fast checking if ROIs need to be drawn
    RegionRequest fullRequest;
    Shape shapeRegion = g2d.getClip();
    if (shapeRegion == null)
        fullRequest = RegionRequest.createInstance(server.getPath(), downsampleFactor, imageRegion);
    else
        fullRequest = RegionRequest.createInstance(server.getPath(), downsampleFactor, AwtTools.getImageRegion(shapeRegion, imageRegion.getZ(), imageRegion.getT()));
    // If we have a filter, we might not need to do anything
    var filter = getOverlayOptions().getPixelClassificationRegionFilter();
    // Avoid this check; it causes confusion when zoomed in
    // if (!filter.test(imageData, fullRequest))
    // return;
    var renderer = this.renderer.get();
    if (renderer != null && rendererLastTimestamp != renderer.getLastChangeTimestamp()) {
        clearCache();
        rendererLastTimestamp = renderer.getLastChangeTimestamp();
    }
    // double requestedDownsample = classifier.getMetadata().getInputPixelSizeMicrons() / server.getAveragedPixelSizeMicrons();
    double requestedDownsample = ServerTools.getPreferredDownsampleFactor(server, downsampleFactor);
    var gCopy = (Graphics2D) g2d.create();
    if (requestedDownsample > server.getDownsampleForResolution(0))
        gCopy.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    else
        // Only use specified interpolation when upsampling
        setInterpolation(gCopy);
    // gCopy.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
    var comp = getAlphaComposite();
    var previousComposite = gCopy.getComposite();
    if (comp != null) {
        if (previousComposite instanceof AlphaComposite)
            gCopy.setComposite(comp.derive(((AlphaComposite) previousComposite).getAlpha() * comp.getAlpha()));
        else
            gCopy.setComposite(comp);
    }
    Collection<TileRequest> tiles = server.getTileRequestManager().getTileRequests(fullRequest);
    if (fullRequest != null) {
        double x = (Math.max(0, fullRequest.getMinX()) + Math.min(server.getWidth(), fullRequest.getMaxX())) / 2.0;
        double y = (Math.max(0, fullRequest.getMinY()) + Math.min(server.getHeight(), fullRequest.getMaxY())) / 2.0;
        var p = new Point2(x, y);
        tiles = new ArrayList<>(tiles);
        ((List<TileRequest>) tiles).sort(Comparator.comparingDouble((TileRequest t) -> p.distanceSq(t.getImageX() + t.getImageWidth() / 2.0, t.getImageY() + t.getImageHeight() / 2.0)));
    }
    // Clear pending requests, since we'll insert new ones (perhaps in a different order)
    this.pendingRequests.clear();
    // Loop through & paint classified tiles if we have them, or request tiles if we don't
    for (TileRequest tile : tiles) {
        var request = tile.getRegionRequest();
        if (filter != null && !filter.test(imageData, request))
            continue;
        // Try to get an RGB image, supplying a server that can be queried for a corresponding non-RGB cached tile if needed
        BufferedImage imgRGB = getCachedTileRGB(tile, server);
        if (imgRGB != null) {
            gCopy.setColor(colorComplete);
            gCopy.fillRect(request.getX(), request.getY(), request.getWidth(), request.getHeight());
            // Get the cached RGB painted version (since painting can be a fairly expensive operation)
            gCopy.drawImage(imgRGB, request.getX(), request.getY(), request.getWidth(), request.getHeight(), null);
            // System.err.println(request.getHeight() == imgRGB.getHeight());
            continue;
        }
        // Request a tile
        if (livePrediction) {
            requestTile(tile, imageData, server);
        }
    }
    gCopy.dispose();
}
Also used : Shape(java.awt.Shape) Point2(qupath.lib.geom.Point2) AlphaComposite(java.awt.AlphaComposite) TileRequest(qupath.lib.images.servers.TileRequest) List(java.util.List) ArrayList(java.util.ArrayList) RegionRequest(qupath.lib.regions.RegionRequest) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D)

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