Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
py-3d-face-reconstruction
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Richard Torenvliet
py-3d-face-reconstruction
Commits
5116af65
Commit
5116af65
authored
Nov 26, 2016
by
Richard Torenvliet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use clang++ instead of g++
parent
d99c5f0e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
80 additions
and
78 deletions
+80
-78
makefile
makefile
+2
-2
src/reconstruction/fit-model.cpp
src/reconstruction/fit-model.cpp
+78
-76
No files found.
makefile
View file @
5116af65
...
...
@@ -50,7 +50,7 @@ $(SITE_PACKAGES)/cv%:
src/reconstruction/fit.so
:
src/reconstruction/fit-model.cpp
$(BASE_DOCKER_CMD)
/bin/bash
-c
\
'(cd reconstruction; \
g++ -fPIC -O3 -shared -std=c++11
\
clang++ -fPIC -O3 -shared -std=c++14
\
-I/usr/local/include/pybind11/include/ \
-I/usr/local/eos/include/ \
-I/usr/local/eos/3rdparty/glm/ \
...
...
@@ -61,7 +61,7 @@ src/reconstruction/fit.so: src/reconstruction/fit-model.cpp
-L/usr/lib/x86_64-linux-gnu/ \
-L/usr/local/lib/ \
-lboost_program_options \
-l
file_
system \
-l
boost_file
system \
-lopencv_world \
`python-config --cflags --ldflags` \
$(
notdir
$^
)
-o
$(
notdir
$@
)
\
...
...
src/reconstruction/fit-model.cpp
View file @
5116af65
...
...
@@ -45,8 +45,10 @@ int add(int i, int j) {
#include <fstream>
using
namespace
eos
;
namespace
po
=
boost
::
program_options
;
namespace
fs
=
boost
::
filesystem
;
using
eos
::
core
::
Landmark
;
using
eos
::
core
::
LandmarkCollection
;
using
cv
::
Mat
;
...
...
@@ -68,82 +70,82 @@ using std::string;
* is estimated, and then, using this camera matrix, the shape is fitted
* to the landmarks.
*/
int
fit
(
int
argc
,
char
*
argv
[])
{
// Load the image, landmarks, LandmarkMapper and the Morphable Model:
Mat
image
=
cv
::
imread
(
imagefile
.
string
());
LandmarkCollection
<
cv
::
Vec2f
>
landmarks
;
try
{
landmarks
=
read_pts_landmarks
(
landmarksfile
.
string
());
}
catch
(
const
std
::
runtime_error
&
e
)
{
cout
<<
"Error reading the landmarks: "
<<
e
.
what
()
<<
endl
;
return
EXIT_FAILURE
;
}
morphablemodel
::
MorphableModel
morphable_model
;
try
{
morphable_model
=
morphablemodel
::
load_model
(
modelfile
.
string
());
}
catch
(
const
std
::
runtime_error
&
e
)
{
cout
<<
"Error loading the Morphable Model: "
<<
e
.
what
()
<<
endl
;
return
EXIT_FAILURE
;
}
core
::
LandmarkMapper
landmark_mapper
=
mappingsfile
.
empty
()
?
core
::
LandmarkMapper
()
:
core
::
LandmarkMapper
(
mappingsfile
);
// Draw the loaded landmarks:
Mat
outimg
=
image
.
clone
();
for
(
auto
&&
lm
:
landmarks
)
{
cv
::
rectangle
(
outimg
,
cv
::
Point2f
(
lm
.
coordinates
[
0
]
-
2.0
f
,
lm
.
coordinates
[
1
]
-
2.0
f
),
cv
::
Point2f
(
lm
.
coordinates
[
0
]
+
2.0
f
,
lm
.
coordinates
[
1
]
+
2.0
f
),
{
255
,
0
,
0
});
}
// These will be the final 2D and 3D points used for the fitting:
vector
<
Vec4f
>
model_points
;
// the points in the 3D shape model
vector
<
int
>
vertex_indices
;
// their vertex indices
vector
<
Vec2f
>
image_points
;
// the corresponding 2D landmark points
// Sub-select all the landmarks which we have a mapping for (i.e. that are defined in the 3DMM):
for
(
int
i
=
0
;
i
<
landmarks
.
size
();
++
i
)
{
auto
converted_name
=
landmark_mapper
.
convert
(
landmarks
[
i
].
name
);
if
(
!
converted_name
)
{
// no mapping defined for the current landmark
continue
;
}
int
vertex_idx
=
std
::
stoi
(
converted_name
.
get
());
Vec4f
vertex
=
morphable_model
.
get_shape_model
().
get_mean_at_point
(
vertex_idx
);
model_points
.
emplace_back
(
vertex
);
vertex_indices
.
emplace_back
(
vertex_idx
);
image_points
.
emplace_back
(
landmarks
[
i
].
coordinates
);
}
// Estimate the camera (pose) from the 2D - 3D point correspondences
fitting
::
ScaledOrthoProjectionParameters
pose
=
fitting
::
estimate_orthographic_projection_linear
(
image_points
,
model_points
,
true
,
image
.
rows
);
fitting
::
RenderingParameters
rendering_params
(
pose
,
image
.
cols
,
image
.
rows
);
// The 3D head pose can be recovered as follows:
float
yaw_angle
=
glm
::
degrees
(
glm
::
yaw
(
rendering_params
.
get_rotation
()));
// and similarly for pitch and roll.
// Estimate the shape coefficients by fitting the shape to the landmarks:
Mat
affine_from_ortho
=
fitting
::
get_3x4_affine_camera_matrix
(
rendering_params
,
image
.
cols
,
image
.
rows
);
vector
<
float
>
fitted_coeffs
=
fitting
::
fit_shape_to_landmarks_linear
(
morphable_model
,
affine_from_ortho
,
image_points
,
vertex_indices
);
// Obtain the full mesh with the estimated coefficients:
render
::
Mesh
mesh
=
morphable_model
.
draw_sample
(
fitted_coeffs
,
vector
<
float
>
());
// Extract the texture from the image using given mesh and camera parameters:
Mat
isomap
=
render
::
extract_texture
(
mesh
,
affine_from_ortho
,
image
);
// Save the mesh as textured obj:
outputfile
+=
fs
::
path
(
".obj"
);
render
::
write_textured_obj
(
mesh
,
outputfile
.
string
());
// And save the isomap:
outputfile
.
replace_extension
(
".isomap.png"
);
cv
::
imwrite
(
outputfile
.
string
(),
isomap
);
cout
<<
"Finished fitting and wrote result mesh and isomap to files with basename "
<<
outputfile
.
stem
().
stem
()
<<
"."
<<
endl
;
return
EXIT_SUCCESS
;
}
//
int fit(int argc, char *argv[])
//
{
//
// Load the image, landmarks, LandmarkMapper and the Morphable Model:
//
Mat image = cv::imread(imagefile.string());
//
LandmarkCollection<cv::Vec2f> landmarks;
//
try {
//
landmarks = read_pts_landmarks(landmarksfile.string());
//
}
//
catch (const std::runtime_error& e) {
//
cout << "Error reading the landmarks: " << e.what() << endl;
//
return EXIT_FAILURE;
//
}
//
morphablemodel::MorphableModel morphable_model;
//
try {
//
morphable_model = morphablemodel::load_model(modelfile.string());
//
}
//
catch (const std::runtime_error& e) {
//
cout << "Error loading the Morphable Model: " << e.what() << endl;
//
return EXIT_FAILURE;
//
}
//
core::LandmarkMapper landmark_mapper = mappingsfile.empty() ? core::LandmarkMapper() : core::LandmarkMapper(mappingsfile);
//
//
// Draw the loaded landmarks:
//
Mat outimg = image.clone();
//
for (auto&& lm : landmarks) {
//
cv::rectangle(outimg, cv::Point2f(lm.coordinates[0] - 2.0f, lm.coordinates[1] - 2.0f), cv::Point2f(lm.coordinates[0] + 2.0f, lm.coordinates[1] + 2.0f), { 255, 0, 0 });
//
}
//
//
// These will be the final 2D and 3D points used for the fitting:
//
vector<Vec4f> model_points; // the points in the 3D shape model
//
vector<int> vertex_indices; // their vertex indices
//
vector<Vec2f> image_points; // the corresponding 2D landmark points
//
//
// Sub-select all the landmarks which we have a mapping for (i.e. that are defined in the 3DMM):
//
for (int i = 0; i < landmarks.size(); ++i) {
//
auto converted_name = landmark_mapper.convert(landmarks[i].name);
//
if (!converted_name) { // no mapping defined for the current landmark
//
continue;
//
}
//
int vertex_idx = std::stoi(converted_name.get());
//
Vec4f vertex = morphable_model.get_shape_model().get_mean_at_point(vertex_idx);
//
model_points.emplace_back(vertex);
//
vertex_indices.emplace_back(vertex_idx);
//
image_points.emplace_back(landmarks[i].coordinates);
//
}
//
//
// Estimate the camera (pose) from the 2D - 3D point correspondences
//
fitting::ScaledOrthoProjectionParameters pose = fitting::estimate_orthographic_projection_linear(image_points, model_points, true, image.rows);
//
fitting::RenderingParameters rendering_params(pose, image.cols, image.rows);
//
//
// The 3D head pose can be recovered as follows:
//
float yaw_angle = glm::degrees(glm::yaw(rendering_params.get_rotation()));
//
// and similarly for pitch and roll.
//
//
// Estimate the shape coefficients by fitting the shape to the landmarks:
//
Mat affine_from_ortho = fitting::get_3x4_affine_camera_matrix(rendering_params, image.cols, image.rows);
//
vector<float> fitted_coeffs = fitting::fit_shape_to_landmarks_linear(morphable_model, affine_from_ortho, image_points, vertex_indices);
//
//
// Obtain the full mesh with the estimated coefficients:
//
render::Mesh mesh = morphable_model.draw_sample(fitted_coeffs, vector<float>());
//
//
// Extract the texture from the image using given mesh and camera parameters:
//
Mat isomap = render::extract_texture(mesh, affine_from_ortho, image);
//
//
// Save the mesh as textured obj:
//
outputfile += fs::path(".obj");
//
render::write_textured_obj(mesh, outputfile.string());
//
//
// And save the isomap:
//
outputfile.replace_extension(".isomap.png");
//
cv::imwrite(outputfile.string(), isomap);
//
//
cout << "Finished fitting and wrote result mesh and isomap to files with basename " << outputfile.stem().stem() << "." << endl;
//
//
return EXIT_SUCCESS;
//
}
PYBIND11_PLUGIN
(
fit
)
{
py
::
module
m
(
"fit"
,
"fit example"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment