Skip to content
Snippets Groups Projects
Commit 578cc3bb authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Resolve "Accelerate N:N"

parent b57b6375
No related branches found
No related tags found
No related merge requests found
Showing with 43 additions and 61 deletions
...@@ -25,9 +25,6 @@ import java.util.List; ...@@ -25,9 +25,6 @@ import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
import javax.imageio.ImageIO; 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. * This class encapsulates data for a 3D scan of a single human face.
...@@ -47,7 +44,11 @@ public class HumanFace implements Serializable { ...@@ -47,7 +44,11 @@ public class HumanFace implements Serializable {
private MeshModel meshModel; 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; private Plane symmetryPlane;
......
...@@ -5,8 +5,6 @@ import com.esotericsoftware.kryo.io.Input; ...@@ -5,8 +5,6 @@ import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy; import com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy;
import cz.fidentis.analyst.Logger; 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.CornerTable;
import cz.fidentis.analyst.mesh.core.CornerTableRow; import cz.fidentis.analyst.mesh.core.CornerTableRow;
import cz.fidentis.analyst.mesh.core.MeshFacetImpl; import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
...@@ -121,8 +119,6 @@ public class HumanFaceFactory { ...@@ -121,8 +119,6 @@ public class HumanFaceFactory {
HumanFaceFactory.kryo.register(CornerTableRow.class); HumanFaceFactory.kryo.register(CornerTableRow.class);
HumanFaceFactory.kryo.register(BBox.class); HumanFaceFactory.kryo.register(BBox.class);
HumanFaceFactory.kryo.register(Plane.class); HumanFaceFactory.kryo.register(Plane.class);
HumanFaceFactory.kryo.register(KdTree.class);
HumanFaceFactory.kryo.register(KdNode.class);
HumanFaceFactory.kryo.register(Point3d.class); HumanFaceFactory.kryo.register(Point3d.class);
HumanFaceFactory.kryo.register(Vector3d.class); HumanFaceFactory.kryo.register(Vector3d.class);
HumanFaceFactory.kryo.register(ArrayList.class); HumanFaceFactory.kryo.register(ArrayList.class);
......
...@@ -6,13 +6,15 @@ import cz.fidentis.analyst.mesh.core.MeshFacet; ...@@ -6,13 +6,15 @@ import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshFacetImpl; import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
import cz.fidentis.analyst.mesh.core.MeshModel; import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.visitors.mesh.HausdorffDistance; import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; 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.Point3d;
import javax.vecmath.Vector3d; import javax.vecmath.Vector3d;
...@@ -63,9 +65,13 @@ public class AvgFaceConstructor extends KdTreeVisitor { ...@@ -63,9 +65,13 @@ public class AvgFaceConstructor extends KdTreeVisitor {
} }
// fill vertTarns with empty list for each facet // fill vertTarns with empty list for each facet
templateFacets.parallelStream().forEach( templateFacets.parallelStream().forEach(f -> {
f -> this.transformations.put(f, new ArrayList<>(f.getVertices().size())) //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 { ...@@ -90,24 +96,20 @@ public class AvgFaceConstructor extends KdTreeVisitor {
HausdorffDistance.Strategy.POINT_TO_POINT, HausdorffDistance.Strategy.POINT_TO_POINT,
false, // relative distance false, // relative distance
true, // parallel computation true, // parallel computation
false // auto cut false // auto crop
); );
transformations.keySet().forEach(f -> hDist.visitMeshFacet(f)); transformations.keySet().forEach(f -> hDist.visitMeshFacet(f));
// compute shifts of my vertices // compute shifts of my vertices
for (MeshFacet myFacet: transformations.keySet()) { for (MeshFacet myFacet: transformations.keySet()) {
List<Point3d> closestPoints = hDist.getNearestPoints().get(myFacet); List<Point3d> closestPoints = hDist.getNearestPoints().get(myFacet);
for (int i = 0; i < myFacet.getNumberOfVertices(); i++) {
//Vector3d moveDir = new Vector3d(myFacet.getVertex(i).getPosition()); // shift vertices concurrently
//moveDir.sub(closestPoints.get(i)); IntStream.range(0, closestPoints.size()).parallel().forEach(i -> {
Vector3d moveDir = new Vector3d(closestPoints.get(i)); Vector3d moveDir = new Vector3d(closestPoints.get(i));
moveDir.sub(myFacet.getVertex(i).getPosition()); moveDir.sub(myFacet.getVertex(i).getPosition());
if (transformations.get(myFacet).size() < myFacet.getNumberOfVertices()) { // First inspected facet transformations.get(myFacet).get(i).add(moveDir);
transformations.get(myFacet).add(moveDir); });
} else {
transformations.get(myFacet).get(i).add(moveDir);
}
}
} }
} }
...@@ -120,11 +122,11 @@ public class AvgFaceConstructor extends KdTreeVisitor { ...@@ -120,11 +122,11 @@ public class AvgFaceConstructor extends KdTreeVisitor {
avgMeshModel = new MeshModel(); avgMeshModel = new MeshModel();
for (MeshFacet f: transformations.keySet()) { // clone all facets of the template face for (MeshFacet f: transformations.keySet()) { // clone all facets of the template face
MeshFacet newFacet = new MeshFacetImpl(f); 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)); Vector3d tr = new Vector3d(transformations.get(f).get(i));
tr.scale(1.0/numInspectedFacets); tr.scale(1.0/numInspectedFacets);
newFacet.getVertex(i).getPosition().add(tr); newFacet.getVertex(i).getPosition().add(tr);
} });
avgMeshModel.addFacet(newFacet); avgMeshModel.addFacet(newFacet);
} }
} }
......
...@@ -31,7 +31,7 @@ import java.util.stream.DoubleStream; ...@@ -31,7 +31,7 @@ import java.util.stream.DoubleStream;
public class ApproxHausdorffDistTask extends SimilarityTask { public class ApproxHausdorffDistTask extends SimilarityTask {
private final Stopwatch totalTime = new Stopwatch("Total computation time:\t\t"); 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 loadTime = new Stopwatch("Disk access time:\t\t");
private final Stopwatch kdTreeConstructionTime = new Stopwatch("KD trees construction 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"); private final Stopwatch finalHdComputationTime = new Stopwatch("Hausdorff distance finalization time:\t");
...@@ -103,7 +103,9 @@ public class ApproxHausdorffDistTask extends SimilarityTask { ...@@ -103,7 +103,9 @@ public class ApproxHausdorffDistTask extends SimilarityTask {
.flatMap(List::stream).collect(Collectors.toList())); .flatMap(List::stream).collect(Collectors.toList()));
hdComputationTime.stop(); 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 { } else {
distCache.add(DoubleStream.generate(() -> 0.0d) distCache.add(DoubleStream.generate(() -> 0.0d)
.limit(templateFace.getMeshModel().getNumVertices()) .limit(templateFace.getMeshModel().getNumVertices())
...@@ -133,8 +135,8 @@ public class ApproxHausdorffDistTask extends SimilarityTask { ...@@ -133,8 +135,8 @@ public class ApproxHausdorffDistTask extends SimilarityTask {
protected void printTimeStats() { protected void printTimeStats() {
Logger.print(hdComputationTime.toString()); Logger.print(hdComputationTime.toString());
Logger.print(loadTime.toString());
Logger.print(finalHdComputationTime.toString()); Logger.print(finalHdComputationTime.toString());
Logger.print(loadTime.toString());
Logger.print(kdTreeConstructionTime.toString()); Logger.print(kdTreeConstructionTime.toString());
Logger.print(totalTime.toString()); Logger.print(totalTime.toString());
} }
......
...@@ -128,7 +128,7 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> { ...@@ -128,7 +128,7 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> {
if (computeAvgFace) { // AVG template face if (computeAvgFace) { // AVG template face
kdTreeConstructionTime.start(); 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(); kdTreeConstructionTime.stop();
avgFaceComputationTime.start(); avgFaceComputationTime.start();
...@@ -139,7 +139,7 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> { ...@@ -139,7 +139,7 @@ public class IcpTask extends SwingWorker<MeshModel, HumanFace> {
avgFaceComputationTime.stop(); 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 publish(face); // update progress bar and possibly render the transformed face
} }
......
...@@ -189,8 +189,8 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL ...@@ -189,8 +189,8 @@ public class RegistrationAction extends ControlPanelAction implements HumanFaceL
protected void applyProcrustes() { protected void applyProcrustes() {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
controlPanel, controlPanel,
"This method is not finished yet", "This method is not finished yet (neither feature points nor symmetry planes are transformed properly)",
"Neither feature points nor symmetry planes are transformed properly", "Warning",
JOptionPane.INFORMATION_MESSAGE); JOptionPane.INFORMATION_MESSAGE);
Logger out = Logger.measureTime(); Logger out = Logger.measureTime();
......
...@@ -88,6 +88,9 @@ public class RegistrationPanel extends ControlPanel { ...@@ -88,6 +88,9 @@ public class RegistrationPanel extends ControlPanel {
jButtonInfo1.addActionListener((ActionEvent e) -> { jButtonInfo1.addActionListener((ActionEvent e) -> {
showAutoAlignmentInfo(); showAutoAlignmentInfo();
}); });
jFormattedTextField1.setValue(Double.valueOf(0.3));
jFormattedTextField2.setValue(Integer.valueOf(50));
} }
/** /**
...@@ -166,7 +169,7 @@ public class RegistrationPanel extends ControlPanel { ...@@ -166,7 +169,7 @@ public class RegistrationPanel extends ControlPanel {
} }
public double getMinIcpErrorParam() { public double getMinIcpErrorParam() {
return ((Number) jFormattedTextField2.getValue()).doubleValue(); return ((Number) jFormattedTextField1.getValue()).doubleValue();
} }
/** /**
......
package cz.fidentis.analyst.kdtree; package cz.fidentis.analyst.kdtree;
import cz.fidentis.analyst.mesh.core.MeshFacet; import cz.fidentis.analyst.mesh.core.MeshFacet;
import java.io.Serializable;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
...@@ -15,7 +14,7 @@ import javax.vecmath.Point3d; ...@@ -15,7 +14,7 @@ import javax.vecmath.Point3d;
* *
* @author Maria Kocurekova * @author Maria Kocurekova
*/ */
public class KdNode implements Serializable { public class KdNode /* implements Serializable */ {
/** /**
* Current depth in the kd-tree * Current depth in the kd-tree
...@@ -37,7 +36,6 @@ public class KdNode implements Serializable { ...@@ -37,7 +36,6 @@ public class KdNode implements Serializable {
*/ */
private KdNode lesser = null; private KdNode lesser = null;
private KdNode greater = null; private KdNode greater = null;
private KdNode parent;
/** /**
* Constructor of KdNode * Constructor of KdNode
...@@ -61,7 +59,6 @@ public class KdNode implements Serializable { ...@@ -61,7 +59,6 @@ public class KdNode implements Serializable {
} }
this.facets.putIfAbsent(facet, index); this.facets.putIfAbsent(facet, index);
this.depth = depth; this.depth = depth;
this.parent = parent;
this.location = new Point3d(facet.getVertex(index).getPosition()); this.location = new Point3d(facet.getVertex(index).getPosition());
} }
...@@ -92,7 +89,6 @@ public class KdNode implements Serializable { ...@@ -92,7 +89,6 @@ public class KdNode implements Serializable {
this.facets.putIfAbsent(facets.get(i), indices.get(i)); this.facets.putIfAbsent(facets.get(i), indices.get(i));
} }
this.depth = depth; this.depth = depth;
this.parent = parent;
this.location = new Point3d(facets.get(0).getVertex(indices.get(0)).getPosition()); this.location = new Point3d(facets.get(0).getVertex(indices.get(0)).getPosition());
} }
...@@ -138,15 +134,6 @@ public class KdNode implements Serializable { ...@@ -138,15 +134,6 @@ public class KdNode implements Serializable {
return greater; 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. * Set lesser node.
* *
...@@ -179,17 +166,6 @@ public class KdNode implements Serializable { ...@@ -179,17 +166,6 @@ public class KdNode implements Serializable {
return Collections.unmodifiableMap(facets); 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 @Override
public String toString() { public String toString() {
String ret = ""; String ret = "";
......
...@@ -34,7 +34,8 @@ import javax.vecmath.Point3d; ...@@ -34,7 +34,8 @@ import javax.vecmath.Point3d;
/** /**
* Utility class for loading human face from OBJ data format. * Utility class for loading human face from OBJ data format.
* Expects only one human face in one file stored as one object. * Expects only one human face in one file stored as one object.
* @author Marek Bařinka *
* @author Marek Barinka
*/ */
public class MeshObjLoader { public class MeshObjLoader {
...@@ -71,7 +72,7 @@ public class MeshObjLoader { ...@@ -71,7 +72,7 @@ public class MeshObjLoader {
/** /**
* Parse OBJObject into MeshModel * Parse OBJObject into MeshModel
* @param model Model is needed in future. It's holding data pools * @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 * @return Returns complete model
* @throws IOException Data are corrupted * @throws IOException Data are corrupted
*/ */
...@@ -96,7 +97,7 @@ public class MeshObjLoader { ...@@ -96,7 +97,7 @@ public class MeshObjLoader {
MeshFacet meshFacet = new MeshFacetImpl(); MeshFacet meshFacet = new MeshFacetImpl();
Map<MeshPoint, Integer> vertices = new HashMap<>(); Map<MeshPoint, Integer> vertices = new HashMap<>();
Map<Edge, Integer> edges = new HashMap<>(); Map<Edge, Integer> edges = new HashMap<>();
for (OBJFace face : mesh.getFaces()) { for (OBJFace face : mesh.getFaces()) {
processFace(model, face, meshFacet, vertices, edges); processFace(model, face, meshFacet, vertices, edges);
} }
...@@ -191,7 +192,8 @@ public class MeshObjLoader { ...@@ -191,7 +192,8 @@ public class MeshObjLoader {
/** /**
* Helper class for finding opposite corners * Helper class for finding opposite corners
* @author Marek Bařinka *
* @author Marek Barinka
*/ */
private static class Edge { private static class Edge {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment