22 #ifndef LINEARSHAPEFITTING_HPP_ 23 #define LINEARSHAPEFITTING_HPP_ 25 #include "eos/morphablemodel/MorphableModel.hpp" 29 #include "opencv2/core/core.hpp" 31 #include "boost/optional.hpp" 60 inline std::vector<float>
fit_shape_to_landmarks_linear(
morphablemodel::MorphableModel morphable_model, cv::Mat affine_camera_matrix, std::vector<cv::Vec2f> landmarks, std::vector<int> vertex_ids, cv::Mat base_face=cv::Mat(),
float lambda=3.0f, boost::optional<int> num_coefficients_to_fit=boost::optional<int>(), boost::optional<float> detector_standard_deviation=boost::optional<float>(), boost::optional<float> model_standard_deviation=boost::optional<float>())
63 assert(landmarks.size() == vertex_ids.size());
66 int num_landmarks =
static_cast<int>(landmarks.size());
68 if (base_face.empty())
75 Mat V_hat_h = Mat::zeros(4 * num_landmarks, num_coeffs_to_fit, CV_32FC1);
77 for (
int i = 0; i < num_landmarks; ++i) {
80 basis_rows.colRange(0, num_coeffs_to_fit).copyTo(V_hat_h.rowRange(row_index, row_index + 3));
84 Mat P = Mat::zeros(3 * num_landmarks, 4 * num_landmarks, CV_32FC1);
85 for (
int i = 0; i < num_landmarks; ++i) {
86 Mat submatrix_to_replace = P.colRange(4 * i, (4 * i) + 4).rowRange(3 * i, (3 * i) + 3);
87 affine_camera_matrix.copyTo(submatrix_to_replace);
94 float sigma_squared_2D = std::pow(detector_standard_deviation.get_value_or(std::sqrt(3.0f)), 2) + std::pow(model_standard_deviation.get_value_or(0.0f), 2);
95 Mat Sigma = Mat::zeros(3 * num_landmarks, 3 * num_landmarks, CV_32FC1);
96 for (
int i = 0; i < 3 * num_landmarks; ++i) {
97 Sigma.at<
float>(i, i) = 1.0f / std::sqrt(sigma_squared_2D);
99 Mat Omega = Sigma.t() * Sigma;
101 Mat y = Mat::ones(3 * num_landmarks, 1, CV_32FC1);
102 for (
int i = 0; i < num_landmarks; ++i) {
103 y.at<
float>(3 * i, 0) = landmarks[i][0];
104 y.at<
float>((3 * i) + 1, 0) = landmarks[i][1];
108 Mat v_bar = Mat::ones(4 * num_landmarks, 1, CV_32FC1);
109 for (
int i = 0; i < num_landmarks; ++i) {
111 cv::Vec4f model_mean(base_face.at<
float>(vertex_ids[i] * 3), base_face.at<
float>(vertex_ids[i] * 3 + 1), base_face.at<
float>(vertex_ids[i] * 3 + 2), 1.0f);
112 v_bar.at<
float>(4 * i, 0) = model_mean[0];
113 v_bar.at<
float>((4 * i) + 1, 0) = model_mean[1];
114 v_bar.at<
float>((4 * i) + 2, 0) = model_mean[2];
121 Mat b = P * v_bar - y;
124 const int num_shape_pc = num_coeffs_to_fit;
125 Mat AtOmegaA = A.t() * Omega * A;
126 Mat AtOmegaAReg = AtOmegaA + lambda * Mat::eye(num_shape_pc, num_shape_pc, CV_32FC1);
140 bool non_singular = cv::solve(AtOmegaAReg, -A.t() * Omega.t() * b, c_s, cv::DECOMP_SVD);
143 return std::vector<float>(c_s);
cv::Mat get_normalised_pca_basis() const
Definition: PcaModel.hpp:188
int get_num_principal_components() const
Definition: PcaModel.hpp:84
Namespace containing all of eos's 3D model fitting functionality.
std::vector< float > fit_shape_to_landmarks_linear(morphablemodel::MorphableModel morphable_model, cv::Mat affine_camera_matrix, std::vector< cv::Vec2f > landmarks, std::vector< int > vertex_ids, cv::Mat base_face=cv::Mat(), float lambda=3.0f, boost::optional< int > num_coefficients_to_fit=boost::optional< int >(), boost::optional< float > detector_standard_deviation=boost::optional< float >(), boost::optional< float > model_standard_deviation=boost::optional< float >())
Definition: linear_shape_fitting.hpp:60
cv::Mat get_mean() const
Definition: PcaModel.hpp:119
PcaModel get_shape_model() const
Definition: MorphableModel.hpp:77
A class representing a 3D Morphable Model, consisting of a shape- and colour (albedo) PCA model...
Definition: MorphableModel.hpp:54