use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.
the class Scalebar method updateScalebar.
public void updateScalebar() {
if (viewer == null) {
scaleLine.setVisible(false);
// setText("");
// setText(null);
}
try {
scaleLine.setVisible(true);
// Check the downsample has changed
double currentDownsample = viewer.getDownsampleFactor();
if (lastDownsample == currentDownsample)
return;
// System.out.println("UPDATING SCALE BAR! " + currentDownsample);
ImageServer<?> server = viewer.getServer();
// The scalebar is shown horizontally - so request the horizontal scale, if known
double scale = 1.0;
String unit = "px";
PixelCalibration cal = server.getPixelCalibration();
if (cal.hasPixelSizeMicrons()) {
scale = cal.getPixelWidthMicrons();
unit = GeneralTools.micrometerSymbol();
}
// The size of one pixel... in some kind of units
double pxSize = scale * currentDownsample;
// Find the permitted scalebar size closest to the preferred length
scaledLength = getPermittedScale(pxSize * preferredLength);
scaledLengthPixels = scaledLength / pxSize;
// Switch to mm if appropriate
String labelText = df.format(scaledLength) + unit;
if (scaledLength >= 1000 && GeneralTools.micrometerSymbol().equals(unit)) {
labelText = df.format(scaledLength / 1000) + "mm";
}
// String label = String.format("%f %s", scaledLength, unit);
// If it make sense, could convert microns to mm... but let's not do that for now
// if (server.pixelSizeMicronsKnown() && scaledLength >= 1000)
// label = String.format("%f %s", scaledLength, "mm");
double width = scaledLengthPixels;
double height = 5;
canvas.setWidth(width + 2);
canvas.setHeight(height);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.clearRect(0, 0, width + 2, height);
gc.save();
int x = 1;
gc.setStroke(color);
gc.setLineWidth(2);
gc.strokeLine(x, 0, x, height);
gc.strokeLine(x, height / 2, x + width, height / 2);
gc.strokeLine(x + width, 0, x + width, height);
gc.restore();
scaleLine.setStartX(0.0);
scaleLine.setStartY(0.0);
scaleLine.setEndY(0.0);
scaleLine.setEndX(scaledLength);
label.setText(labelText);
lastDownsample = currentDownsample;
} catch (NullPointerException e) {
label.setText("");
}
}
use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.
the class GridOverlay method drawGrid.
private static void drawGrid(final GridLines gridLines, final Graphics g, final ImageServer<?> server, final double downsample, final ImageRegion imageRegion, final Color color) {
// Get the image server, and check if we know the pixel size in microns
if (server == null || (gridLines.useMicrons() && !server.getPixelCalibration().hasPixelSizeMicrons()))
return;
Graphics2D g2d = (Graphics2D) g.create();
// Convert microns to pixels if needed
double startXpx = gridLines.getStartX();
double startYpx = gridLines.getStartY();
double spaceXpx = gridLines.getSpaceX();
double spaceYpx = gridLines.getSpaceY();
if (gridLines.useMicrons()) {
PixelCalibration cal = server.getPixelCalibration();
startXpx /= cal.getPixelWidthMicrons();
startYpx /= cal.getPixelHeightMicrons();
spaceXpx /= cal.getPixelWidthMicrons();
spaceYpx /= cal.getPixelHeightMicrons();
}
// Do the painting
if (color != null)
g2d.setColor(color);
// Compute image coordinate boundaries according to what is actually visible within the image
int minImageX = imageRegion.getX();
int maxImageX = imageRegion.getX() + imageRegion.getWidth();
int minImageY = imageRegion.getY();
int maxImageY = imageRegion.getY() + imageRegion.getHeight();
// If the lines will be too dense, fill a rectangle instead
if (spaceXpx > 0) {
if (spaceXpx > downsample) {
for (double x = startXpx; x < server.getWidth(); x += spaceXpx) {
// Check if we are within range
if (x < minImageX || x > maxImageX)
continue;
g2d.drawLine((int) (x + .5), minImageY, (int) (x + .5), maxImageY);
}
} else {
g2d.fillRect(imageRegion.getX(), imageRegion.getY(), imageRegion.getWidth(), imageRegion.getHeight());
}
}
if (spaceYpx > 0 && spaceYpx >= downsample) {
if (spaceYpx > downsample) {
for (double y = startYpx; y < server.getHeight(); y += spaceYpx) {
// Check if we are within range
if (y < minImageY || y > maxImageY)
continue;
g2d.drawLine(minImageX, (int) (y + .5), maxImageX, (int) (y + .5));
}
} else {
g2d.fillRect(imageRegion.getX(), imageRegion.getY(), imageRegion.getWidth(), imageRegion.getHeight());
}
}
g2d.dispose();
}
use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.
the class SubcellularDetection method processObject.
/**
* Initial version of subcellular detection processing.
*
* @param pathObject
* @param params
* @param imageWrapper
* @return
* @throws InterruptedException
* @throws IOException
*/
static boolean processObject(final PathObject pathObject, final ParameterList params, final ImageWrapper imageWrapper) throws InterruptedException, IOException {
// Get the base classification for the object as it currently stands
PathClass baseClass = PathClassTools.getNonIntensityAncestorClass(pathObject.getPathClass());
// Variable to hold estimated spot count
double estimatedSpots;
// We assume that after this processing, any previous sub-cellular objects should be removed
pathObject.clearPathObjects();
// Ensure we have no existing subcellular detection measurements - if we do, remove them
String[] existingMeasurements = pathObject.getMeasurementList().getMeasurementNames().stream().filter(n -> n.startsWith("Subcellular:")).toArray(n -> new String[n]);
if (existingMeasurements.length > 0) {
pathObject.getMeasurementList().removeMeasurements(existingMeasurements);
pathObject.getMeasurementList().close();
}
// // If we're part of a TMA core, request the whole core...
// if (pathObject.getParent() instanceof TMACoreObject && pathObject.getParent().hasROI()) {
// regionStore.getImage(server, RegionRequest.createInstance(server.getPath(), 1, pathObject.getParent().getROI()), 25, true);
// }
ROI pathROI = pathObject.getROI();
if (pathROI == null || pathROI.isEmpty())
return false;
// double downsample = 0.5;
double downsample = 1;
// Determine spot size
ImageServer<BufferedImage> server = imageWrapper.getServer();
PixelCalibration cal = server.getPixelCalibration();
double minSpotArea, maxSpotArea, singleSpotArea;
double pixelWidth, pixelHeight;
if (cal.hasPixelSizeMicrons()) {
double spotSizeMicrons = params.getDoubleParameterValue("spotSizeMicrons");
double minSpotSizeMicrons = params.getDoubleParameterValue("minSpotSizeMicrons");
double maxSpotSizeMicrons = params.getDoubleParameterValue("maxSpotSizeMicrons");
pixelWidth = cal.getPixelWidthMicrons() * downsample;
pixelHeight = cal.getPixelHeightMicrons() * downsample;
singleSpotArea = spotSizeMicrons / (pixelWidth * pixelHeight);
minSpotArea = minSpotSizeMicrons / (pixelWidth * pixelHeight);
maxSpotArea = maxSpotSizeMicrons / (pixelWidth * pixelHeight);
} else {
singleSpotArea = params.getDoubleParameterValue("spotSizePixels");
minSpotArea = params.getDoubleParameterValue("minSpotSizePixels");
maxSpotArea = params.getDoubleParameterValue("maxSpotSizePixels");
pixelWidth = downsample;
pixelHeight = downsample;
}
boolean includeClusters = Boolean.TRUE.equals(params.getBooleanParameterValue("includeClusters"));
boolean doSmoothing = Boolean.TRUE.equals(params.getBooleanParameterValue("doSmoothing"));
boolean splitByIntensity = Boolean.TRUE.equals(params.getBooleanParameterValue("splitByIntensity"));
boolean splitByShape = Boolean.TRUE.equals(params.getBooleanParameterValue("splitByShape"));
// Get region to request - give a pixel as border
int xStart = (int) Math.max(0, pathROI.getBoundsX() - 1);
int yStart = (int) Math.max(0, pathROI.getBoundsY() - 1);
int width = (int) Math.min(server.getWidth() - 1, pathROI.getBoundsX() + pathROI.getBoundsWidth() + 1.5) - xStart;
int height = (int) Math.min(server.getHeight() - 1, pathROI.getBoundsY() + pathROI.getBoundsHeight() + 1.5) - yStart;
if (width <= 0 || height <= 0) {
logger.error("Negative ROI size for {}", pathROI);
pathObject.setPathClass(baseClass);
return false;
}
int z = pathROI.getZ();
int t = pathROI.getT();
// Don't associate with channel
int c = -1;
RegionRequest region = RegionRequest.createInstance(server.getPath(), 1.0, xStart, yStart, width, height, z, t);
// Mask to indicate pixels within the cell
byte[] cellMask = null;
for (String channelName : imageWrapper.getChannelNames(true, true)) {
double detectionThreshold = params.getDoubleParameterValue("detection[" + channelName + "]");
if (Double.isNaN(detectionThreshold) || detectionThreshold < 0)
continue;
// // TODO: Consider whether to use channel numbers for non-brightfield images
// if (!imageWrapper.imageData.isBrightfield())
// c++;
SimpleImage img = imageWrapper.getRegion(region, channelName);
// Get an ImageJ-friendly calibration for ROI conversion
Calibration calIJ = new Calibration();
calIJ.xOrigin = -xStart / downsample;
calIJ.yOrigin = -yStart / downsample;
// Create a cell mask
if (cellMask == null) {
BufferedImage imgMask = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2d = imgMask.createGraphics();
if (downsample != 1)
g2d.scale(1.0 / downsample, 1.0 / downsample);
g2d.translate(-xStart, -yStart);
Shape shape = RoiTools.getShape(pathROI);
g2d.setColor(Color.WHITE);
g2d.fill(shape);
g2d.dispose();
cellMask = (byte[]) ((DataBufferByte) imgMask.getRaster().getDataBuffer()).getData(0);
}
// Get a buffer containing the image pixels
int w = img.getWidth();
int h = img.getHeight();
// Identify (& try to separate) spots
// Mask out non-cell areas as we go
FloatProcessor fpDetection = new FloatProcessor(w, h);
if (doSmoothing) {
for (int i = 0; i < w * h; i++) fpDetection.setf(i, img.getValue(i % w, i / w));
fpDetection.smooth();
for (int i = 0; i < w * h; i++) {
if (cellMask[i] == (byte) 0)
fpDetection.setf(i, 0f);
}
} else {
for (int i = 0; i < w * h; i++) {
if (cellMask[i] == (byte) 0)
fpDetection.setf(i, 0f);
else
fpDetection.setf(i, img.getValue(i % w, i / w));
}
}
ByteProcessor bpSpots;
if (splitByIntensity)
bpSpots = new MaximumFinder().findMaxima(fpDetection, detectionThreshold / 10.0, detectionThreshold, MaximumFinder.SEGMENTED, false, false);
else
bpSpots = SimpleThresholding.thresholdAboveEquals(fpDetection, (float) detectionThreshold);
if (splitByShape) {
new EDM().toWatershed(bpSpots);
}
// Loop through spot ROIs & make a decision
bpSpots.setThreshold(1, ImageProcessor.NO_THRESHOLD, ImageProcessor.NO_LUT_UPDATE);
List<PolygonRoi> possibleSpotRois = RoiLabeling.getFilledPolygonROIs(bpSpots, Wand.FOUR_CONNECTED);
List<PathObject> spotObjects = new ArrayList<>();
List<PathObject> clusterObjects = new ArrayList<>();
estimatedSpots = 0;
for (PolygonRoi spotRoi : possibleSpotRois) {
fpDetection.setRoi(spotRoi);
ImageStatistics stats = fpDetection.getStatistics();
// In v0.2
// ImagePlane plane = ImagePlane.getPlaneWithChannel(spotRoi.getCPosition(), spotRoi.getZPosition(), spotRoi.getTPosition());
// In v0.3
ImagePlane plane = ImagePlane.getPlaneWithChannel(c, z, t);
PathObject spotOrCluster = null;
if (stats.pixelCount >= minSpotArea && stats.pixelCount <= maxSpotArea) {
ROI roi = IJTools.convertToROI(spotRoi, calIJ, downsample, plane);
// cluster = new SubcellularObject(roi, 1);
spotOrCluster = createSubcellularObject(roi, 1);
estimatedSpots += 1;
} else if (includeClusters && stats.pixelCount >= minSpotArea) {
// Add a cluster
ROI roi = IJTools.convertToROI(spotRoi, calIJ, downsample, plane);
double nSpots = stats.pixelCount / singleSpotArea;
estimatedSpots += nSpots;
// cluster = new SubcellularObject(roi, nSpots);
spotOrCluster = createSubcellularObject(roi, nSpots);
}
if (spotOrCluster != null) {
boolean isCluster = spotOrCluster.getMeasurementList().getMeasurementValue("Num spots") > 1;
int rgb = imageWrapper.getChannelColor(channelName);
rgb = isCluster ? ColorTools.makeScaledRGB(rgb, 0.5) : ColorTools.makeScaledRGB(rgb, 1.5);
PathClass pathClass = PathClassFactory.getDerivedPathClass(spotOrCluster.getPathClass(), channelName + " object", rgb);
spotOrCluster.setPathClass(pathClass);
spotOrCluster.getMeasurementList().putMeasurement("Subcellular cluster: " + channelName + ": Area", stats.pixelCount * pixelWidth * pixelHeight);
spotOrCluster.getMeasurementList().putMeasurement("Subcellular cluster: " + channelName + ": Mean channel intensity", stats.mean);
// cluster.getMeasurementList().putMeasurement("Subcellular cluster: " + channelName + ": Max channel intensity", stats.max);
spotOrCluster.getMeasurementList().close();
if (isCluster)
clusterObjects.add(spotOrCluster);
else
spotObjects.add(spotOrCluster);
}
}
// Add measurements
MeasurementList measurementList = pathObject.getMeasurementList();
measurementList.putMeasurement("Subcellular: " + channelName + ": Num spots estimated", estimatedSpots);
measurementList.putMeasurement("Subcellular: " + channelName + ": Num single spots", spotObjects.size());
measurementList.putMeasurement("Subcellular: " + channelName + ": Num clusters", clusterObjects.size());
// Add spots
pathObject.addPathObjects(spotObjects);
pathObject.addPathObjects(clusterObjects);
}
return true;
}
use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.
the class HaralickFeaturesPlugin method processObject.
static boolean processObject(final PathObject pathObject, final ParameterList params, final ImageServer<BufferedImage> server, final ColorDeconvolutionStains stains) throws IOException {
String stainsName = (String) params.getChoiceParameterValue("stainChoice");
double mag = params.getDoubleParameterValue("magnification");
int d = params.getIntParameterValue("haralickDistance");
int nBins = params.getIntParameterValue("haralickBins");
boolean includeStats = params.getBooleanParameterValue("includeStats");
boolean doCircular = params.getBooleanParameterValue("doCircular");
double downsample;
boolean hasMagnification = !Double.isNaN(server.getMetadata().getMagnification());
PixelCalibration cal = server.getPixelCalibration();
if (hasMagnification)
downsample = server.getMetadata().getMagnification() / mag;
else if (cal.hasPixelSizeMicrons()) {
downsample = params.getDoubleParameterValue("pixelSizeMicrons") / cal.getAveragedPixelSizeMicrons();
} else
downsample = params.getDoubleParameterValue("downsample");
// double downsample = server.getMagnification() / mag;
// Try to get ROI
ROI pathROI = null;
if (pathObject instanceof PathCellObject && Boolean.TRUE.equals(params.getBooleanParameterValue("useNucleusROIs")))
pathROI = ((PathCellObject) pathObject).getNucleusROI();
else
pathROI = pathObject.getROI();
if (pathROI == null)
return false;
// Get bounds
ImmutableDimension size = getPreferredTileSizePixels(server, params);
RegionRequest region;
boolean createMaskROI = false;
if (size.getWidth() <= 0 || size.getHeight() <= 0) {
region = RegionRequest.createInstance(server.getPath(), downsample, pathObject.getROI());
createMaskROI = true;
doCircular = false;
} else if (size.getWidth() / downsample < 1 || size.getHeight() / downsample < 1)
// Positive size, but insufficient to make measurements
return false;
else {
// RegionRequest region = RegionRequest.createInstance(server.getPath(), downsample, (int)(pathROI.getCentroidX() + .5) - size.width/2, (int)(pathROI.getCentroidY() + .5) - size.height/2, size.width, size.height, pathROI.getT(), pathROI.getZ());
// Try to align with pixel boundaries according to the downsample being used - otherwise, interpolation can cause some strange, pattern artefacts
int xStart = (int) ((int) (pathROI.getCentroidX() / downsample + .5) * downsample) - size.width / 2;
int yStart = (int) ((int) (pathROI.getCentroidY() / downsample + .5) * downsample) - size.height / 2;
int width = Math.min(server.getWidth(), xStart + size.width) - xStart;
int height = Math.min(server.getHeight(), yStart + size.height) - yStart;
region = RegionRequest.createInstance(server.getPath(), downsample, xStart, yStart, width, height, pathROI.getT(), pathROI.getZ());
}
// Check image large enough to do *anything* of value
if (region.getWidth() / downsample < 3 || region.getHeight() / downsample < 3)
return false;
// System.out.println(bounds);
// System.out.println("Size: " + size);
BufferedImage img = server.readBufferedImage(region);
if (img == null) {
logger.error("Could not read image - unable to compute Haralick features for {}", pathObject);
return false;
}
// Create mask ROI if necessary
byte[] maskBytes = null;
if (createMaskROI) {
ROI roi = pathObject.getROI();
// if (pathObject instanceof PathCellObject && ((PathCellObject)pathObject).getNucleusROI() != null)
// roi = ((PathCellObject)pathObject).getNucleusROI();
BufferedImage imgMask = BufferedImageTools.createROIMask(img.getWidth(), img.getHeight(), roi, region);
maskBytes = ((DataBufferByte) imgMask.getRaster().getDataBuffer()).getData();
}
double minValue = Double.NaN;
double maxValue = Double.NaN;
// Get a buffer containing the image pixels
int w = img.getWidth();
int h = img.getHeight();
int[] buf = img.getRGB(0, 0, w, h, null, 0, w);
// Create a color transformer to get the images we need
float[] pixels = new float[buf.length];
SimpleModifiableImage pxImg = SimpleImages.createFloatImage(pixels, w, h);
MeasurementList measurementList = pathObject.getMeasurementList();
String postfix = maskBytes == null ? " (" + getDiameterString(server, params) + ")" : "";
if (stainsName.equals("H-DAB")) {
minValue = 0;
maxValue = 2.0;
processTransformedImage(pxImg, buf, pixels, measurementList, "Hematoxylin" + postfix, ColorTransformer.ColorTransformMethod.Hematoxylin_H_DAB, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "DAB" + postfix, ColorTransformer.ColorTransformMethod.DAB_H_DAB, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
} else if (stainsName.equals("H&E")) {
minValue = 0;
maxValue = 2;
processTransformedImage(pxImg, buf, pixels, measurementList, "Hematoxylin" + postfix, ColorTransformer.ColorTransformMethod.Hematoxylin_H_E, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Eosin" + postfix, ColorTransformer.ColorTransformMethod.Eosin_H_E, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
} else if (stainsName.equals("H-DAB (8-bit)")) {
minValue = 0;
maxValue = 255;
processTransformedImage(pxImg, buf, pixels, measurementList, "Hematoxylin 8-bit" + postfix, ColorTransformer.ColorTransformMethod.Hematoxylin_H_DAB_8_bit, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "DAB 8-bit" + postfix, ColorTransformer.ColorTransformMethod.DAB_H_DAB_8_bit, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
} else if (stainsName.equals("H&E (8-bit)")) {
minValue = 0;
maxValue = 255;
processTransformedImage(pxImg, buf, pixels, measurementList, "Hematoxylin 8-bit" + postfix, ColorTransformer.ColorTransformMethod.Hematoxylin_H_E_8_bit, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Eosin 8-bit" + postfix, ColorTransformer.ColorTransformMethod.Eosin_H_E_8_bit, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
} else if (stainsName.equals("Optical density")) {
minValue = 0;
maxValue = 2.5;
processTransformedImage(pxImg, buf, pixels, measurementList, "OD sum" + postfix, ColorTransformer.ColorTransformMethod.Optical_density_sum, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
} else if (stainsName.equals("RGB")) {
minValue = 0;
maxValue = 255;
processTransformedImage(pxImg, buf, pixels, measurementList, "Red" + postfix, ColorTransformer.ColorTransformMethod.Red, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Green" + postfix, ColorTransformer.ColorTransformMethod.Green, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Blue" + postfix, ColorTransformer.ColorTransformMethod.Blue, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
} else if (stainsName.equals("RGB OD")) {
minValue = 0;
// Actual possible max is around 2.4 for 8-bit input... but this gives a lot of bins for (almost) saturated pixels
maxValue = 1.5;
processTransformedImage(pxImg, buf, pixels, measurementList, "Red OD" + postfix, ColorTransformer.ColorTransformMethod.Red_OD, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Green OD" + postfix, ColorTransformer.ColorTransformMethod.Green_OD, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Blue OD" + postfix, ColorTransformer.ColorTransformMethod.Blue_OD, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
} else if (stainsName.equals("Grayscale")) {
minValue = 0;
maxValue = 255;
processTransformedImage(pxImg, buf, pixels, measurementList, "Grayscale" + postfix, ColorTransformer.ColorTransformMethod.RGB_mean, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
} else if (stainsName.equals("HSB")) {
minValue = 0;
maxValue = 1;
float[] hsb = null;
double sinX = 0;
double cosX = 0;
float[] pixelsBrightness = new float[pixels.length];
float[] pixelsSaturation = new float[pixels.length];
for (int i = 0; i < buf.length; i++) {
if (maskBytes != null && maskBytes[i] == (byte) 0)
continue;
int val = buf[i];
hsb = Color.RGBtoHSB(ColorTools.red(val), ColorTools.green(val), ColorTools.blue(val), hsb);
pixelsSaturation[i] = hsb[1];
pixelsBrightness[i] = hsb[2];
double alpha = hsb[0] * 2 * Math.PI;
sinX += Math.sin(alpha);
cosX += Math.cos(alpha);
}
measurementList.putMeasurement("Mean hue", Math.atan2(sinX, cosX) / (2 * Math.PI) + 0.5);
// measurementList.putMeasurement("Mean saturation", hsb[1]);
// measurementList.putMeasurement("Mean brightness", hsb[2]);
processTransformedImage(SimpleImages.createFloatImage(pixelsSaturation, w, h), buf, pixelsSaturation, measurementList, "Saturation" + postfix, null, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
processTransformedImage(SimpleImages.createFloatImage(pixelsBrightness, w, h), buf, pixelsBrightness, measurementList, "Brightness" + postfix, null, minValue, maxValue, d, nBins, stains, maskBytes, includeStats, doCircular);
}
measurementList.close();
return true;
}
use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.
the class IntensityFeaturesPlugin method getDiameterString.
static String getDiameterString(final ImageServer<BufferedImage> server, final ParameterList params) {
RegionType regionType = (RegionType) params.getChoiceParameterValue("region");
PixelCalibration cal = server.getPixelCalibration();
String shape = regionType == RegionType.SQUARE ? "Square" : (regionType == RegionType.CIRCLE ? "Circle" : "ROI");
String unit = cal.hasPixelSizeMicrons() ? GeneralTools.micrometerSymbol() : "px";
double pixelSize = cal.hasPixelSizeMicrons() ? params.getDoubleParameterValue("pixelSizeMicrons") : params.getDoubleParameterValue("downsample");
double regionSize = cal.hasPixelSizeMicrons() ? params.getDoubleParameterValue("tileSizeMicrons") : params.getDoubleParameterValue("tileSizePixels");
if (regionType == RegionType.ROI) {
return String.format("ROI: %.2f %s per pixel", pixelSize, unit);
} else if (regionType == RegionType.NUCLEUS) {
return String.format("Nucleus: %.2f %s per pixel", pixelSize, unit);
} else {
return String.format("%s: Diameter %.1f %s: %.2f %s per pixel", shape, regionSize, unit, pixelSize, unit);
}
}
Aggregations