Search in sources :

Example 1 with EllipseROI

use of qupath.lib.roi.EllipseROI in project qupath by qupath.

the class IconFactory method createROIIcon.

/**
 * Create an icon depicting a ROI.
 * @param roi the region of interest
 * @param width the preferred icon width
 * @param height the preferred icon height
 * @param color the icon (line) color
 * @return a node that may be used as an icon resembling the shape of the ROI
 */
public static Node createROIIcon(ROI roi, int width, int height, Color color) {
    double scale = Math.min(width / roi.getBoundsWidth(), height / roi.getBoundsHeight());
    if (roi instanceof RectangleROI) {
        Rectangle rect = new Rectangle(0, 0, roi.getBoundsWidth() * scale, roi.getBoundsHeight() * scale);
        rect.setStroke(color);
        rect.setFill(null);
        return rect;
    } else if (roi instanceof EllipseROI) {
        double w = roi.getBoundsWidth() * scale;
        double h = roi.getBoundsHeight() * scale;
        Ellipse ellipse = new Ellipse(w / 2, height / 2, w / 2, h / 2);
        ellipse.setStroke(color);
        ellipse.setFill(null);
        return ellipse;
    } else if (roi instanceof LineROI) {
        LineROI l = (LineROI) roi;
        double xMin = Math.min(l.getX1(), l.getX2());
        double yMin = Math.min(l.getY1(), l.getY2());
        Line line = new Line((l.getX1() - xMin) * scale, (l.getY1() - yMin) * scale, (l.getX2() - xMin) * scale, (l.getY2() - yMin) * scale);
        line.setStroke(color);
        line.setFill(null);
        return line;
    } else if (roi.isPoint()) {
        // Just show generic points
        Node node = IconFactory.createNode(Math.min(width, height), Math.min(width, height), IconFactory.PathIcons.POINTS_TOOL);
        if (node instanceof Glyph) {
            var glyph = (Glyph) node;
            glyph.textFillProperty().unbind();
            glyph.setColor(color);
        }
        return node;
    } else {
        var path = pathCache.getOrDefault(roi, null);
        if (path == null) {
            var shape = roi.isArea() ? RoiTools.getArea(roi) : RoiTools.getShape(roi);
            if (shape != null) {
                var transform = new AffineTransform();
                transform.translate(-roi.getBoundsX(), -roi.getBoundsY());
                transform.scale(scale, scale);
                PathIterator iterator = shape.getPathIterator(transform, Math.max(0.5, 1.0 / scale));
                path = createShapeIcon(iterator, color);
                pathCache.put(roi, path);
            }
        } else {
            path = new Path(path.getElements());
            path.setStroke(color);
        }
        if (path != null)
            return path;
    }
    logger.warn("Unable to create icon for ROI: {}", roi);
    return null;
}
Also used : Path(javafx.scene.shape.Path) ClosePath(javafx.scene.shape.ClosePath) Ellipse(javafx.scene.shape.Ellipse) PathIterator(java.awt.geom.PathIterator) Node(javafx.scene.Node) Rectangle(javafx.scene.shape.Rectangle) Line(javafx.scene.shape.Line) RectangleROI(qupath.lib.roi.RectangleROI) EllipseROI(qupath.lib.roi.EllipseROI) Glyph(org.controlsfx.glyphfont.Glyph) AffineTransform(java.awt.geom.AffineTransform) LineROI(qupath.lib.roi.LineROI)

Example 2 with EllipseROI

use of qupath.lib.roi.EllipseROI in project qupath by qupath.

the class IJTools method convertToIJRoi.

/**
 * Convert a QuPath ROI to an ImageJ Roi.
 * @param <T>
 * @param pathROI
 * @param xOrigin x-origin indicating relationship of ImagePlus to the original image, as stored in ImageJ Calibration object
 * @param yOrigin y-origin indicating relationship of ImagePlus to the original image, as stored in ImageJ Calibration object
 * @param downsampleFactor downsample factor at which the ImagePlus was extracted from the full-resolution image
 * @return
 */
public static <T extends PathImage<ImagePlus>> Roi convertToIJRoi(ROI pathROI, double xOrigin, double yOrigin, double downsampleFactor) {
    if (pathROI instanceof PolygonROI)
        return ROIConverterIJ.convertToPolygonROI((PolygonROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof RectangleROI)
        return ROIConverterIJ.getRectangleROI((RectangleROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof EllipseROI)
        return ROIConverterIJ.convertToOvalROI((EllipseROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof LineROI)
        return ROIConverterIJ.convertToLineROI((LineROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof PolylineROI)
        return ROIConverterIJ.convertToPolygonROI((PolylineROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    if (pathROI instanceof PointsROI)
        return ROIConverterIJ.convertToPointROI((PointsROI) pathROI, xOrigin, yOrigin, downsampleFactor);
    // If we have any other kind of shape, create a general shape roi
    if (pathROI != null && pathROI.isArea()) {
        // TODO: Deal with non-AWT area ROIs!
        Shape shape = RoiTools.getArea(pathROI);
        // "scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY"
        shape = new AffineTransform(1.0 / downsampleFactor, 0, 0, 1.0 / downsampleFactor, xOrigin, yOrigin).createTransformedShape(shape);
        return ROIConverterIJ.setIJRoiProperties(new ShapeRoi(shape), pathROI);
    }
    // TODO: Integrate ROI not supported exception...?
    return null;
}
Also used : PolygonROI(qupath.lib.roi.PolygonROI) ShapeRoi(ij.gui.ShapeRoi) RectangleROI(qupath.lib.roi.RectangleROI) Shape(java.awt.Shape) EllipseROI(qupath.lib.roi.EllipseROI) PolylineROI(qupath.lib.roi.PolylineROI) PointsROI(qupath.lib.roi.PointsROI) AffineTransform(java.awt.geom.AffineTransform) LineROI(qupath.lib.roi.LineROI)

Example 3 with EllipseROI

use of qupath.lib.roi.EllipseROI in project qupath by qupath.

the class PathObjectTools method transformObject.

/**
 * Create a(n optionally) transformed version of a {@link PathObject}.
 * <p>
 * Note: only detections (including tiles and cells) and annotations are fully supported by this method.
 * Root objects are duplicated.
 * TMA core objects are transformed only if the resulting transform creates an ellipse ROI, since this is
 * currently the only ROI type supported for a TMA core (this behavior may change).
 * Any other object types result in an {@link UnsupportedOperationException} being thrown.
 *
 * @param pathObject the object to transform; this will be unchanged
 * @param transform optional affine transform; if {@code null}, this effectively acts to duplicate the object
 * @param copyMeasurements if true, the measurement list of the new object will be populated with the measurements of pathObject
 *
 * @return a duplicate of pathObject, with affine transform applied to the object's ROI(s) if required
 */
public static PathObject transformObject(PathObject pathObject, AffineTransform transform, boolean copyMeasurements) {
    ROI roi = maybeTransformROI(pathObject.getROI(), transform);
    PathClass pathClass = pathObject.getPathClass();
    PathObject newObject;
    if (pathObject instanceof PathCellObject) {
        ROI roiNucleus = maybeTransformROI(((PathCellObject) pathObject).getNucleusROI(), transform);
        newObject = PathObjects.createCellObject(roi, roiNucleus, pathClass, null);
    } else if (pathObject instanceof PathTileObject) {
        newObject = PathObjects.createTileObject(roi, pathClass, null);
    } else if (pathObject instanceof PathDetectionObject) {
        newObject = PathObjects.createDetectionObject(roi, pathClass, null);
    } else if (pathObject instanceof PathAnnotationObject) {
        newObject = PathObjects.createAnnotationObject(roi, pathClass, null);
    } else if (pathObject instanceof PathRootObject) {
        newObject = new PathRootObject();
    } else if (pathObject instanceof TMACoreObject && roi instanceof EllipseROI) {
        var core = (TMACoreObject) pathObject;
        newObject = PathObjects.createTMACoreObject(roi.getBoundsX(), roi.getBoundsY(), roi.getBoundsWidth(), roi.getBoundsHeight(), core.isMissing());
    } else
        throw new UnsupportedOperationException("Unable to transform object " + pathObject);
    if (copyMeasurements && !pathObject.getMeasurementList().isEmpty()) {
        MeasurementList measurements = pathObject.getMeasurementList();
        for (int i = 0; i < measurements.size(); i++) {
            String name = measurements.getMeasurementName(i);
            double value = measurements.getMeasurementValue(i);
            newObject.getMeasurementList().addMeasurement(name, value);
        }
        newObject.getMeasurementList().close();
    }
    return newObject;
}
Also used : MeasurementList(qupath.lib.measurements.MeasurementList) EllipseROI(qupath.lib.roi.EllipseROI) PointsROI(qupath.lib.roi.PointsROI) LineROI(qupath.lib.roi.LineROI) ROI(qupath.lib.roi.interfaces.ROI) PathClass(qupath.lib.objects.classes.PathClass) EllipseROI(qupath.lib.roi.EllipseROI)

Aggregations

EllipseROI (qupath.lib.roi.EllipseROI)3 LineROI (qupath.lib.roi.LineROI)3 AffineTransform (java.awt.geom.AffineTransform)2 PointsROI (qupath.lib.roi.PointsROI)2 RectangleROI (qupath.lib.roi.RectangleROI)2 ShapeRoi (ij.gui.ShapeRoi)1 Shape (java.awt.Shape)1 PathIterator (java.awt.geom.PathIterator)1 Node (javafx.scene.Node)1 ClosePath (javafx.scene.shape.ClosePath)1 Ellipse (javafx.scene.shape.Ellipse)1 Line (javafx.scene.shape.Line)1 Path (javafx.scene.shape.Path)1 Rectangle (javafx.scene.shape.Rectangle)1 Glyph (org.controlsfx.glyphfont.Glyph)1 MeasurementList (qupath.lib.measurements.MeasurementList)1 PathClass (qupath.lib.objects.classes.PathClass)1 PolygonROI (qupath.lib.roi.PolygonROI)1 PolylineROI (qupath.lib.roi.PolylineROI)1 ROI (qupath.lib.roi.interfaces.ROI)1