Commit ea140ed2 authored by Patrik Huber's avatar Patrik Huber

Added conversions to Matlab for Mesh

This contains conversion for vector<glm::tvecX> for the vertices, colours, and texcoords, and vector<array<int, 3>> for the triangle indices.
We can now successfully return a Mesh to Matlab.
parent 80d6c0cd
...@@ -12,7 +12,7 @@ function [mesh, rendering_parameters] = fit_shape_and_pose(morphable_model, ... ...@@ -12,7 +12,7 @@ function [mesh, rendering_parameters] = fit_shape_and_pose(morphable_model, ...
% It fits the pose (camera), PCA shape model, and expression blendshapes % It fits the pose (camera), PCA shape model, and expression blendshapes
% in an iterative way. % in an iterative way.
% %
% landmarks must be a 68 x 2 vector with ibug landmarks, in the order % landmarks must be a 68 x 2 matrix with ibug landmarks, in the order
% from 1 to 68. % from 1 to 68.
% %
% Default values for some of the parameters:: num_iterations = 5, % Default values for some of the parameters:: num_iterations = 5,
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "eos/render/Mesh.hpp" #include "eos/render/Mesh.hpp"
#include "mexplus_eigen.hpp" #include "mexplus_eigen.hpp"
#include "mexplus_eos_types.hpp"
#include "mexplus.h" #include "mexplus.h"
...@@ -46,7 +47,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) ...@@ -46,7 +47,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{ {
using std::string; using std::string;
// Check for proper number of input and output arguments: // Check for proper number of input and output arguments:
mexPrintf("nlhs: %d, nrhs: %d\n", nlhs, nrhs);
if (nrhs != 12) { if (nrhs != 12) {
mexErrMsgIdAndTxt("eos:fitting:nargin", "fit_shape_and_pose requires 12 input arguments."); mexErrMsgIdAndTxt("eos:fitting:nargin", "fit_shape_and_pose requires 12 input arguments.");
} }
...@@ -92,9 +92,17 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) ...@@ -92,9 +92,17 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
fitting::RenderingParameters rendering_parameters; fitting::RenderingParameters rendering_parameters;
std::tie(mesh, rendering_parameters) = fitting::fit_shape_and_pose(morphable_model, blendshapes, landmarks, landmark_mapper, image_width, image_height, edge_topology, contour_landmarks, model_contour, num_iterations, num_shape_coefficients_to_fit, lambda); std::tie(mesh, rendering_parameters) = fitting::fit_shape_and_pose(morphable_model, blendshapes, landmarks, landmark_mapper, image_width, image_height, edge_topology, contour_landmarks, model_contour, num_iterations, num_shape_coefficients_to_fit, lambda);
// C++ counts the vertex indices starting at zero, Matlab starts counting
// at one - therefore, add +1 to all triangle indices:
for (auto&& t : mesh.tvi) {
for (auto&& idx : t) {
idx += 1;
}
}
// Return the mesh and the rendering_parameters: // Return the mesh and the rendering_parameters:
OutputArguments output(nlhs, plhs, 2); OutputArguments output(nlhs, plhs, 2);
output.set(0, landmarks_in); // the Mesh output.set(0, mesh);
output.set(1, landmarks_in); // RenderingParameters output.set(1, landmarks_in); // RenderingParameters
}; };
......
/*
* eos - A 3D Morphable Model fitting library written in modern C++11/14.
*
* File: matlab/include/mexplus_eos_types.hpp
*
* Copyright 2016 Patrik Huber
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifndef MEXPLUS_EOS_TYPES_HPP_
#define MEXPLUS_EOS_TYPES_HPP_
#include "eos/render/Mesh.hpp"
#include "mexplus/mxarray.h"
#include "glm/vec4.hpp"
#include "Eigen/Core"
#include "mex.h"
/**
* Todo: Add a doxygen file comment? See opencv cereal?
*/
namespace mexplus {
// We have an overload for vector<tvec4<float>> directly because otherwise a cell
// will be used. However, such overload for tvec4<float> can be added without affecting
// this one, this overload takes precedence!
// Todo: Numeric<float> instead?
template<>
mxArray* MxArray::from(const std::vector<glm::tvec2<float>>& vec)
{
MxArray out_array(MxArray::Numeric<double>(vec.size(), 2));
for (int r = 0; r < vec.size(); ++r) {
for (int c = 0; c < 2; ++c) {
out_array.set(r, c, vec[r][c]);
}
}
return out_array.release();
};
template<>
mxArray* MxArray::from(const std::vector<glm::tvec3<float>>& vec)
{
MxArray out_array(MxArray::Numeric<double>(vec.size(), 3));
for (int r = 0; r < vec.size(); ++r) {
for (int c = 0; c < 3; ++c) {
out_array.set(r, c, vec[r][c]);
}
}
return out_array.release();
};
template<>
mxArray* MxArray::from(const std::vector<glm::tvec4<float>>& vec)
{
MxArray out_array(MxArray::Numeric<double>(vec.size(), 4));
for (int r = 0; r < vec.size(); ++r) {
for (int c = 0; c < 4; ++c) {
out_array.set(r, c, vec[r][c]);
}
}
return out_array.release();
};
// This is for tvi and tci - return them as matrix, not as cell-array.
template<>
mxArray* MxArray::from(const std::vector<std::array<int, 3>>& vec)
{
MxArray out_array(MxArray::Numeric<int>(vec.size(), 3));
for (int r = 0; r < vec.size(); ++r) {
for (int c = 0; c < 3; ++c) {
out_array.set(r, c, vec[r][c]);
}
}
return out_array.release();
};
/**
* @brief Define a template specialisation for ... .
*
* Todo: Documentation.
*/
template<>
mxArray* MxArray::from(const eos::render::Mesh& mesh) {
MxArray out_array(MxArray::Struct());
out_array.set("vertices", mesh.vertices);
out_array.set("colors", mesh.colors);
out_array.set("texcoords", mesh.texcoords);
out_array.set("tvi", mesh.tvi);
out_array.set("tci", mesh.tci);
return out_array.release();
};
/**
* @brief Define a template specialisation for Eigen::MatrixXd for ... .
*
* Todo: Documentation.
*/
/*
template<>
void MxArray::to(const mxArray* in_array, Eigen::MatrixXd* eigen_matrix)
{
MxArray array(in_array);
if (array.dimensionSize() > 2)
{
mexErrMsgIdAndTxt("eos:matlab", "Given array has > 2 dimensions. Can only create 2-dimensional matrices (and vectors).");
}
if (array.dimensionSize() == 1 || array.dimensionSize() == 0)
{
mexErrMsgIdAndTxt("eos:matlab", "Given array has 0 or 1 dimensions but we expected a 2-dimensional matrix (or row/column vector).");
// Even when given a single value dimensionSize() is 2, with n=m=1. When does this happen?
}
if (!array.isDouble())
{
mexErrMsgIdAndTxt("eos:matlab", "Trying to create a Eigen::MatrixXd in C++, but the given data is not of type double.");
}
// We can be sure now that the array is 2-dimensional (or 0, but then we're screwed anyway)
auto nrows = array.dimensions()[0]; // or use array.rows()
auto ncols = array.dimensions()[1];
// I think I can just use Eigen::Matrix, not a Map - the Matrix c'tor that we call creates a Map anyway?
Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>> eigen_map(array.getData<double>(), nrows, ncols);
// Not sure that's alright - who owns the data? I think as it is now, everything points to the data in the mxArray owned by Matlab, but I'm not 100% sure.
*eigen_matrix = eigen_map;
};
*/
} /* namespace mexplus */
#endif /* MEXPLUS_EOS_TYPES_HPP_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment