diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java index 52e5700c5090618f652744b849212c41f5b42d23..302d52a76af9d079aee0572b74fda3803c87ae4d 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java @@ -25,9 +25,6 @@ import java.util.List; import java.util.ArrayList; import java.util.Objects; import javax.imageio.ImageIO; -//import org.nustaq.serialization.FSTConfiguration; -//import org.nustaq.serialization.FSTObjectInput; -//import org.nustaq.serialization.FSTObjectOutput; /** * This class encapsulates data for a 3D scan of a single human face. @@ -47,7 +44,11 @@ public class HumanFace implements Serializable { private MeshModel meshModel; - private KdTree kdTree; + /** + * {@code KdTree} is marked as transient because the Kryo library is not able + * to handle the reference of {@code KdNode} to {@code MeshModel}s. + */ + private transient KdTree kdTree; private Plane symmetryPlane; diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java index 85e3b9d897a3c5b28496691d9421bbaccda8f310..6076af44f551b88b5e4ed6dd4695c14e58585d91 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFaceFactory.java @@ -5,8 +5,6 @@ import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy; import cz.fidentis.analyst.Logger; -import cz.fidentis.analyst.kdtree.KdNode; -import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.CornerTable; import cz.fidentis.analyst.mesh.core.CornerTableRow; import cz.fidentis.analyst.mesh.core.MeshFacetImpl; @@ -121,8 +119,6 @@ public class HumanFaceFactory { HumanFaceFactory.kryo.register(CornerTableRow.class); HumanFaceFactory.kryo.register(BBox.class); HumanFaceFactory.kryo.register(Plane.class); - HumanFaceFactory.kryo.register(KdTree.class); - HumanFaceFactory.kryo.register(KdNode.class); HumanFaceFactory.kryo.register(Point3d.class); HumanFaceFactory.kryo.register(Vector3d.class); HumanFaceFactory.kryo.register(ArrayList.class); diff --git a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/AvgFaceConstructor.java b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/AvgFaceConstructor.java index ff112a6d1b5789313172a4f47ae10a2eaffcc29a..d169156f0243e3be431566119e1e33f1d2a56f7a 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/AvgFaceConstructor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/visitors/kdtree/AvgFaceConstructor.java @@ -6,13 +6,15 @@ import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshFacetImpl; import cz.fidentis.analyst.mesh.core.MeshModel; import cz.fidentis.analyst.visitors.mesh.HausdorffDistance; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; @@ -63,9 +65,13 @@ public class AvgFaceConstructor extends KdTreeVisitor { } // fill vertTarns with empty list for each facet - templateFacets.parallelStream().forEach( - f -> this.transformations.put(f, new ArrayList<>(f.getVertices().size())) - ); + templateFacets.parallelStream().forEach(f -> { + //transformations.put(f, new ArrayList<>(f.getVertices().size())); + transformations.put(f, Stream.generate(Vector3d::new) + .limit(f.getVertices().size()) + .collect(Collectors.toList()) + ); + }); } /** @@ -90,24 +96,20 @@ public class AvgFaceConstructor extends KdTreeVisitor { HausdorffDistance.Strategy.POINT_TO_POINT, false, // relative distance true, // parallel computation - false // auto cut + false // auto crop ); transformations.keySet().forEach(f -> hDist.visitMeshFacet(f)); // compute shifts of my vertices for (MeshFacet myFacet: transformations.keySet()) { List<Point3d> closestPoints = hDist.getNearestPoints().get(myFacet); - for (int i = 0; i < myFacet.getNumberOfVertices(); i++) { - //Vector3d moveDir = new Vector3d(myFacet.getVertex(i).getPosition()); - //moveDir.sub(closestPoints.get(i)); + + // shift vertices concurrently + IntStream.range(0, closestPoints.size()).parallel().forEach(i -> { Vector3d moveDir = new Vector3d(closestPoints.get(i)); moveDir.sub(myFacet.getVertex(i).getPosition()); - if (transformations.get(myFacet).size() < myFacet.getNumberOfVertices()) { // First inspected facet - transformations.get(myFacet).add(moveDir); - } else { - transformations.get(myFacet).get(i).add(moveDir); - } - } + transformations.get(myFacet).get(i).add(moveDir); + }); } } @@ -120,11 +122,11 @@ public class AvgFaceConstructor extends KdTreeVisitor { avgMeshModel = new MeshModel(); for (MeshFacet f: transformations.keySet()) { // clone all facets of the template face MeshFacet newFacet = new MeshFacetImpl(f); - for (int i = 0; i < newFacet.getNumberOfVertices(); i++ ) { // move all vertices + IntStream.range(0, newFacet.getNumberOfVertices()).parallel().forEach(i -> { Vector3d tr = new Vector3d(transformations.get(f).get(i)); tr.scale(1.0/numInspectedFacets); newFacet.getVertex(i).getPosition().add(tr); - } + }); avgMeshModel.addFacet(newFacet); } } diff --git a/GUI/src/main/java/cz/fidentis/analyst/batch/ApproxHausdorffDistTask.java b/GUI/src/main/java/cz/fidentis/analyst/batch/ApproxHausdorffDistTask.java index 8cbb5965f5c8395b3118b7f635bfc8dc6c71176b..3b4ba0be74ec235cda25da935a1548d95f9526b3 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/batch/ApproxHausdorffDistTask.java +++ b/GUI/src/main/java/cz/fidentis/analyst/batch/ApproxHausdorffDistTask.java @@ -31,7 +31,7 @@ import java.util.stream.DoubleStream; public class ApproxHausdorffDistTask extends SimilarityTask { private final Stopwatch totalTime = new Stopwatch("Total computation time:\t\t"); - private final Stopwatch hdComputationTime = new Stopwatch("Hausdorff distance preparation time:\t"); + private final Stopwatch hdComputationTime = new Stopwatch("Hausdorff distance computation time:\t"); private final Stopwatch loadTime = new Stopwatch("Disk access time:\t\t"); private final Stopwatch kdTreeConstructionTime = new Stopwatch("KD trees construction time:\t\t"); private final Stopwatch finalHdComputationTime = new Stopwatch("Hausdorff distance finalization time:\t"); @@ -103,7 +103,9 @@ public class ApproxHausdorffDistTask extends SimilarityTask { .flatMap(List::stream).collect(Collectors.toList())); hdComputationTime.stop(); - face.removeKdTree(); // k-d tree construction is fast, and the memory is more valuable + // Memory is more valuable. And it's probable that we will not need + // k-d trees anymore. If yes, then they are quicly re-computed. + face.removeKdTree(); } else { distCache.add(DoubleStream.generate(() -> 0.0d) .limit(templateFace.getMeshModel().getNumVertices()) @@ -133,8 +135,8 @@ public class ApproxHausdorffDistTask extends SimilarityTask { protected void printTimeStats() { Logger.print(hdComputationTime.toString()); - Logger.print(loadTime.toString()); Logger.print(finalHdComputationTime.toString()); + Logger.print(loadTime.toString()); Logger.print(kdTreeConstructionTime.toString()); Logger.print(totalTime.toString()); } diff --git a/GUI/src/main/java/cz/fidentis/analyst/batch/IcpTask.java b/GUI/src/main/java/cz/fidentis/analyst/batch/IcpTask.java index d3146792114b593bba51035875b5882d911ae270..ecd13150a8c63f47646dd126b46c960b3caef3e8 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/batch/IcpTask.java +++ b/GUI/src/main/java/cz/fidentis/analyst/batch/IcpTask.java @@ -128,7 +128,7 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> { if (computeAvgFace) { // AVG template face kdTreeConstructionTime.start(); - face.computeKdTree(computeICP); // if transformed by ICP, force rk-d tree e-computation + face.computeKdTree(computeICP); // if transformed by ICP, force k-d tree re-computation kdTreeConstructionTime.stop(); avgFaceComputationTime.start(); @@ -139,7 +139,7 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> { avgFaceComputationTime.stop(); } - face.removeKdTree(); // k-d tree construction is fast, and a free memory is more required + //face.removeKdTree(); // preserve k-d tree for the similarity computation phase publish(face); // update progress bar and possibly render the transformed face } diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java index 70cb46e723aa1bbc9167357791e3a602f755e638..b8ceea78b48a0ea4b7010e594102f553b84cd638 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java +++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationAction.java @@ -189,8 +189,8 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL protected void applyProcrustes() { JOptionPane.showMessageDialog( controlPanel, - "This method is not finished yet", - "Neither feature points nor symmetry planes are transformed properly", + "This method is not finished yet (neither feature points nor symmetry planes are transformed properly)", + "Warning", JOptionPane.INFORMATION_MESSAGE); Logger out = Logger.measureTime(); diff --git a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java index 82b45c3ce16654e289143d52f82cfc94b6135983..bc2214834b7ef705e82c155c344b62e5fa83bbeb 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java +++ b/GUI/src/main/java/cz/fidentis/analyst/registration/RegistrationPanel.java @@ -88,6 +88,9 @@ public class RegistrationPanel extends ControlPanel { jButtonInfo1.addActionListener((ActionEvent e) -> { showAutoAlignmentInfo(); }); + + jFormattedTextField1.setValue(Double.valueOf(0.3)); + jFormattedTextField2.setValue(Integer.valueOf(50)); } /** @@ -166,7 +169,7 @@ public class RegistrationPanel extends ControlPanel { } public double getMinIcpErrorParam() { - return ((Number) jFormattedTextField2.getValue()).doubleValue(); + return ((Number) jFormattedTextField1.getValue()).doubleValue(); } /** diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java index feccf7bf761453f9383ce95c641f90afd7628951..4995bbf66c59ddf745951294f1792b05444bafc5 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java @@ -1,7 +1,6 @@ package cz.fidentis.analyst.kdtree; import cz.fidentis.analyst.mesh.core.MeshFacet; -import java.io.Serializable; import java.util.Collections; import java.util.HashMap; @@ -15,7 +14,7 @@ import javax.vecmath.Point3d; * * @author Maria Kocurekova */ -public class KdNode implements Serializable { +public class KdNode /* implements Serializable */ { /** * Current depth in the kd-tree @@ -37,7 +36,6 @@ public class KdNode implements Serializable { */ private KdNode lesser = null; private KdNode greater = null; - private KdNode parent; /** * Constructor of KdNode @@ -61,7 +59,6 @@ public class KdNode implements Serializable { } this.facets.putIfAbsent(facet, index); this.depth = depth; - this.parent = parent; this.location = new Point3d(facet.getVertex(index).getPosition()); } @@ -92,7 +89,6 @@ public class KdNode implements Serializable { this.facets.putIfAbsent(facets.get(i), indices.get(i)); } this.depth = depth; - this.parent = parent; this.location = new Point3d(facets.get(0).getVertex(indices.get(0)).getPosition()); } @@ -138,15 +134,6 @@ public class KdNode implements Serializable { return greater; } - /** - * Tree traversal - go to the parent node. - * - * @return parent of this node, null if current node is root - */ - public KdNode getParent() { - return parent; - } - /** * Set lesser node. * @@ -179,17 +166,6 @@ public class KdNode implements Serializable { return Collections.unmodifiableMap(facets); } - /** - * Set parent node. - * - * @param parent Node to be set as parent - * @return current node - */ - public KdNode setParent(KdNode parent) { - this.parent = parent; - return this; - } - @Override public String toString() { String ret = ""; diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java index 0cdfb0e9545f40aaeb948010620d55e5bacb216f..2a74e73ec91163a2b715bb20bb623111ccb0ae47 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/io/MeshObjLoader.java @@ -34,7 +34,8 @@ import javax.vecmath.Point3d; /** * Utility class for loading human face from OBJ data format. * Expects only one human face in one file stored as one object. - * @author Marek Bařinka + * + * @author Marek Barinka */ public class MeshObjLoader { @@ -71,7 +72,7 @@ public class MeshObjLoader { /** * Parse OBJObject into MeshModel * @param model Model is needed in future. It's holding data pools - * @param object Object to parse. It corespond to our MeshModel + * @param object Object to parse. It corresponds to our MeshModel * @return Returns complete model * @throws IOException Data are corrupted */ @@ -96,7 +97,7 @@ public class MeshObjLoader { MeshFacet meshFacet = new MeshFacetImpl(); Map<MeshPoint, Integer> vertices = new HashMap<>(); Map<Edge, Integer> edges = new HashMap<>(); - + for (OBJFace face : mesh.getFaces()) { processFace(model, face, meshFacet, vertices, edges); } @@ -191,7 +192,8 @@ public class MeshObjLoader { /** * Helper class for finding opposite corners - * @author Marek Bařinka + * + * @author Marek Barinka */ private static class Edge {