Skip to content
Snippets Groups Projects
ProcrustesAnalysisFaceModel.java 4.71 KiB
Newer Older
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.fidentis.analyst.procrustes;

import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.feature.FeaturePoint;
import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.mesh.core.MeshPoint;
import cz.fidentis.analyst.procrustes.utils.ProcrustesAnalysisUtils;
import org.ejml.simple.SimpleMatrix;
import java.util.HashMap;
import java.util.List;

/**
 * Holds important face attributes that are required for procrustes analysis.
 *
 * @author Jakub Kolman
 */
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 final HashMap<Integer, Integer> featurePointTypeCorrespondence;
    public ProcrustesAnalysisFaceModel(HumanFace face) {
        this.humanFace = face;
        // getFeaturePoints() returns unmodifiable List. To sort it we need to make copy first
        List<FeaturePoint> modifiableFeaturePointList = new ArrayList<>(face.getFeaturePoints());

        // To be able to move vertices we have to make a copy of them because  getFacets() returns unmodifiable List
        List<MeshPoint> modifiableVertices = new ArrayList<>(face.getMeshModel().getFacets().get(0).getVertices());

        this.vertices = modifiableVertices;
        this.meshModel = face.getMeshModel();
        this.featurePointsMap = createFeaturePointMap(
                ProcrustesAnalysisUtils.sortListByFeaturePointType(modifiableFeaturePointList));
        this.featurePointTypeCorrespondence = createFeaturePointTypeCorrespondence(face.getFeaturePoints());
        this.verticesMatrix = ProcrustesAnalysisUtils.createMatrixFromList(modifiableVertices);
//        this.featurePointMatrix = ProcrustesAnalysisUtils.createMatrixFromList(modifiableFeaturePointList);
    /**
     * sets feature points map and also sets feature point on human face for visualisation
     *
     * @param featurePointsMap
     */
    public void setFeaturePointsMap(HashMap<Integer, FeaturePoint> featurePointsMap) {
        this.featurePointsMap = featurePointsMap;
        this.humanFace.setFeaturePoints(getFeaturePointValues());
    public MeshModel getMeshModel() {
        return meshModel;
    }

    public List<FeaturePoint> getFeaturePointValues() {
        return new ArrayList<>(this.getFeaturePointsMap().values());
}

    public List<MeshPoint> getVertices() {

    public HashMap<Integer, FeaturePoint> getFeaturePointsMap() {
        return featurePointsMap;
    }

    /**
     * sets vertices map and also sets feature point on human face for visualisation
     *
     * @param verticesMatrix
     */
    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) {
            map.put(fp.getFeaturePointType().getType(), fp);
        }
        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}
     * so we can get back type of feature point after working with matrices where the type is not stored,
     * but instead are used matrix indexes.
     *
     * @param fpList
     * @return
     */
    private HashMap<Integer, Integer> createFeaturePointTypeCorrespondence(List<FeaturePoint> fpList) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < fpList.size(); i++) {
            map.put(i, fpList.get(i).getFeaturePointType().getType());
        }
        return map;
    }