Commit 60f0ac1d authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Merge branch 'issue-186/procrustes-documentation' into 'master'

MR [#186] documentation

See merge request grp-fidentis/analyst2!205
parents 27c3d80f 013ccf8f
Loading
Loading
Loading
Loading
+12 −14
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ public class ProcrustesAnalysis {
     * Using generalized orthogonal procrustes analysis need to be first moved
     * over each other, then scale and then rotate.
     *
     * @return ProcrustesTransformation computed for secondary face
     * @throws DataFormatException if faces have less than 3 feature points in
     * which case analysis doesn't make sense
     */
@@ -136,19 +137,10 @@ public class ProcrustesAnalysis {
        });
    }

    /**
     * Moves face model by given vector values. Different vector value is used
     * for vertices and feature points. This method is used to fit feature
     * points to already superimposed position over given face1, but move
     * vertices of face back to original position of face so all the vertex
     * movement is done by Procrustes visitor.
     *
     * @param faceModel on which adjustment will be applied
     * @param vertexVector vertex adjustment
     * @param featurePointVector feature points adjustment
     */
    /**
     * By rotation of matrices solves orthogonal procrustes problem.
     * 
     * @return rotation matrix
     */
    private SimpleMatrix rotate() {
        SimpleMatrix primaryMatrix = createMatrixFromList(this.faceModel2.getFeaturePointValues());
@@ -205,7 +197,7 @@ public class ProcrustesAnalysis {
    /**
     * Finds centroid from given feature point List
     *
     * @param featurePointList
     * @param featurePointList list of feature points for which we want to find centroid
     * @return centroid of feature points (Vector3F)
     */
    private Point3d findCentroidOfFeaturePoints(List<FeaturePoint> featurePointList) {
@@ -263,8 +255,8 @@ public class ProcrustesAnalysis {
     * Finds corresponding subset of feature points from both faces so the
     * procrustes analysis can be applied on the subset.
     *
     * @param featurePoints
     * @param featurePoints0
     * @param featurePoints1
     * @param featurePoints2
     *
     * @return List of feature point types that are in both sets of feature
     * points
@@ -284,6 +276,12 @@ public class ProcrustesAnalysis {
        return vaiablePoints;
    }

    /**
     * scales list by recalculating its points position values
     * 
     * @param list of points to be scaled
     * @param scaleFactor factor by how much the points should be scaled
     */
    private void scaleFeaturePoints(List<FeaturePoint> list, double scaleFactor) {
        for (FeaturePoint point : list) {
            ProcrustesUtils.scalePointDistance(point, scaleFactor);
+2 −2
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ public class ProcrustesAnalysisFaceModel {
     *
     * @param featurePoints
     * @param viablePoints
     * @return
     * @return list containing subset of feature points defined over a face that are marked as a viable points
     */
    private List<FeaturePoint> getSelectionOfFeaturePoints(List<FeaturePoint> featurePoints, List<Integer> viablePoints) {
        ArrayList<FeaturePoint> selection = new ArrayList<>();
@@ -87,7 +87,7 @@ public class ProcrustesAnalysisFaceModel {
     * Map key is feature point type (Integer). Value is feature point itself.
     *
     * @param featurePointList
     * @return
     * @return hash map of feature points
     */
    private HashMap<Integer, FeaturePoint> createFeaturePointMap(List<FeaturePoint> featurePointList) {
        HashMap<Integer, FeaturePoint> map = new HashMap<>();
+29 −39
Original line number Diff line number Diff line
@@ -19,42 +19,26 @@ public class ProcrustesTransformation {
    private Vector3d superImpositionAdjustment;
    private SimpleMatrix rotationMatrix;

//    /**
//     * constructor
//     *
//     * @param scale determines by how much should be faced enlarged or minimized
//     * @param adjustment determines how should be face moved to make faces
//     * superimposed considering feature points
//     * @param rotationMatrix determines how to rotate face
//     * @param updatedFaceModel holds information about adjusted face
//     */
//    public ProcrustesTransformation(
//            double scale,
//            Vector3d centroidAdjustment,
//            Vector3d superImpositionAdjustment,
//            SimpleMatrix rotationMatrix,
//            HashMap<Integer, FeaturePoint> updatedFeaturePointsMap) {
//        this.scale = scale;
//        this.centroidAdjustment = centroidAdjustment;                   
//        this.superImpositionAdjustment = superImpositionAdjustment;
//        this.rotationMatrix = rotationMatrix;
//        this.featurePointsMap = featurePointsMap;
//    }
//
//    /**
//     * Constructor (for more info take a look on 
//     * {@link #ProcrustesTransformation(double, javax.vecmath.Vector3d, org.ejml.simple.SimpleMatrix, cz.fidentis.analyst.procrustes.ProcrustesAnalysisFaceModel) }
//     *
//     * @param adjustment
//     * @param rotationMatrix
//     */
//    public ProcrustesTransformation(
//            Vector3d centroidAdjustment, 
//            Vector3d superImpositionAdjustment, 
//            SimpleMatrix rotationMatrix, 
//            HashMap<Integer, FeaturePoint> updatedFeaturePointsMap) {
//        this(1d, centroidAdjustment, superImpositionAdjustment, rotationMatrix, updatedFeaturePointsMap);
//    }
    /**
     * constructor
     * 
     * @param scale determines by how much should be faced enlarged or minimized
     * @param centroidAdjustment is vector determining how should be face moved to make (0,0,0)
     * @param superImpositionAdjustment is vector determining how should be face 
     * moved to be superimposed over primary face
     * @param rotationMatrix determines how to rotate face
     */
    public ProcrustesTransformation(
            double scale,
            Vector3d centroidAdjustment,
            Vector3d superImpositionAdjustment,
            SimpleMatrix rotationMatrix) {
        this.scale = scale;
        this.centroidAdjustment = centroidAdjustment;                   
        this.superImpositionAdjustment = superImpositionAdjustment;
        this.rotationMatrix = rotationMatrix;
    }


    /**
     * Empty constructor with values that won't transform face. To set values later attribute setters can be used.
@@ -104,6 +88,7 @@ public class ProcrustesTransformation {
    /**
     * Calculates quaternion from rotation matrix.
     * 
     * @param matrix
     * @return quaternion with rotation values
     */
    public Quaternion getMatrixAsQuaternion(SimpleMatrix matrix) {
@@ -131,8 +116,13 @@ public class ProcrustesTransformation {
        this.rotationMatrix = rotationMatrix;
    }
    
    /**
     * Generates an identity matrix which doesn't cause any transformation and returns it.
     * 
     * @return identity matrix
     */
    public SimpleMatrix getIdentityMatrix() {
        SimpleMatrix r = new SimpleMatrix(3, 3);    // identity matrix
        SimpleMatrix r = new SimpleMatrix(3, 3);
        r.set(0, 0, 1);
        r.set(0, 1, 0);
        r.set(0, 2, 0);
+1 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ public class ProcrustesUtils {
     * @param point
     * @param scaleFactor
     * @param <T>
     * @return
     * @return point with recalculated values
     */
    public static <T extends IPosition> T scalePointDistance(T point, double scaleFactor) {
        point.getPosition().x = point.getX() * scaleFactor;
+14 −36
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ import javax.vecmath.Vector3d;
import org.ejml.simple.SimpleMatrix;

/**
 * Visitor class for use of Procrustes analysis.
 * 
 * @author Jakub Kolman
 */
@@ -48,6 +49,12 @@ public class ProcrustesVisitor extends HumanFaceVisitor {
        return this.transformations;
    }

    /**
     * Visits secondary face, computes transformation values and readjusts the face
     * to be superimposed over the primary face.
     * 
     * @param humanFace 
     */
    @Override
    public void visitHumanFace(HumanFace humanFace) {
        try {
@@ -66,15 +73,14 @@ public class ProcrustesVisitor extends HumanFaceVisitor {
    /**
     * Applies transformations computed from procrustes analysis to face.
     *
     * @param transformation
     * @param humanFace
     * @param transformation computed by procrustes analysis
     * @param humanFace to which the transformation will be applied to
     */
    private void applyTransformations(ProcrustesTransformation transformation, HumanFace humanFace) {
        moveFace(humanFace, transformation.getCentroidAdjustment());
        scaleFace(humanFace, transformation.getScale());
        rotateFace(humanFace, transformation.getRotationMatrix());
        moveFace(humanFace, transformation.getSuperImpositionAdjustment());
//        moveFeaturePoints(humanFace, transformation.getFeaturePointsMap());
    }

    /**
@@ -118,7 +124,7 @@ public class ProcrustesVisitor extends HumanFaceVisitor {
     * <p>
     * For more details check out single vertex rotation {@link #rotateVertex}.
     *
     * @param vertices
     * @param humanFace
     * @param matrix 
     */
    private void rotateFace(HumanFace humanFace, SimpleMatrix matrix) {
@@ -135,8 +141,8 @@ public class ProcrustesVisitor extends HumanFaceVisitor {
    /**
     * Rotates vertex v by simulating matrix multiplication with given matrix
     *
     * @param v
     * @param matrix
     * @param v is vertex than is going to be rotated
     * @param matrix is rotation matrix
     */
    private <T extends IPosition> void rotateVertex(T v, SimpleMatrix matrix) {
        double x = ((v.getX() * matrix.get(0, 0))
@@ -153,32 +159,4 @@ public class ProcrustesVisitor extends HumanFaceVisitor {
        v.getPosition().z = z;
    }

    /**
     * Moves feature points to calculated new position by computing procrustes
     * analysis. {@link cz.fidentis.analyst.procrustes.ProcrustesAnalysis}. If
     * feature point was not used in the analysis, it's position will be kept as
     * it had in the original list.
     *
     * Move of the feature point is done to remove them from user vision first.
     *
     * @param secondFace
     * @param movedFeaturePoints
     */
    /*
    private static void moveFeaturePoints(HumanFace humanFace, Map<Integer, FeaturePoint> movedFeaturePoints) {
        humanFace.getFeaturePoints().forEach(fp -> {
            FeaturePoint movedFp = movedFeaturePoints.get(fp.getFeaturePointType().getType());
            if (movedFp != null) {
                if (fp.getFeaturePointType().getType()
                        != movedFp.getFeaturePointType().getType()) {
                    throw new RuntimeException("Types do not correspond");
                }
                fp.getPosition().x = movedFp.getX();
                fp.getPosition().y = movedFp.getY();
                fp.getPosition().z = movedFp.getZ();
            }
        });
    }
    */

}
Loading