Newer
Older
package cz.fidentis.analyst.tests;
import cz.fidentis.analyst.batch.Stopwatch;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.face.HumanFaceUtils;
import cz.fidentis.analyst.icp.UndersampledMeshFacet;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
import cz.fidentis.analyst.visitors.mesh.sampling.CurvatureSampling;
import cz.fidentis.analyst.visitors.mesh.sampling.NoSampling;
import cz.fidentis.analyst.visitors.mesh.sampling.PointSampling;
import cz.fidentis.analyst.visitors.mesh.sampling.RandomSampling;
import cz.fidentis.analyst.visitors.mesh.sampling.UniformSpaceSampling;
import cz.fidentis.analyst.visitors.mesh.sampling.UniformSurfaceSampling;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;
/**
* This class evaluates efficiency (acceleration) and precision of ICP with different
* point sampling algorithms and different downsampling strength.
*
* @author Radek Oslejsek
*/
public class IcpDownsampling {
private static final String DATA_DIR = "../../analyst-data-antropologie/_ECA";
private static final int MAX_SAMPLES = 500;
/**
* Main method
* @param args Input arguments
* @throws IOException on IO error
*/
public static void main(String[] args) throws IOException, ClassNotFoundException, Exception {
List<Path> faces = Files.list(new File(DATA_DIR).toPath())
.filter(f -> f.toString().endsWith(".obj"))
.sorted()
.limit(MAX_SAMPLES)
.collect(Collectors.toList());
SortedMap<Integer, Stopwatch> efficiency = new TreeMap<>(Collections.reverseOrder());
SortedMap<Integer, List<Double>> precision = new TreeMap<>(Collections.reverseOrder());
//String alg = "gaussian";
//String alg = "uniform space";
for (int i = 0; i < faces.size(); i += 5) {
for (int j = i; j < faces.size(); j += 5) { // starts with "i"!
if (i != j) { // register only different faces
System.out.println();
System.out.println("Iteration: " + counter);
compareFaces(faces.get(i), faces.get(j), efficiency, precision, alg);
printResults(efficiency, precision, counter, alg);
counter++;
}
}
}
}
protected static void printResults(SortedMap<Integer, Stopwatch> efficiency, SortedMap<Integer, List<Double>> precision, double counter, String sampling) {
System.out.println();
System.out.println("Avg. Time (ms) - " + sampling + " sampling:");
efficiency.entrySet().forEach(e -> {
System.out.println(e.getKey() + ";" + (e.getValue().getTotalTime() / counter));
});
System.out.println();
System.out.println("Avg. Precision - " + sampling + " sampling:");
System.out.println("# samples;dissimilarity;variance");
precision.entrySet().forEach(e -> {
double avg = e.getValue().stream()
.mapToDouble(val -> val)
.summaryStatistics()
.getAverage();
double variance = e.getValue().stream()
.mapToDouble(val -> Math.pow(Math.abs(val - avg), 2))
.average()
.orElse(-1);
System.out.println(e.getKey() + ";" + avg + ";" + variance);
});
}
protected static void compareFaces(
Path priFacePath, Path secFacePath,
Map<Integer, Stopwatch> efficiency, Map<Integer, List<Double>> precision,
String samp) throws IOException {
//double[] percs = new double[]{0.5,1,2,4,6,8,10,15,20,30,40,50,60,70,80,85,90,92,94,96,98,100};
//double[] percs = new double[]{100,90,80,70,60,50,40,30,20,15,10,8,6,4,2,1,0.5};
//int[] samples = new int[]{0,200,500,1000,2000,3000,5000,10000,20000,30000,40000};
//int[] samples = new int[]{0,200,500,1000,2000,3000,5000};
//int[] samples = new int[]{50,100,150,300,400};
//int[] samples = new int[]{0,50,100,150,200,300,400,500,1000,2000,3000,5000,10000,20000,30000};
//int[] samples = new int[]{5,10,20,30,40,50};
int[] samples = new int[]{0,40,50,100,150,200,300,400,500,1000,2000,3000,5000,10000,20000,30000};
HumanFace priFace = new HumanFace(priFacePath.toFile());
priFace.computeKdTree(false);
HumanFace secFaceFromFile = new HumanFace(secFacePath.toFile());
System.out.println(secFaceFromFile.getShortName());
for (int i: samples) {
HumanFace secFace = new HumanFace(new MeshModel(secFaceFromFile.getMeshModel()), secFaceFromFile.getId());
PointSampling secSampling;
PointSampling priSampling;
switch (samp) {
case "random":
secSampling = new RandomSampling();
priSampling = new RandomSampling();
break;
case "gaussian":
secSampling = new CurvatureSampling(CurvatureSampling.CurvatureAlg.GAUSSIAN);
priSampling = new CurvatureSampling(CurvatureSampling.CurvatureAlg.GAUSSIAN);
break;
case "uniform space":
secSampling = new UniformSpaceSampling();
priSampling = new UniformSpaceSampling();
secSampling = new UniformSurfaceSampling();
priSampling = new UniformSurfaceSampling();
default:
return;
}
/*
if (samples[i] == 0) {
secSampling = new NoSampling();
priSampling = new NoSampling();
} else {
secSampling.setRequiredSamples(i);
priSampling.setRequiredSamples(i);
}
*/
priSampling = new NoSampling();
priSampling.setRequiredSamples(i);
secSampling.setRequiredSamples(5000);
efficiency.computeIfAbsent(i, k-> new Stopwatch("")).start();
HumanFaceUtils.alignMeshes(
downsamplePriFace(priFace, priSampling),
secFace, // is transformed
100, // max iterations
false,// scale
0.05, // error
secSampling,
false // drop k-d tree of the secFace, if exists
);
/*
HumanFaceUtils.alignMeshes( /// ORIG SETTING
priFace,
secFace, // is transformed
100, // max iterations
false,// scale
0.05, // error
secSampling,
false // drop k-d tree of the secFace, if exists
efficiency.get(i).stop();
System.out.println(" Primary face: " + priSampling);
System.out.println("Secondary face: " + secSampling);
HausdorffDistance hd = new HausdorffDistance(
priFace.getKdTree(),
HausdorffDistance.Strategy.POINT_TO_POINT,
false, // relative distance
true, // parallel
true // crop
);
secFace.getMeshModel().compute(hd);
precision.computeIfAbsent(i, k -> new ArrayList<>()).add(hd.getStats().getAverage());
}
System.out.println();
}
private static HumanFace downsamplePriFace(HumanFace priFace, PointSampling sampling) {
MeshFacet reducedFacet = new UndersampledMeshFacet(priFace.getMeshModel().getFacets().get(0), sampling);
MeshModel model = new MeshModel();
model.setFacets(List.of(reducedFacet));
HumanFace ret = new HumanFace(model, priFace.getId());
return ret;
}