From 6158f068236e65f2cb813b35567cafde2143c536 Mon Sep 17 00:00:00 2001 From: Thomas MUSSET <thomas.musset@pasteur.fr> Date: Wed, 5 Apr 2023 18:06:58 +0200 Subject: [PATCH] update pom parent, add .DS_Store in gitignore, update some classes --- .gitignore | 3 +- pom.xml | 53 +- .../ConnectedComponent.java | 288 +++----- .../ConnectedComponentDescriptor.java | 329 ++++----- .../ConnectedComponents$1.class | Bin 1797 -> 0 bytes .../ConnectedComponents$2.class | Bin 3054 -> 0 bytes .../ConnectedComponents$ExtractionType.class | Bin 1520 -> 0 bytes .../ConnectedComponents$Label.class | Bin 1399 -> 0 bytes .../ConnectedComponents$Sorting$1.class | Bin 1261 -> 0 bytes .../ConnectedComponents$Sorting$2.class | Bin 1261 -> 0 bytes .../ConnectedComponents$Sorting.class | Bin 1959 -> 0 bytes .../ConnectedComponents.java | 637 +++++++----------- 12 files changed, 480 insertions(+), 830 deletions(-) delete mode 100644 src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$1.class delete mode 100644 src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$2.class delete mode 100644 src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$ExtractionType.class delete mode 100644 src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Label.class delete mode 100644 src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting$1.class delete mode 100644 src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting$2.class delete mode 100644 src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting.class diff --git a/.gitignore b/.gitignore index 5abffee..b2f15ce 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ bin/ *.jar .classpath .project -export.jardesc \ No newline at end of file +export.jardesc +**/.DS_Store \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1ebb6b9..07534cb 100644 --- a/pom.xml +++ b/pom.xml @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> - <artifactId>pom-icy</artifactId> <groupId>org.bioimageanalysis.icy</groupId> - <version>2.0.0</version> + <artifactId>pom-icy</artifactId> + <version>2.2.0</version> </parent> <artifactId>connected-components</artifactId> - <version>4.8.8</version> + <version>4.8.9</version> <packaging>jar</packaging> @@ -22,55 +22,36 @@ Output can be pushed to the swimming pool for other plug-ins to further exploit the extracted objects. </description> - <profiles> - <profile> - <id>icy-plugin</id> - <activation> - <activeByDefault>true</activeByDefault> - </activation> - </profile> - </profiles> - <dependencies> - <dependency> - <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>icy-kernel</artifactId> - <version>${icy-kernel.version}</version> - </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>blocks</artifactId> - <version>${blocks.version}</version> + <artifactId>ezplug</artifactId> </dependency> - <dependency> + <dependency> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>icy-bioformats</artifactId> - <version>${icy-bioformats.version}</version> + <artifactId>protocols</artifactId> </dependency> - <dependency> + + <dependency> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>jama</artifactId> - <version>${jama.version}</version> - </dependency> - <dependency> - <groupId>net.sourceforge.jexcelapi</groupId> - <artifactId>jxl</artifactId> - <version>${jxl.version}</version> + <artifactId>vecmath</artifactId> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>spot-detection-utilities</artifactId> - <version>${spot-detection-utilities.version}</version> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> <artifactId>quickhull</artifactId> - <version>${quickhull.version}</version> </dependency> <dependency> <groupId>org.bioimageanalysis.icy</groupId> - <artifactId>vecmath</artifactId> - <version>${vecmath.version}</version> + <artifactId>jama</artifactId> + </dependency> + + <dependency> + <groupId>net.sourceforge.jexcelapi</groupId> + <artifactId>jxl</artifactId> </dependency> </dependencies> diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java index 0b20a5b..fe242f9 100644 --- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java +++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponent.java @@ -19,8 +19,7 @@ import plugins.kernel.roi.roi2d.ROI2DArea; import plugins.kernel.roi.roi3d.ROI3DArea; import plugins.nchenouard.spot.Detection; -public class ConnectedComponent extends Detection implements Iterable<Point3i> -{ +public class ConnectedComponent extends Detection implements Iterable<Point3i> { private int c = -1; /** @@ -60,18 +59,16 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Creates a new connected component with given initial capacity - * + * * @param initialCapacity int */ - public ConnectedComponent(int initialCapacity) - { + public ConnectedComponent(int initialCapacity) { super(0, 0, 0, 0); - this.points = new ArrayList<Point3i>(initialCapacity); + this.points = new ArrayList<>(initialCapacity); coordsSum = new Point3d(); } - void addPointInternal(Point3i point) - { + void addPointInternal(Point3i point) { points.add(point); // accumulate coordinates to compute the mass center @@ -84,12 +81,10 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Adds a point to this component and updates the mass center - * - * @param point - * the point to add + * + * @param point the point to add */ - public void addPoint(Point3i point) - { + public void addPoint(Point3i point) { addPointInternal(point); updateDetectionCoords(); } @@ -97,12 +92,10 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Adds a point to this component. This method also accumulates coordinates to optimize the mass * center computation - * - * @param point - * the point to add + * + * @param point the point to add */ - void removePointInternal(Point3i point) - { + void removePointInternal(Point3i point) { if (!points.remove(point)) return; @@ -114,8 +107,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> coordsDirty = true; } - public void removeAllPoints() - { + public void removeAllPoints() { points.clear(); coordsSum.set(0, 0, 0); x = 0; @@ -126,69 +118,60 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * @return true is the object touches the image edge along X */ - public boolean isOnEdgeX() - { + public boolean isOnEdgeX() { return onEdgeX; } /** * @return true is the object touches the image edge along Y */ - public boolean isOnEdgeY() - { + public boolean isOnEdgeY() { return onEdgeY; } /** * @return true is the object touches the image edge along Z (always true for 2D images) */ - public boolean isOnEdgeZ() - { + public boolean isOnEdgeZ() { return onEdgeZ; } /** * Computes the bounding box of this component, and stores the result into the given arguments - * - * @param start - * the first corner of the bounding box in X-Y-Z order (Upper-Left hand-Top) - * @param end - * the second corner of the bounding box in X-Y-Z order (Lower-Right hand-Bottom) - * @deprecated Use - * {@link ConnectedComponentDescriptor#computeBoundingBox(ConnectedComponent, Point3i, Point3i)} - * instead - */ - public void computeBoundingBox(Point3i start, Point3i end) - { + * + * @param start the first corner of the bounding box in X-Y-Z order (Upper-Left hand-Top) + * @param end the second corner of the bounding box in X-Y-Z order (Lower-Right hand-Bottom) + * @deprecated Use {@link ConnectedComponentDescriptor#computeBoundingBox(ConnectedComponent, Point3i, Point3i)} + * instead + */ + @Deprecated + public void computeBoundingBox(Point3i start, Point3i end) { shapeDescriptor.computeBoundingBox(this, start, end); } /** * Computes the average intensity of the component on each channel of the given sequence, at the * time point where this component was found - * + * * @param sequence Sequence * @return an array containing the average intensity of the component in each band */ - public double[] computeMeanIntensity(Sequence sequence) - { + public double[] computeMeanIntensity(Sequence sequence) { return computeMeanIntensity(sequence, t); } /** * Computes the average intensity of the component on each channel of the given sequence and the * specified time point - * + * * @param sequence Sequence - * @param t int + * @param t int * @return an array containing the average intensity of the component in each band */ - public double[] computeMeanIntensity(Sequence sequence, int t) - { + public double[] computeMeanIntensity(Sequence sequence, int t) { double[] intensitySum = new double[sequence.getSizeC()]; - for (Point3i point : points) - { + for (Point3i point : points) { int offsetXY = point.x + point.y * sequence.getSizeX(); Object dataCXY = sequence.getDataXYC(t, point.z); @@ -206,36 +189,32 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Computes the minimum intensity of the component on each channel of the given sequence, at the * time point where this component was found - * + * * @param sequence Sequence * @return an array containing the average intensity of the component in each band */ - public double[] computeMinIntensity(Sequence sequence) - { + public double[] computeMinIntensity(Sequence sequence) { return computeMinIntensity(sequence, t); } /** * Computes the minimum intensity of the component on each channel of the given sequence and the * specified time point - * + * * @param sequence Sequence - * @param t int + * @param t int * @return an array containing the average intensity of the component in each band */ - public double[] computeMinIntensity(Sequence sequence, int t) - { + public double[] computeMinIntensity(Sequence sequence, int t) { double[] minIntensity = new double[sequence.getSizeC()]; Arrays.fill(minIntensity, Double.MAX_VALUE); - for (Point3i point : points) - { + for (Point3i point : points) { int offsetXY = point.x + point.y * sequence.getSizeX(); Object dataCXY = sequence.getImage(t, point.z).getDataXYC(); - for (int c = 0; c < minIntensity.length; c++) - { + for (int c = 0; c < minIntensity.length; c++) { double val = Array1DUtil.getValue(((Object[]) dataCXY)[c], offsetXY, sequence.getDataType_().isSigned()); if (val < minIntensity[c]) @@ -248,12 +227,11 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Computes the maximum intensity of the component on each channel of the given sequence, at the * time point where this component was found - * + * * @param sequence Sequence * @return an array containing the average intensity of the component in each band */ - public double[] computeMaxIntensity(Sequence sequence) - { + public double[] computeMaxIntensity(Sequence sequence) { return computeMaxIntensity(sequence, t); } @@ -262,21 +240,18 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> * and the specified time point * * @param sequence Sequence - * @param t int + * @param t int * @return an array containing the average intensity of the component in each band */ - public double[] computeMaxIntensity(Sequence sequence, int t) - { + public double[] computeMaxIntensity(Sequence sequence, int t) { double[] maxIntensity = new double[sequence.getSizeC()]; - for (Point3i point : points) - { + for (Point3i point : points) { int offsetXY = point.x + point.y * sequence.getSizeX(); Object dataCXY = sequence.getImage(t, point.z).getDataXYC(); - for (int c = 0; c < maxIntensity.length; c++) - { + for (int c = 0; c < maxIntensity.length; c++) { double val = Array1DUtil.getValue(((Object[]) dataCXY)[c], offsetXY, sequence.getDataType_().isSigned()); if (val > maxIntensity[c]) @@ -289,19 +264,15 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Computes the closest euclidean distance between any two points of this component and the * given component - * - * @param component - * the component to compute the distance to + * + * @param component the component to compute the distance to * @return double */ - public double distanceTo(ConnectedComponent component) - { + public double distanceTo(ConnectedComponent component) { double distance = Double.MAX_VALUE; - for (Point3i srcPt : this) - { + for (Point3i srcPt : this) { Vector3d srcV = new Vector3d(srcPt.x, srcPt.y, srcPt.z); - for (Point3i dstPt : component) - { + for (Point3i dstPt : component) { Vector3d dstV = new Vector3d(dstPt.x, dstPt.y, dstPt.z); dstV.sub(srcV); double length = dstV.length(); @@ -315,11 +286,10 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Returns an iterator over the internal points array. Useful to browse all points without * duplicating the array - * + * * @return Point3i Iterator */ - public Iterable<Point3i> getIterablePoints() - { + public Iterable<Point3i> getIterablePoints() { return points; } @@ -328,32 +298,28 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> * points of this component. Note that the result vector orientation is meaningless if the * component is spherical.<br> * NOTE: this is an potentially expensive operation: O(N log N) - * + * * @return 3D Vector */ - public Vector3d getMajorAxis() - { + public Vector3d getMajorAxis() { double maxDist = 0; Vector3d vector = new Vector3d(); Point3d pid = new Point3d(), pjd = new Point3d(); int n = points.size(); - for (int i = 0; i < n - 1; i++) - { + for (int i = 0; i < n - 1; i++) { Point3i pi = points.get(i); pid.set(pi.x, pi.y, pi.z); - for (int j = i + 1; j < n; j++) - { + for (int j = i + 1; j < n; j++) { Point3i pj = points.get(j); pjd.set(pj.x, pj.y, pj.z); // compare the squared distance to save the square root operation double dist = pid.distanceSquared(pjd); - if (dist > maxDist) - { + if (dist > maxDist) { maxDist = dist; vector.sub(pjd, pid); } @@ -363,8 +329,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> return vector; } - void updateDetectionCoords() - { + void updateDetectionCoords() { double factor = 1.0 / getSize(); x = coordsSum.x * factor; y = coordsSum.y * factor; @@ -372,30 +337,26 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> coordsDirty = false; } - public int getC() - { + public int getC() { return c; } @Override - public double getX() - { + public double getX() { if (coordsDirty) updateDetectionCoords(); return x; } @Override - public double getY() - { + public double getY() { if (coordsDirty) updateDetectionCoords(); return y; } @Override - public double getZ() - { + public double getZ() { if (coordsDirty) updateDetectionCoords(); return z; @@ -403,11 +364,10 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Computes the mass center of this component - * + * * @return 3D Point */ - public Point3d getMassCenter() - { + public Point3d getMassCenter() { if (coordsDirty) updateDetectionCoords(); return new Point3d(x, y, z); @@ -418,16 +378,14 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Returns the maximum distance between any point of this component and the specified point - * + * * @param point 3D Point * @return double */ - public double getMaxDistanceTo(Point3d point) - { + public double getMaxDistanceTo(Point3d point) { double maxDist = 0; - for (Point3i p : this) - { + for (Point3i p : this) { double dist = point.distance(new Point3d(p.x, p.y, p.z)); if (dist > maxDist) maxDist = dist; @@ -438,32 +396,27 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * The size in pixels (or voxels) of this component - * + * * @return The size in pixels (or voxels) of this component */ - public int getSize() - { + public int getSize() { return points.size(); } /** * @return An array containing all the pixels of this component */ - public Point3i[] getPoints() - { + public Point3i[] getPoints() { return points.toArray(new Point3i[getSize()]); } /** - * @param outputSequence - * (set to null if not wanted) an output sequence to receive the extracted contour + * @param outputSequence (set to null if not wanted) an output sequence to receive the extracted contour * @return An array containing all the contour pixels of this component */ - public Point3i[] getContourPoints(Sequence outputSequence) - { - if (contourPoints == null) - { - ArrayList<Point3i> list = new ArrayList<Point3i>(getSize() / 2); + public Point3i[] getContourPoints(Sequence outputSequence) { + if (contourPoints == null) { + ArrayList<Point3i> list = new ArrayList<>(getSize() / 2); Point3i min = new Point3i(), max = new Point3i(); shapeDescriptor.computeBoundingBox(this, min, max); @@ -476,8 +429,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> byte[][] outputMask = null; - if (outputSequence != null) - { + if (outputSequence != null) { outputSequence.removeAllImages(); for (int i = 0; i < d; i++) outputSequence.setImage(0, i, new IcyBufferedImage(w, h, 1, DataType.UBYTE)); @@ -495,28 +447,25 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> Point3i localP = new Point3i(); - if (min.z != max.z) - { - mainLoop: for (Point3i p : points) - { + if (min.z != max.z) { + mainLoop: + for (Point3i p : points) { localP.sub(p, min); int xy = localP.y * w + localP.x; if (localP.x == 0 || localP.y == 0 || localP.x == w - 1 || localP.y == h - 1 || localP.z == 0 - || localP.z == d - 1) - { + || localP.z == d - 1) { list.add(p); if (outputMask != null) outputMask[localP.z][xy] = (byte) 1; continue; } - for (byte[] z : new byte[][] {mask_z_xy[localP.z - 1], mask_z_xy[localP.z], + for (byte[] z : new byte[][]{mask_z_xy[localP.z - 1], mask_z_xy[localP.z], mask_z_xy[localP.z + 1]}) if (z[xy - w] == 0 || z[xy - 1] == 0 || z[xy + 1] == 0 || z[xy + w] == 0 || z[xy - w - 1] == 0 - || z[xy - w + 1] == 0 || z[xy + w - 1] == 0 || z[xy + w + 1] == 0) - { + || z[xy - w + 1] == 0 || z[xy + w - 1] == 0 || z[xy + w + 1] == 0) { list.add(p); if (outputMask != null) outputMask[localP.z][xy] = (byte) 1; @@ -524,22 +473,18 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> } // the top and bottom neighbors were forgotten in the previous loop - if (mask_z_xy[localP.z - 1][xy] == 0 || mask_z_xy[localP.z + 1][xy] == 0) - { + if (mask_z_xy[localP.z - 1][xy] == 0 || mask_z_xy[localP.z + 1][xy] == 0) { list.add(p); } } } - else - { - for (Point3i p : points) - { + else { + for (Point3i p : points) { localP.sub(p, min); int xy = localP.y * w + localP.x; - if (localP.x == 0 || localP.y == 0 || localP.x == w - 1 || localP.y == h - 1) - { + if (localP.x == 0 || localP.y == 0 || localP.x == w - 1 || localP.y == h - 1) { list.add(p); if (outputMask != null) outputMask[localP.z][xy] = (byte) 1; @@ -574,21 +519,18 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * @param component ConnectedComponent * @return true if this component intersects (e.g. has at least one voxel overlapping with) the - * specified component + * specified component */ - public boolean intersects(ConnectedComponent component) - { + public boolean intersects(ConnectedComponent component) { int thisSize = getSize(); int componentSize = component.getSize(); Point3i thisPt = new Point3i(); Point3i componentPt = new Point3i(); - for (int i = 0; i < thisSize; i++) - { + for (int i = 0; i < thisSize; i++) { thisPt.set(points.get(i)); - for (int j = 0; j < componentSize; j++) - { + for (int j = 0; j < componentSize; j++) { componentPt.set(component.points.get(j)); if (thisPt.equals(componentPt)) return true; @@ -600,20 +542,17 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Creates a new component with the intersection between the current and specified components - * + * * @param component ConnectedComponent * @return ConnectedComponent */ - public ConnectedComponent intersection(ConnectedComponent component) - { + public ConnectedComponent intersection(ConnectedComponent component) { ConnectedComponent intersection = new ConnectedComponent(0); // construct the intersection for (Point3i srcPt : this) - for (Point3i dstPt : component) - { - if (srcPt.equals(dstPt)) - { + for (Point3i dstPt : component) { + if (srcPt.equals(dstPt)) { intersection.addPointInternal(srcPt); break; } @@ -623,45 +562,35 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> } @Override - public Iterator<Point3i> iterator() - { + public Iterator<Point3i> iterator() { return points.iterator(); } /** * Paints this component onto the given sequence with the specified value - * - * @param s - * Sequence - * @param t - * int - * @param c - * int - * @param value - * double - * @throws InterruptedException - */ - public void paintOnSequence(Sequence s, int t, int c, double value) throws InterruptedException - { + * + * @param s Sequence + * @param t int + * @param c int + * @param value double + */ + public void paintOnSequence(Sequence s, int t, int c, double value) throws InterruptedException { DataIteratorUtil.set(new SequenceDataIterator(s, toROI(), true, -1, t, c), value); } - public void setC(int c) - { + public void setC(int c) { this.c = c; } /** * @return a region of interest of type area representing this connected component */ - public ROI toROI() - { + public ROI toROI() { int z = 0; ROI3DArea area3D = new ROI3DArea(); area3D.beginUpdate(); - for (Point3i pt : this) - { + for (Point3i pt : this) { z = pt.z; area3D.addPoint(pt.x, pt.y, pt.z); } @@ -681,11 +610,10 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> /** * Creates a new byte sequence filled with this component. The sequence has a unique time point, * and the image size is equal to the bounding box of this component. - * + * * @return Sequence */ - public Sequence toSequence() - { + public Sequence toSequence() { Sequence seq = new Sequence(); // get the bounding box first @@ -706,16 +634,13 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> // force non volatile boolean v = seq.isVolatile(); seq.setVolatile(false); - try - { + try { // fill up the created sequence byte[][] z_xy = seq.getDataXYZAsByte(0, 0); for (Point3i point : points) z_xy[point.z - start.z][(point.y - start.y) * width + (point.x - start.x)] = (byte) 1; - } - finally - { + } finally { // restore volatile state seq.setVolatile(v); } @@ -724,8 +649,7 @@ public class ConnectedComponent extends Detection implements Iterable<Point3i> } @Override - public String toString() - { + public String toString() { return "[" + getX() + ", " + getY() + ", " + getZ() + "], " + getSize() + " points"; } } diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java index dd037cb..21b6d2a 100644 --- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java +++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponentDescriptor.java @@ -25,9 +25,8 @@ import plugins.adufour.quickhull.QuickHull3D; import plugins.adufour.vars.lang.Var; import plugins.adufour.vars.lang.VarDouble; -public class ConnectedComponentDescriptor extends Plugin implements PluginBundled, Block -{ - Var<ConnectedComponent> varCC = new Var<ConnectedComponent>("Connected component", ConnectedComponent.class); +public class ConnectedComponentDescriptor extends Plugin implements PluginBundled, Block { + Var<ConnectedComponent> varCC = new Var<>("Connected component", ConnectedComponent.class); VarDouble perimeter = new VarDouble("perimeter", 0.0); @@ -42,20 +41,17 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle VarDouble shortAxisZ = new VarDouble("short diameter (Z)", 0.0); @Override - public String getMainPluginClassName() - { + public String getMainPluginClassName() { return ConnectedComponents.class.getName(); } @Override - public void declareInput(VarList inputMap) - { + public void declareInput(VarList inputMap) { inputMap.add("component", varCC); } @Override - public void declareOutput(VarList outputMap) - { + public void declareOutput(VarList outputMap) { outputMap.add("perimeter", perimeter); outputMap.add("long diameter", longAxis); outputMap.add("short diameter", shortAxis); @@ -65,8 +61,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle } @Override - public void run() - { + public void run() { ConnectedComponent cc = varCC.getValue(); if (cc == null) @@ -85,32 +80,26 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle /** * @param cc ConnectedComponent - * @return a triplet representing the radiuses of the best fitting ellipse (the third value is 0 - * for 2D objects) + * @return a triplet representing the radius of the best fitting ellipse (the third value is 0 + * for 2D objects) */ - public double[] computeEllipseDimensions(ConnectedComponent cc) - { + public double[] computeEllipseDimensions(ConnectedComponent cc) { double[] axes = new double[3]; - try - { - if (is2D(cc)) - { + try { + if (is2D(cc)) { Point2d radii = new Point2d(); computeEllipse(cc, null, radii, null, null); - if (radii.x > radii.y) - { + if (radii.x > radii.y) { axes[0] = radii.x; axes[1] = radii.y; } - else - { + else { axes[0] = radii.y; axes[1] = radii.x; } } - else - { + else { Point3d radii = new Point3d(); computeEllipse(cc, null, radii, null, null); axes[0] = radii.x; @@ -118,8 +107,8 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle axes[2] = radii.z; } } - catch (Exception e) - { + catch (Exception e) { + // Do nothing } return axes; @@ -127,40 +116,31 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle /** * Computes the bounding box of this component, and stores the result into the given arguments - * - * @param cc - * the input component - * @param minBounds - * the first corner of the bounding box in X-Y-Z order (Upper-Left hand-Top) - * @param maxBounds - * the second corner of the bounding box in X-Y-Z order (Lower-Right hand-Bottom) + * + * @param cc the input component + * @param minBounds the first corner of the bounding box in X-Y-Z order (Upper-Left hand-Top) + * @param maxBounds the second corner of the bounding box in X-Y-Z order (Lower-Right hand-Bottom) */ - public void computeBoundingBox(ConnectedComponent cc, Point3i minBounds, Point3i maxBounds) - { - if (minBounds != null) - { + public void computeBoundingBox(ConnectedComponent cc, Point3i minBounds, Point3i maxBounds) { + if (minBounds != null) { minBounds.x = Integer.MAX_VALUE; minBounds.y = Integer.MAX_VALUE; minBounds.z = Integer.MAX_VALUE; } - if (maxBounds != null) - { + if (maxBounds != null) { maxBounds.x = 0; maxBounds.y = 0; maxBounds.z = 0; } - for (Point3i point : cc) - { - if (minBounds != null) - { + for (Point3i point : cc) { + if (minBounds != null) { minBounds.x = Math.min(minBounds.x, point.x); minBounds.y = Math.min(minBounds.y, point.y); minBounds.z = Math.min(minBounds.z, point.z); } - if (maxBounds != null) - { + if (maxBounds != null) { maxBounds.x = Math.max(maxBounds.x, point.x); maxBounds.y = Math.max(maxBounds.y, point.y); maxBounds.z = Math.max(maxBounds.z, point.z); @@ -170,32 +150,25 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle /** * Computes the bounding box of this component, and stores the result into the given arguments - * - * @param cc - * the input component - * @param bsCenter - * the computed center of the bounding sphere - * @param bsRadius - * the computed radius of the bounding sphere + * + * @param cc the input component + * @param bsCenter the computed center of the bounding sphere + * @param bsRadius the computed radius of the bounding sphere */ - public void computeBoundingSphere(ConnectedComponent cc, Point3d bsCenter, VarDouble bsRadius) - { + public void computeBoundingSphere(ConnectedComponent cc, Point3d bsCenter, VarDouble bsRadius) { bsCenter.set(cc.getMassCenter()); bsRadius.setValue(cc.getMaxDistanceTo(bsCenter)); } /** - * @param cc ConnectedComponent - * @param contourPoints - * (set to <code>null</code> if not wanted) an output list of extracted contour - * points - * @param outputSequence - * (set to <code>null</code> if not wanted) an output sequence to receive the - * extracted contour + * @param cc ConnectedComponent + * @param contourPoints (set to <code>null</code> if not wanted) an output list of extracted contour + * points + * @param outputSequence (set to <code>null</code> if not wanted) an output sequence to receive the + * extracted contour * @return The 3D perimeter (or 3D surface) of this component */ - public double computePerimeter(ConnectedComponent cc, ArrayList<Point3i> contourPoints, Sequence outputSequence) - { + public double computePerimeter(ConnectedComponent cc, ArrayList<Point3i> contourPoints, Sequence outputSequence) { double perimeter = 0; if (contourPoints != null) @@ -212,8 +185,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle byte[][] outputMask = null; - if (outputSequence != null) - { + if (outputSequence != null) { outputSequence.removeAllImages(); for (int i = 0; i < d; i++) outputSequence.setImage(0, i, new IcyBufferedImage(w, h, 1, DataType.UBYTE)); @@ -234,8 +206,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle // count the edges and corners in 2D/3D double a = 0, b = 0; - for (Point3i p : cc) - { + for (Point3i p : cc) { localP.sub(p, min); int xy = localP.y * w + localP.x; @@ -252,16 +223,14 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle nbEdges++; if (localP.y == h - 1 || z[xy + w] == 0) nbEdges++; - if (min.z != max.z) - { // 3D + if (min.z != max.z) { // 3D if (localP.z == 0 || mask_z_xy[localP.z - 1][xy] == 0) nbEdges++; if (localP.z == d - 1 || mask_z_xy[localP.z + 1][xy] == 0) nbEdges++; } - switch (nbEdges) - { + switch (nbEdges) { case 0: break; case 1: @@ -280,8 +249,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle perimeter += Math.sqrt(3); } - if (nbEdges > 0) - { + if (nbEdges > 0) { if (contourPoints != null) contourPoints.add(p); if (outputMask != null) @@ -305,13 +273,11 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle * NOTE: the circularity index is adjusted to work with digitized contours, and partially * corrects for digitization artifacts (see the * {@link #computePerimeter(ConnectedComponent, ArrayList, Sequence)} method) - * - * @param cc - * the input component + * + * @param cc the input component * @return 1 for a perfect circle (or sphere), and lower than 1 otherwise */ - public double computeSphericity(ConnectedComponent cc) - { + public double computeSphericity(ConnectedComponent cc) { double dim = is2D(cc) ? 2.0 : 3.0; double area = cc.getSize(); @@ -342,38 +308,30 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle * Computes the eccentricity of the given component. This method fits an ellipse with radii a * and b (in 2D) or an ellipsoid with radii a, b and c (in 3D) and returns in both cases the * ratio b/a - * - * @param cc - * the input component + * + * @param cc the input component * @return the ratio b/a, where a and b are the two first largest ellipse radii (there are only - * two in 2D) + * two in 2D) */ - public double computeEccentricity(ConnectedComponent cc) - { - if (is2D(cc)) - { - try - { + public double computeEccentricity(ConnectedComponent cc) { + if (is2D(cc)) { + try { Point2d radii = new Point2d(); computeEllipse(cc, null, radii, null, null); return radii.x / radii.y; } - catch (RuntimeException e) - { + catch (RuntimeException e) { // error during the ellipse computation return Double.NaN; } } - else - { + else { Point3d radii = new Point3d(); - try - { + try { computeEllipse(cc, null, radii, null, null); return radii.x / radii.y; } - catch (Exception e) - { + catch (Exception e) { return Double.NaN; } } @@ -382,10 +340,9 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle /** * @param cc ConnectedComponent * @return The hull ratio, measured as the ratio between the object volume and its convex hull - * (envelope) + * (envelope) */ - public double computeHullRatio(ConnectedComponent cc) - { + public double computeHullRatio(ConnectedComponent cc) { double hull = computeConvexAreaAndVolume(cc)[1]; return hull == 0.0 ? 0.0 : Math.min(1.0, cc.getSize() / hull); @@ -394,21 +351,19 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle /** * @param cc ConnectedComponent * @return An array containing [contour, area] of the smallest convex envelope surrounding the - * object. The 2 values are returned together because their computation is simultaneous - * (in the 3D case only) + * object. The 2 values are returned together because their computation is simultaneous + * (in the 3D case only) */ - public double[] computeConvexAreaAndVolume(ConnectedComponent cc) - { + public double[] computeConvexAreaAndVolume(ConnectedComponent cc) { int i = 0, n = cc.getSize(); if (n == 1) - return new double[] {0.0, 1.0}; + return new double[]{0.0, 1.0}; double contour = 0.0; double area = 0.0; - if (is2D(cc)) - { - List<Point2D> points = new ArrayList<Point2D>(); + if (is2D(cc)) { + List<Point2D> points = new ArrayList<>(); for (Point3i p : cc) points.add(new Point2D.Double(p.x, p.y)); @@ -419,10 +374,9 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle // volume = sum( sqrt[ (x[i] - x[i-1])^2 + (y[i] - y[i-1])^2 ] ) // area = 0.5 * sum( (x[i-1] * y[i]) - (y[i-1] * x[i]) ) - Point2D p1 = points.get(points.size() - 1), p2 = null; + Point2D p1 = points.get(points.size() - 1), p2; - for (i = 0; i < points.size(); i++) - { + for (i = 0; i < points.size(); i++) { p2 = points.get(i); contour += p1.distance(p2); area += (p2.getX() * p1.getY()) - (p2.getY() * p1.getX()); @@ -432,8 +386,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle area *= 0.5; } else - try - { + try { Point3d[] points = new Point3d[n]; for (Point3i p : cc) @@ -447,8 +400,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle Vector3d v13 = new Vector3d(); Vector3d cross = new Vector3d(); - for (int[] face : hullFaces) - { + for (int[] face : hullFaces) { Point3d p1 = hullPoints[face[0]]; Point3d p2 = hullPoints[face[1]]; Point3d p3 = hullPoints[face[2]]; @@ -463,41 +415,33 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle area += contour * cross.x * (p1.x + p2.x + p3.x); } } - catch (IllegalArgumentException e) - { + catch (IllegalArgumentException e) { // less than 4 points, or coplanarity detected - return new double[] {n, n}; + return new double[]{n, n}; } - return new double[] {contour, area}; + return new double[]{contour, area}; } /** * Computes the geometric moment of the given component - * - * @param cc - * the input component - * @param p - * the moment order along X - * @param q - * the moment order along Y - * @param r - * the moment order along Z (set to 0 if the object is 2D) + * + * @param cc the input component + * @param p the moment order along X + * @param q the moment order along Y + * @param r the moment order along Z (set to 0 if the object is 2D) * @return the geometric moment */ - public double computeGeometricMoment(ConnectedComponent cc, int p, int q, int r) - { + public double computeGeometricMoment(ConnectedComponent cc, int p, int q, int r) { double moment = 0; Point3d center = cc.getMassCenter(); - if (is2D(cc)) - { + if (is2D(cc)) { for (Point3i point : cc) moment += Math.pow(point.x - center.x, p) * Math.pow(point.y - center.y, q); } - else - { + else { for (Point3i point : cc) moment += Math.pow(point.x - center.x, p) * Math.pow(point.y - center.y, q) * Math.pow(point.z - center.z, r); @@ -508,38 +452,28 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle /** * Compute the best fitting ellipsoid for the given component.<br> * This method is adapted from Yury Petrov's Matlab code and ported to Java by the BoneJ project - * - * @param cc - * the component to fit - * @param center - * (set to null if not wanted) the calculated ellipsoid center - * @param radii - * (set to null if not wanted) the calculated ellipsoid radius in each - * eigen-direction - * @param eigenVectors - * (set to null if not wanted) the calculated ellipsoid eigen-vectors - * @param equation - * (set to null if not wanted) an array of size 9 containing the calculated ellipsoid - * equation - * @throws IllegalArgumentException - * if the number of points in the component is too low (minimum is 9) - * @throws SingularMatrixException - * if the component is flat (i.e. lies in a 2D plane) + * + * @param cc the component to fit + * @param center (set to null if not wanted) the calculated ellipsoid center + * @param radii (set to null if not wanted) the calculated ellipsoid radius in each + * eigen-direction + * @param eigenVectors (set to null if not wanted) the calculated ellipsoid eigen-vectors + * @param equation (set to null if not wanted) an array of size 9 containing the calculated ellipsoid + * equation + * @throws IllegalArgumentException if the number of points in the component is too low (minimum is 9) + * @throws SingularMatrixException if the component is flat (i.e. lies in a 2D plane) */ public void computeEllipse(ConnectedComponent cc, Point3d center, Point3d radii, Vector3d[] eigenVectors, - double[] equation) throws IllegalArgumentException - { + double[] equation) throws IllegalArgumentException { int nPoints = cc.getSize(); - if (nPoints < 9) - { + if (nPoints < 9) { throw new IllegalArgumentException("Too few points; need at least 9 to calculate a unique ellipsoid"); } Point3i[] points = cc.getPoints(); double[][] d = new double[nPoints][9]; - for (int i = 0; i < nPoints; i++) - { + for (int i = 0; i < nPoints; i++) { double x = points[i].x; double y = points[i].y; double z = points[i].z; @@ -558,12 +492,10 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle Matrix ones = ones(nPoints, 1); Matrix V; - try - { + try { V = D.transpose().times(D).inverse().times(D.transpose().times(ones)); } - catch (RuntimeException e) - { + catch (RuntimeException e) { throw new SingularMatrixException("The component is most probably flat (i.e. lies in a 2D plane)"); } @@ -590,8 +522,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle if (center != null) center.set(C.get(0, 0), C.get(1, 0), C.get(2, 0)); - if (eigenVectors != null && eigenVectors.length == 3) - { + if (eigenVectors != null && eigenVectors.length == 3) { eigenVectors[0] = new Vector3d(eVec.get(0, 0), eVec.get(0, 1), eVec.get(0, 2)); eigenVectors[1] = new Vector3d(eVec.get(1, 0), eVec.get(1, 1), eVec.get(1, 2)); eigenVectors[2] = new Vector3d(eVec.get(2, 0), eVec.get(2, 1), eVec.get(2, 2)); @@ -603,34 +534,26 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle /** * 2D direct ellipse fitting.<br> * (Java port of Chernov's MATLAB implementation of the direct ellipse fit) - * - * @param cc - * the component to fit - * @param center - * (set to null if not wanted) the calculated ellipse center - * @param radii - * (set to null if not wanted) the calculated ellipse radius in each eigen-direction - * @param angle - * (set to null if not wanted) the calculated ellipse orientation - * @param equation - * (set to null if not wanted) a 6-element array, {a b c d f g}, which are the - * calculated algebraic parameters of the fitting ellipse: <i>ax</i><sup>2</sup> + 2 - * <i>bxy</i> + <i>cy</i><sup>2</sup> +2<i>dx</i> + 2<i>fy</i> + <i>g</i> = 0. The - * vector <b>A</b> represented in the array is normed, so that ||<b>A</b>||=1. - * @throws RuntimeException - * if the ellipse calculation fails (e.g. if a singular matrix is detected) + * + * @param cc the component to fit + * @param center (set to null if not wanted) the calculated ellipse center + * @param radii (set to null if not wanted) the calculated ellipse radius in each eigen-direction + * @param angle (set to null if not wanted) the calculated ellipse orientation + * @param equation (set to null if not wanted) a 6-element array, {a b c d f g}, which are the + * calculated algebraic parameters of the fitting ellipse: <i>ax</i><sup>2</sup> + 2 + * <i>bxy</i> + <i>cy</i><sup>2</sup> +2<i>dx</i> + 2<i>fy</i> + <i>g</i> = 0. The + * vector <b>A</b> represented in the array is normed, so that ||<b>A</b>||=1. + * @throws RuntimeException if the ellipse calculation fails (e.g. if a singular matrix is detected) */ public void computeEllipse(ConnectedComponent cc, Point2d center, Point2d radii, VarDouble angle, double[] equation) - throws RuntimeException - { + throws RuntimeException { Point3i[] points = cc.getPoints(); Point3d ccenter = cc.getMassCenter(); double[][] d1 = new double[cc.getSize()][3]; double[][] d2 = new double[cc.getSize()][3]; - for (int i = 0; i < d1.length; i++) - { + for (int i = 0; i < d1.length; i++) { final double xixC = points[i].x - ccenter.x; final double yiyC = points[i].y - ccenter.y; @@ -672,10 +595,8 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle Matrix cond = (R1.times(4)).arrayTimes(R3).minus(R2.arrayTimes(R2)); int _f = 0; - for (int i = 0; i < 3; i++) - { - if (cond.get(0, i) > 0) - { + for (int i = 0; i < 3; i++) { + if (cond.get(0, i) > 0) { _f = i; break; } @@ -717,23 +638,27 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle // semiaxis length final double af = 2 * (a * f * f + c * d * d + g * b * b - 2 * b * d * f - a * c * g); - final double aL = Math.sqrt((af) / ((b * b - a * c) * (Math.sqrt((a - c) * (a - c) + 4 * b * b) - (a + c)))); + final double sqrt = Math.sqrt((a - c) * (a - c) + 4 * b * b); + //final double aL = Math.sqrt((af) / ((b * b - a * c) * (Math.sqrt((a - c) * (a - c) + 4 * b * b) - (a + c)))); + final double aL = Math.sqrt((af) / ((b * b - a * c) * (sqrt - (a + c)))); + //final double bL = Math.sqrt((af) / ((b * b - a * c) * (-Math.sqrt((a - c) * (a - c) + 4 * b * b) - (a + c)))); + final double bL = Math.sqrt((af) / ((b * b - a * c) * (-sqrt - (a + c)))); - final double bL = Math.sqrt((af) / ((b * b - a * c) * (-Math.sqrt((a - c) * (a - c) + 4 * b * b) - (a + c)))); double phi = 0; - if (b == 0) - { + if (b == 0) { if (a <= c) phi = 0; - else if (a > c) + else phi = Math.PI / 2; } - else - { + else { + final double atan = Math.atan(2 * b / (a - c)) / 2; if (a < c) - phi = Math.atan(2 * b / (a - c)) / 2; + //phi = Math.atan(2 * b / (a - c)) / 2; + phi = atan; else if (a > c) - phi = Math.atan(2 * b / (a - c)) / 2 + Math.PI / 2; + //phi = Math.atan(2 * b / (a - c)) / 2 + Math.PI / 2; + phi = atan + Math.PI / 2; } if (center != null) @@ -744,8 +669,7 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle angle.setValue(phi); } - public boolean is2D(ConnectedComponent cc) - { + public boolean is2D(ConnectedComponent cc) { Point3i minBB = new Point3i(); Point3i maxBB = new Point3i(); computeBoundingBox(cc, minBB, maxBB); @@ -753,19 +677,16 @@ public class ConnectedComponentDescriptor extends Plugin implements PluginBundle return minBB.z == maxBB.z; } - private Matrix diag(Matrix matrix) - { + private Matrix diag(Matrix matrix) { int min = Math.min(matrix.getRowDimension(), matrix.getColumnDimension()); double[][] diag = new double[min][1]; - for (int i = 0; i < min; i++) - { + for (int i = 0; i < min; i++) { diag[i][0] = matrix.get(i, i); } return new Matrix(diag); } - private Matrix ones(int m, int n) - { + private Matrix ones(int m, int n) { double[][] array = new double[m][n]; for (double[] row : array) Arrays.fill(row, 1.0); diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$1.class b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$1.class deleted file mode 100644 index 3a65f5464ac163f7fc4b922f0614bd1e0e738542..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1797 zcmbVM-%ry}6#nj3S2l|bl<`AAl%Zn`Dxd;xPGEv!hQ!S9z*}iAqgYy8I}H3eMq^^s zXoA!DV0iMuKgxJ+8G<kt!<MG!o}T-ibH4NA*YEE?0F2_Xi~z&rrd2MQwySDJdDSVG zRNb*{u6x|josCV$=C<dmxdUD9uP#0!Lt==oYg?LXX?9UvTv?}kGC~aT<Dh&;Xw=!A zC9RY<U60$m#1Qh<OgDa$g2*4g@Sjnn2_$3Mrk7>NB+iU7u*4wc9D|3!(5OI0Lj*xI zDF`FV5KIVzro3tMC*_S5UV5gjSe&6H@93IEDVgG2RZ1c$hV)s3iH}fHO<Psa+!|5K z4Tg!6*&QV{oj3Ju)#WeB+}62Ts0wKjc(`B|ZOto}DCDR0VKS${WKYMBpc7p(E;F>& z3_(FRdKemt+$)$neA%aSK8#*mlW~<{{EVen(1$ox%P?JCD;cv!k-G%me}ea;G|f1U z#Wgz}!F42L++b)vY~bog1p`Pj$Xl9K=8LNgvBdH~{)8D}q%bUFh@tOz3N>6RP(hvE z;Bs$C025t_BcS`kL*){vqYB1wiy<P6P1p3BO`<5Mm?4*jRHy4bbrYo?YOwjss;jnB z%1X5`93qX;6Z^NBw>J+Odc3Zq(>sQ0Q}8tX`GU4t9gVU2&6lplhm0wPu6hJVXl7>= zv?4}~6?}H)OfjDAHP+U!s3VQRNmq5VJlI+FvTd5Rb<1&0ySTu;HOEl!NGy+tSWl*A zQSUP-^R!$`IZJb0?$QWQ0q8jg7LAIfLwh+$PZ%Pn^CV3mKz|^T9Q*<$`4tyF(<y*v zq4U3p+i%c9XNB$v?L}OoH}w}{WYI=)0PQ~7E0QESr&2$WOjXb!y@o8kg%r#tccJX! zO7}PPS1@>Rs$fL;lYD<M@&vr2(|hvwfujG2L45LkC--ryzR3e_<BlIs3gdnjE$F}` z?oxhfLfMa1SY^oS9%(`dMyFUubeiJMl1^klMAm|j#^m50?x*(9S;6!n0U_T3tzj|| bBuU8m(t~Q!vzYU>y?BUuk_4%OBKrLSfm7-e diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$2.class b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$2.class deleted file mode 100644 index bdcd201539ae2e983a556fbb1f8bd35ec81a9df8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3054 zcmb_eZF3V<6n<`-HfdPWSOo#GtP-&eErEhmXhqsIrKM@Bq_iR`Zj#&d!m?X;H|6D{ zGyWE5{Dgpr4l?K{<LJ-vyZYQs(zg^wJ0!EY_ndq0Ip=xK$+`Q--#<PEFaRrx7J*aC zcD14$KVy}vi*D7+lw8M=r9hTT?)7EYkxt-evJG8!RhJrwA|jByYOPoq+j1(I+2U26 zi=tg1wb`h=tu>k4?Rm?~D?gBq^aR?2CFQ4%GKl=<1OG9KA%VG6VPSGEJ8@-hWHg^^ zcuv*fq_!}W+6qqYX5d++K)KG`tz{|Da(R*g4l73mX9R|OwjE*byg(%DmSqP7It@e- zi=!1U8Q6g?fz}?qp);=>Ia9q}l-`_GwCTSq@0Ki^bSW*@l@U#tz|eMsNez&&&Xu~+ z>=M%^%L1wy-TH)W-`z%1hcwcTf~q)HQ1yuM-t+wqZyV+&zh_<`f;h9d-#`amXIguD zFHgpC0B=NL3XE^Fh*KNGHSi`53PfG6tQ^Y@OJuSGZ{h7I4haly(~E%~^a|{jtA#!- zgC(~-CId^+i`m5XY7OMAqO^x%I4p3j5Liyx^2+9Qmh@?}Zp}9>+cuZgO=<gPSuHL~ zkB!3&SYiB;W<{+?$1GZ<YZcF}I%RXkva7Ps^kjv$Z0Y-^yQp_6&r}ZEgRg>Har7e- z#Sww-&6qcaX5c7}kuhHea|}peS5JPeFBJk$ITaRP495k&S_NQhRPuiUS%c7LF1a`4 ziuBguZG^5Q3Gt-qOQN>cGvbC#(vRUCf$Y2{p?@tQ&*Aij3YJ19{bgBFi;8iF6vi+p zaP-3L<W^_3TGbMuoaJi3c)qAgr^LTryU$*)C*99ZJDU&NMa+>m!axNkn)YtdUAMd} za;rtByDP2k-q_x#thczOCLgQ0W;`#jB?#<fDU_~FTg!FV$DiMhhSt?o?XF`@MKQvD z@XYdL$hu)<4ZMmy`U1%5))Ch|<D7vB=sPCNBfI((yGaxHZ4%r;2U7;}Al32Fk?hpD z3$qtz#<Y6Iz^qnxt*Ni%M@Dn`T)6z9feU)MmBpjC&l$L=<+k~e{KZ@p3j+Jr{#!F{ zp;}rRSJE!$JkRx_h|^&qtgUgS@3B2wT((EF0f8@@32nl^KKYFohZkA|ojIpuyFNQa ztsNTpOkc}!eeo;HR=0`4nB*&wm$fb5mrPV*V>QEMUR(LJp(UBr_dAe`>ooH<E5c_7 z46g3v>|M0*3&hihze6JZJ(Ay2YQf7|7p`b4_wfp4eMW0{VK+yi3y3@Ra^8Y{p|!s_ zYo%O#h}Zfap!>)-6!^KsN1xTcO+FbuXZTE~?;~*^sjl<`^nH!~hBy$4-3{?XD0Vi) zlN5E7kub{BNO1lG?~+Hf`xB0FJb}j;#1s1X8D}|W@e9WBE2i-qYw0QL=XY56Gel+9 zBCexi?BwKB7;O=!F+@bev|q!n*WTlrjy;ODo<t(CBRN7M-ltO2*-vAdfSu{XPjI&H z2@X8K=o+K#p<NOBCF{wUzP0N|@A07K==@!bU3!YhorQ-OfBYyumA;Gf<T5h*H6jZX zrYW>Fgbyf08$y9Xdri1>4`X-8P?GuCk9m4IgkFwm9LGtHgXAU4u{Gqd7FR9Hx*9aT zgXoxu;-i1KL2%SR^O)NBLkBvwE%>-z2AA;(<p^I5KE)Nzy11r6>CXXbKR>(oUl_@I AX#fBK diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$ExtractionType.class b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$ExtractionType.class deleted file mode 100644 index 5bade0851a76b5ec7660fe31ba70fbed7a6c53ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1520 zcmb_cYfsZq7=8}j)@@WS6S)i!FDTnU=2Y;qiNF{-8C#^VWNKncDYK+&m#!o3fA~Xm ze1K>qe)dNh-ctsfiGDHbho1ACzR!C*&)Z+WznubjfM+6l7}l#sy{wzHxUyH@x9WCW zwM<h}9c@pwDpkwWOs5u4U!0{c&!#h<99vNx-7>cuRZWD4q3=LBRN{tWmg5<-USSBX zuB10!ZWVU&YYeY)-3gUs2(|rw$gQkqavAdPEw1EtG7Q32A<NL4$?t4VyGJrZ_Feaa z`%|i+o4T_^p(4>DgC}k6X?}QvU>KAT!c_)es%0`9$+f#8JGO3?li6r7K(^N;c;WLy z<X}{S$bp}OaS4770vueI5P*;GZb%5Cm!UtWn_9kJ+12cAW!KQCAvsG`jG|)e9J_}> z2pFW~oR4~q@;OwDx<;FgNVIFc2qJ=*h$zEAM~#h|qg5o#VvZr8*tXJ8t!jfI*4c@| z?g5D`neAxK#SwLfL3Hyi>@&RYq_r9t?bdDbCf%2C4+(~a&Om8HsnwDl*<D6%SIRX` zVhqYOHmbI+^NSe$%c#tA3iU$P%ckPgZ8Ce?;hDQhb*rEyN=VAm1lw)}T1~_ghR6Ro zc{I|0j`?zeWGK+@!@E4j#S73%x^-8Qth<t0fq^jBDp`6+$`Y;+uaD4Y!u;9(4ps{F z3&$8Z!jKDwJuVn=!I;+tVHZsJTresAAd=9;kX-UKF(Q||O@!r=uZc<d2vc9lZx3$L z`z}ok@PaZ(Q{**_Ad4_wV;Y;7K^_Ub!6Q7!EtkPrG_<V@6I36sP>jt^9OHJ|sgDfM zB1!IEB!^Tg1-nBb&kJ0nws87z6H}!PA$D3y@vJw6@e|C<eW5SsDV}>{mnj5Dg!3&Q mF|y&Yf*}?=LHsA!zj*@v$+^#mR1jYmu*jLjr)$U4<*_r&b%Hhk diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Label.class b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Label.class deleted file mode 100644 index 286aafc760e2fffd02cef831392ef551ec31e150..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1399 zcmbu8O>fgc5Qg7%KAXBt2vADDXd!KrK<g%H`79ujQYj+9p(vugZJZ^zxONpgJ@ALP za6zIVao~!?k3!6DoYV?Ak&9<{X6JooXUD(){P+o=jE4zm43AIkZrgG^gSWcx+-}D( zUB?loFIuL1a_Tz5@jav3_f-eJT%9+Coj{Z!bIi}UVRNT#ylx&-E<?&X;ce02c2_X4 zJv!s_PFwgYsqd~aOorSHPwQh9^N1npSs#g*aGmF^ws=eIqrvWQup(c4*K#cX2}3Nu zS1U9qv+A})3K3k<k-=4lNWRdR0K+vMF~sHSx{d^r4C%V%h*#Z{rs%xkO`CYxx@&T~ z!8?}R2hOPf-tq`=*6TvdmJOq`)P{Y_;dZze1glBJO&t?RrD&DYaRbW?QwKgbKfL6p zfohVQrtrMn7Q?grnEfgoNoGNZjwyz|a*3fjuJVy=X<x7`DVsW`!<5QJd|SrLI@00z z4h_)(&7&#yE!pDP5i__c2aiFo(ZqJDHupT?C2*hN-ha*!y_R|vEK@}h`b!ct3-tQ5 zlIx_h^gzl^s=X$gM|(|PPg%MKS$Q^tOQe&f)gh@x$)=0nak;pDj+x@(IcC3*OT!#} zvofq1h-xKFXk|=m70i==S(TB-LI6!;k;-9G3QGi$MbexEm=|PaY^L}XE5DE;Gy6%I zm2bH9nIaKIQwrLyBIv!0fUrtuV$i1dStf}!tOvrYfpClz^HQf*bx&tb>1cG{B#O8l zq^!{y@*!TFKS%!JrvK*L8Hw2##w>&|#%RpOFeaR{H4;-A#w>*}mC=~eFlLZLH{Mp= Q*}+}1@<*m=!~>-M0u{9l_y7O^ diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting$1.class b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting$1.class deleted file mode 100644 index a575676183f4f2f945a6e9278aebdc4471ff5296..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1261 zcmbtTOK;Oa5dJnvV`|(aO$)TVT1udKwN{G+NT~`{0#c<E4yk%T;;?ZR$Ca}i`N7ZN zmvG@y5C_DWABC8;Q!2Hb%whKN?aVhbJ2St2fByks7q)>M!@<;#T~CHKAH^S39N3PM zQaF(qIchRhQphN@yXRQ<FIF3<Ao8SJ+c8jJsGRbT-1fP2?YF~IvNup<SWeJ5@_eG0 zOnJZ~6)+U{Jn2RI4EcKFgrU$?BVi(s>lO@LV<`7MDc;1Bp$Lxo&=(BVzH+#K!UIp= zXJ8>3dm%%&|KBNe7z~{*56D+o&q&zGYS%b4v4k52mKmOAOUA-Y+@h~^Mf5KD*Pe-0 z+%a&Qp>$E3BOZ+{+{HaALg=|No{&ww*XS|i)DFY*tSM;wU53qi|H4_?2%W2l&X?h# zg$foK%mKBXBVK#D&@2CFwQWtwFh8Jxc@*m!4X=`>$faJ}%bL$VwM6-qbbJ+3lOKs_ ztVRZ!3@@_PCp@1Q2J4UpEa>_?3`J;Qi{V*DPU_m(6k?q|G*2=|qn#(AIilM<ou1In zXrF6-h53aJIasusv;*%^pvMI|S*a3ADASDw8jG}Qf<EbJ%2MkL)i#Oy4J)5M6Ou9& z6U$-3vYu+rSjYzVv6j4-D8x17DhI^;V8*;f+M0Qx+4_m4Hpv+_E)%EW>0k?}B~BmV aak6iso}dj{TO?HqsDU=NU#=!D3Hk${{Z}mj diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting$2.class b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting$2.class deleted file mode 100644 index 8d3491cc8d4cad2b56a233c56aba2e354cd4ae55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1261 zcmbtTOK;Oa5dJnvV`|(aO$)TVT1udKwH84Fq*R3}0jW|7hg3aq+c=Bk%Gr(l;Aikl zxNs?m1LDk&Ld@DJm0C{bF#Gs+=9`(FnP0!Z{{YZ|Z6L>RF!N*AlcCMW@dp(LwxgsJ zP9(;Tn$DCIG79b9IoA7&)rKmFJn7at1_}(7Q~r_LK9{cjZgfia28s-;2^vS9PZZM` z4|t>khT@(ly=b2yUvHc+6nbhbOyqIhf`Mxc<$))~+ju$>!7(5Cf}uK44);%Z;OYAu zEJPD8Wath4JB2QTq0{97`3mb93A<VC8iyuUaKpeV!?SG3Sh$H>^p&oN-Y5UsH?fX8 z25vKyE^2ecqltyPxJN|@Jy*t4vZ?nQeTJNR!tf$%3fjKIuw5TqI7=I$dlk|7GCZ_U z!7_t6q_%U!8&4N{?H{eSt0@^4hZHc6VqK%rRnio>)N6ZL^Vz4CD8H7DuR?0_BN0v1 z*g%uvWw!c+=kvl~9nydWJ)ei62o3BoJkQ8UT|1vbY|@A3Nfv0d^CUD!bX%m;Q`#Br z3(c=EztABEi&m3%V1fcYF44(Kl~6*NZZyzXrd1ORNJmqa+GnV?NZfB&`}CQRl&P3l zP7{{RRCCTkHn@+C<h?{8ZXj1VAm#^i<{i@3%uCJIPpq^_&aicvI1Nt+TR<&w`UsDc YeH--zZP3~xsZu}<w6XhYJ#k6UAGnHFMF0Q* diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting.class b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents$Sorting.class deleted file mode 100644 index 67cb4c595fb10b50662c392e6673f9714dd67db0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1959 zcmb_cZBG+H5Pp_xd+m8*sfthqMJv(*R!~4~1xj0EV^P9ElVXfH$_YoxU30w>`w#p% zT4OX4iJ$#Z#@X#vQ1J`(lG~Tr+1Y1io|*4Iz8nIW#$y>h3=6etW81XqNqwvF+HN?> zifvg&#Wl7n_Fm1l49l%2vmIIXmn^2)j%!-mGJFiZyZXMKtm@WwGH*5Z7($uVrNY{3 zX0^<aDR%ipitOd`D{D_)Wwb1V(q8BCV#87Dj_%qHLw`}=Xt-vTAa~^ax@K-$y4!FJ zhLsbQ(x(KOnkVyT^3T?nW2H=SJ+Cn=y*Q<<dMBo2GMKJZP0MuW8KkjziNTk(w~QeC z3K%Y^xQKp+K-yE87;8HvGN8E*<t0@((a%)86e0@)D*OlpA<MW-8R{}Yu_*;n3~^Lp zZvCnXnOhIaxc(okPb(O~5I1~NMGyhLx~1YQdKu0YP0M)J*xNLmHGQ*6`Hd9qie4@0 zj>-3)Q1b%x2Q|9Ldc34S!UXqul9+c=0@|TYst7@$1iCwBopbazc+FY|VqjmdHVo3p zjm5iXkb)V^$(UsbAJwMTth>gZiu-s#HK99>-mKWQCPU&l{O6myRR10R2ugKC1<piS z0Db<NVg2|uk9P5{$<O2ZNX0`C_h*j3kge+Vdg^bc$B&74`=RntG-_oP<FUyZF>pfr zy3M1)p#5?6w1hY+UEUAW0<};_z%}YJatw2)tT2kU*Jl@}i1iXRZvWySuU&v<sxmQC zQP4>rCmLy;p>+?`aFmw_t$kE9=MbioKH9w%y1>c-SUD1r*e9I-fJ<UG=sQ5P{0Uct zY*@&y`42EcvKvAc3w)((QVW-~vaf|<t?X|hrhUNZd-3WRjl+ZsDA8D^_cy3QUgA0o z#Ib`}tkKNz@t?XFjcvRMfo_9*^wF7`7$*?piOG++%`HpdmU~46_Q``cbgL;WaSNo6 zJDy*n+(>UqNSPQzbS_bJrg7Jc!Ysv*N3*|$(ehI%aac}s$CjnbpK)*E9i8-u7XzdZ z`a76I#LJXtBSAX+REe;}XQaP@{rjGT1z~g1^EQJe+D8ckLl$|;Wt8^(8);8J0dLU? A(EtDd diff --git a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java index 1ae45da..cc010e0 100644 --- a/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java +++ b/src/main/java/plugins/adufour/connectedcomponents/ConnectedComponents.java @@ -36,12 +36,10 @@ import plugins.adufour.blocks.util.VarList; import plugins.adufour.ezplug.EzGroup; import plugins.adufour.ezplug.EzLabel; import plugins.adufour.ezplug.EzPlug; -import plugins.adufour.ezplug.EzVar; import plugins.adufour.ezplug.EzVarBoolean; import plugins.adufour.ezplug.EzVarEnum; import plugins.adufour.ezplug.EzVarFile; import plugins.adufour.ezplug.EzVarInteger; -import plugins.adufour.ezplug.EzVarListener; import plugins.adufour.ezplug.EzVarSequence; import plugins.adufour.vars.lang.VarGenericArray; import plugins.adufour.vars.lang.VarROIArray; @@ -52,15 +50,13 @@ import plugins.kernel.roi.roi3d.ROI3DArea; import plugins.nchenouard.spot.DetectionResult; import plugins.nchenouard.spot.Spot; -public class ConnectedComponents extends EzPlug implements Block -{ +public class ConnectedComponents extends EzPlug implements Block { /** * List of extraction methods suitable for the Connected Components plugin - * + * * @author Alexandre Dufour */ - public enum ExtractionType - { + public enum ExtractionType { /** * The user defined value is considered as the background, and all components with a * different intensity should be extracted (regardless of intensity variations) @@ -82,8 +78,7 @@ public class ConnectedComponents extends EzPlug implements Block ROI } - public enum Sorting - { + public enum Sorting { /** * Components are not sorted */ @@ -91,41 +86,25 @@ public class ConnectedComponents extends EzPlug implements Block /** * Components are sorted by ascending depth value */ - DEPTH_ASC(new Comparator<ConnectedComponent>() - { - @Override - public int compare(ConnectedComponent o1, ConnectedComponent o2) - { - return (int) Math.signum(o1.getZ() - o2.getZ()); - } - }), + DEPTH_ASC((o1, o2) -> (int) Math.signum(o1.getZ() - o2.getZ())), /** * Components are sorted by descending depth value */ - DEPTH_DESC(new Comparator<ConnectedComponent>() - { - @Override - public int compare(ConnectedComponent o1, ConnectedComponent o2) - { - return (int) Math.signum(o2.getZ() - o1.getZ()); - } - }); + DEPTH_DESC((o1, o2) -> (int) Math.signum(o2.getZ() - o1.getZ())); /** * The comparator which can be used to sort an array of connected components */ public final Comparator<ConnectedComponent> comparator; - Sorting(Comparator<ConnectedComponent> comparator) - { + Sorting(Comparator<ConnectedComponent> comparator) { this.comparator = comparator; } } protected EzVarSequence input = new EzVarSequence("Input"); - protected EzVarEnum<ExtractionType> extractionMethod = new EzVarEnum<ExtractionType>("Extraction mode", - ExtractionType.values()); + protected EzVarEnum<ExtractionType> extractionMethod = new EzVarEnum<>("Extraction mode", ExtractionType.values()); protected EzLabel extractionMethodDetail = new EzLabel("Description"); @@ -146,8 +125,7 @@ public class ConnectedComponents extends EzPlug implements Block protected EzVarBoolean exportSequence = new EzVarBoolean("Labeled sequence", true); - protected EzVarEnum<Sorting> labelSorting = new EzVarEnum<ConnectedComponents.Sorting>("Sort components", - Sorting.values(), Sorting.ARBITRARY); + protected EzVarEnum<Sorting> labelSorting = new EzVarEnum<>("Sort components", Sorting.values(), Sorting.ARBITRARY); protected EzVarBoolean exportSwPool = new EzVarBoolean("Swimming pool", false); protected EzVarBoolean exportROI = new EzVarBoolean("ROI", false); @@ -155,52 +133,38 @@ public class ConnectedComponents extends EzPlug implements Block protected EzVarFile exportExcelFile = new EzVarFile("Excel file", ""); protected VarSequence outputSequence = new VarSequence("output", null); - protected VarGenericArray<ConnectedComponent[]> outputCCs = new VarGenericArray<ConnectedComponent[]>("components", - ConnectedComponent[].class, null); + protected VarGenericArray<ConnectedComponent[]> outputCCs = new VarGenericArray<>("components", ConnectedComponent[].class, null); protected VarROIArray outputROIs = new VarROIArray("list of ROI"); @Override - protected void initialize() - { + protected void initialize() { addEzComponent(input); - input.addVarChangeListener(new EzVarListener<Sequence>() - { - @Override - public void variableChanged(EzVar<Sequence> source, Sequence newValue) - { - if (newValue != null) - { - boolean doZ = newValue.getSizeZ() > 1; - discardEdgesZ.setValue(doZ); - discardEdgesZ.setVisible(doZ); - } + input.addVarChangeListener((source, newValue) -> { + if (newValue != null) { + boolean doZ = newValue.getSizeZ() > 1; + discardEdgesZ.setValue(doZ); + discardEdgesZ.setVisible(doZ); } }); addEzComponent(extractionMethod); - extractionMethod.addVarChangeListener(new EzVarListener<ExtractionType>() - { - @Override - public void variableChanged(EzVar<ExtractionType> source, ExtractionType newValue) - { - switch (newValue) - { - case BACKGROUND: - extractionMethodDetail.setText( - "Standard mode: extracts all pixels different than the given background value, regardless of their intensity"); - break; - case BACKGROUND_LABELED: - extractionMethodDetail.setText( - "Standard labeled mode: extracts all pixels different than the background, however different intensities are seen as different objects"); - break; - case VALUE: - extractionMethodDetail - .setText("Value-extraction mode: extracts all pixels with the specified value"); - break; - case ROI: - extractionMethodDetail.setText("ROI mode: extracts all ROI in the input sequence"); - break; - } + extractionMethod.addVarChangeListener((source, newValue) -> { + switch (newValue) { + case BACKGROUND: + extractionMethodDetail.setText( + "Standard mode: extracts all pixels different than the given background value, regardless of their intensity"); + break; + case BACKGROUND_LABELED: + extractionMethodDetail.setText( + "Standard labeled mode: extracts all pixels different than the background, however different intensities are seen as different objects"); + break; + case VALUE: + extractionMethodDetail + .setText("Value-extraction mode: extracts all pixels with the specified value"); + break; + case ROI: + extractionMethodDetail.setText("ROI mode: extracts all ROI in the input sequence"); + break; } }); @@ -228,8 +192,7 @@ public class ConnectedComponents extends EzPlug implements Block } @Override - public void declareInput(VarList inputMap) - { + public void declareInput(VarList inputMap) { inputMap.add("input", input.getVariable()); inputMap.add("method", extractionMethod.getVariable()); inputMap.add("value", background.getVariable()); @@ -244,18 +207,16 @@ public class ConnectedComponents extends EzPlug implements Block } @Override - public void declareOutput(VarList outputMap) - { + public void declareOutput(VarList outputMap) { outputMap.add("labeled sequence", outputSequence); outputMap.add("objects", outputCCs); outputMap.add("list of extracted ROI", outputROIs); } @Override - protected void execute() - { - ArrayList<ConnectedComponent> componentsList = new ArrayList<ConnectedComponent>(); - Map<Integer, List<ConnectedComponent>> componentsMap = new TreeMap<Integer, List<ConnectedComponent>>(); + protected void execute() { + ArrayList<ConnectedComponent> componentsList = new ArrayList<>(); + Map<Integer, List<ConnectedComponent>> componentsMap; int min = boundSize.getValue() ? minSize.getValue() : 0; int max = boundSize.getValue() ? maxSize.getValue() : Integer.MAX_VALUE; @@ -269,14 +230,13 @@ public class ConnectedComponents extends EzPlug implements Block // never remove objects touching the Z edge in 2D (that would remove... everything!) boolean discardEdgesAlongZ = (inputSequence.getSizeZ() > 1 && discardEdgesZ.getValue()); - try - { - if (extractionMethod.getValue() == ExtractionType.ROI) - { + try { + if (extractionMethod.getValue() == ExtractionType.ROI) { int width = inputSequence.getWidth(); int height = inputSequence.getHeight(); - Sequence labeledSequence = new Sequence(inputSequence.getMetadata()); + //Sequence labeledSequence = new Sequence(inputSequence.getMetadata()); + Sequence labeledSequence = new Sequence(inputSequence.getOMEXMLMetadata()); for (int t = 0; t < inputSequence.getSizeT(); t++) for (int z = 0; z < inputSequence.getSizeZ(); z++) labeledSequence.setImage(t, z, new IcyBufferedImage(width, height, 1, DataType.USHORT)); @@ -288,15 +248,13 @@ public class ConnectedComponents extends EzPlug implements Block componentsMap = extractConnectedComponents(labeledSequence, 0, ExtractionType.BACKGROUND_LABELED, discardEdgesX.getValue(), discardEdgesY.getValue(), discardEdgesAlongZ, min, max, output); } - else - { + else { componentsMap = extractConnectedComponents(inputSequence, background.getValue(), extractionMethod.getValue(), discardEdgesX.getValue(), discardEdgesY.getValue(), discardEdgesAlongZ, min, max, output); } } - catch (InterruptedException e) - { + catch (InterruptedException e) { new FailedAnnounceFrame(e.getMessage()); return; } @@ -304,44 +262,37 @@ public class ConnectedComponents extends EzPlug implements Block outputSequence.setValue(output); int nbObjects = 0; - for (List<ConnectedComponent> ccs : componentsMap.values()) - { + for (List<ConnectedComponent> ccs : componentsMap.values()) { nbObjects += ccs.size(); componentsList.addAll(ccs); } outputCCs.setValue(componentsList.toArray(new ConnectedComponent[nbObjects])); - if (getUI() != null) - { + if (getUI() != null) { objectCount.setText("Total: " + nbObjects + " components"); - if (exportSequence.getValue()) - { + if (exportSequence.getValue()) { createLabeledSequence(output, componentsMap, labelSorting.getValue().comparator); addSequence(output); } } - if (exportSwPool.getValue()) - { + if (exportSwPool.getValue()) { DetectionResult result = convertToDetectionResult(componentsMap, input.getValue()); SwimmingObject object = new SwimmingObject(result, "Set of " + nbObjects + " connected components"); Icy.getMainInterface().getSwimmingPool().add(object); } - if (exportROI.getValue() || outputROIs.isReferenced()) - { - if (output.getSizeZ() > 1) - { - ArrayList<ROI3DArea> rois = new ArrayList<ROI3DArea>(componentsMap.size()); + if (exportROI.getValue() || outputROIs.isReferenced()) { + if (output.getSizeZ() > 1) { + ArrayList<ROI3DArea> rois = new ArrayList<>(componentsMap.size()); int ccID = 1; for (List<ConnectedComponent> ccs : componentsMap.values()) - for (ConnectedComponent cc : ccs) - { + for (ConnectedComponent cc : ccs) { ROI3DArea area = new ROI3DArea(); area.setName("Object #" + ccID++); area.beginUpdate(); @@ -354,13 +305,11 @@ public class ConnectedComponents extends EzPlug implements Block outputROIs.setValue(rois.toArray(new ROI3DArea[rois.size()])); } - else - { - ArrayList<ROI2DArea> rois = new ArrayList<ROI2DArea>(componentsMap.size()); + else { + ArrayList<ROI2DArea> rois = new ArrayList<>(componentsMap.size()); for (List<ConnectedComponent> ccs : componentsMap.values()) - for (ConnectedComponent cc : ccs) - { + for (ConnectedComponent cc : ccs) { ROI2DArea area = new ROI2DArea(); area.beginUpdate(); for (Point3i pt : cc) @@ -373,8 +322,7 @@ public class ConnectedComponents extends EzPlug implements Block outputROIs.setValue(rois.toArray(new ROI2DArea[rois.size()])); } - if (exportROI.getValue()) - { + if (exportROI.getValue()) { // replace all ROI on the input by the new ones Sequence in = input.getValue(); @@ -390,23 +338,20 @@ public class ConnectedComponents extends EzPlug implements Block } } - if (exportExcel.getValue()) - { + if (exportExcel.getValue()) { int page = 1; - WritableSheet sheet = null; - WritableWorkbook workbook = null; + WritableSheet sheet; + WritableWorkbook workbook; - try - { + try { File f = exportExcelFile.getValue(true); if (!FileUtil.getFileExtension(f.getPath(), false).equalsIgnoreCase("xls")) f = new File(f.getPath() + ".xls"); workbook = XLSUtil.createWorkbook(f); sheet = XLSUtil.createNewPage(workbook, "Page " + page); } - catch (Exception e) - { + catch (Exception e) { throw new IcyHandledException(e.getMessage()); } @@ -455,8 +400,7 @@ public class ConnectedComponents extends EzPlug implements Block ConnectedComponentDescriptor shapeDescriptor = new ConnectedComponentDescriptor(); int cpt = 2; for (Integer time : componentsMap.keySet()) - for (ConnectedComponent cc : componentsMap.get(time)) - { + for (ConnectedComponent cc : componentsMap.get(time)) { boolean is2D = shapeDescriptor.is2D(cc); Point3d center = cc.getMassCenter(); center.x *= resolution.x; @@ -477,59 +421,65 @@ public class ConnectedComponents extends EzPlug implements Block XLSUtil.setCellNumber(sheet, 11, cpt, shapeDescriptor.computeEccentricity(cc)); double[] contour_area = shapeDescriptor.computeConvexAreaAndVolume(cc); - XLSUtil.setCellNumber(sheet, 12, cpt, - contour_area[1] == 0.0 ? 0.0 : Math.min(1.0, cc.getSize() / contour_area[1])); + XLSUtil.setCellNumber(sheet, 12, cpt, contour_area[1] == 0.0 ? 0.0 : Math.min(1.0, cc.getSize() / contour_area[1])); XLSUtil.setCellNumber(sheet, 13, cpt, shapeDescriptor.computeGeometricMoment(cc, 1, 0, 0)); XLSUtil.setCellNumber(sheet, 14, cpt, shapeDescriptor.computeGeometricMoment(cc, 0, 1, 0)); + if (!is2D) XLSUtil.setCellNumber(sheet, 15, cpt, shapeDescriptor.computeGeometricMoment(cc, 0, 0, 1)); + XLSUtil.setCellNumber(sheet, 16, cpt, shapeDescriptor.computeGeometricMoment(cc, 1, 1, 0)); + if (!is2D) XLSUtil.setCellNumber(sheet, 17, cpt, shapeDescriptor.computeGeometricMoment(cc, 1, 0, 1)); + if (!is2D) XLSUtil.setCellNumber(sheet, 18, cpt, shapeDescriptor.computeGeometricMoment(cc, 0, 1, 1)); + if (!is2D) XLSUtil.setCellNumber(sheet, 19, cpt, shapeDescriptor.computeGeometricMoment(cc, 1, 1, 1)); + XLSUtil.setCellNumber(sheet, 20, cpt, shapeDescriptor.computeGeometricMoment(cc, 2, 0, 0)); XLSUtil.setCellNumber(sheet, 21, cpt, shapeDescriptor.computeGeometricMoment(cc, 0, 2, 0)); + if (!is2D) XLSUtil.setCellNumber(sheet, 22, cpt, shapeDescriptor.computeGeometricMoment(cc, 0, 0, 2)); + XLSUtil.setCellNumber(sheet, 23, cpt, shapeDescriptor.computeGeometricMoment(cc, 2, 2, 0)); + if (!is2D) XLSUtil.setCellNumber(sheet, 24, cpt, shapeDescriptor.computeGeometricMoment(cc, 2, 0, 2)); + if (!is2D) XLSUtil.setCellNumber(sheet, 25, cpt, shapeDescriptor.computeGeometricMoment(cc, 0, 2, 2)); + if (!is2D) XLSUtil.setCellNumber(sheet, 26, cpt, shapeDescriptor.computeGeometricMoment(cc, 2, 2, 2)); + XLSUtil.setCellNumber(sheet, 27, cpt, contour_area[0]); XLSUtil.setCellNumber(sheet, 28, cpt, contour_area[1]); cpt++; - if (cpt == Short.MAX_VALUE) - { + if (cpt == Short.MAX_VALUE) { page++; sheet = XLSUtil.createNewPage(workbook, "Page " + page); cpt = 1; } } - try - { + try { XLSUtil.saveAndClose(workbook); } - catch (Exception e) - { + catch (Exception e) { throw new IcyHandledException(e.getMessage()); } } } @Override - public void clean() - { + public void clean() { } - private static class Label - { + private static class Label { final double imageValue; /** @@ -553,31 +503,19 @@ public class ConnectedComponents extends EzPlug implements Block /** * Creates a new label with the given value. If no parent is set to this label, the given * value will be the final one - * - * @param value - * the pixel value - * @param label - * the label value - * @param onEdgeX - * true if the pixel is on the image edge along X - * @param onEdgeY - * true if the pixel is on the image edge along Y - * @param onEdgeZ - * true if the pixel is on the image edge along Z + * + * @param value the pixel value + * @param label the label value */ - Label(double value, int label) - { + Label(double value, int label) { this.imageValue = value; this.targetLabelValue = label; } /** * Retrieves the final object label (recursively) - * - * @return */ - int getFinalLabelValue() - { + int getFinalLabelValue() { return targetLabel == null ? targetLabelValue : targetLabel.getFinalLabelValue(); } } @@ -586,19 +524,15 @@ public class ConnectedComponents extends EzPlug implements Block * Extracts the connected components in the given sequence with specified size bounds. Note that * the method works on both binary gray-scale images. If the input is not binary, any value * other than 0 will be extracted as a component. - * - * @param inputSequence - * A binary or gray-scale sequence. If the sequence is gray-scale, any value other - * than 0 will be extracted as a component - * @param labeledSequence - * a single-band integer sequence that will be filled with the labeled components + * + * @param inputSequence A binary or gray-scale sequence. If the sequence is gray-scale, any value other + * than 0 will be extracted as a component + * @param labeledSequence a single-band integer sequence that will be filled with the labeled components * @return a map with extracted components, indexed by the sequence time points * @see ExtractionType * @see ConnectedComponent */ - public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, - Sequence labeledSequence) - { + public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, Sequence labeledSequence) { return extractConnectedComponents(inputSequence, false, 0, Integer.MAX_VALUE, labeledSequence); } @@ -606,23 +540,17 @@ public class ConnectedComponents extends EzPlug implements Block * Extracts the connected components in the given sequence with specified size bounds. Note that * the method works on both binary gray-scale images. If the input is not binary, any value * other than 0 will be extracted as a component. - * - * @param inputSequence - * A binary or gray-scale sequence. If the sequence is gray-scale, any value other - * than 0 will be extracted as a component - * @param minSize - * the minimum size of the objects to extract - * @param maxSize - * the maximum size of the objects to extract - * @param labeledSequence - * a single-band integer sequence that will be filled with the labeled components + * + * @param inputSequence A binary or gray-scale sequence. If the sequence is gray-scale, any value other + * than 0 will be extracted as a component + * @param minSize the minimum size of the objects to extract + * @param maxSize the maximum size of the objects to extract + * @param labeledSequence a single-band integer sequence that will be filled with the labeled components * @return a map with extracted components, indexed by the sequence time points * @see ExtractionType * @see ConnectedComponent */ - public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, int minSize, - int maxSize, Sequence labeledSequence) - { + public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, int minSize, int maxSize, Sequence labeledSequence) { return extractConnectedComponents(inputSequence, false, minSize, maxSize, labeledSequence); } @@ -631,24 +559,17 @@ public class ConnectedComponents extends EzPlug implements Block * the method works on both binary gray-scale images. If the input is not binary, an option can * be set to distinguish touching objects which have a different intensity value, or to extract * a specific intensity value - * - * @param inputSequence - * A binary or gray-scale sequence. - * @param isInputLabeled - * if true, touching components with different pixel values are extracted separately - * @param minSize - * the minimum size of the objects to extract - * @param maxSize - * the maximum size of the objects to extract - * @param labeledSequence - * a single-band integer sequence that will be filled with the labeled components + * + * @param inputSequence A binary or gray-scale sequence. + * @param isInputLabeled if true, touching components with different pixel values are extracted separately + * @param minSize the minimum size of the objects to extract + * @param maxSize the maximum size of the objects to extract + * @param labeledSequence a single-band integer sequence that will be filled with the labeled components * @return a map with extracted components, indexed by the sequence time points * @see ExtractionType * @see ConnectedComponent */ - public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, - boolean isInputLabeled, int minSize, int maxSize, Sequence labeledSequence) - { + public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, boolean isInputLabeled, int minSize, int maxSize, Sequence labeledSequence) { return extractConnectedComponents(inputSequence, 0, isInputLabeled ? ExtractionType.BACKGROUND_LABELED : ExtractionType.BACKGROUND, minSize, maxSize, labeledSequence); @@ -659,28 +580,19 @@ public class ConnectedComponents extends EzPlug implements Block * the method works on both binary gray-scale images. If the input is not binary, an option can * be set to distinguish touching objects which have a different intensity value, or to extract * a specific intensity value - * - * @param inputSequence - * A binary or gray-scale sequence. - * @param value - * the user value to be interpreted depending on the type parameter - * @param type - * the extraction method (or how to interpret the value parameter) - * @param minSize - * the minimum size of the objects to extract - * @param maxSize - * the maximum size of the objects to extract - * @param labeledSequence - * a single-band integer sequence that will be filled with the labeled components + * + * @param inputSequence A binary or gray-scale sequence. + * @param value the user value to be interpreted depending on the type parameter + * @param type the extraction method (or how to interpret the value parameter) + * @param minSize the minimum size of the objects to extract + * @param maxSize the maximum size of the objects to extract + * @param labeledSequence a single-band integer sequence that will be filled with the labeled components * @return a map with extracted components, indexed by the sequence time points * @see ExtractionType * @see ConnectedComponent */ - public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, - double value, ExtractionType type, int minSize, int maxSize, Sequence labeledSequence) - { - return extractConnectedComponents(inputSequence, value, type, false, false, false, minSize, maxSize, - labeledSequence); + public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, double value, ExtractionType type, int minSize, int maxSize, Sequence labeledSequence) { + return extractConnectedComponents(inputSequence, value, type, false, false, false, minSize, maxSize, labeledSequence); } /** @@ -688,38 +600,28 @@ public class ConnectedComponents extends EzPlug implements Block * the method works on both binary gray-scale images. If the input is not binary, an option can * be set to distinguish touching objects which have a different intensity value, or to extract * a specific intensity value - * - * @param inputSequence - * A binary or gray-scale sequence. - * @param value - * the user value to be interpreted depending on the type parameter - * @param type - * the extraction type (or how to interpret the value parameter) - * @param noEdgeX - * set to true if components touching the image edge along X should be discarded - * during the extraction - * @param noEdgeY - * set to true if components touching the image edge along Y should be discarded - * during the extraction - * @param noEdgeZ - * set to true if components touching the image edge along Z should be discarded - * during the extraction - * @param minSize - * the minimum size of the objects to extract - * @param maxSize - * the maximum size of the objects to extract - * @param labeledSequence - * a single-band integer sequence that will be filled with the labeled components + * + * @param inputSequence A binary or gray-scale sequence. + * @param value the user value to be interpreted depending on the type parameter + * @param type the extraction type (or how to interpret the value parameter) + * @param noEdgeX set to true if components touching the image edge along X should be discarded + * during the extraction + * @param noEdgeY set to true if components touching the image edge along Y should be discarded + * during the extraction + * @param noEdgeZ set to true if components touching the image edge along Z should be discarded + * during the extraction + * @param minSize the minimum size of the objects to extract + * @param maxSize the maximum size of the objects to extract + * @param labeledSequence a single-band integer sequence that will be filled with the labeled components * @return a map with extracted components, indexed by the sequence time points * @see ExtractionType * @see ConnectedComponent */ - public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents(Sequence inputSequence, - double value, ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, - int maxSize, Sequence labeledSequence) - { + public static Map<Integer, List<ConnectedComponent>> extractConnectedComponents( + Sequence inputSequence, double value, ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, int maxSize, Sequence labeledSequence + ) { if (inputSequence == null || inputSequence.getSizeT() == 0) - throw new IllegalArgumentException("Cannot extract connected components from an emtpy sequence !"); + throw new IllegalArgumentException("Cannot extract connected components from an empty sequence !"); int width = inputSequence.getSizeX(); int height = inputSequence.getSizeY(); @@ -727,10 +629,9 @@ public class ConnectedComponents extends EzPlug implements Block if (labeledSequence == null) labeledSequence = new Sequence(); - Map<Integer, List<ConnectedComponent>> componentsMap = new TreeMap<Integer, List<ConnectedComponent>>(); + Map<Integer, List<ConnectedComponent>> componentsMap = new TreeMap<>(); - for (int t = 0; t < inputSequence.getSizeT(); t++) - { + for (int t = 0; t < inputSequence.getSizeT(); t++) { for (int z = 0; z < inputSequence.getSizeZ(); z++) labeledSequence.setImage(t, z, new IcyBufferedImage(width, height, 1, DataType.UINT)); @@ -741,8 +642,7 @@ public class ConnectedComponents extends EzPlug implements Block noEdgeZ, minSize, maxSize, volOUT); // int cpt=1; - for (ConnectedComponent cc : components) - { + for (ConnectedComponent cc : components) { cc.setT(t); // System.out.println(t + "\t" + cpt++ + "\t" + (int)cc.getMassCenter().x + "\t" + // (int)cc.getMassCenter().y); @@ -759,38 +659,29 @@ public class ConnectedComponents extends EzPlug implements Block /** * Extracts the connected components in the given volumetric image with specified size bounds. - * The the method works on both binary gray-scale images. If the input is not binary, an option + * The method works on both binary gray-scale images. If the input is not binary, an option * can be set to distinguish touching objects which have a different intensity value, or to * extract a specific intensity value - * - * @param stack - * A binary or gray-scale volumetric image. - * @param value - * the user value to be interpreted depending on the type parameter - * @param type - * the extraction type (or how to interpret the value parameter) - * @param noEdgeX - * set to true if components touching the image edge along X should be discarded - * during the extraction - * @param noEdgeY - * set to true if components touching the image edge along Y should be discarded - * during the extraction - * @param noEdgeZ - * set to true if components touching the image edge along Z should be discarded - * during the extraction - * @param minSize - * the minimum size of the objects to extract - * @param maxSize - * the maximum size of the objects to extract + * + * @param stack A binary or gray-scale volumetric image. + * @param value the user value to be interpreted depending on the type parameter + * @param type the extraction type (or how to interpret the value parameter) + * @param noEdgeX set to true if components touching the image edge along X should be discarded + * during the extraction + * @param noEdgeY set to true if components touching the image edge along Y should be discarded + * during the extraction + * @param noEdgeZ set to true if components touching the image edge along Z should be discarded + * during the extraction + * @param minSize the minimum size of the objects to extract + * @param maxSize the maximum size of the objects to extract * @return a collection containing all components extracted. * @see ExtractionType * @see ConnectedComponent */ - public static List<ConnectedComponent> extractConnectedComponents(VolumetricImage stack, double value, - ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, int maxSize) - { - return extractConnectedComponents(stack, value, type, noEdgeX, noEdgeY, noEdgeZ, minSize, maxSize, - new VolumetricImage()); + public static List<ConnectedComponent> extractConnectedComponents( + VolumetricImage stack, double value, ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, int maxSize + ) { + return extractConnectedComponents(stack, value, type, noEdgeX, noEdgeY, noEdgeZ, minSize, maxSize, new VolumetricImage()); } /** @@ -798,40 +689,29 @@ public class ConnectedComponents extends EzPlug implements Block * The the method works on both binary gray-scale images. If the input is not binary, an option * can be set to distinguish touching objects which have a different intensity value, or to * extract a specific intensity value - * - * @param stack - * A binary or gray-scale volumetric image. - * @param value - * the user value to be interpreted depending on the type parameter - * @param type - * the extraction type (or how to interpret the value parameter) - * @param noEdgeX - * set to true if components touching the image edge along X should be discarded - * during the extraction - * @param noEdgeY - * set to true if components touching the image edge along Y should be discarded - * during the extraction - * @param noEdgeZ - * set to true if components touching the image edge along Z should be discarded - * during the extraction - * @param minSize - * the minimum size of the objects to extract - * @param maxSize - * the maximum size of the objects to extract - * @param labeledStack - * a volumetric image where labeled information will be stored during the extraction. - * Note that this volumetric image should be non-null and filled with zero-values (no - * cleaning is performed to optimize recursive processes) + * + * @param stack A binary or gray-scale volumetric image. + * @param value the user value to be interpreted depending on the type parameter + * @param type the extraction type (or how to interpret the value parameter) + * @param noEdgeX set to true if components touching the image edge along X should be discarded + * during the extraction + * @param noEdgeY set to true if components touching the image edge along Y should be discarded + * during the extraction + * @param noEdgeZ set to true if components touching the image edge along Z should be discarded + * during the extraction + * @param minSize the minimum size of the objects to extract + * @param maxSize the maximum size of the objects to extract + * @param labeledStack a volumetric image where labeled information will be stored during the extraction. + * Note that this volumetric image should be non-null and filled with zero-values (no + * cleaning is performed to optimize recursive processes) * @return a collection containing all components extracted. - * @throws NullPointerException - * is labeledStack is null + * @throws NullPointerException is labeledStack is null * @see ExtractionType * @see ConnectedComponent */ - public static List<ConnectedComponent> extractConnectedComponents(VolumetricImage stack, double value, - ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, int maxSize, - final VolumetricImage labeledStack) throws NullPointerException - { + public static List<ConnectedComponent> extractConnectedComponents( + VolumetricImage stack, double value, ExtractionType type, boolean noEdgeX, boolean noEdgeY, boolean noEdgeZ, int minSize, int maxSize, final VolumetricImage labeledStack + ) throws NullPointerException { int width = stack.getFirstImage().getSizeX(); int height = stack.getFirstImage().getSizeY(); int depth = stack.getSize(); @@ -847,12 +727,11 @@ public class ConnectedComponents extends EzPlug implements Block int highestKnownLabel = 0; - boolean onEdgeX = false; - boolean onEdgeY = false; - boolean onEdgeZ = false; + boolean onEdgeX; + boolean onEdgeY; + boolean onEdgeZ; - for (int z = 0; z < depth; z++) - { + for (int z = 0; z < depth; z++) { onEdgeZ = (z == 0 || z == depth - 1); final IcyBufferedImage currentSliceImage = labeledStack.getImage(z); @@ -866,12 +745,10 @@ public class ConnectedComponents extends EzPlug implements Block Object inputData = stack.getImage(z).getDataXY(0); DataType dataType = stack.getImage(z).getDataType_(); - for (int y = 0; y < height; y++) - { + for (int y = 0; y < height; y++) { onEdgeY = (y == 0 || y == height - 1); - for (int x = 0; x < width; x++, voxelOffset++) - { + for (int x = 0; x < width; x++, voxelOffset++) { onEdgeX = (x == 0 || x == width - 1); double pixelValue = Array1DUtil.getValue(inputData, voxelOffset, dataType); @@ -898,20 +775,16 @@ public class ConnectedComponents extends EzPlug implements Block // n = valid neighbor // . = other neighbor - if (z == 0) - { - if (y == 0) - { - if (x == 0) - { + if (z == 0) { + if (y == 0) { + if (x == 0) { // e e e // e x . // e . . // do nothing } - else - { + else { // e e e // n x . // . . . @@ -920,12 +793,10 @@ public class ConnectedComponents extends EzPlug implements Block neighborhoodSize = 1; } } - else - { + else { int north = voxelOffset - width; - if (x == 0) - { + if (x == 0) { // e n n // e x . // e . . @@ -934,8 +805,7 @@ public class ConnectedComponents extends EzPlug implements Block neighborLabelValues[1] = _labelsInCurrentSlice[north + 1]; neighborhoodSize = 2; } - else if (x == width - 1) - { + else if (x == width - 1) { // n n e // n x e // . . e @@ -945,8 +815,7 @@ public class ConnectedComponents extends EzPlug implements Block neighborLabelValues[2] = _labelsInCurrentSlice[voxelOffset - 1]; neighborhoodSize = 3; } - else - { + else { // n n n // n x . // . . . @@ -959,14 +828,11 @@ public class ConnectedComponents extends EzPlug implements Block } } } - else - { - if (y == 0) - { + else { + if (y == 0) { int south = voxelOffset + width; - if (x == 0) - { + if (x == 0) { // e e e | e e e // e n n | e x . // e n n | e . . @@ -977,8 +843,7 @@ public class ConnectedComponents extends EzPlug implements Block neighborLabelValues[3] = _labelsInUpperSlice[south + 1]; neighborhoodSize = 4; } - else if (x == width - 1) - { + else if (x == width - 1) { // e e e | e e e // n n e | n x e // n n e | . . e @@ -990,8 +855,7 @@ public class ConnectedComponents extends EzPlug implements Block neighborLabelValues[4] = _labelsInCurrentSlice[voxelOffset - 1]; neighborhoodSize = 5; } - else - { + else { // e e e | e e e // n n n | n x . // n n n | . . . @@ -1006,12 +870,10 @@ public class ConnectedComponents extends EzPlug implements Block neighborhoodSize = 7; } } - else if (y == height - 1) - { + else if (y == height - 1) { int north = voxelOffset - width; - if (x == 0) - { + if (x == 0) { // e n n | e n n // e n n | e x . // e e e | e e e @@ -1024,8 +886,7 @@ public class ConnectedComponents extends EzPlug implements Block neighborLabelValues[5] = _labelsInCurrentSlice[north + 1]; neighborhoodSize = 6; } - else if (x == width - 1) - { + else if (x == width - 1) { // n n e | n n e // n n e | n x e // e e e | e e e @@ -1039,8 +900,7 @@ public class ConnectedComponents extends EzPlug implements Block neighborLabelValues[6] = _labelsInCurrentSlice[voxelOffset - 1]; neighborhoodSize = 7; } - else - { + else { // n n n | n n n // n n n | n x . // e e e | e e e @@ -1058,13 +918,11 @@ public class ConnectedComponents extends EzPlug implements Block neighborhoodSize = 10; } } - else - { + else { int north = voxelOffset - width; int south = voxelOffset + width; - if (x == 0) - { + if (x == 0) { // e n n | e n n // e n n | e x . // e n n | e . . @@ -1079,8 +937,7 @@ public class ConnectedComponents extends EzPlug implements Block neighborLabelValues[7] = _labelsInCurrentSlice[north + 1]; neighborhoodSize = 8; } - else if (x == width - 1) - { + else if (x == width - 1) { int northwest = north - 1; int west = voxelOffset - 1; @@ -1099,8 +956,7 @@ public class ConnectedComponents extends EzPlug implements Block neighborLabelValues[8] = _labelsInCurrentSlice[west]; neighborhoodSize = 9; } - else - { + else { int northwest = north - 1; int west = voxelOffset - 1; int northeast = north + 1; @@ -1137,8 +993,7 @@ public class ConnectedComponents extends EzPlug implements Block // find the minimum non-zero label in the neighborhood // and assign that minimum label right now - for (int i = 0; i < neighborhoodSize; i++) - { + for (int i = 0; i < neighborhoodSize; i++) { int neighborLabelValue = neighborLabelValues[i]; // zero labels are not interesting... @@ -1152,14 +1007,12 @@ public class ConnectedComponents extends EzPlug implements Block // here, the neighbor label is valid // => check if it is lower - if (neighborLabelValue < currentVoxelLabelValue) - { + if (neighborLabelValue < currentVoxelLabelValue) { currentVoxelLabelValue = neighborLabelValue; } } - if (currentVoxelLabelValue == Integer.MAX_VALUE) - { + if (currentVoxelLabelValue == Integer.MAX_VALUE) { // currentVoxelLabel didn't change // => no lower neighbor value found // => new label @@ -1167,8 +1020,7 @@ public class ConnectedComponents extends EzPlug implements Block currentVoxelLabelValue = highestKnownLabel; labels[currentVoxelLabelValue] = new Label(pixelValue, currentVoxelLabelValue); } - else - { + else { // currentVoxelLabelValue has been modified // -> browse its neighborhood again // -> find all neighbors with a higher label value @@ -1177,12 +1029,10 @@ public class ConnectedComponents extends EzPlug implements Block Label currentVoxelLabel = labels[currentVoxelLabelValue]; - for (int i = 0; i < neighborhoodSize; i++) - { + for (int i = 0; i < neighborhoodSize; i++) { int neighborLabelValue = neighborLabelValues[i]; - if (neighborLabelValue > currentVoxelLabelValue) - { + if (neighborLabelValue > currentVoxelLabelValue) { Label label = labels[neighborLabelValue]; if (type == ExtractionType.BACKGROUND_LABELED && label.imageValue != pixelValue) @@ -1194,13 +1044,11 @@ public class ConnectedComponents extends EzPlug implements Block if (currentVoxelLabel.targetLabelValue == finalLabelValue) continue; - if (currentVoxelLabelValue < finalLabelValue) - { + if (currentVoxelLabelValue < finalLabelValue) { finalLabel.targetLabel = currentVoxelLabel; finalLabel.targetLabelValue = currentVoxelLabelValue; } - else if (currentVoxelLabelValue > finalLabelValue) - { + else if (currentVoxelLabelValue > finalLabelValue) { currentVoxelLabel.targetLabel = finalLabel; currentVoxelLabel.targetLabelValue = finalLabelValue; } @@ -1224,7 +1072,7 @@ public class ConnectedComponents extends EzPlug implements Block // end of the first pass, all pixels have a label // (though might not be unique within a given component) - HashMap<Integer, ConnectedComponent> componentsMap = new HashMap<Integer, ConnectedComponent>(); + HashMap<Integer, ConnectedComponent> componentsMap = new HashMap<>(); // fusion strategy: fuse higher labels with lower ones // "highestKnownLabel" holds the highest known label @@ -1232,14 +1080,12 @@ public class ConnectedComponents extends EzPlug implements Block int finalLabel = 0; - for (int labelValue = highestKnownLabel; labelValue > 0; labelValue--) - { + for (int labelValue = highestKnownLabel; labelValue > 0; labelValue--) { Label label = labels[labelValue]; int targetLabelValue = label.targetLabelValue; - if (targetLabelValue < labelValue) - { + if (targetLabelValue < labelValue) { // label should be fused to targetLabel Label targetLabel = labels[targetLabelValue]; @@ -1255,28 +1101,24 @@ public class ConnectedComponents extends EzPlug implements Block // -> mark label to fuse with targetLabel label.targetLabel = labels[targetLabelValue]; } - else - { + else { // label has same labelValue and targetLabelValue // -> it cannot be fused to anything // -> this is a terminal label // -> check if it obeys to user constraints - if (label.size < minSize || label.size > maxSize) - { + if (label.size < minSize || label.size > maxSize) { // the component size is out of the given range // -> mark the object for deletion label.targetLabelValue = 0; } - else if ((noEdgeX && label.onEdgeX) || (noEdgeY && label.onEdgeY) || (noEdgeZ && label.onEdgeZ)) - { + else if ((noEdgeX && label.onEdgeX) || (noEdgeY && label.onEdgeY) || (noEdgeZ && label.onEdgeZ)) { // the component size is on an edge to discard // -> mark the object for deletion label.targetLabelValue = 0; } - else - { + else { // the label is clean and user-valid // -> assign its final labelValue (for the final image labeling pass) finalLabel++; @@ -1295,17 +1137,14 @@ public class ConnectedComponents extends EzPlug implements Block // 3) second image pass: replace all labels by their final values - for (int z = 0; z < depth; z++) - { + for (int z = 0; z < depth; z++) { final IcyBufferedImage sliceImage = labeledStack.getImage(z); int[] _outputSlice = sliceImage.getDataXYAsInt(0); int pixelOffset = 0; - for (int j = 0; j < height; j++) - { - for (int i = 0; i < width; i++, pixelOffset++) - { + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++, pixelOffset++) { int targetLabelValue = _outputSlice[pixelOffset]; if (targetLabelValue == 0) @@ -1329,17 +1168,14 @@ public class ConnectedComponents extends EzPlug implements Block sliceImage.setDataXY(0, _outputSlice); } - return new ArrayList<ConnectedComponent>(componentsMap.values()); + return new ArrayList<>(componentsMap.values()); } - public static DetectionResult convertToDetectionResult(Map<Integer, List<ConnectedComponent>> detections, - Sequence sequence) - { + public static DetectionResult convertToDetectionResult(Map<Integer, List<ConnectedComponent>> detections, Sequence sequence) { DetectionResult detectionResult = new DetectionResult(); for (Integer t : detections.keySet()) - for (ConnectedComponent cc : detections.get(t)) - { + for (ConnectedComponent cc : detections.get(t)) { // TODO: add points information Spot spot = new Spot(cc.getMassCenter().x, cc.getMassCenter().y, cc.getMassCenter().z); detectionResult.addDetection(t, spot); @@ -1353,17 +1189,12 @@ public class ConnectedComponents extends EzPlug implements Block /** * Fill the channel 0 of the given sequence with the list of components sorted using the given * comparator. The method does nothing if the given comparator is null - * - * @param output - * a sequence of type INT - * @param components - * Map of List of ConnectedComponent - * @param comparator - * Comparator of ConnectedComponents + * + * @param output a sequence of type INT + * @param components Map of List of ConnectedComponent + * @param comparator Comparator of ConnectedComponents */ - public static void createLabeledSequence(Sequence output, Map<Integer, List<ConnectedComponent>> components, - Comparator<ConnectedComponent> comparator) - { + public static void createLabeledSequence(Sequence output, Map<Integer, List<ConnectedComponent>> components, Comparator<ConnectedComponent> comparator) { if (comparator == null) return; @@ -1371,14 +1202,11 @@ public class ConnectedComponents extends EzPlug implements Block int[] ids = new int[output.getSizeC()]; Arrays.fill(ids, 1); - for (Integer t : components.keySet()) - { - for (int c = 0; c < output.getSizeC(); c++) - { + for (Integer t : components.keySet()) { + for (int c = 0; c < output.getSizeC(); c++) { // retrieve all objects in that channel - ArrayList<ConnectedComponent> cComponents = new ArrayList<ConnectedComponent>(); - for (ConnectedComponent cc : components.get(t)) - { + ArrayList<ConnectedComponent> cComponents = new ArrayList<>(); + for (ConnectedComponent cc : components.get(t)) { if (cc.getC() == -1 || cc.getC() == c) cComponents.add(cc); } @@ -1387,21 +1215,16 @@ public class ConnectedComponents extends EzPlug implements Block Arrays.sort(ccs, comparator); final boolean outputVolatile = output.isVolatile(); - try - { + try { int[][] data = output.getDataXYZAsInt(t, c); - for (ConnectedComponent cc : ccs) - { - for (Point3i pt : cc) - { + for (ConnectedComponent cc : ccs) { + for (Point3i pt : cc) { data[pt.z][pt.y * width + pt.x] = ids[c]; } ids[c]++; } - } - finally - { + } finally { // restore back volatile state output.setVolatile(outputVolatile); } -- GitLab