diff --git a/.gitignore b/.gitignore index 465f3e45..3208a17c 100644 --- a/.gitignore +++ b/.gitignore @@ -216,3 +216,4 @@ Temporary Items .apdisk # End of https://www.toptal.com/developers/gitignore/api/macos +test_models/ \ No newline at end of file diff --git a/pye3d/refraction_models/default_refraction_model_gaze_vector_degree_3.save b/pye3d/refraction_models/default_refraction_model_gaze_vector_degree_3.save index 2ff9717d..d10e53bd 100644 Binary files a/pye3d/refraction_models/default_refraction_model_gaze_vector_degree_3.save and b/pye3d/refraction_models/default_refraction_model_gaze_vector_degree_3.save differ diff --git a/pye3d/refraction_models/default_refraction_model_pupil_circle_degree_3.save b/pye3d/refraction_models/default_refraction_model_pupil_circle_degree_3.save index fa050fa0..aabb4ec6 100644 Binary files a/pye3d/refraction_models/default_refraction_model_pupil_circle_degree_3.save and b/pye3d/refraction_models/default_refraction_model_pupil_circle_degree_3.save differ diff --git a/pye3d/refraction_models/default_refraction_model_radius_degree_3.save b/pye3d/refraction_models/default_refraction_model_radius_degree_3.save index 284098bb..5b2c9d32 100644 Binary files a/pye3d/refraction_models/default_refraction_model_radius_degree_3.save and b/pye3d/refraction_models/default_refraction_model_radius_degree_3.save differ diff --git a/pye3d/refraction_models/default_refraction_model_sphere_center_degree_3.save b/pye3d/refraction_models/default_refraction_model_sphere_center_degree_3.save index 311ad327..663a79d9 100644 Binary files a/pye3d/refraction_models/default_refraction_model_sphere_center_degree_3.save and b/pye3d/refraction_models/default_refraction_model_sphere_center_degree_3.save differ diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..54fca8d0 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +log_cli=true +log_level=20 \ No newline at end of file diff --git a/tests/integration/test_synthetic_metrics.py b/tests/integration/test_synthetic_metrics.py index 423004f9..c414631f 100644 --- a/tests/integration/test_synthetic_metrics.py +++ b/tests/integration/test_synthetic_metrics.py @@ -1,16 +1,16 @@ -from pye3d.detector_3d import CameraModel -from pye3d.detector_3d import Detector3D as Pye3D -from pye3d.detector_3d import DetectorMode - +import logging import math + import numpy as np import pandas as pd +import pytest import skimage.measure as skmeas +from pye3d.detector_3d import CameraModel +from pye3d.detector_3d import Detector3D as Pye3D +from pye3d.detector_3d import DetectorMode -import pytest from .utils import abs_diff, input_dir, output_dir, remove_file - # Define all input files INPUT_PATH = input_dir().joinpath("pye3d_test_input.npz") @@ -30,6 +30,12 @@ OUTPUT_GAZE_ANGLE_THETA_PLOT_PATH = output_dir().joinpath( "pye3d_test_gaze_angle_theta_plot.png" ) +OUTPUT_GAZE_ANGLE_VECTOR_PLOT_PATH = output_dir().joinpath( + "pye3d_test_gaze_angle_vector_plot.png" +) +OUTPUT_GAZE_ANGLE_ERROR_BY_INPUT_ORIENTATION_PLOT_PATH = output_dir().joinpath( + "pye3d_test_gaze_angle_error_by_input_orientation_plot.png" +) OUTPUT_EYE_CENTER_3D_PLOT_PATH = output_dir().joinpath( "pye3d_test_eye_center_3d_error_plot.png" ) @@ -75,6 +81,7 @@ def test_datum_component_phi(dataset, convergence_time): ylabel="[°]", ylim=(gaze_angle_phi_gr_mean - 55, gaze_angle_phi_gr_mean + 55), v_threshold=convergence_time, + v_threshold_label=f"convergence time = {convergence_time} seconds", # Image Path path=OUTPUT_GAZE_ANGLE_PHI_PLOT_PATH, ) @@ -112,6 +119,7 @@ def test_datum_component_theta(dataset, convergence_time): ylabel="[°]", ylim=(gaze_angle_theta_gr_mean - 55, gaze_angle_theta_gr_mean + 55), v_threshold=convergence_time, + v_threshold_label=f"convergence time = {convergence_time} seconds", # Image Path path=OUTPUT_GAZE_ANGLE_THETA_PLOT_PATH, ) @@ -149,6 +157,7 @@ def test_pupil_radius(dataset, convergence_time): ylabel="[mm]", ylim=(0, 5), v_threshold=convergence_time, + v_threshold_label=f"convergence time = {convergence_time} seconds", # Image Path path=OUTPUT_PUPIL_RADIUS_PLOT_PATH, ) @@ -157,6 +166,7 @@ def test_pupil_radius(dataset, convergence_time): ax=gr_df["timestamp"], ay=pupil_radius_error, a_color="r", + a_label="pupil radius error", # Legend figsize=(10, 4), title="pupil radius error\n", @@ -164,7 +174,9 @@ def test_pupil_radius(dataset, convergence_time): ylabel="[mm]", ylim=(0, 1), h_threshold=PUPIL_RADIUS_EPS, + h_threshold_label=f"pupil radius eps = {PUPIL_RADIUS_EPS} mm", v_threshold=convergence_time, + v_threshold_label=f"convergence time = {convergence_time} seconds", # Image Path path=OUTPUT_PUPIL_RADIUS_ERROR_PLOT_PATH, ) @@ -181,6 +193,7 @@ def test_eye_center_3d(dataset, convergence_time, eye_center_3d_errors): ax=gr_df["timestamp"], ay=eye_center_3d_errors, a_color="r", + a_label="eye center 3d errors", # Legend figsize=(10, 4), title="eye center 3d error\n", @@ -188,7 +201,9 @@ def test_eye_center_3d(dataset, convergence_time, eye_center_3d_errors): ylabel="[mm]", ylim=(0, 5), h_threshold=EYE_CENTER_3D_EPS, + h_threshold_label=f"eye center eps = {EYE_CENTER_3D_EPS} mm", v_threshold=convergence_time, + v_threshold_label=f"convergence time = {convergence_time} seconds", # Image Path path=OUTPUT_EYE_CENTER_3D_PLOT_PATH, ) @@ -217,18 +232,47 @@ def test_gaze_angle(dataset, convergence_time): a_color="r", # Legend figsize=(10, 4), - title="eye center 3d error\n", + title="gaze angle error over time", xlabel="time [s]", - ylabel="[mm]", + ylabel="[°]", ylim=(0, 5), h_threshold=GAZE_ANGLE_EPS, + h_threshold_label=f"gaze angle eps = {GAZE_ANGLE_EPS} deg", v_threshold=convergence_time, + v_threshold_label=f"convergence time = {convergence_time} seconds", # Image Path - path=OUTPUT_EYE_CENTER_3D_PLOT_PATH, + path=OUTPUT_GAZE_ANGLE_VECTOR_PLOT_PATH, ) gaze_angle_error = gaze_angle_error[gr_df["timestamp"] > convergence_time] + input_phi = gt_df.loc[gr_df["timestamp"] > convergence_time, "phi"] + input_phi = np.rad2deg(input_phi) + 90.0 + + input_theta = gt_df.loc[gr_df["timestamp"] > convergence_time, "theta"] + input_theta = np.rad2deg(input_theta) - 90.0 + + save_plot( + ax=input_phi, + ay=gaze_angle_error, + a_label="phi", + a_color="C0", + bx=input_theta, + by=gaze_angle_error, + b_label="theta", + b_color="C1", + # Legend + figsize=(10, 4), + title="gaze angle error by input orientation (after convergence)", + xlabel="centered ground truth input orientation [°]", + ylabel="gaze angle error [°]", + ylim=(0, 3), + h_threshold=GAZE_ANGLE_EPS, + h_threshold_label=f"gaze angle eps = {GAZE_ANGLE_EPS} deg", + # Image Path + path=OUTPUT_GAZE_ANGLE_ERROR_BY_INPUT_ORIENTATION_PLOT_PATH, + ) + assert np.all(gaze_angle_error <= GAZE_ANGLE_EPS) # TODO: Add description @@ -239,6 +283,7 @@ def convergence_time(dataset, eye_center_3d_errors): eye_center_3d_convergence = eye_center_3d_errors > EYE_CENTER_3D_EPS convergence_index = -np.argwhere(eye_center_3d_convergence[::-1])[0][0] - 1 convergence_time = gt_df.timestamp.iloc[convergence_index] + logging.getLogger().info(f"Calculated convergence time: {convergence_time} seconds") return convergence_time @@ -456,7 +501,9 @@ def save_plot( a_color="b", b_color="g", h_threshold=None, + h_threshold_label="", v_threshold=None, + v_threshold_label="", figsize=(10, 4), xlabel="", ylabel="", @@ -472,17 +519,25 @@ def save_plot( axis.plot(bx, by, b_color, alpha=1, label=b_label) if h_threshold: - xlim_lo = min( - map(lambda x: x.iloc[0], filter(lambda x: x is not None, [ax, bx])) - ) - xlim_hi = max( - map(lambda x: x.iloc[-1], filter(lambda x: x is not None, [ax, bx])) - ) + xlim_lo = min(map(lambda x: x.min(), filter(lambda x: x is not None, [ax, bx]))) + xlim_hi = max(map(lambda x: x.max(), filter(lambda x: x is not None, [ax, bx]))) xlim = xlim_lo, xlim_hi - axis.hlines([h_threshold], *xlim, colors="C2", linestyles="dashed") + axis.hlines( + [h_threshold], + *xlim, + colors="C2", + linestyles="dashed", + label=h_threshold_label, + ) if v_threshold: - axis.vlines([v_threshold], *ylim, colors="C4", linestyles="dashed") + axis.vlines( + [v_threshold], + *ylim, + colors="C4", + linestyles="dashed", + label=v_threshold_label, + ) axis.set_ylim(*ylim)