use of qupath.lib.geom.Point2 in project qupath by qupath.
the class DnnTools method detectKeypointsROI.
/**
* TODO: Non-public placeholder until better designed/validated - subject to change
* @param model
* @param mat
* @param request
* @param mask
* @param threshold
* @return
*/
static ROI detectKeypointsROI(KeypointsModel model, Mat mat, RegionRequest request, ROI mask, double threshold) {
float thresh = (float) threshold;
Point2fVector output;
synchronized (model) {
output = model.estimate(mat, thresh);
}
double downsample = request.getDownsample();
double xOrigin = request.getX();
double yOrigin = request.getY();
var pointsArray = output.get();
var points = new ArrayList<Point2>();
for (var p : pointsArray) {
double x = xOrigin + p.x() * downsample;
double y = yOrigin + p.y() * downsample;
// TODO: Consider IndexedPointInAreaLocator if needed for performance
if (mask == null || mask.contains(x, y))
points.add(new Point2(x, y));
}
return ROIs.createPointsROI(points, request.getPlane());
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class FindConvexHullDetectionsPlugin method getConvexHullDetections.
static List<PathObject> getConvexHullDetections(final PathObjectHierarchy hierarchy, final PathObject parent, final int nIterations) {
Map<Point2, PathObject> pointsMap = new HashMap<>();
List<PathObject> convexDetections = new ArrayList<>();
Collection<PathObject> pathObjects = PathObjectTools.getDescendantObjects(parent, null, PathDetectionObject.class);
if (pathObjects.isEmpty())
return Collections.emptyList();
// Populate the points map
pointsMap.clear();
for (PathObject child : pathObjects) {
if (!child.hasROI())
continue;
pointsMap.put(new Point2(child.getROI().getCentroidX(), child.getROI().getCentroidY()), child);
}
// Determine what to remove
List<Point2> points = new ArrayList<>(pointsMap.keySet());
for (int i = 0; i < nIterations; i++) {
List<Point2> convexPoints = ConvexHull.getConvexHull(points);
if (convexPoints != null) {
for (Point2 p : convexPoints) convexDetections.add(pointsMap.get(p));
points.removeAll(convexPoints);
}
}
return convexDetections;
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class PathObjectTools method convertToPoints.
/**
* Convert a collection of PathObjects to Point annotations, based on ROI centroids.
* Each output annotation contains all points corresponding to input objects with the same classification.
* Consequently, the size of the output collection is equal to the number of distinct classifications
* found among the input objects.
*
* @param pathObjects input objects; these are expected to have ROIs
* @param preferNucleus if true, request the nucleus ROI from cell objects where possible; if false, request the outer ROI.
* This has no effect if the object is not a cell, or does not have two ROIs.
* @return a collection of annotations with point ROIs
*
* @see #convertToPoints(PathObjectHierarchy, Collection, boolean, boolean)
*/
public static Collection<PathObject> convertToPoints(Collection<PathObject> pathObjects, boolean preferNucleus) {
// Create Points lists for each class
Map<PathClass, Map<ImagePlane, List<Point2>>> pointsMap = new HashMap<>();
for (PathObject pathObject : pathObjects) {
var roi = PathObjectTools.getROI(pathObject, preferNucleus);
if (roi == null)
continue;
var plane = roi.getImagePlane();
PathClass pathClass = pathObject.getPathClass();
var pointsMapByClass = pointsMap.computeIfAbsent(pathClass, p -> new HashMap<>());
var points = pointsMapByClass.computeIfAbsent(plane, p -> new ArrayList<>());
points.add(new Point2(roi.getCentroidX(), roi.getCentroidY()));
}
// Create & add annotation objects to hierarchy
List<PathObject> annotations = new ArrayList<>();
for (Entry<PathClass, Map<ImagePlane, List<Point2>>> entry : pointsMap.entrySet()) {
var pathClass = entry.getKey();
for (var entry2 : entry.getValue().entrySet()) {
var plane = entry2.getKey();
var points = entry2.getValue();
PathObject pointObject = PathObjects.createAnnotationObject(ROIs.createPointsROI(points, plane), pathClass);
annotations.add(pointObject);
}
}
return annotations;
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class PointIO method putPointObjectFromString.
/**
* Helper method that takes a String representing any row taken from a 'Point2 annotations
* TSV file' and creates a Point2 object to put into the provided map.
* @param line
* @param cols
* @param pointsMap
*/
private static void putPointObjectFromString(String line, String[] cols, Map<String[], List<Point2>> pointsMap) {
String[] info = new String[cols.length - 2];
String[] values = line.split("(?<=\t)");
// Core columns
double x = Double.parseDouble(values[0].trim());
double y = Double.parseDouble(values[1].trim());
// Optional columns
for (int i = 2; i < values.length; i++) {
info[i - 2] = values[i].trim();
}
boolean found = false;
for (var key : pointsMap.keySet()) {
if (Arrays.equals(key, info)) {
pointsMap.get(key).add(new Point2(x, y));
found = true;
break;
}
}
if (!found) {
List<Point2> newArray = new ArrayList<>();
newArray.add(new Point2(x, y));
pointsMap.put(info, newArray);
}
}
use of qupath.lib.geom.Point2 in project qupath by qupath.
the class PointIO method writePoints.
/**
* Write a list of point annotations to a stream.
* @param stream
* @param pathObjects
* @throws IOException
*/
public static void writePoints(OutputStream stream, Collection<? extends PathObject> pathObjects) throws IOException {
// Check that all PathObjects contain only point annotations
int unfilteredSize = pathObjects.size();
pathObjects = pathObjects.stream().filter(p -> p.getROI() instanceof PointsROI).collect(Collectors.toList());
int filteredSize = pathObjects.size();
if (unfilteredSize != filteredSize)
logger.warn(unfilteredSize - filteredSize + " of the " + filteredSize + " elements in list is/are not point annotations. These will be skipped.");
try (Writer writer = new BufferedWriter(new OutputStreamWriter(stream, StandardCharsets.UTF_8))) {
List<String> cols = new ArrayList<>();
cols.addAll(Arrays.asList("x", "y"));
String sep = "\t";
ImagePlane defaultPlane = ImagePlane.getDefaultPlane();
boolean hasClass = pathObjects.stream().anyMatch(p -> p.getPathClass() != null);
boolean hasName = pathObjects.stream().anyMatch(p -> p.getName() != null);
boolean hasColor = pathObjects.stream().anyMatch(p -> p.getColorRGB() != null);
boolean hasC = pathObjects.stream().anyMatch(p -> p.getROI().getC() > defaultPlane.getC());
boolean hasZ = pathObjects.stream().anyMatch(p -> p.getROI().getZ() > defaultPlane.getZ());
boolean hasT = pathObjects.stream().anyMatch(p -> p.getROI().getT() > defaultPlane.getT());
if (hasC)
cols.add("c");
if (hasZ)
cols.add("z");
if (hasT)
cols.add("t");
if (hasClass)
cols.add("class");
if (hasName)
cols.add("name");
if (hasColor)
cols.add("color");
for (String col : cols) writer.write(col + sep);
writer.write(System.lineSeparator());
for (PathObject pathObject : pathObjects) {
if (!PathObjectTools.hasPointROI(pathObject))
continue;
PointsROI points = (PointsROI) pathObject.getROI();
for (Point2 point : points.getAllPoints()) {
String[] row = new String[cols.size()];
row[cols.indexOf("x")] = point.getX() + "";
row[cols.indexOf("y")] = sep + point.getY();
if (hasC)
row[cols.indexOf("c")] = sep + points.getC();
if (hasZ)
row[cols.indexOf("z")] = sep + points.getZ();
if (hasT)
row[cols.indexOf("t")] = sep + points.getT();
if (hasClass)
row[cols.indexOf("class")] = pathObject.getPathClass() != null ? sep + pathObject.getPathClass() : sep;
if (hasName)
row[cols.indexOf("name")] = pathObject.getName() != null ? sep + pathObject.getName() : sep;
if (hasColor)
row[cols.indexOf("color")] = pathObject.getColorRGB() != null ? sep + pathObject.getColorRGB() : sep;
for (String val : row) writer.write(val);
writer.write(System.lineSeparator());
}
}
}
}
Aggregations