public static PathShape combineROIs(PathShape shape1, PathShape shape2, CombineOp op) { return combineROIs(shape1, shape2, op, -1); }
/** * Dilate or erode a ROI using a circular structuring element. * * @param roi The ROI to dilate or erode. * @param radius The radius of the structuring element to use. If positive this will be a dilation, if negative an erosion. * @return */ public static PathShape roiMorphology(final ROI roi, final double radius) { return getShapeROI(shapeMorphology(getShape(roi), radius), roi.getC(), roi.getZ(), roi.getT()); }
public static PolygonROI[][] splitAreaToPolygons(final AreaROI pathROI) { if (pathROI instanceof AWTAreaROI) return splitAreaToPolygons(new Area(((AWTAreaROI)pathROI).getShape())); else { logger.debug("Converting {} to {}", pathROI, AWTAreaROI.class.getSimpleName()); return splitAreaToPolygons(new Area(new AWTAreaROI(pathROI).getShape())); } // logger.error("Splitting non-AWT area ROIs not yet supported!"); // TODO: Support splitting non-AWT area ROIs! // return new PolygonROI[0][0]; }
/** * Warning: Currently, this only compares the actual shape, *not* the channel, timepoint or z-slice. * However this may change in the future. * A * * TODO: Consider comparing channels, time-points & z-slices. */ public static boolean containsShape(final PathShape shape1, final PathShape shape2) { return containsShape(getShape(shape1), getShape(shape2)); }
PathShape pathShape = (PathShape)pathObject.getROI(); if (path == null) path = new Path2D.Float(PathROIToolsAwt.getShape(pathShape)); else path.append(PathROIToolsAwt.getShape(pathShape), false); tiles.add(pathObject); ROI parentROI = parentObject.getROI(); if (parentROI != null) pathROINew = PathROIToolsAwt.getShapeROI(new Area(path), parentROI.getC(), parentROI.getZ(), parentROI.getT()); else pathROINew = PathROIToolsAwt.getShapeROI(new Area(path), -1, 0, 0); pathSingleAnnotation = new PathAnnotationObject(pathROINew, pathClass); if (!deleteTiles) Area area = PathROIToolsAwt.getArea(pathShape); if (area.isSingular()) { pathAnnotations.add(pathSingleAnnotation); PolygonROI[][] polygons = PathROIToolsAwt.splitAreaToPolygons(area); for (PolygonROI poly : polygons[1]) { PathShape shape = poly; shape = PathROIToolsAwt.combineROIs(shape, hole, PathROIToolsAwt.CombineOp.SUBTRACT);
Shape shape = PathROIToolsAwt.getShape(pathObject.getROI()); Area area = PathROIToolsAwt.shapeMorphology(shape, radiusPixels); parentShape = new Area(bounds); else parentShape = PathROIToolsAwt.getArea(parent.getROI()); area.intersect(parentShape); ROI roi2 = PathROIToolsAwt.getShapeROI(area, roi.getC(), roi.getZ(), roi.getT(), 0.5);
public static PathShape combineROIs(PathShape shape1, PathShape shape2, CombineOp op, double flatness) { // Check we can combine if (!ROIHelpers.sameImagePlane(shape1, shape2)) throw new IllegalArgumentException("Cannot combine - shapes " + shape1 + " and " + shape2 + " do not share the same image plane"); Area area1 = getArea(shape1); Area area2 = getArea(shape2); // Do a quick check to see if a combination might be avoided if (op == CombineOp.INTERSECT) { if (area1.contains(area2.getBounds2D())) return shape2; if (area2.contains(area1.getBounds2D())) return shape1; } else if (op == CombineOp.ADD) { if (area1.contains(area2.getBounds2D())) return shape1; if (area2.contains(area1.getBounds2D())) return shape2; } combineAreas(area1, area2, op); // I realise the following looks redundant... however direct use of the areas with the // brush tool led to strange artefacts appearing & disappearing... performing an additional // conversion seems to help // area1 = new Area(new Path2D.Float(area1)); // Return simplest ROI that works - prefer a rectangle or polygon over an area return getShapeROI(area1, shape1.getC(), shape1.getZ(), shape1.getT(), flatness); }
public static Collection<? extends ROI> computeTiledROIs(ImageData<?> imageData, PathObject parentObject, ImmutableDimension sizePreferred, ImmutableDimension sizeMax, boolean fixedSize, int overlap) { ROI parentROI = parentObject.getROI(); if (parentROI == null) parentROI = new RectangleROI(0, 0, imageData.getServer().getWidth(), imageData.getServer().getHeight()); return computeTiledROIs(parentROI, sizePreferred, sizeMax, fixedSize, overlap); }
/** * Get a java.awt.geom.Area object representing a ROI. * * @param roi * @return */ public static Area getArea(final ROI roi) { Shape shape = getShape(roi); if (shape instanceof Area) return (Area)shape; return new Area(shape); }
public static PathShape getShapeROI(Area area, int c, int z, int t) { return getShapeROI(area, c, z, t, -1); }
boolean trimToROI = params.getBooleanParameterValue("trimToROI"); List<ROI> pathROIs = PathROIToolsAwt.makeTiles((PathArea)roi, tileWidth, tileHeight, trimToROI);
Area areaOriginal = PathROIToolsAwt.getArea(shapeMask); Area areaNew = new Area(areaOriginal); Iterator<PathObject> iter = pathObjects.iterator(); while (iter.hasNext()) { PathObject temp = iter.next(); Area areaTemp = PathROIToolsAwt.getArea(temp.getROI()); PathObject annotationNew = null; if (op == PathROIToolsAwt.CombineOp.SUBTRACT) { areaTemp.subtract(areaNew); PathShape shapeNew = PathROIToolsAwt.getShapeROI(areaTemp, shapeMask.getC(), shapeMask.getZ(), shapeMask.getT()); annotationNew = new PathAnnotationObject(shapeNew, temp.getPathClass()); } else if (op == PathROIToolsAwt.CombineOp.INTERSECT) { areaTemp.intersect(areaNew); PathShape shapeNew = PathROIToolsAwt.getShapeROI(areaTemp, shapeMask.getC(), shapeMask.getZ(), shapeMask.getT()); annotationNew = new PathAnnotationObject(shapeNew, temp.getPathClass()); } else { PathROIToolsAwt.combineAreas(areaNew, areaTemp, op); PathShape shapeNew = PathROIToolsAwt.getShapeROI(areaNew, shapeMask.getC(), shapeMask.getZ(), shapeMask.getT()); objectsToAdd.add(new PathAnnotationObject(shapeNew, pathObject.getPathClass()));
for (PathObject tempObject : overlapObjects) { if (tempObject.getROI() instanceof PathArea) { Shape shapeTemp = PathROIToolsAwt.getShape(tempObject.getROI()); Area areaTemp = new Area(shapeTemp); mapOld.put(areaTemp, tempObject); areaNew = PathROIToolsAwt.getArea(pathAreaNew); temp.intersect(areaNew); if (temp.isEmpty())
Collection<? extends ROI> pathROIs = PathROIToolsAwt.computeTiledROIs(imageData, parentObject, sizePreferred, sizeMax, false, getTileOverlap(imageData, params)); if (pathROIs.isEmpty()) return;
/** * Create a grayscale BufferedImage representing a mask for a specified ROI. * * Pixels inside the ROI will be 255, pixels outside will be 0. * * @param width Width of the requested mask image * @param height Height of the requested mask image * @param roi ROI for mask * @param xOrigin Pixel x coordinate of the top left of the region to include in the mask. * @param yOrigin Pixel y coordinate of the top left of the region to include in the mask. * @param downsample Downsample factor to use when generating the mask, i.e. the amoutn to scale. * @return */ public static BufferedImage createROIMask(final int width, final int height, final ROI roi, final double xOrigin, final double yOrigin, final double downsample) { BufferedImage imgMask = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); Shape shape = PathROIToolsAwt.getShape(roi); Graphics2D g2d = imgMask.createGraphics(); g2d.scale(1.0/downsample, 1.0/downsample); g2d.translate(-xOrigin, -yOrigin); g2d.setColor(Color.WHITE); g2d.fill(shape); // g2d.draw(shape); g2d.dispose(); return imgMask; }
/** * Get a PathShape from an Area. * This will try to return a PathRectangleROI or PathPolygonROI if possible, * or PathAreaROI if neither of the other classes can adequately represent the area. * * In the input shape is an Ellipse2D then an EllipseROI will be returned. * * @param area * @param c * @param z * @param t * @param flatness - can be used to prefer polygons, see Shape.getPathIterator(AffineTransform at, double flatness) * @return */ public static PathShape getShapeROI(Shape shape, int c, int z, int t, double flatness) { if (shape instanceof Rectangle2D) { Rectangle2D bounds = shape.getBounds2D(); return new RectangleROI(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), c, z, t); } if (shape instanceof Ellipse2D) { Rectangle2D bounds = shape.getBounds2D(); return new EllipseROI(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), c, z, t); } return getShapeROI(new Area(shape), c, z, t, flatness); }
public static List<ROI> makeTiles(final PathArea pathROI, final int tileWidth, final int tileHeight, final boolean trimToROI) { Area area = getArea(pathROI); List<ROI> tiles = new ArrayList<>();
Collection<? extends ROI> rois = PathROIToolsAwt.computeTiledROIs(roi, sizePreferred, sizePreferred, false, 0); if (rois.size() > 1) logger.info("Splitting {} into {} tiles for intensity measurements", roi, rois.size());