22 #ifndef BLENDSHAPEFITTING_HPP_ 23 #define BLENDSHAPEFITTING_HPP_ 25 #include "eos/morphablemodel/Blendshape.hpp" 27 #include "opencv2/core/core.hpp" 50 inline std::vector<float>
fit_blendshapes_to_landmarks_linear(std::vector<eos::morphablemodel::Blendshape> blendshapes, cv::Mat face_instance, cv::Mat affine_camera_matrix, std::vector<cv::Vec2f> landmarks, std::vector<int> vertex_ids,
float lambda=500.0f)
53 assert(landmarks.size() == vertex_ids.size());
55 int num_coeffs_to_fit = blendshapes.size();
56 int num_landmarks =
static_cast<int>(landmarks.size());
59 cv::Mat blendshapes_as_basis(blendshapes[0].deformation.rows, blendshapes.size(), CV_32FC1);
60 for (
int i = 0; i < blendshapes.size(); ++i)
62 blendshapes[i].deformation.copyTo(blendshapes_as_basis.col(i));
67 Mat V_hat_h = Mat::zeros(4 * num_landmarks, num_coeffs_to_fit, CV_32FC1);
69 for (
int i = 0; i < num_landmarks; ++i) {
71 Mat basis_rows = blendshapes_as_basis.rowRange(vertex_ids[i] * 3, (vertex_ids[i] * 3) + 3);
73 basis_rows.colRange(0, num_coeffs_to_fit).copyTo(V_hat_h.rowRange(row_index, row_index + 3));
77 Mat P = Mat::zeros(3 * num_landmarks, 4 * num_landmarks, CV_32FC1);
78 for (
int i = 0; i < num_landmarks; ++i) {
79 Mat submatrix_to_replace = P.colRange(4 * i, (4 * i) + 4).rowRange(3 * i, (3 * i) + 3);
80 affine_camera_matrix.copyTo(submatrix_to_replace);
84 Mat y = Mat::ones(3 * num_landmarks, 1, CV_32FC1);
85 for (
int i = 0; i < num_landmarks; ++i) {
86 y.at<
float>(3 * i, 0) = landmarks[i][0];
87 y.at<
float>((3 * i) + 1, 0) = landmarks[i][1];
91 Mat v_bar = Mat::ones(4 * num_landmarks, 1, CV_32FC1);
92 for (
int i = 0; i < num_landmarks; ++i) {
94 cv::Vec4f model_mean(face_instance.at<
float>(vertex_ids[i]*3), face_instance.at<
float>(vertex_ids[i]*3 + 1), face_instance.at<
float>(vertex_ids[i]*3 + 2), 1.0f);
95 v_bar.at<
float>(4 * i, 0) = model_mean[0];
96 v_bar.at<
float>((4 * i) + 1, 0) = model_mean[1];
97 v_bar.at<
float>((4 * i) + 2, 0) = model_mean[2];
104 Mat b = P * v_bar - y;
106 Mat AtAReg = A.t() * A + lambda * Mat::eye(num_coeffs_to_fit, num_coeffs_to_fit, CV_32FC1);
109 bool non_singular = cv::solve(AtAReg, -A.t() * b, c_s, cv::DECOMP_SVD);
112 return std::vector<float>(c_s);
Namespace containing all of eos's 3D model fitting functionality.
std::vector< float > fit_blendshapes_to_landmarks_linear(std::vector< eos::morphablemodel::Blendshape > blendshapes, cv::Mat face_instance, cv::Mat affine_camera_matrix, std::vector< cv::Vec2f > landmarks, std::vector< int > vertex_ids, float lambda=500.0f)
Definition: blendshape_fitting.hpp:50