use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.
the class PixelClassifierTools method classifyObjectsByCentroid.
/**
* Apply classification from a server to a collection of objects.
*
* @param classifierServer an {@link ImageServer} with output type
* @param pathObjects
* @param preferNucleusROI
*/
public static void classifyObjectsByCentroid(ImageServer<BufferedImage> classifierServer, Collection<PathObject> pathObjects, boolean preferNucleusROI) {
var labels = classifierServer.getMetadata().getClassificationLabels();
var reclassifiers = pathObjects.parallelStream().map(p -> {
try {
var roi = PathObjectTools.getROI(p, preferNucleusROI);
int x = (int) roi.getCentroidX();
int y = (int) roi.getCentroidY();
int ind = getClassification(classifierServer, x, y, roi.getZ(), roi.getT());
return new Reclassifier(p, labels.getOrDefault(ind, null), false);
} catch (Exception e) {
return new Reclassifier(p, null, false);
}
}).collect(Collectors.toList());
reclassifiers.parallelStream().forEach(r -> r.apply());
}
use of qupath.lib.roi.interfaces.ROI 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;
}
use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.
the class PathObjectTools method mergePointsForSelectedObjectClasses.
// private static void addPathObjectsRecursively(Collection<PathObject> pathObjectsInput, Collection<PathObject> pathObjects, Class<? extends PathObject> cls) {
// Collection<PathObject> buffer = null;
// for (PathObject childObject : pathObjectsInput) {
// if (cls == null || cls.isInstance(childObject)) {
// pathObjects.add(childObject);
// }
// if (childObject.hasChildren()) {
// if (buffer == null)
// buffer = new ArrayList<>();
// else
// buffer.clear();
// childObject.getChildObjects(buffer);
// addPathObjectsRecursively(buffer, pathObjects, cls);
// }
// }
// }
// /**
// * Split annotations containing multi-point ROIs into separate single-point ROIs.
// *
// * @param hierarchy the object hierarchy
// * @param selectedOnly if true, consider only annotations that are currently selected; if false, consider all point annotations in the hierarchy
// * @return true if changes are made to the hierarchy, false otherwise
// */
// public static boolean splitPoints(PathObjectHierarchy hierarchy, boolean selectedOnly) {
// if (hierarchy == null) {
// logger.debug("No hierarchy available, cannot split points!");
// return false;
// }
// return splitPoints(hierarchy, selectedOnly ? hierarchy.getSelectionModel().getSelectedObjects() : hierarchy.getAnnotationObjects());
// }
//
// /**
// * Split annotations containing multi-point ROIs into separate single-point ROIs.
// *
// * @param hierarchy the object hierarchy
// * @param pathObjects a collection of point annotations to split; non-points and non-annotations will be ignored
// * @return pathObjects if changes are made to the hierarchy, false otherwise
// */
// public static boolean splitPoints(PathObjectHierarchy hierarchy, Collection<PathObject> pathObjects) {
// var points = pathObjects.stream().filter(p -> p.isAnnotation() && p.getROI().isPoint() && p.getROI().getNumPoints() > 1).collect(Collectors.toList());
// if (points.isEmpty()) {
// logger.debug("No (multi)point ROIs available to split!");
// return false;
// }
// List<PathObject> newObjects = new ArrayList<>();
// for (PathObject pathObject : points) {
// ROI p = pathObject.getROI();
// ImagePlane plane = p.getImagePlane();
// PathClass pathClass = pathObject.getPathClass();
// for (Point2 p2 : p.getAllPoints()) {
// PathObject temp = PathObjects.createAnnotationObject(ROIs.createPointsROI(p2.getX(), p2.getY(), plane), pathClass);
// newObjects.add(temp);
// }
// }
// hierarchy.removeObjects(points, true);
// hierarchy.addPathObjects(newObjects);
// // Reset the selection
// hierarchy.getSelectionModel().clearSelection();
// return true;
// }
/**
* Merge point annotations sharing the same {@link PathClass} and {@link ImagePlane} as the selected annotations,
* creating multi-point annotations for all matching points and removing the (previously-separated) annotations.
*
* @param hierarchy object hierarchy to modify
* @return true if changes are made to the hierarchy, false otherwise
*/
public static boolean mergePointsForSelectedObjectClasses(PathObjectHierarchy hierarchy) {
var pathClasses = hierarchy.getSelectionModel().getSelectedObjects().stream().filter(p -> p.isAnnotation() && p.getROI().isPoint()).map(p -> p.getPathClass()).collect(Collectors.toSet());
boolean changes = false;
for (PathClass pathClass : pathClasses) changes = changes || mergePointsForClass(hierarchy, pathClass);
return changes;
}
use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.
the class PathObjectTileCache method getGeometry.
Geometry getGeometry(PathObject pathObject) {
ROI roi = pathObject.getROI();
Geometry geometry = geometryMap.get(roi);
if (geometry == null) {
geometry = roi.getGeometry();
if (pathObject.isAnnotation() || pathObject.isTMACore()) {
geometryMap.put(roi, geometry);
}
// // long startTime = System.currentTimeMillis();
// if (!geometry.isValid()) {
// int nVertices = geometry.getNumPoints();
// if (geometry.getNumPoints() < 100)
// logger.warn("{} is not a valid geometry! Actual geometry {}", pathObject, geometry);
// else
// logger.warn("{} is not a valid geometry! Actual geometry {} ({} vertices)", pathObject, geometry.getGeometryType(), nVertices);
// }
// // long endTime = System.currentTimeMillis();
// // System.err.println("Testing " + (endTime - startTime) + " ms for " + geometry);
}
return geometry;
}
use of qupath.lib.roi.interfaces.ROI in project qupath by qupath.
the class ParallelTileObject method getObjectsForRegion.
/**
* Get all the objects whose bounding box intersects with a specified region
* @param region
* @return
*/
List<PathObject> getObjectsForRegion(Rectangle2D region) {
List<PathObject> pathObjects = new ArrayList<>();
for (PathObject child : getChildObjectsAsArray()) {
ROI childROI = child.getROI();
if (childROI != null && childROI.isArea() && region.intersects(getBounds2D(childROI))) {
pathObjects.add(child);
}
}
Collections.sort(pathObjects, DefaultPathObjectComparator.getInstance());
return pathObjects;
}
Aggregations