py::modulecore_module=eos_module.def_submodule("core","Essential functions and classes to work with 3D face models and landmarks.");
py::class_<core::LandmarkMapper>(core_module,"LandmarkMapper","Represents a mapping from one kind of landmarks to a different format(e.g.model vertices).")
.def(py::init<>(),"Constructs a new landmark mapper that performs an identity mapping, that is, its output is the same as the input.")
.def("__init__",[](core::LandmarkMapper&instance,std::stringfilename){// wrap the fs::path c'tor with std::string
new(&instance)core::LandmarkMapper(filename);
},"Constructs a new landmark mapper from a file containing mappings from one set of landmark identifiers to another.")
// We can't expose the convert member function yet - need std::optional (or some trick with self/this and a lambda)
;
/**
* Bindings for the eos::morphablemodel namespace:
* - PcaModel
...
...
@@ -206,8 +225,8 @@ PYBIND11_PLUGIN(eos) {
.def("get_data_dimension",&morphablemodel::PcaModel::get_data_dimension,"Returns the dimension of the data, i.e. the number of shape dimensions.")
.def("get_triangle_list",&morphablemodel::PcaModel::get_triangle_list,"Returns a list of triangles on how to assemble the vertices into a mesh.")
.def("get_mean",&morphablemodel::PcaModel::get_mean,"Returns the mean of the model.")
.def("get_mean_at_point",&morphablemodel::PcaModel::get_mean_at_point,"Return the value of the mean at a given vertex index.")
.def("draw_sample",(cv::Mat(morphablemodel::PcaModel::*)(std::vector<float>)const)&morphablemodel::PcaModel::draw_sample,"Returns a sample from the model with the given PCA coefficients. The given coefficients should follow a standard normal distribution, i.e. not be \"normalised\" with their eigenvalues/variances.")
.def("get_mean_at_point",&morphablemodel::PcaModel::get_mean_at_point,"Return the value of the mean at a given vertex index.",py::arg("vertex_index"))
.def("draw_sample",(cv::Mat(morphablemodel::PcaModel::*)(std::vector<float>)const)&morphablemodel::PcaModel::draw_sample,"Returns a sample from the model with the given PCA coefficients. The given coefficients should follow a standard normal distribution, i.e. not be scaled with their eigenvalues/variances.",py::arg("coefficients"))
;
py::class_<morphablemodel::MorphableModel>(morphablemodel_module,"MorphableModel","A class representing a 3D Morphable Model, consisting of a shape- and colour (albedo) PCA model, as well as texture (uv) coordinates.")
...
...
@@ -228,11 +247,37 @@ PYBIND11_PLUGIN(eos) {
morphablemodel_module.def("load_blendshapes",&morphablemodel::load_blendshapes,"Load a file with blendshapes from a cereal::BinaryInputArchive (.bin) from the harddisk.");
/**
* - EdgeTopology
* - load_edge_topology()
*/
py::class_<morphablemodel::EdgeTopology>(morphablemodel_module,"EdgeTopology","A struct containing a 3D shape model's edge topology.");
morphablemodel_module.def("load_edge_topology",&morphablemodel::load_edge_topology,"Load a 3DMM edge topology file from a json file.");
/**
* Bindings for the eos::render namespace:
* (Note: Defining Mesh before using it below in fitting::fit_shape_and_pose)
* - Mesh
*/
py::modulerender_module=eos_module.def_submodule("render","3D mesh and texture extraction functionality.");
py::class_<render::Mesh>(render_module,"Mesh","This class represents a 3D mesh consisting of vertices, vertex colour information and texture coordinates.")
py::modulefitting_module=eos_module.def_submodule("fitting","Pose and shape fitting of a 3D Morphable Model.");
...
...
@@ -245,7 +290,7 @@ PYBIND11_PLUGIN(eos) {
py::class_<fitting::RenderingParameters>(fitting_module,"RenderingParameters","Represents a set of estimated model parameters (rotation, translation) and camera parameters (viewing frustum).")
.def(py::init<fitting::ScaledOrthoProjectionParameters,int,int>(),"Create a RenderingParameters object from an instance of estimated ScaledOrthoProjectionParameters.")
.def("get_rotation",[](constfitting::RenderingParameters&p){returnglm::vec4(p.get_rotation().w,p.get_rotation().x,p.get_rotation().y,p.get_rotation().z);},"Returns the rotation quaternion [w x y z].")
.def("get_rotation",[](constfitting::RenderingParameters&p){returnglm::vec4(p.get_rotation().x,p.get_rotation().y,p.get_rotation().z,p.get_rotation().w);},"Returns the rotation quaternion [x y z w].")
.def("get_rotation_euler_angles",[](constfitting::RenderingParameters&p){returnglm::eulerAngles(p.get_rotation());},"Returns the rotation's Euler angles (in radians) as [pitch, yaw, roll].")
.def("get_modelview",&fitting::RenderingParameters::get_modelview,"Returns the 4x4 model-view matrix.")
.def("get_projection",&fitting::RenderingParameters::get_projection,"Returns the 4x4 projection matrix.")
...
...
@@ -262,5 +307,30 @@ PYBIND11_PLUGIN(eos) {
},"This algorithm estimates the parameters of a scaled orthographic projection, given a set of corresponding 2D-3D points.",py::arg("image_points"),py::arg("model_points"),py::arg("is_viewport_upsidedown"),py::arg("viewport_height")=0)
;
py::class_<fitting::ContourLandmarks>(fitting_module,"ContourLandmarks","Defines which 2D landmarks comprise the right and left face contour.")
.def_static("load",&fitting::ContourLandmarks::load,"Helper method to load contour landmarks from a text file with landmark mappings, like ibug2did.txt.")
;
py::class_<fitting::ModelContour>(fitting_module,"ModelContour","Definition of the vertex indices that define the right and left model contour.")
.def_static("load",&fitting::ModelContour::load,"Helper method to load a ModelContour from a json file from the hard drive.")
},"Fit the pose (camera), shape model, and expression blendshapes to landmarks, in an iterative way. Returns a tuple (mesh, rendering_parameters, shape_coefficients, blendshape_coefficients).",py::arg("morphable_model"),py::arg("blendshapes"),py::arg("landmarks"),py::arg("landmark_ids"),py::arg("landmark_mapper"),py::arg("image_width"),py::arg("image_height"),py::arg("edge_topology"),py::arg("contour_landmarks"),py::arg("model_contour"),py::arg("num_iterations")=5,py::arg("num_shape_coefficients_to_fit")=-1,py::arg("lambda")=30.0f)