Skip to content

Commit

Permalink
Slice Geometry: Handle ROIs (or lack of them) more gracefully (#346)
Browse files Browse the repository at this point in the history
Seems like there has been a regression or change of behaviour in
IJ, around ROIs and getting bounds.

This code change makes ROI handling more explicit and uses only
ImagePlus methods (not ImageProcessor or ImageStack).

Fixes #345
  • Loading branch information
mdoube authored May 14, 2024
1 parent af1af29 commit b9da758
Showing 1 changed file with 74 additions and 29 deletions.
103 changes: 74 additions & 29 deletions Legacy/bonej/src/main/java/org/bonej/plugins/SliceGeometry.java
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,16 @@ private double calculateCentroids(final ImagePlus imp, final double min,
final double max)
{
final ImageStack stack = imp.getImageStack();
final Rectangle r = stack.getRoi();
int rx = 0; int ry = 0; int rwidth = 0; int rheight = 0;
if (imp.getRoi() == null) {
rwidth = imp.getWidth();
rheight = imp.getHeight();
} else {
rx = imp.getRoi().getBounds().x;
ry = imp.getRoi().getBounds().y;
rwidth = imp.getRoi().getBounds().width;
rheight = imp.getRoi().getBounds().height;
}
// 2D centroids
sliceCentroids = new double[2][al];
// pixel counters
Expand All @@ -473,8 +482,8 @@ private double calculateCentroids(final ImagePlus imp, final double min,
meanDensity = new double[al];
weightedCentroids = new double[2][al];
final double pixelArea = vW * vH;
final int roiXEnd = r.x + r.width;
final int roiYEnd = r.y + r.height;
final int roiXEnd = rx + rwidth;
final int roiYEnd = ry + rheight;
for (int s = startSlice; s <= endSlice; s++) {
IJ.showStatus("Calculating centroids...");
IJ.showProgress(s - startSlice, endSlice);
Expand All @@ -486,8 +495,8 @@ private double calculateCentroids(final ImagePlus imp, final double min,
double wSumX = 0;
double wSumY = 0;
final ImageProcessor ip = stack.getProcessor(s);
for (int y = r.y; y < roiYEnd; y++) {
for (int x = r.x; x < roiXEnd; x++) {
for (int y = ry; y < roiYEnd; y++) {
for (int x = rx; x < roiXEnd; x++) {
final double pixel = ip.get(x, y);
if (pixel >= min && pixel <= max) {
count++;
Expand Down Expand Up @@ -533,7 +542,16 @@ private void calculateMoments(final ImagePlus imp, final double min,
final double max)
{
final ImageStack stack = imp.getImageStack();
final Rectangle r = stack.getRoi();
int rx = 0; int ry = 0; int rwidth = 0; int rheight = 0;
if (imp.getRoi() == null) {
rwidth = imp.getWidth();
rheight = imp.getHeight();
} else {
rx = imp.getRoi().getBounds().x;
ry = imp.getRoi().getBounds().y;
rwidth = imp.getRoi().getBounds().width;
rheight = imp.getRoi().getBounds().height;
}
theta = new double[al];
for (int s = startSlice; s <= endSlice; s++) {
IJ.showStatus("Calculating Ix and Iy...");
Expand All @@ -543,16 +561,16 @@ private void calculateMoments(final ImagePlus imp, final double min,
double sxxs = 0;
double syys = 0;
double sxys = 0;
final int roiXEnd = r.x + r.width;
final int roiYEnd = r.y + r.height;
final int roiXEnd = rx + rwidth;
final int roiYEnd = ry + rheight;
if (emptySlices[s]) {
theta[s] = Double.NaN;
continue;
}
final ImageProcessor ip = stack.getProcessor(s);
double sumAreaFractions = 0;
for (int y = r.y; y < roiYEnd; y++) {
for (int x = r.x; x < roiXEnd; x++) {
for (int y = ry; y < roiYEnd; y++) {
for (int x = rx; x < roiXEnd; x++) {
final double pixel = ip.get(x, y);
if (pixel >= min && pixel <= max) {
final double xVw = x * vW;
Expand Down Expand Up @@ -615,7 +633,16 @@ private double[][] calculateAngleMoments(final ImagePlus imp,
final double min, final double max, final double[] angles)
{
final ImageStack stack = imp.getImageStack();
final Rectangle r = stack.getRoi();
int rx = 0; int ry = 0; int rwidth = 0; int rheight = 0;
if (imp.getRoi() == null) {
rwidth = imp.getWidth();
rheight = imp.getHeight();
} else {
rx = imp.getRoi().getBounds().x;
ry = imp.getRoi().getBounds().y;
rwidth = imp.getRoi().getBounds().width;
rheight = imp.getRoi().getBounds().height;
}
final double[] I1 = new double[al];
final double[] I2 = new double[al];
final double[] Ip = new double[al];
Expand Down Expand Up @@ -654,15 +681,15 @@ private double[][] calculateAngleMoments(final ImagePlus imp,
double maxRadCentreS = 0;
final double cosTheta = Math.cos(angles[s]);
final double sinTheta = Math.sin(angles[s]);
final int roiYEnd = r.y + r.height;
final int roiXEnd = r.x + r.width;
final int roiYEnd = ry + rheight;
final int roiXEnd = rx + rwidth;
final double xC = sliceCentroids[0][s];
final double yC = sliceCentroids[1][s];
final double cS = cslice[s];
double sumAreaFractions = 0;
for (int y = r.y; y < roiYEnd; y++) {
for (int y = ry; y < roiYEnd; y++) {
final double yYc = y * vH - yC;
for (int x = r.x; x < roiXEnd; x++) {
for (int x = rx; x < roiXEnd; x++) {
final double pixel = ip.get(x, y);
if (pixel >= min && pixel <= max) {
final double areaFraction = doPartialVolume ? filledFraction(
Expand Down Expand Up @@ -749,7 +776,16 @@ private void calculateThickness3D(final ImagePlus imp, final double min,
maxCortThick3D = new double[al];
meanCortThick3D = new double[al];
stdevCortThick3D = new double[al];
final Rectangle r = imp.getProcessor().getRoi();
int rx = 0; int ry = 0; int rwidth = 0; int rheight = 0;
if (imp.getRoi() == null) {
rwidth = imp.getWidth();
rheight = imp.getHeight();
} else {
rx = imp.getRoi().getBounds().x;
ry = imp.getRoi().getBounds().y;
rwidth = imp.getRoi().getBounds().width;
rheight = imp.getRoi().getBounds().height;
}

// convert to binary
final ImagePlus binaryImp = convertToBinary(imp, min, max);
Expand All @@ -768,10 +804,10 @@ private void calculateThickness3D(final ImagePlus imp, final double min,
double sumPix = 0;
double sliceMax = 0;
double pixCount = 0;
final int roiXEnd = r.x + r.width;
final int roiYEnd = r.y + r.height;
for (int y = r.y; y < roiYEnd; y++) {
for (int x = r.x; x < roiXEnd; x++) {
final int roiXEnd = rx + rwidth;
final int roiYEnd = ry + rheight;
for (int y = ry; y < roiYEnd; y++) {
for (int x = rx; x < roiXEnd; x++) {
final float pixel = Float.intBitsToFloat(ip.get(x, y));
if (pixel > 0) {
pixCount++;
Expand All @@ -785,8 +821,8 @@ private void calculateThickness3D(final ImagePlus imp, final double min,
maxCortThick3D[s] = sliceMax;

double sumSquares = 0;
for (int y = r.y; y < roiYEnd; y++) {
for (int x = r.x; x < roiXEnd; x++) {
for (int y = ry; y < roiYEnd; y++) {
for (int x = rx; x < roiXEnd; x++) {
final float pixel = Float.intBitsToFloat(ip.get(x, y));
if (pixel > 0) {
final double d = sliceMean - pixel;
Expand Down Expand Up @@ -1035,7 +1071,16 @@ public void run() {
}
final ImageProcessor ip = impT.getImageStack().getProcessor(s);
final ImagePlus sliceImp = new ImagePlus(" " + s, ip);
final Rectangle r = ip.getRoi();
int rx = 0; int ry = 0; int rwidth = 0; int rheight = 0;
if (sliceImp.getRoi() == null) {
rwidth = sliceImp.getWidth();
rheight = sliceImp.getHeight();
} else {
rx = sliceImp.getRoi().getBounds().x;
ry = sliceImp.getRoi().getBounds().y;
rwidth = sliceImp.getRoi().getBounds().width;
rheight = sliceImp.getRoi().getBounds().height;
}
// binarise
final ImagePlus binaryImp = convertToBinary(sliceImp, min, max);
final Calibration cal = impT.getCalibration();
Expand All @@ -1047,10 +1092,10 @@ public void run() {
double sumPix = 0;
double sliceMax = 0;
double pixCount = 0;
final double roiXEnd = r.x + r.width;
final double roiYEnd = r.y + r.height;
for (int y = r.y; y < roiYEnd; y++) {
for (int x = r.x; x < roiXEnd; x++) {
final double roiXEnd = rx + rwidth;
final double roiYEnd = ry + rheight;
for (int y = ry; y < roiYEnd; y++) {
for (int x = rx; x < roiXEnd; x++) {
final float pixel = Float.intBitsToFloat(thickIp.get(x, y));
if (pixel > 0) {
pixCount++;
Expand All @@ -1064,8 +1109,8 @@ public void run() {
maxThick[s] = sliceMax;

double sumSquares = 0;
for (int y = r.y; y < roiYEnd; y++) {
for (int x = r.x; x < roiXEnd; x++) {
for (int y = ry; y < roiYEnd; y++) {
for (int x = rx; x < roiXEnd; x++) {
final float pixel = Float.intBitsToFloat(thickIp.get(x, y));
if (pixel > 0) {
final double d = sliceMean - pixel;
Expand Down

0 comments on commit b9da758

Please sign in to comment.