From cda9762b868cb58be3fed5c94cfbb7d0a2c9395e Mon Sep 17 00:00:00 2001 From: Jakub Kolman <kubokolman@gmail.com> Date: Tue, 30 Nov 2021 15:03:53 +0100 Subject: [PATCH] [#38] refactor: adding documantation and deleting dead code --- .../procrustes/ProcrustesAnalysis.java | 199 +++--------------- .../ProcrustesAnalysisFaceModel.java | 36 +--- .../utils/ProcrustesAnalysisUtils.java | 77 ------- .../analyst/feature/api/IPosition.java | 1 + 4 files changed, 44 insertions(+), 269 deletions(-) diff --git a/Comparison/src/main/java/cz/fidentis/analyst/procrustes/ProcrustesAnalysis.java b/Comparison/src/main/java/cz/fidentis/analyst/procrustes/ProcrustesAnalysis.java index 400b13e9..43280fe2 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/procrustes/ProcrustesAnalysis.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/procrustes/ProcrustesAnalysis.java @@ -27,9 +27,6 @@ public class ProcrustesAnalysis { private Point3d modelCentroid1; private Point3d modelCentroid2; - // based on some example models this is an approximate centroid of feature points -// private Point3d centroid = new Point3d(0, 0, 0); - /** * Constructor * @@ -48,12 +45,8 @@ public class ProcrustesAnalysis { throw new ProcrustesAnalysisException("Lists of feature points do not have the same size"); } -// this.orderedFeaturePointList1 = new ArrayList<>(model1.getFeaturePointsMap().values()); -// this.orderedFeaturePointList2 = new ArrayList<>(model2.getFeaturePointsMap().values()); - - if (!featurePointTypesEquivalence( - model1.getFeaturePointValues(), - model2.getFeaturePointValues())) { + if (!ProcrustesAnalysisUtils.checkFeaturePointsType( + model1.getFeaturePointValues(), model2.getFeaturePointValues())) { throw new ProcrustesAnalysisException("Lists of feature points do not have the same feature point types"); } @@ -62,85 +55,42 @@ public class ProcrustesAnalysis { this.modelCentroid1 = ProcrustesAnalysisUtils.findCentroidOfFeaturePoints(model1.getFeaturePointValues()); this.modelCentroid2 = ProcrustesAnalysisUtils.findCentroidOfFeaturePoints(model2.getFeaturePointValues()); - - } - - public ProcrustesAnalysisFaceModel getFaceModel1() { - return faceModel1; - } - - public ProcrustesAnalysisFaceModel getFaceModel2() { - return faceModel2; } + /** + * Method called for analysis after creating initial data in constructor. This method causes superimposition + * and rotation of the faces. + */ public void analyze() { - List<SimpleMatrix> transformation = new ArrayList<>(); - this.superImpose(); this.rotate(); } - private Point3d computeCentroidsDistance(Point3d centroid1, Point3d centroid2) { - double x = (centroid1.x - centroid2.x); - double y = (centroid1.y - centroid2.y); - double z = (centroid1.z - centroid2.z); - - Point3d computedCentroid = new Point3d(x, y, z); - return computedCentroid; - } - /** * Imposes two face models (lists of feature points and vertices) over each other */ private void superImpose() { - - // moves vertices of face models -// moveModelToSameOrigin(this.faceModel2.getVertices(), this.faceModel2.getFeaturePointsMap()); - - normalize(this.faceModel1, this.modelCentroid1); - normalize(this.faceModel2, this.modelCentroid2); - -// moveVertices(this.modelCentroid1, featurePointModel1.getVertices()); -// moveModelToPoint(this.modelCentroid1, faceModel1.getVertices(), faceModel1.getFeaturePointsMap()); -// moveModelToPoint(this.modelCentroid1, faceModel2.getVertices(), faceModel2.getFeaturePointsMap()); - } - - private void normalize(ProcrustesAnalysisFaceModel faceModel, Point3d centroid) { -// float size = ProcrustesAnalysisUtils.countSize(centroid, faceModel.getFeaturePointsMap()); - centerToOrigin(faceModel, centroid); + centerToOrigin(this.faceModel1, this.modelCentroid1); + centerToOrigin(this.faceModel2, this.modelCentroid2); } + /** + * Centers given face model to origin that is given centroid. + * Moves all vertices and feature points by value of difference between vertex/feature point and centroid. + * + * @param faceModel + * @param centroid + */ private void centerToOrigin(ProcrustesAnalysisFaceModel faceModel, Point3d centroid) { for (FeaturePoint fp: faceModel.getFeaturePointsMap().values()) { fp.getPosition().x -= centroid.x; fp.getPosition().y -= centroid.y; fp.getPosition().z -= centroid.z; } - SimpleMatrix centeredVertices = new SimpleMatrix( - faceModel.getVerticesMatrix().numRows(), faceModel.getVerticesMatrix().numCols()); - for (int i = 0; i < faceModel.getVerticesMatrix().numRows(); i++) { - centeredVertices.set(i, 0, faceModel.getVerticesMatrix().get(i, 0) - centroid.x); - centeredVertices.set(i, 1, faceModel.getVerticesMatrix().get(i, 1) - centroid.y); - centeredVertices.set(i, 2, faceModel.getVerticesMatrix().get(i, 2) - centroid.z); - } - faceModel.setVerticesMatrix(centeredVertices); - } - - private void moveModelToSameOrigin(List<MeshPoint> vertices, HashMap<Integer, FeaturePoint> featurePointsMap) { - Point3d diff = computeCentroidsDistance(this.modelCentroid1, this.modelCentroid2); - moveModelToPoint(diff, vertices, featurePointsMap); - } - - private void moveModelToPoint(Point3d centroid, List<MeshPoint> vertices, HashMap<Integer, FeaturePoint> featurePointsMap) { - moveVertices(centroid, vertices); - moveFeaturePointsToVertices(centroid, featurePointsMap); - } - - private void moveFeaturePointsToVertices(Point3d centroid, HashMap<Integer, FeaturePoint> featurePointsMap) { - for (FeaturePoint fp : featurePointsMap.values()) { - fp.getPosition().x = fp.getPosition().x + centroid.x; - fp.getPosition().y = fp.getPosition().y + centroid.y; - fp.getPosition().z = fp.getPosition().z + centroid.z; + for (MeshPoint v : faceModel.getVertices()) { + v.getPosition().x = v.getX() - centroid.x; + v.getPosition().y = v.getY() - centroid.y; + v.getPosition().z = v.getZ() - centroid.z; } } @@ -148,11 +98,6 @@ public class ProcrustesAnalysis { * By rotation of matrices solves orthogonal procrustes problem */ private void rotate() { - - // There is no reason trying to rotate less than 3 elements - if (this.getFaceModel1().getFeaturePointsMap().size() < 3) { - throw new ProcrustesAnalysisException("To do procrustes analysis models have to have at least 3 feature points"); - } SimpleMatrix primaryMatrix = ProcrustesAnalysisUtils.createMatrixFromList(this.faceModel2.getFeaturePointValues()); SimpleMatrix transposedMatrix = ProcrustesAnalysisUtils.createMatrixFromList( this.faceModel1.getFeaturePointValues()).transpose(); @@ -160,44 +105,23 @@ public class ProcrustesAnalysis { SimpleMatrix svdMatrix = transposedMatrix.mult(primaryMatrix); SimpleSVD<SimpleMatrix> singularValueDecomposition = svdMatrix.svd(); SimpleMatrix transposedU = singularValueDecomposition.getU().transpose(); - SimpleMatrix r = singularValueDecomposition.getV().mult(transposedU); - primaryMatrix = primaryMatrix.mult(r); + SimpleMatrix rotationMatrix = singularValueDecomposition.getV().mult(transposedU); + primaryMatrix = primaryMatrix.mult(rotationMatrix); this.faceModel2.setFeaturePointsMap( ProcrustesAnalysisUtils.createFeaturePointMapFromMatrix( primaryMatrix, this.faceModel2)); -// for (int i = 0; i < this.faceModel2.getFeaturePointTypeCorrespondence().size(); i++) { -// FeaturePoint fp = new FeaturePoint( -// primaryMatrix.get(i, 0), -// primaryMatrix.get(i, 1), -// primaryMatrix.get(i, 2), -// this.faceModel2.getFeaturePointsMap().get( -// this.faceModel2.getFeaturePointTypeCorrespondence().get(i)).getFeaturePointType() -// ); -// this.faceModel2.getFeaturePointsMap().put(i, fp); -// } - - rotateVertices(this.faceModel2.getVertices(), r); - -// SimpleMatrix rotatedVertices = this.faceModel2.getVerticesMatrix().mult(r); -// createListFromMatrix(rotatedVertices, this.faceModel2); + rotateVertices(this.faceModel2.getVertices(), rotationMatrix); } - private void createListFromMatrix(SimpleMatrix rotatedVertices, ProcrustesAnalysisFaceModel faceModel) { - if (faceModel.getVertices() != null) { - for (int i = 0; i < rotatedVertices.numRows(); i++) { - faceModel.getVertices().get(i).getPosition().x = rotatedVertices.get(i, 0); - faceModel.getVertices().get(i).getPosition().y = rotatedVertices.get(i, 1); - faceModel.getVertices().get(i).getPosition().z = rotatedVertices.get(i, 2); - } - } - } /** - * Rotates every vertex of model by given matrix + * Rotates all vertices. * - * @param model + * For more details check out single vertex rotation {@link #rotateVertex}. + * + * @param vertices * @param matrix */ // if rotated vertices are drawn immediately it is better to set them after rotating them all @@ -210,7 +134,13 @@ public class ProcrustesAnalysis { } } - public static void rotateVertex(MeshPoint v,SimpleMatrix matrix) { + /** + * Rotates vertex v by simulating matrix multiplication with given matrix + * + * @param v + * @param matrix + */ + private static void rotateVertex(MeshPoint v, SimpleMatrix matrix) { double x = ((v.getX() * matrix.get(0, 0)) + (v.getY() * matrix.get(1, 0)) + (v.getZ() * matrix.get(2, 0))); @@ -225,67 +155,4 @@ public class ProcrustesAnalysis { v.getPosition().z = z; } - /** - * Calculates new vertices adjusted to the centroid by method {@see findCenteroidOfFeaturePoints}, - * so moved featurepoints would correspond with the same place on face as they did before. - * - * @param centroid - * @param vertices - * @return - */ - private void moveVertices(Point3d centroid, List<MeshPoint> vertices) { - if (vertices != null && centroid != null) { -// List<MeshPoint> movedVertices = null; - for (MeshPoint v : vertices) { - v.getPosition().x = (v.getPosition().x + centroid.x); - v.getPosition().y = (v.getPosition().y + centroid.y); - v.getPosition().z = (v.getPosition().z + centroid.z); - } - } else { - throw new ProcrustesAnalysisException("Could not compute vertices locations after moving the centroid from model to feature points"); - } - } - - /** - * Creates sorted feature point lists and compares them whether they have - * the same feature point types. - * - * @param fpList1 - * @param fpList2 - * @return - */ - private boolean featurePointTypesEquivalence(List<FeaturePoint> fpList1, List<FeaturePoint> fpList2) { - return ProcrustesAnalysisUtils.checkFeaturePointsType(fpList1, fpList2); - } - - /** - * Calculate scaling ratio of how much the appropriate object corresponding - * to the second feature point list has to be scale up or shrunk. - * <p> - * If returned ratioValue is greater 1 then it means that the second object - * should be scaled up ratioValue times. If returned ratioValue is smaller 1 - * than the second object should be shrunk. - * - * @return ratioValue - */ -// private double calculateScalingValue() { -// double[] distancesOfList1 = ProcrustesAnalysisUtils.calculateMeanDistancesFromOrigin( -// this.faceModel1.getFeaturePointValues()); -// double[] distancesOfList2 = ProcrustesAnalysisUtils.calculateMeanDistancesFromOrigin( -// this.faceModel2.getFeaturePointValues()); -// -// double[] ratioArray = new double[distancesOfList1.length]; -// double ratioValue = 0; -// -// for (int i = 0; i < distancesOfList1.length; i++) { -// ratioArray[i] += distancesOfList1[i] / distancesOfList2[i]; -// } -// -// for (double ratio : ratioArray) { -// ratioValue += ratio; -// } -// -// return ratioValue / distancesOfList1.length; -// } - } diff --git a/Comparison/src/main/java/cz/fidentis/analyst/procrustes/ProcrustesAnalysisFaceModel.java b/Comparison/src/main/java/cz/fidentis/analyst/procrustes/ProcrustesAnalysisFaceModel.java index d828f00f..35b5114b 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/procrustes/ProcrustesAnalysisFaceModel.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/procrustes/ProcrustesAnalysisFaceModel.java @@ -26,7 +26,6 @@ public class ProcrustesAnalysisFaceModel { private final HumanFace humanFace; private HashMap<Integer, FeaturePoint> featurePointsMap; // sorted by feature point type private List<MeshPoint> vertices; - private SimpleMatrix verticesMatrix; private MeshModel meshModel; private final HashMap<Integer, Integer> featurePointTypeCorrespondence; @@ -43,8 +42,6 @@ public class ProcrustesAnalysisFaceModel { this.featurePointsMap = createFeaturePointMap( ProcrustesAnalysisUtils.sortListByFeaturePointType(modifiableFeaturePointList)); this.featurePointTypeCorrespondence = createFeaturePointTypeCorrespondence(face.getFeaturePoints()); - this.verticesMatrix = ProcrustesAnalysisUtils.createMatrixFromList(modifiableVertices); -// this.featurePointMatrix = ProcrustesAnalysisUtils.createMatrixFromList(modifiableFeaturePointList); } /** @@ -74,28 +71,19 @@ public class ProcrustesAnalysisFaceModel { return featurePointsMap; } + public HashMap<Integer, Integer> getFeaturePointTypeCorrespondence() { + return featurePointTypeCorrespondence; + } + /** - * sets vertices map and also sets feature point on human face for visualisation + * Creates feature point hash map for internal use in Procrustes Analysis. + * + * Map key is feature point type (Integer). + * Value is feature point itself. * - * @param verticesMatrix + * @param featurePointList + * @return */ - public void setVerticesMatrix(SimpleMatrix verticesMatrix) { - this.verticesMatrix = verticesMatrix; - changeVerticesValues(verticesMatrix); - } - - public SimpleMatrix getVerticesMatrix() { - return verticesMatrix; - } - - private void changeVerticesValues(SimpleMatrix matrix) { - for (int i = 0; i < vertices.size(); i++) { - vertices.get(i).getPosition().x = (float) matrix.get(i, 0); - vertices.get(i).getPosition().y = (float) matrix.get(i, 1); - vertices.get(i).getPosition().z = (float) matrix.get(i, 2); - } - } - private HashMap<Integer, FeaturePoint> createFeaturePointMap(List<FeaturePoint> featurePointList) { HashMap<Integer, FeaturePoint> map = new HashMap<>(); for (FeaturePoint fp: featurePointList) { @@ -104,10 +92,6 @@ public class ProcrustesAnalysisFaceModel { return map; } - public HashMap<Integer, Integer> getFeaturePointTypeCorrespondence() { - return featurePointTypeCorrespondence; - } - /** * Creates corresponding key value pair of matrix row index and a feature point type value. * It is used in {@link cz.fidentis.analyst.procrustes.utils.ProcrustesAnalysisUtils#createFeaturePointMapFromMatrix} diff --git a/Comparison/src/main/java/cz/fidentis/analyst/procrustes/utils/ProcrustesAnalysisUtils.java b/Comparison/src/main/java/cz/fidentis/analyst/procrustes/utils/ProcrustesAnalysisUtils.java index 78baf70d..7d278cc5 100644 --- a/Comparison/src/main/java/cz/fidentis/analyst/procrustes/utils/ProcrustesAnalysisUtils.java +++ b/Comparison/src/main/java/cz/fidentis/analyst/procrustes/utils/ProcrustesAnalysisUtils.java @@ -34,21 +34,6 @@ public class ProcrustesAnalysisUtils { return featurePointList; } - /** - * Creates hash map with a key feature point type and value feature point - * @param featurePointList - * @return - */ - public static HashMap<Integer, FeaturePoint> generateFeaturePointHashMap(List<FeaturePoint> featurePointList) { - HashMap<Integer, FeaturePoint> map = new HashMap<>(); - for (FeaturePoint fp : featurePointList) { - if (fp.getFeaturePointType().getType() > 0) { - map.put(fp.getFeaturePointType().getType(), fp); - } - } - return map; - } - /** * Checks if two feature point lists have the same types of feature points. * <p> @@ -75,20 +60,6 @@ public class ProcrustesAnalysisUtils { return true; } - /** - * Creates array of distance values from feature point to origin (0,0,0). - * - * @param featurePointList - * @return array of distances - */ - public static double[] calculateMeanDistancesFromOrigin(List<FeaturePoint> featurePointList) { - double[] distances = new double[featurePointList.size()]; - for (int i = 0; i < featurePointList.size(); i++) { - distances[i] = calculatePointDistanceFromOrigin(featurePointList.get(i)); - } - return distances; - } - /** * Finds centrioid from given feature point List * @@ -107,33 +78,6 @@ public class ProcrustesAnalysisUtils { return new Point3d(x / featurePointList.size(), y / featurePointList.size(), z / featurePointList.size()); } - /** - * Calculates distance of one feature point from another - * - * @param fp1 - * @param fp2 - * @return distance - */ - public static double calculateDistanceOfTwoPoints(FeaturePoint fp1, FeaturePoint fp2) { - return Math.sqrt( - (Math.pow(fp1.getX(), 2) - Math.pow(fp2.getX(), 2)) - + (Math.pow(fp1.getY(), 2) - Math.pow(fp2.getY(), 2)) - + (Math.pow(fp1.getZ(), 2) - Math.pow(fp2.getZ(), 2))); - } - - /** - * Calculates distance of single feature point from origin (0,0,0) - * - * @param fp - * @return distance - */ - public static double calculatePointDistanceFromOrigin(FeaturePoint fp) { - return Math.sqrt( - Math.pow(fp.getX(), 2) - + Math.pow(fp.getY(), 2) - + Math.pow(fp.getZ(), 2)); - } - /** * Creates matrix from given feature point list * @@ -174,25 +118,4 @@ public class ProcrustesAnalysisUtils { return map; } - - public static float countSize(Point3d point, HashMap<Integer, FeaturePoint> featurePointsMap) { - float size = 0; - for (FeaturePoint fp: featurePointsMap.values()) { - size += (fp.getX() - point.x) * (fp.getX() - point.x); - size += (fp.getY() - point.y) * (fp.getY() - point.y); - size += (fp.getZ() - point.z) * (fp.getZ() - point.z); - } - return ((float) Math.sqrt(size)); - } - -// public List<MeshPoint> CreateVerticesListFromMatrix (SimpleMatrix matrix) { -// List<MeshPoint> verticesList = new ArrayList<>(); -// for (int i = 0; i < matrix.numRows(); i++) { -// float x = (float) matrix.get(i, 0); -// float y = (float) matrix.get(i, 1); -// float z = (float) matrix.get(i, 2); -// verticesList.add(new MeshPoint() { -// }) -// } -// } } diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/feature/api/IPosition.java b/MeshModel/src/main/java/cz/fidentis/analyst/feature/api/IPosition.java index 3b7d412f..f1aea467 100644 --- a/MeshModel/src/main/java/cz/fidentis/analyst/feature/api/IPosition.java +++ b/MeshModel/src/main/java/cz/fidentis/analyst/feature/api/IPosition.java @@ -8,6 +8,7 @@ package cz.fidentis.analyst.feature.api; import javax.vecmath.Point3d; /** + * Interface for working. * * @author Jakub Kolman */ -- GitLab