use of ij.process.FloatBlitter in project gdsc by aherbert.
the class CellOutliner_PlugIn method findCells.
@Nullable
private PolygonRoi[] findCells(ImageProcessor inputProcessor) {
// Limit processing to where it is needed
final Rectangle bounds = createBounds(inputProcessor, xpoints, ypoints, getCellRange());
ImageProcessor ip = inputProcessor.duplicate();
ip.setRoi(bounds);
ip = ip.crop();
if (kernels == null) {
kernels = createKernels();
convolved = null;
}
if (convolved == null) {
convolved = convolveImage(ip, kernels);
// showConvolvedImages(convolved)
}
if (ImageJUtils.isInterrupted()) {
return null;
}
FloatProcessor combinedIp = null;
Blitter blitter = null;
ImagePlus combinedImp = null;
if (debug) {
combinedIp = new FloatProcessor(ip.getWidth(), ip.getHeight());
blitter = new FloatBlitter(combinedIp);
combinedImp = displayImage(combinedIp, "Combined edge projection");
}
final PolygonRoi[] cells = new PolygonRoi[xpoints.length];
if (!this.buildMaskOutput) {
IJ.showStatus("Finding cells ...");
}
// Process each point
for (int n = 0; n < xpoints.length; n++) {
if (!this.buildMaskOutput) {
IJ.showProgress(n, xpoints.length);
}
final int cx = xpoints[n] - bounds.x;
final int cy = ypoints[n] - bounds.y;
// Restrict bounds using the cell radius and tolerance
final Rectangle pointBounds = createBounds(ip, cx, cy, cx, cy, getCellRange());
// Calculate the angle
final FloatProcessor angle = createAngleProcessor(cx, cy, pointBounds);
if (ImageJUtils.isInterrupted()) {
return null;
}
final FloatProcessor edgeProjection = computeEdgeProjection(convolved, pointBounds, angle);
// Initialise the edge as a circle.
PolygonRoi cell = null;
double[] params = { cx - pointBounds.x, cy - pointBounds.y, settings.cellRadius, settings.cellRadius, settings.cellRadius, 0 };
final double range = settings.cellRadius * 0.9;
// Iterate to find the best cell outline
boolean returnEllipticalFit = settings.ellipticalFit;
for (int iter = 0; iter < settings.iterations; iter++) {
// Use the current elliptical edge to define the weights for the edge projection
final FloatProcessor weights = createWeightMap(pointBounds, params, range);
if (ImageJUtils.isInterrupted() || weights == null) {
return null;
}
if (debug) {
displayImage(weights, "Weight map");
}
final FloatProcessor weightedEdgeProjection = applyWeights(edgeProjection, weights);
if (debug) {
blitter.copyBits(weightedEdgeProjection, pointBounds.x, pointBounds.y, Blitter.ADD);
combinedIp.resetMinAndMax();
combinedImp.updateAndDraw();
displayImage(weightedEdgeProjection, "Weighted edge projection");
}
cell = findPolygonalCell((int) Math.round(params[0]), (int) Math.round(params[1]), weightedEdgeProjection, angle);
// weights
final FloatProcessor weightMap = weightedEdgeProjection;
final double[] newParams = fitPolygonalCell(cell, params, weightMap);
if (newParams == null) {
returnEllipticalFit = false;
break;
}
// Set the parameters for the weight map
params = newParams;
}
assert cell != null : "No cell";
// Return either the fitted elliptical cell or the last polygon outline
if (returnEllipticalFit) {
final EllipticalCell e = new EllipticalCell();
final FloatPolygon ellipse = e.drawEllipse(params);
cell = new PolygonRoi(ellipse.xpoints, ellipse.ypoints, ellipse.npoints, Roi.POLYGON);
}
PolygonRoi finalCell = cell;
if (settings.dilate > 0) {
// Dilate the cell and then trace the new outline
final ByteProcessor bp = new ByteProcessor(pointBounds.width, pointBounds.height);
bp.setColor(CELL & 0xff);
bp.draw(cell);
for (int i = 0; i < settings.dilate; i++) {
dilate(bp);
}
cell = traceOutline(bp);
if (cell != null) {
finalCell = cell;
}
}
final Rectangle pos = finalCell.getBounds();
// Does not work in IJ 1.46+
// finalCell.setLocation(pos.x + bounds.x + pointBounds.x, pos.y + bounds.y + pointBounds.y)
// Create a new Polygon with the correct coordinates. This is required since IJ 1.46
// since setting the location is not passed through when drawing an overlay
final int[] xCoords = finalCell.getXCoordinates();
final int[] yCoords = finalCell.getYCoordinates();
final int npoints = finalCell.getNCoordinates();
for (int i = 0; i < npoints; i++) {
xCoords[i] += pos.x + bounds.x + pointBounds.x;
yCoords[i] += pos.y + bounds.y + pointBounds.y;
}
finalCell = new PolygonRoi(xCoords, yCoords, npoints, Roi.POLYGON);
cells[n] = finalCell;
}
return cells;
}
Aggregations