Commit 5a82334a authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Feature points

parent 7e384425
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package cz.fidentis.analyst.core;

import cz.fidentis.analyst.canvas.Canvas;
import cz.fidentis.analyst.scene.DrawableFace;
import cz.fidentis.analyst.scene.DrawableFeaturePoints;
import cz.fidentis.analyst.scene.Scene;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
@@ -82,6 +83,14 @@ public abstract class ControlPanelAction extends AbstractAction {
        return (canvas.getScene() != null) ? canvas.getScene().getDrawableFace(1) : null;
    }
    
    protected DrawableFeaturePoints getPrimaryFeaturePoints() {
        return (canvas.getScene() != null) ? canvas.getScene().getDrawableFeaturePoints(0) : null;
    }
    
    protected DrawableFeaturePoints getSecondaryFeaturePoints() {
        return (canvas.getScene() != null) ? canvas.getScene().getDrawableFeaturePoints(1) : null;
    }

    protected void renderScene() {
        canvas.renderScene();
    }
+46 −0
Original line number Diff line number Diff line
@@ -13,7 +13,12 @@ import org.openide.util.NbBundle.Messages;
import cz.fidentis.analyst.Project;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.face.HumanFaceFactory;
import cz.fidentis.analyst.feature.FeaturePoint;
import cz.fidentis.analyst.feature.services.FeaturePointImportExportService;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -306,6 +311,20 @@ public final class ProjectTopComp extends TopComponent {
        } else {
            String faceId = HumanFaceFactory.instance().loadFace(file);
            HumanFace face = HumanFaceFactory.instance().getFace(faceId);
            
            try {
                // simple hack:
                Path path = Paths.get(file.getAbsolutePath());
                Path folder = path.getParent();
                Path filename = path.getFileName();
                String filestr = filename.toString();
                filestr = filestr.split("_ECA.obj")[0];
                filestr = filestr + "_landmarks.csv";
                face.loadFeaturePoints(folder.toString(), filestr);
            } catch(IOException ex) {
                ex.printStackTrace();
            }
            
            this.project.setPrimaryFace(face);
            jLabel1.setText(face.getName());
            createSingleFaceTab(face, face.getName());
@@ -339,6 +358,33 @@ public final class ProjectTopComp extends TopComponent {
            String faceId2 = HumanFaceFactory.instance().loadFace(file2);
            HumanFace face1 = HumanFaceFactory.instance().getFace(faceId1);
            HumanFace face2 = HumanFaceFactory.instance().getFace(faceId2);
            
            try {
                // simple hack:
                Path path = Paths.get(file1.getAbsolutePath());
                Path folder = path.getParent();
                Path filename = path.getFileName();
                String filestr = filename.toString();
                filestr = filestr.split("_ECA.obj")[0];
                filestr = filestr + "_landmarks.csv";
                face1.loadFeaturePoints(folder.toString(), filestr);
            } catch(IOException ex) {
                ex.printStackTrace();
            }
            
            try {
                // simple hack:
                Path path = Paths.get(file2.getAbsolutePath());
                Path folder = path.getParent();
                Path filename = path.getFileName();
                String filestr = filename.toString();
                filestr = filestr.split("_ECA.obj")[0];
                filestr = filestr + "_landmarks.csv";
                face2.loadFeaturePoints(folder.toString(), filestr);
            } catch(IOException ex) {
                ex.printStackTrace();
            }
            
            this.project.setPrimaryFace(face1);
            this.project.setSecondaryFaces(List.of(face2));
            jLabel1.setText(face1.getName());
+98 −57
Original line number Diff line number Diff line
package cz.fidentis.analyst.registration;

import com.jogamp.opengl.GL2;
import cz.fidentis.analyst.canvas.Canvas;
import cz.fidentis.analyst.core.ControlPanelAction;
import cz.fidentis.analyst.feature.FeaturePoint;
import cz.fidentis.analyst.icp.IcpTransformer;
import cz.fidentis.analyst.icp.NoUndersampling;
import cz.fidentis.analyst.icp.RandomStrategy;
import cz.fidentis.analyst.icp.UndersamplingStrategy;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshPoint;
import cz.fidentis.analyst.scene.DrawableFace;
import cz.fidentis.analyst.scene.DrawableFeaturePoints;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.Optional;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JToggleButton;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

@@ -46,12 +51,16 @@ public class RegistrationAction extends ControlPanelAction {
    public static final String ACTION_COMMAND_RESET_SCALE = "reset scale";
    public static final String ACTION_COMMAND_APPLY_TRANSFORMATIONS = "apply transformations";
    public static final String ACTION_COMMAND_TRANSPARENCY = "transparency";
    public static final String ACTION_COMMAND_FP_CLOSENESS_THRESHOLD = "fp closeness treshold";
    public static final String ACTION_COMMAND_ICP_SCALE = "ICP scale";
    public static final String ACTION_COMMAND_ICP_MAX_ITERATIONS = "ICP iterations";
    public static final String ACTION_COMMAND_ICP_ERROR = "ICP error";
    public static final String ACTION_COMMAND_ICP_UNDERSAMPLING = "ICP undersampling";
    
    
    /*
     * Attributes handling the state
     */
    private IcpTransformer visitor = null;
    private boolean scale = true;
    private int maxIterations = 10;
    private double error = 0.3;
@@ -66,7 +75,7 @@ public class RegistrationAction extends ControlPanelAction {
    /**
     * Threshold of feature points showing too far away
     */
    private double featurePointsThreshold = 0.1;
    private double featurePointsThreshold = 5.0;

    private final RegistrationPanel controlPanel;
    
@@ -86,13 +95,17 @@ public class RegistrationAction extends ControlPanelAction {
        double value;
        String action = ae.getActionCommand();
        
        /*
         * OTHER ACTIONS ARE INVOKED BY DIRECT CALL (to be refactored)
         */
        
        switch (action) {
            case ACTION_COMMAND_SHOW_HIDE_PANEL:
                hideShowPanelActionPerformed(ae, this.controlPanel);
                if (((JToggleButton) ae.getSource()).isSelected()) {
                    calculateFeaturePoints(); // color points 
                } else {
                    for (int i = 0; i < getPrimaryFeaturePoints().getFeaturePoints().size(); i++) {
                        getPrimaryFeaturePoints().setColor(i, DrawableFeaturePoints.DEFAULT_COLOR);
                        getSecondaryFeaturePoints().setColor(i, DrawableFeaturePoints.DEFAULT_COLOR);
                    }
                }
                break;
            case ACTION_COMMAND_APPLY_ICP:
                applyICP();
@@ -101,31 +114,49 @@ public class RegistrationAction extends ControlPanelAction {
            case ACTION_COMMAND_SHIFT_X:
                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                getSecondaryDrawableFace().getTranslation().x = value;
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().getTranslation().x = value;
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_SHIFT_Y:
                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                getSecondaryDrawableFace().getTranslation().y = value;
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().getTranslation().y = value;
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_SHIFT_Z:
                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                getSecondaryDrawableFace().getTranslation().z = value;
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().getTranslation().z = value;
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_ROTATE_X:
                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                getSecondaryDrawableFace().getRotation().x = value;
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().getRotation().x = value;
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_ROTATE_Y:
                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                getSecondaryDrawableFace().getRotation().y = value;
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().getRotation().y = value;
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_ROTATE_Z:
                value = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                getSecondaryDrawableFace().getRotation().z = value;
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().getRotation().z = value;
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_SCALE:
@@ -133,6 +164,11 @@ public class RegistrationAction extends ControlPanelAction {
                getSecondaryDrawableFace().getScale().x = value;
                getSecondaryDrawableFace().getScale().y = value;
                getSecondaryDrawableFace().getScale().z = value;
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().getScale().x = value;
                    getSecondaryFeaturePoints().getScale().y = value;
                    getSecondaryFeaturePoints().getScale().z = value;
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_FRONT_VIEW:
@@ -144,14 +180,23 @@ public class RegistrationAction extends ControlPanelAction {
                break;
            case ACTION_COMMAND_RESET_TRANSLATION:
                getSecondaryDrawableFace().setTranslation(new Vector3d(0, 0, 0));
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().setTranslation(new Vector3d(0, 0, 0));
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_RESET_ROTATION:
                getSecondaryDrawableFace().setRotation(new Vector3d(0, 0, 0));
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().setRotation(new Vector3d(0, 0, 0));
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_RESET_SCALE:
                getSecondaryDrawableFace().setScale(new Vector3d(0, 0, 0));
                if (getSecondaryFeaturePoints() != null) {
                    getSecondaryFeaturePoints().setScale(new Vector3d(0, 0, 0));
                }
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_RESET_ALL:
@@ -170,6 +215,32 @@ public class RegistrationAction extends ControlPanelAction {
                int transparency = ((JSlider) ae.getSource()).getValue();
                setTransparency(transparency);
                break;
            case ACTION_COMMAND_FP_CLOSENESS_THRESHOLD:
                featurePointsThreshold = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                calculateFeaturePoints();
                break;
            case ACTION_COMMAND_ICP_SCALE:
                this.scale = ((JCheckBox) ae.getSource()).isSelected();
                break;
            case ACTION_COMMAND_ICP_MAX_ITERATIONS:
                maxIterations = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).intValue();
                break;
            case ACTION_COMMAND_ICP_ERROR:
                error = ((Number)(((JFormattedTextField) ae.getSource()).getValue())).doubleValue();
                break;
            case ACTION_COMMAND_ICP_UNDERSAMPLING:
                String item = (String)((JComboBox) ae.getSource()).getSelectedItem();
                switch (item) {
                    case "None":
                        this.undersampling = new NoUndersampling();
                        break;
                    case "Random 200":
                        this.undersampling = new RandomStrategy(200);
                        break;
                    default:
                        throw new UnsupportedOperationException(item);
                }
                break;
            default:
                throw new UnsupportedOperationException(action);
        }
@@ -178,11 +249,9 @@ public class RegistrationAction extends ControlPanelAction {
    }
    
    protected void applyICP() {
        if (visitor == null) { 
            this.visitor = new IcpTransformer(getPrimaryDrawableFace().getModel(), maxIterations, scale, error, undersampling);
        IcpTransformer visitor = new IcpTransformer(getPrimaryDrawableFace().getModel(), maxIterations, scale, error, undersampling);
        getSecondaryDrawableFace().getModel().compute(visitor); // NOTE: the secondary face is physically transformed
    }
    }
    
    /**
     * Sets the transparency of {@link #primaryFace} or {@link #secondaryFace}
@@ -210,14 +279,19 @@ public class RegistrationAction extends ControlPanelAction {
     * otherwise set color to default
     */
    private void calculateFeaturePoints() {
        if (getPrimaryDrawableFace() == null || !getPrimaryDrawableFace().isRenderFeaturePoints()) {
        if (getPrimaryDrawableFace() == null) { // scene not yet initiated
            return;
        }
        
        if (getPrimaryFeaturePoints() == null || 
                getSecondaryFeaturePoints() == null ||
                getPrimaryFeaturePoints().getFeaturePoints().size() != getSecondaryFeaturePoints().getFeaturePoints().size()) {
            return;
        }
                
        List<Color> color = getSecondaryDrawableFace().getFeaturePointsColor();
        for (int i = 0; i < getPrimaryDrawableFace().getFeaturePoints().size(); i++) {
            FeaturePoint primary = getPrimaryDrawableFace().getFeaturePoints().get(i);
            FeaturePoint secondary = getSecondaryDrawableFace().getFeaturePoints().get(i);
        for (int i = 0; i < getPrimaryFeaturePoints().getFeaturePoints().size(); i++) {
            FeaturePoint primary = getPrimaryFeaturePoints().getFeaturePoints().get(i);
            FeaturePoint secondary = getSecondaryFeaturePoints().getFeaturePoints().get(i);
            Point3d transformed = new Point3d(secondary.getX(), secondary.getY(), secondary.getZ());
            transformPoint(transformed);
            double distance = Math.sqrt(
@@ -225,9 +299,11 @@ public class RegistrationAction extends ControlPanelAction {
                Math.pow(transformed.y - primary.getY(), 2) + 
                Math.pow(transformed.z - primary.getZ(), 2));
            if (distance > featurePointsThreshold) {
                color.set(i, Color.RED);
                getPrimaryFeaturePoints().setColor(i, Color.RED);
                getSecondaryFeaturePoints().setColor(i, Color.RED);
            } else {
                color.set(i, DrawableFace.SKIN_COLOR_SECONDARY);
                getPrimaryFeaturePoints().setColor(i, DrawableFeaturePoints.DEFAULT_COLOR);
                getSecondaryFeaturePoints().setColor(i, DrawableFeaturePoints.DEFAULT_COLOR);
            }
        }
    }
@@ -243,13 +319,12 @@ public class RegistrationAction extends ControlPanelAction {
                transformPoint(comparedPoint.getPosition());
            }
        }
        for (int i = 0; i < getSecondaryDrawableFace().getFeaturePoints().size(); i++) {
            FeaturePoint point = getSecondaryDrawableFace().getFeaturePoints().get(i);
        for (int i = 0; i < getSecondaryFeaturePoints().getFeaturePoints().size(); i++) {
            FeaturePoint point = getSecondaryFeaturePoints().getFeaturePoints().get(i);
            Point3d transformed = new Point3d(point.getX(), point.getY(), point.getZ());
            transformPoint(transformed);
            point = new FeaturePoint(transformed.x, transformed.y, 
                    transformed.z, point.getFeaturePointType());
            getSecondaryDrawableFace().getFeaturePoints().set(i, point);
            point = new FeaturePoint(transformed.x, transformed.y, transformed.z, point.getFeaturePointType());
            getSecondaryFeaturePoints().getFeaturePoints().set(i, point);
        }
    }
    
@@ -310,38 +385,4 @@ public class RegistrationAction extends ControlPanelAction {
        point.z *= 1 + getSecondaryDrawableFace().getScale().z;
    }
    
    public double getFeaturePointsThreshold() {
        return featurePointsThreshold;
    }

    public void setFeaturePointsThreshold(double featurePointsThreshold) {
        this.featurePointsThreshold = featurePointsThreshold;
        calculateFeaturePoints();
        renderScene();
    }

    
    
    /////////////////////////////

    protected boolean areFeaturePointsActive() {
        return getPrimaryDrawableFace().isRenderFeaturePoints();
    }
    
    protected void setFeaturePointsActive(boolean state) {
        getPrimaryDrawableFace().setRenderFeaturePoints(state);
        getSecondaryDrawableFace().setRenderFeaturePoints(state);
        calculateFeaturePoints();
        renderScene();
    }

    protected boolean isShowBackfaceActive() {
        return getPrimaryDrawableFace().isShowBackface();
    }
    
    protected void setShowBackfaceActive(boolean state) {
        getPrimaryDrawableFace().setShowBackface(state);
        getSecondaryDrawableFace().setShowBackface(state);
        renderScene();
    }
}
+105 −93

File changed.

Preview size limit exceeded, changes collapsed.

+90 −112

File changed.

Preview size limit exceeded, changes collapsed.

Loading