use of qupath.imagej.tools.PixelImageIJ in project qupath by qupath.
the class ObjectMeasurements method addIntensityMeasurements.
/**
* Measure all channels of an image for one individual object or cell.
* All compartments are measured where possible (nucleus, cytoplasm, membrane and full cell).
* <p>
* Note: This implementation is likely to change in the future, to enable neighboring cells to be
* measured more efficiently.
*
* @param server the server containing the pixels (and channels) to be measured
* @param pathObject the cell to measure (the {@link MeasurementList} will be updated)
* @param downsample resolution at which to request pixels
* @param measurements requested measurements to make
* @param compartments the cell compartments to measure; ignored if the object is not a cell
* @throws IOException
*/
public static void addIntensityMeasurements(ImageServer<BufferedImage> server, PathObject pathObject, double downsample, Collection<Measurements> measurements, Collection<Compartments> compartments) throws IOException {
var roi = pathObject.getROI();
int pad = (int) Math.ceil(downsample * 2);
var request = RegionRequest.createInstance(server.getPath(), downsample, roi).pad2D(pad, pad).intersect2D(0, 0, server.getWidth(), server.getHeight());
var pathImage = IJTools.convertToImagePlus(server, request);
var imp = pathImage.getImage();
Map<String, ImageProcessor> channels = new LinkedHashMap<>();
var serverChannels = server.getMetadata().getChannels();
if (server.isRGB() && imp.getStackSize() == 1 && imp.getProcessor() instanceof ColorProcessor) {
ColorProcessor cp = (ColorProcessor) imp.getProcessor();
for (int i = 0; i < serverChannels.size(); i++) {
channels.put(serverChannels.get(i).getName(), cp.getChannel(i + 1, null));
}
} else {
assert imp.getStackSize() == serverChannels.size();
for (int i = 0; i < imp.getStackSize(); i++) {
channels.put(serverChannels.get(i).getName(), imp.getStack().getProcessor(i + 1));
}
}
ByteProcessor bpCell = new ByteProcessor(imp.getWidth(), imp.getHeight());
bpCell.setValue(1.0);
var roiIJ = IJTools.convertToIJRoi(roi, pathImage);
bpCell.fill(roiIJ);
if (pathObject instanceof PathCellObject) {
var cell = (PathCellObject) pathObject;
ByteProcessor bpNucleus = new ByteProcessor(imp.getWidth(), imp.getHeight());
if (cell.getNucleusROI() != null) {
bpNucleus.setValue(1.0);
var roiNucleusIJ = IJTools.convertToIJRoi(cell.getNucleusROI(), pathImage);
bpNucleus.fill(roiNucleusIJ);
}
measureCells(bpNucleus, bpCell, Map.of(1.0, cell), channels, compartments, measurements);
} else {
var imgLabels = new PixelImageIJ(bpCell);
for (var entry : channels.entrySet()) {
var img = new PixelImageIJ(entry.getValue());
measureObjects(img, imgLabels, new PathObject[] { pathObject }, entry.getKey(), measurements);
}
}
}
use of qupath.imagej.tools.PixelImageIJ in project qupath by qupath.
the class ObjectMeasurements method measureCells.
/**
* Make cell measurements based on labelled images.
* All compartments are measured where possible (nucleus, cytoplasm, membrane and full cell).
*
* @param ipNuclei labelled image representing nuclei
* @param ipCells labelled image representing cells
* @param pathObjects cell objects mapped to integer values in the labelled images
* @param channels channels to measure, mapped to the name to incorporate into the measurements for that channel
* @param compartments the cell compartments to measure
* @param measurements requested measurements to make
*/
private static void measureCells(ImageProcessor ipNuclei, ImageProcessor ipCells, Map<? extends Number, ? extends PathObject> pathObjects, Map<String, ImageProcessor> channels, Collection<Compartments> compartments, Collection<Measurements> measurements) {
var array = mapToArray(pathObjects);
// PathObjectTools.constrainCellByScaledNucleus(cell, nucleusScaleFactor, keepMeasurements)
int width = ipNuclei.getWidth();
int height = ipNuclei.getHeight();
ImageProcessor ipMembrane = new FloatProcessor(width, height);
ImageProcessor ipCytoplasm = ipCells.duplicate();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float cell = ipCells.getf(x, y);
float nuc = ipNuclei.getf(x, y);
if (nuc != 0f)
ipCytoplasm.setf(x, y, 0f);
if (cell == 0f)
continue;
// Check 4-neighbours to decide if we're at the membrane
if ((y >= 1 && ipCells.getf(x, y - 1) != cell) || (y < height - 1 && ipCells.getf(x, y + 1) != cell) || (x >= 1 && ipCells.getf(x - 1, y) != cell) || (x < width - 1 && ipCells.getf(x + 1, y) != cell))
ipMembrane.setf(x, y, cell);
}
}
var imgNuclei = new PixelImageIJ(ipNuclei);
var imgCells = new PixelImageIJ(ipCells);
var imgCytoplasm = new PixelImageIJ(ipCytoplasm);
var imgMembrane = new PixelImageIJ(ipMembrane);
for (var entry : channels.entrySet()) {
var img = new PixelImageIJ(entry.getValue());
if (compartments.contains(Compartments.NUCLEUS))
measureObjects(img, imgNuclei, array, entry.getKey().trim() + ": " + "Nucleus", measurements);
if (compartments.contains(Compartments.CYTOPLASM))
measureObjects(img, imgCytoplasm, array, entry.getKey().trim() + ": " + "Cytoplasm", measurements);
if (compartments.contains(Compartments.MEMBRANE))
measureObjects(img, imgMembrane, array, entry.getKey().trim() + ": " + "Membrane", measurements);
if (compartments.contains(Compartments.CELL))
measureObjects(img, imgCells, array, entry.getKey().trim() + ": " + "Cell", measurements);
}
}
Aggregations