diff --git a/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java b/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java index 0058b65e2ae91cd12c4c0c7bde8bc69eaa6da412..6ace9bc23fee33da6720bd509fd833e1b886b19b 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/BatchProcessor.java @@ -3,14 +3,27 @@ package cz.fidentis.analyst; import cz.fidentis.analyst.face.AvgFaceConstructor; import cz.fidentis.analyst.face.HumanFace; import cz.fidentis.analyst.face.HumanFaceFactory; +import cz.fidentis.analyst.icp.IcpTransformation; import cz.fidentis.analyst.icp.IcpTransformer; import cz.fidentis.analyst.icp.UndersamplingStrategy; import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.MeshFacet; +import cz.fidentis.analyst.mesh.io.MeshObjExporter; +import cz.fidentis.analyst.symmetry.Plane; +import cz.fidentis.analyst.symmetry.SignificantPoints; +import static cz.fidentis.analyst.symmetry.SignificantPoints.CurvatureAlg.GAUSSIAN; +import cz.fidentis.analyst.symmetry.SymmetryConfig; +import cz.fidentis.analyst.symmetry.SymmetryEstimator; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Matrix4d; +import javax.vecmath.Point3d; +import javax.vecmath.Vector3d; /** * Helper class providing methods for batch N:N processing. @@ -19,11 +32,6 @@ import java.util.List; */ public class BatchProcessor { - /** - * IDs of registered (transformed) faces. - */ - private final List<String> processedFaces = new ArrayList<>(); - /** * Template face computed by averaging vertices processed faces. */ @@ -31,51 +39,112 @@ public class BatchProcessor { private double avgIcpIterations = 0.0; + private SymmetryConfig symmetryConfig; + private SignificantPoints.CurvatureAlg symmetryCurvArg = GAUSSIAN; + /** - * Returns template face that can be used for linear time N:N distance computation. - * - * @return template face. + * Constructor. + * @param symmetryPoints Number of symmetry points used by the symmetry estimator */ - public HumanFace getAvgTemplateFace() { - return templateFace; + public BatchProcessor(int symmetryPoints) { + symmetryConfig = new SymmetryConfig(); + this.symmetryConfig.setSignificantPointCount(symmetryPoints); // default 200, best 500 + } + + /** + * Pre-reads faces from given directory into the HumanFactory. + * @param dir Directory. + * @return Face IDs + */ + public List<String> readFaces(String dir) { + List<String> faces = new ArrayList<>(); + for (File subdir : (new File(dir)).listFiles(File::isDirectory)) { + if (subdir.getName().matches("^\\d\\d$")) { + for (File file: subdir.listFiles(File::isFile)) { + if (file.getName().endsWith(".obj")) { + //System.out.print(file.getName() + " "); + //if (file.getName().endsWith("00002_01_ECA.obj")) { // FOT DEBUGING + String faceId = HumanFaceFactory.instance().loadFace(file); + faces.add(faceId); + //} + } + } + } + } + return faces; + } + + /** + * Pre-computes symmetry planes for given faces. + * @param faceIDs Face IDs + */ + public void computeSymmetryPlanes(List<String> faceIDs) { + for (String facePath: faceIDs) { + String faceId = HumanFaceFactory.instance().loadFace(new File(facePath)); + HumanFace face = HumanFaceFactory.instance().getFace(faceId); + getSymmetryPlaneMesh(face); + } } /** * Registers faces with respect to the given primary face. * * @param primaryFacePath Path to the primary face - * @param faces Paths to faces that are to be superimposed (registered) + * @param faceIDs Paths to faces that are to be superimposed (registered) * @param iters Maximal number of ICP iterations * @param error Maximal error of ICP computation * @param strategy Undersampling strategy */ - public void registerToPrimaryFace(String primaryFacePath, List<String> faces, int iters, double error, UndersamplingStrategy strategy) { - if (faces == null) { + public void superimposeOnPrimaryFace(String primaryFaceId, List<String> faceIDs, + int iters, double error, UndersamplingStrategy strategy, boolean symmetry) { + + if (faceIDs == null) { throw new IllegalArgumentException("faces"); } - HumanFace primaryFace = pathToFace(primaryFacePath); - - int facesCounter = faces.size(); HumanFaceFactory.instance().setStrategy(HumanFaceFactory.Strategy.MRU); - KdTree kdTree = primaryFace.computeKdTree(true); - IcpTransformer icpVisitor = new IcpTransformer(kdTree, iters, true, error, strategy); + + int facesCounter = faceIDs.size(); + HumanFace primaryFace = HumanFaceFactory.instance().getFace(primaryFaceId); + IcpTransformer primPlaneTr = new IcpTransformer(getSymmetryPlaneMesh(primaryFace), iters, true, error, strategy); + KdTree primKdTree = primaryFace.computeKdTree(true); + + IcpTransformer icpTransformer = new IcpTransformer(primKdTree, iters, true, error, strategy); - for (String facePath: faces) { - String faceId = HumanFaceFactory.instance().loadFace(new File(facePath)); + for (String faceId: faceIDs) { + //String faceId = HumanFaceFactory.instance().getFace(new File(facePath)); if (primaryFace.getId().equals(faceId)) { // skip the same face - processedFaces.add(faceId); facesCounter--; continue; } HumanFace face = HumanFaceFactory.instance().getFace(faceId); - face.getMeshModel().compute(icpVisitor); + + if (symmetry) { + MeshFacet plane = getSymmetryPlaneMesh(face); + primPlaneTr.visitMeshFacet(plane); + IcpTransformation tr = primPlaneTr.getTransformations().get(plane).get(0); + for (MeshFacet f: face.getMeshModel().getFacets()) { // apply transformation onto the face + primPlaneTr.applyTransformation(f, tr); + } + + if (faceId.endsWith("00004_01_ECA.obj")) { + MeshObjExporter exp = new MeshObjExporter(face.getMeshModel()); + try { + System.out.println("../../analyst-data/multi-scan-models-anonymized-fixed/test04.obj"); + exp.exportModelToObj(new File("../../analyst-data/multi-scan-models-anonymized-fixed/test04.obj")); + } catch (IOException ex) { + Logger.getLogger(BatchProcessor.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + face.getMeshModel().compute(icpTransformer); + face.removeKdTree(); } int itersCounter = 0; - for (MeshFacet f: icpVisitor.getTransformations().keySet()) { - itersCounter += icpVisitor.getTransformations().get(f).size(); + for (MeshFacet f: icpTransformer.getTransformations().keySet()) { + itersCounter += icpTransformer.getTransformations().get(f).size(); } this.avgIcpIterations = itersCounter / (double) facesCounter; } @@ -85,54 +154,36 @@ public class BatchProcessor { * are already superimposed (registered) with the template face. * * @param initTempPath Path to the face used as an initial template for the computation of the averaged face - * @param faces Paths to faces that are used to compute averaged face + * @param faceIDs Paths to faces that are used to compute averaged face */ - public void computeTemplateFace(String initTempPath, List<String> faces) { - if (faces == null) { + public void computeTemplateFace(String initTempFaceId, List<String> faceIDs) { + if (faceIDs == null) { throw new IllegalArgumentException("faces"); } - this.templateFace = pathToFace(initTempPath); + this.templateFace = HumanFaceFactory.instance().getFace(initTempFaceId); HumanFaceFactory.instance().setStrategy(HumanFaceFactory.Strategy.MRU); AvgFaceConstructor constructor = new AvgFaceConstructor(this.templateFace.getMeshModel()); - for (String facePath: faces) { - String faceId = HumanFaceFactory.instance().loadFace(new File(facePath)); - if (this.templateFace.getId().equals(faceId)) { // skip the same face - processedFaces.add(faceId); - continue; + for (String faceId: faceIDs) { + System.out.println(faceId); + //String faceId = HumanFaceFactory.instance().loadFace(new File(facePath)); + if (!this.templateFace.getId().equals(faceId)) { // skip the same face + HumanFace face = HumanFaceFactory.instance().getFace(faceId); + face.computeKdTree(false).accept(constructor); } - - HumanFace face = HumanFaceFactory.instance().getFace(faceId); - face.computeKdTree(false).accept(constructor); } this.templateFace.setMeshModel(constructor.getAveragedMeshModel()); } /** - * Registers faces and simultaneously computes averaged face. - * It is faster (?) combination of {@link registerToGivenFace#registerToPrimaryFace} and - * {@link computeTemplateFaceOnly#computeTemplateFace} + * Returns template face that can be used for linear time N:N distance computation. * - * @param initTempPath Path to the face used as an initial template for the computation of the averaged face - * @param faces Paths to faces that are superimposed (registered) and simultaneously used to compute averaged face - * @param iters Maximal number of ICP iterations - * @param error Maximal error of ICP computation - * @param strategy Undersampling strategy + * @return template face. */ - public void registerToTemplateFace(String initTempPath, List<String> faces, int iters, double error, UndersamplingStrategy strategy) { - if (faces == null) { - throw new IllegalArgumentException("faces"); - } - - try { - this.templateFace = new HumanFace(new File(initTempPath)); - } catch (IOException ex) { - throw new IllegalArgumentException("initTempPath", ex); - } - - // TO DO + public HumanFace getAvgTemplateFace() { + return templateFace; } /** @@ -143,12 +194,18 @@ public class BatchProcessor { return this.avgIcpIterations; } - protected HumanFace pathToFace(String path) { - try { - return new HumanFace(new File(path)); - } catch (IOException ex) { - throw new IllegalArgumentException(ex); + + + + protected MeshFacet getSymmetryPlaneMesh(HumanFace face) { + MeshFacet plane = face.getSymmetryPlaneFacet(); + if (plane == null) { + SymmetryEstimator se = new SymmetryEstimator(this.symmetryConfig, this.symmetryCurvArg); + face.getMeshModel().compute(se); + plane = se.getSymmetryPlaneMesh(); + face.setSymmetryPlane(se.getSymmetryPlane(), plane); } + return plane; } } diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/AvgFaceConstructor.java b/Comparison/src/main/java/cz/fidentis/analyst/face/AvgFaceConstructor.java index e7fe7d0a25c2f9a5a8ad6d20c765375f34d9bf46..3a85a9136fc61f7cdfb8d8d7ec31a206b28d69bb 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/face/AvgFaceConstructor.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/face/AvgFaceConstructor.java @@ -80,6 +80,7 @@ public class AvgFaceConstructor extends KdTreeVisitor { numInspectedFacets++; for (MeshFacet myFacet: transformations.keySet()) { + System.out.println("AAA "+ kdTree.getNumNodes() + " " + kdTree.getDepth()); for (int i = 0; i < myFacet.getNumberOfVertices(); i++) { Point3d myPoint = myFacet.getVertex(i).getPosition(); KdTreeClosestNode visitor = new KdTreeClosestNode(myPoint); @@ -94,6 +95,7 @@ public class AvgFaceConstructor extends KdTreeVisitor { transformations.get(myFacet).get(i).add(moveDir); } } + System.out.println("BBB"); } } 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 1a510e2b73285db0fa6a8f8609266bbfdf95b614..b5a1fb090f5147ff7f273c51fc217ec8e1af3db5 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java @@ -52,6 +52,8 @@ public class HumanFace implements MeshListener, Serializable { private KdTree kdTree; private Plane symmetryPlane; + + private MeshFacet symmetryPlaneMesh; private MeshFacet cuttingPlane; @@ -132,9 +134,11 @@ public class HumanFace implements MeshListener, Serializable { /** * * @param plane The new symmetry plane + * @param paneFacet The symmetry plane mesh */ - public void setSymmetryPlane(Plane plane) { - symmetryPlane = plane; + public void setSymmetryPlane(Plane plane, MeshFacet planeFacet) { + this.symmetryPlane = plane; + this.symmetryPlaneMesh = planeFacet; } /** @@ -144,6 +148,10 @@ public class HumanFace implements MeshListener, Serializable { public Plane getSymmetryPlane() { return symmetryPlane; } + + public MeshFacet getSymmetryPlaneFacet() { + return this.symmetryPlaneMesh; + } /** * @@ -191,6 +199,16 @@ public class HumanFace implements MeshListener, Serializable { } return kdTree; } + + /** + * Removes k-d tree from the Human face. + * @return removed k-d tree or {@code null} + */ + public KdTree removeKdTree() { + KdTree ret = this.kdTree; + this.kdTree = null; + return ret; + } /** * Creates serialized dump of the human face. Event buses are not stored. diff --git a/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java b/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java index 62383fff1425e93f45f4c67f0f3aca8b3f12214f..1d9f181567bd4d9281dbac868e09cd5d64e3a20c 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/icp/IcpTransformer.java @@ -363,7 +363,7 @@ public class IcpTransformer extends MeshVisitor { * @param transformedFacet Facet to be transformed * @param transformation Computed transformation. */ - private void applyTransformation(MeshFacet transformedFacet, IcpTransformation transformation) { + public void applyTransformation(MeshFacet transformedFacet, IcpTransformation transformation) { transformedFacet.getVertices().parallelStream().forEach( p -> { Point3d meshPointPosition = p.getPosition(); diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/ApproxSymmetryPlane.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/ApproxSymmetryPlane.java index 43fbfaad022f877192ae3eeedc7d97dcdadd7f0f..53304801656eb1ac98413f70db804bebf0b34100 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/ApproxSymmetryPlane.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/ApproxSymmetryPlane.java @@ -24,7 +24,7 @@ public class ApproxSymmetryPlane extends Plane implements Comparable<ApproxSymme * @param maxDist Distance limit * @throws UnsupportedOperationException if the symmetry plane cannot be created */ - public ApproxSymmetryPlane(SignificantPoints sigPoints, Config config, int i, int j, double maxDist) throws UnsupportedOperationException { + public ApproxSymmetryPlane(SignificantPoints sigPoints, SymmetryConfig config, int i, int j, double maxDist) throws UnsupportedOperationException { if (i == j) { throw new UnsupportedOperationException(); } @@ -41,7 +41,7 @@ public class ApproxSymmetryPlane extends Plane implements Comparable<ApproxSymme return votes; } - private void setNormAndDist(SignificantPoints sigPoints, Config config, int i, int j) { + private void setNormAndDist(SignificantPoints sigPoints, SymmetryConfig config, int i, int j) { MeshFacet facetI = sigPoints.getMeshFacet(i); MeshFacet facetJ = sigPoints.getMeshFacet(j); int sigPointI = sigPoints.getVertexIndex(i); @@ -81,7 +81,7 @@ public class ApproxSymmetryPlane extends Plane implements Comparable<ApproxSymme * @param config Symmetry plane configuration * @param maxDist Distance limit */ - private void computeVotes(SignificantPoints sigPoints, Config config, double maxDist) { + private void computeVotes(SignificantPoints sigPoints, SymmetryConfig config, double maxDist) { normalize(); Vector3d normal = getNormal(); double d = getDistance(); diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Config.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryConfig.java similarity index 89% rename from Comparison/src/main/java/cz/fidentis/analyst/symmetry/Config.java rename to Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryConfig.java index 22af1f4e0b03bba086409d3f812b48a26987ba7a..c4ee1faa4832f9757285a182e0cee19a1763f86c 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Config.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryConfig.java @@ -8,7 +8,8 @@ package cz.fidentis.analyst.symmetry; * * @author Natalia Bebjakova */ -public class Config { +public class SymmetryConfig { + private static final double DEFAULT_MIN_CURV_RATIO = 0.5; private static final double DEFAULT_MIN_ANGLE_COS = 0.985; private static final double DEFAULT_MIN_NORM_ANGLE_COS = 0.985; @@ -23,6 +24,18 @@ public class Config { private int significantPointCount; private boolean averaging; + /** + * Creates configuration with default values + */ + public SymmetryConfig() { + minCurvRatio = DEFAULT_MIN_CURV_RATIO; + minAngleCos = DEFAULT_MIN_ANGLE_COS; + minNormAngleCos = DEFAULT_MIN_NORM_ANGLE_COS; + maxRelDistance = DEFAULT_MAX_REL_DISTANCE; + significantPointCount = DEFAULT_SIGNIFICANT_POINT_COUNT; + averaging = DEFAULT_AVERAGING; + } + /** * Parameter which denotes how similar the Gaussian curvatures in the two vertices * must be for this criteria to be satisfied. @@ -135,24 +148,6 @@ public class Config { this.averaging = averaging; } - /** - * Creates new configuration with default values - * - * @return configuration with default values - */ - public static Config getDefault() { - Config conf = new Config(); - - conf.minCurvRatio = DEFAULT_MIN_CURV_RATIO; - conf.minAngleCos = DEFAULT_MIN_ANGLE_COS; - conf.minNormAngleCos = DEFAULT_MIN_NORM_ANGLE_COS; - conf.maxRelDistance = DEFAULT_MAX_REL_DISTANCE; - conf.significantPointCount = DEFAULT_SIGNIFICANT_POINT_COUNT; - conf.averaging = DEFAULT_AVERAGING; - - return conf; - } - /** * * @return String representation of configuration diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java index 9ade7e71c17683bfa463bd41f83df2da288ecc39..e3312f554cecd16463f468c300dd92faafb8fdec 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/SymmetryEstimator.java @@ -36,12 +36,10 @@ import javax.vecmath.Vector3d; */ public class SymmetryEstimator extends MeshVisitor { - private final Config config; + private final SymmetryConfig config; private final SignificantPoints sigPointsVisitor; private final BoundingBox bbVisitor = new BoundingBox(); - private CurvatureAlg curvatureAlg; - private Plane symmetryPlane; /** @@ -52,7 +50,7 @@ public class SymmetryEstimator extends MeshVisitor { * See {@link Curvature} for more details. * @throws IllegalArgumentException if some input parameter is missing */ - public SymmetryEstimator(Config config, CurvatureAlg curvatureAlg) { + public SymmetryEstimator(SymmetryConfig config, CurvatureAlg curvatureAlg) { if (config == null) { throw new IllegalArgumentException("config"); } diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java b/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java index 7b301610bbff7f4c465659001016fbca31c133ac..f9b5276a2ac50935f73e34b21b40a3b77da75334 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java +++ b/GUI/src/main/java/cz/fidentis/analyst/gui/GeneralGLEventListener.java @@ -14,7 +14,7 @@ import com.jogamp.opengl.GLEventListener; import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW_MATRIX; import static com.jogamp.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION_MATRIX; import com.jogamp.opengl.glu.GLU; -import cz.fidentis.analyst.symmetry.Config; +import cz.fidentis.analyst.symmetry.SymmetryConfig; import cz.fidentis.analyst.symmetry.SignificantPoints; import cz.fidentis.analyst.symmetry.SymmetryEstimator; import javax.vecmath.Point3d; @@ -244,12 +244,12 @@ public class GeneralGLEventListener implements GLEventListener { //Generate SymmetryPlane first time we request to see it if (symmetryPlane && symmetryPlaneFacet == null) { - SymmetryEstimator estimator = new SymmetryEstimator(Config.getDefault(), SignificantPoints.CurvatureAlg.GAUSSIAN); + SymmetryEstimator estimator = new SymmetryEstimator(new SymmetryConfig(), SignificantPoints.CurvatureAlg.GAUSSIAN); model.getFacets().get(0).accept(estimator); symmetryPlaneFacet = estimator.getSymmetryPlaneMesh(); //Set calculated planes for the loaded Face - glCanvas.loadedFace.setSymmetryPlane(estimator.getSymmetryPlane()); + glCanvas.loadedFace.setSymmetryPlane(estimator.getSymmetryPlane(), symmetryPlaneFacet); glCanvas.loadedFace.setCuttingPlane(symmetryPlaneFacet); } diff --git a/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.java b/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.java index af8c975bae39086c5cdac07282e2bd6aa850a9c7..d5de605ee9e3991d0afc688037cffe8e1bb1a621 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.java +++ b/GUI/src/main/java/cz/fidentis/analyst/gui/SymmetryPanel.java @@ -3,7 +3,7 @@ package cz.fidentis.analyst.gui; import static cz.fidentis.analyst.gui.UserInterface.frameMain; import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshModel; -import cz.fidentis.analyst.symmetry.Config; +import cz.fidentis.analyst.symmetry.SymmetryConfig; import cz.fidentis.analyst.symmetry.Plane; import cz.fidentis.analyst.symmetry.SignificantPoints; import cz.fidentis.analyst.symmetry.SymmetryEstimator; @@ -25,7 +25,7 @@ public final class SymmetryPanel extends javax.swing.JPanel { /** * Configuration with optional parameters of the algorithm */ - private Config config; + private SymmetryConfig config; /** * GL Canvas on which model is displayed @@ -58,7 +58,7 @@ public final class SymmetryPanel extends javax.swing.JPanel { * * @return Configuration for computing symmetry */ - public Config getConfig() { + public SymmetryConfig getConfig() { return config; } @@ -66,7 +66,7 @@ public final class SymmetryPanel extends javax.swing.JPanel { * * @param config Configuration for computing symmetry */ - public void setConfig(Config config) { + public void setConfig(SymmetryConfig config) { this.config = config; } @@ -139,7 +139,7 @@ public final class SymmetryPanel extends javax.swing.JPanel { */ public SymmetryPanel() { initComponents(); - config = Config.getDefault(); + config = new SymmetryConfig(); setSliders(); showPlaneButtonsOnPanel(false); @@ -607,7 +607,7 @@ public final class SymmetryPanel extends javax.swing.JPanel { * @param evt configuration is set to deafult values */ private void defaultValuesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_defaultValuesMouseClicked - config = Config.getDefault(); + config = new SymmetryConfig(); setTextFieldsDueToConfig(); setSliders(); }//GEN-LAST:event_defaultValuesMouseClicked diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/BatchTests.java b/GUI/src/main/java/cz/fidentis/analyst/tests/BatchTests.java index fdd42d31c41f0f28d2a3b6510d3d90446a13ae75..663fc3e918f870066dd0d57b54b4fb09727d3fee 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/tests/BatchTests.java +++ b/GUI/src/main/java/cz/fidentis/analyst/tests/BatchTests.java @@ -13,6 +13,7 @@ import cz.fidentis.analyst.mesh.io.MeshObjExporter; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -27,7 +28,7 @@ public class BatchTests { private static final String primaryFacePath = dataDir + "/average-boy-17-20/average_boy_17-20.obj"; //private static final String primaryFacePath = dataDir + "/average-girl-17-20/average_girl_17-20.obj"; //private static final String primaryFacePath = "../../analyst-data/basic-models/02.obj"; - private static final String templateFacePath = dataDir + "/template.obj"; + private static final String templateFacePath = dataDir + "template.obj"; /** * Main method @@ -35,23 +36,32 @@ public class BatchTests { * @throws IOException on IO error */ public static void main(String[] args) throws IOException, ClassNotFoundException, Exception { - BatchProcessor batch = new BatchProcessor(); + BatchProcessor batch = new BatchProcessor(200); // the best is 500? long startTime, endTime; List<String> faceIDs; - String faceId = HumanFaceFactory.instance().loadFace(new File(primaryFacePath)); - HumanFace primaryFace = HumanFaceFactory.instance().getFace(faceId); - KdTree kdTree = primaryFace.computeKdTree(false); + String primaryFaceId = HumanFaceFactory.instance().loadFace(new File(primaryFacePath)); + HumanFace primaryFace = HumanFaceFactory.instance().getFace(primaryFaceId); + KdTree primaryFacekdTree = primaryFace.computeKdTree(false); ////////////////////////////////////////////// System.out.println(); System.out.println("Loading files:"); startTime = System.currentTimeMillis(); - faceIDs = readFiles(dataDir); + faceIDs = batch.readFaces(dataDir); + endTime = System.currentTimeMillis(); + printTimes(startTime, endTime, faceIDs.size()); + System.out.println(faceIDs.size() + "\t\t Number of files"); + System.out.println(HumanFaceFactory.instance()); + + ////////////////////////////////////////////// + System.out.println(); + System.out.println("Computation of symmetry planes:"); + startTime = System.currentTimeMillis(); + batch.computeSymmetryPlanes(faceIDs); + batch.computeSymmetryPlanes(Collections.singletonList(primaryFaceId)); endTime = System.currentTimeMillis(); printTimes(startTime, endTime, faceIDs.size()); - System.out.println("Number of files: " + faceIDs.size()); - System.out.println("File cache stats: " + HumanFaceFactory.instance()); ////////////////////////////////////////////// //UndersamplingStrategy strategy = new NoUndersampling(); @@ -59,7 +69,7 @@ public class BatchTests { System.out.println(); System.out.println("ICP registration with " + strategy + ":"); startTime = System.currentTimeMillis(); - batch.registerToPrimaryFace(primaryFacePath, faceIDs, 10, 0.05, strategy); + batch.superimposeOnPrimaryFace(primaryFaceId, faceIDs, 10, 0.05, strategy, true); endTime = System.currentTimeMillis(); printTimes(startTime, endTime, faceIDs.size()); System.out.printf("%.2f \t\t Avg number of iterations", batch.getAvgNumIcpIterations()); @@ -69,33 +79,14 @@ public class BatchTests { System.out.println(); System.out.println("Computation of averaged template face:"); startTime = System.currentTimeMillis(); - batch.computeTemplateFace(primaryFacePath, faceIDs); + batch.computeTemplateFace(primaryFaceId, faceIDs); endTime = System.currentTimeMillis(); printTimes(startTime, endTime, faceIDs.size()); - System.out.println("Writing average template to " + templateFacePath + "..."); + System.out.println("Writing average template to " + templateFacePath); MeshObjExporter exp = new MeshObjExporter(batch.getAvgTemplateFace().getMeshModel()); exp.exportModelToObj(new File(templateFacePath)); } - private static List<String> readFiles(String dir) throws IOException { - List<String> faces = new ArrayList<>(); - for (File subdir : (new File(dir)).listFiles(File::isDirectory)) { - if (subdir.getName().matches("^\\d\\d$")) { - for (File file: subdir.listFiles(File::isFile)) { - if (file.getName().endsWith(".obj")) { - //System.out.print(file.getName() + " "); - //if (file.getName().endsWith("00002_01_ECA.obj")) { // FOT DEBUGING - String faceId = HumanFaceFactory.instance().loadFace(file); - faces.add(faceId); - //} - } - } - } - } - //System.out.println(); - return faces; - } - private static void printTimes(long startTime, long endTime, int numFaces) { double timeDist = endTime - startTime; double avgTime = (timeDist/numFaces)/1000.0; diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java index 9b276361dc8edd7367e630c0517b3e97b86ea7fd..e1c4e1a5c48fed5ab54f91b31f9291cbd7423e5b 100644 --- a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java +++ b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java @@ -3,7 +3,7 @@ package cz.fidentis.analyst.tests; import cz.fidentis.analyst.face.HumanFace; import cz.fidentis.analyst.kdtree.KdTree; import cz.fidentis.analyst.mesh.core.MeshFacet; -import cz.fidentis.analyst.symmetry.Config; +import cz.fidentis.analyst.symmetry.SymmetryConfig; import cz.fidentis.analyst.symmetry.Plane; import cz.fidentis.analyst.symmetry.SignificantPoints; import cz.fidentis.analyst.symmetry.SymmetryEstimator; @@ -105,7 +105,7 @@ public class EfficiencyTests { private static void printSymmetryPlane(HumanFace face, boolean concurrently, SignificantPoints.CurvatureAlg curvatureAlg) { long startTime = System.currentTimeMillis(); - SymmetryEstimator est = new SymmetryEstimator(Config.getDefault(), curvatureAlg); + SymmetryEstimator est = new SymmetryEstimator(new SymmetryConfig(), curvatureAlg); face.getMeshModel().compute(est, false); Plane plane = est.getSymmetryPlane(concurrently); long endTime = System.currentTimeMillis(); diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java index ee4e6ca05b606deb0731e229ce405fcb00e1c3b2..3de3a67302e7aeebe9e15db3d22d40259f64b20a 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java @@ -133,6 +133,52 @@ public class KdTree implements Serializable { return ret; } + /** + * Return number of nodes in the k-d tree. + * @return number of nodes in the k-d tree + */ + public int getNumNodes() { + int ret = 0; + Queue<KdNode> queue = new LinkedList<>(); + queue.add(root); + + while (!queue.isEmpty()) { + KdNode node = queue.poll(); + if (node == null) { + continue; + } + queue.add(node.getLesser()); + queue.add(node.getGreater()); + ret++; + } + + return ret; + } + + /** + * Return the length of the longest path. + * @return Return the length of the longest path. + */ + public int getDepth() { + int depth = 0; + Queue<KdNode> queue = new LinkedList<>(); + queue.add(root); + + while (!queue.isEmpty()) { + KdNode node = queue.poll(); + if (node == null) { + continue; + } + queue.add(node.getLesser()); + queue.add(node.getGreater()); + if (node.getDepth() > depth) { + depth = node.getDepth(); + } + } + + return depth; + } + /** * Visits this facet. *