cosanlab / py-feat

Facial Expression Analysis Toolbox
https://py-feat.org/
Other
260 stars 71 forks source link

details on 'facepose' outputs #240

Open HilalNizamoglu opened 1 week ago

HilalNizamoglu commented 1 week ago

Dear all, I would like to create rotation matrix with facepose outputs (i.e. pitch, yaw, roll) to apply rigid inverse affine translation so that I can apply rigid motion correction. However, because the landmarks are in 2D, I do not know how to do this calculation. I thought of getting some clues from the developers on how they calculated the facepose values but I could not find any information. Could you please provide some details? Thanks!

ljchang commented 1 day ago

I believe the facepose outputs on the latest version are 6D with translation and rotation parameters for x,y,z. Rotations have been converted to Euler angles and are in radians.

You could try something like this:

import numpy as np

def euler_to_rotation_matrix(roll, pitch, yaw):
    """
    Convert Euler angles (roll, pitch, yaw) to a rotation matrix.
    """
    Rx = np.array([
        [1, 0, 0],
        [0, np.cos(roll), -np.sin(roll)],
        [0, np.sin(roll), np.cos(roll)]
    ])

    Ry = np.array([
        [np.cos(pitch), 0, np.sin(pitch)],
        [0, 1, 0],
        [-np.sin(pitch), 0, np.cos(pitch)]
    ])

    Rz = np.array([
        [np.cos(yaw), -np.sin(yaw), 0],
        [np.sin(yaw), np.cos(yaw), 0],
        [0, 0, 1]
    ])

    # Combined rotation matrix
    R = Rz @ Ry @ Rx
    return R

def rigid_motion_correction(points, rotation_params, translation_params):
    """
    Apply rigid motion correction to 3D points.

    Parameters:
        points (ndarray): Nx3 array of 3D points.
        rotation_params (tuple): (roll, pitch, yaw) in radians.
        translation_params (tuple): (tx, ty, tz) translation vector.

    Returns:
        ndarray: Corrected Nx3 array of 3D points.
    """
    roll, pitch, yaw = rotation_params
    tx, ty, tz = translation_params

    # Compute rotation matrix
    R = euler_to_rotation_matrix(roll, pitch, yaw)

    # Translation vector
    T = np.array([tx, ty, tz])

    # Apply rigid motion correction
    corrected_points = (R @ points.T).T + T

    return corrected_points

# Example usage:
points = np.array([
    [1.0, 2.0, 3.0],
    [4.0, 5.0, 6.0],
    [7.0, 8.0, 9.0]
])

rotation_params = (np.radians(10), np.radians(20), np.radians(30))  # Roll, Pitch, Yaw in radians
translation_params = (1.0, -2.0, 3.0)  # tx, ty, tz

corrected_points = rigid_motion_correction(points, rotation_params, translation_params)
print("Corrected Points:\n", corrected_points)

but definitely check to make sure this is right I didn't test it.