1 #include "gaze/pipeline_steps/head_pose_estimation.h"
7 #include "dlib/gui_widgets.h"
8 #include "dlib/image_processing.h"
9 #include "opencv2/opencv.hpp"
10 #include "yaml-cpp/yaml.h"
12 #include "gaze/util/config.h"
13 #include "gaze/util/data.h"
20 HeadPoseEstimation::HeadPoseEstimation() {
22 this->
name = config[
"name"] ?
23 config[
"name"].as<
std::string>() :
"HeadPoseEstimation";
25 if (config[
"landmark_indices"]) {
28 this->index_list = {30, 8, 36, 45, 48, 54};
31 if (config[
"model"]) {
34 this->model_points = {
36 {0.0, -0.0636, -0.0125},
37 {-0.0433, 0.0327, -0.026},
38 {0.0433, 0.0327, -0.026},
39 {-0.0289, -0.0289, -0.0241},
40 {0.0289, -0.0289, -0.0241}
44 if (config[
"model_scale"]) {
45 this->model_scale = config[
"model_scale"].as<decltype(this->model_scale)>();
47 this->model_scale = 1;
50 this->coord_base_overlay.
push_back({{-1, -1}, {-1, -1},
51 dlib::rgb_pixel(255, 0, 0)});
52 this->coord_base_overlay.
push_back({{-1, -1}, {-1, -1},
53 dlib::rgb_pixel(0, 255, 0)});
54 this->coord_base_overlay.
push_back({{-1, -1}, {-1, -1},
55 dlib::rgb_pixel(0, 0, 255)});
58 void HeadPoseEstimation::update_overlay(
const util::Data& data) {
59 this->
widget->clear_overlay();
60 if (data.landmarks.num_parts() <= 0) {
67 {0.1 * this->model_scale, 0, 0},
68 {0, 0.1 * this->model_scale, 0},
69 {0, 0, 0.1 * this->model_scale}};
72 this->read_or_set_camera_matrix(data),
76 for (
auto i = decltype(this->coord_base_overlay.
size()){0};
77 i < this->coord_base_overlay.
size(); ++i) {
78 this->coord_base_overlay[i] = dlib::image_display::overlay_line(
79 dlib::point(image_points[0].x, image_points[0].y),
80 dlib::point(image_points[i + 1].x, image_points[i + 1].y),
81 this->coord_base_overlay[i].color);
83 this->
widget->add_overlay(this->coord_base_overlay);
88 data.head_translation, this->read_or_set_camera_matrix(data),
91 auto color_detection = dlib::rgb_pixel(255, 0, 0);
92 auto color_projection = dlib::rgb_pixel(0, 0, 255);
95 for (
auto i = decltype(projected_points.
size()){0};
96 i < projected_points.
size(); ++i) {
97 detections.
push_back(dlib::image_display::overlay_circle(
98 data.landmarks.part(this->index_list[i]), 2, color_detection,
99 "d" + std::to_string(this->index_list[i])));
100 projections.
push_back(dlib::image_display::overlay_circle(
101 dlib::point(projected_points[i].x, projected_points[i].y),
102 2, color_projection,
"p" + std::to_string(this->index_list[i])));
104 this->
widget->add_overlay(detections);
105 this->
widget->add_overlay(projections);
115 for (
auto i : this->index_list) {
128 this->update_overlay(data);
133 if (this->has_camera_matrix) {
134 return this->camera_matrix;
137 if (camera_config[
"camera_matrix"]) {
138 this->camera_matrix = camera_config[
"camera_matrix"].as<
cv::Mat>();
140 this->camera_matrix <<
145 this->has_camera_matrix =
true;
146 return this->camera_matrix;
150 if (this->has_distortions) {
151 return this->distortions;
154 if (camera_config[
"distortion_coefficients"]) {
155 this->distortions = camera_config[
"distortion_coefficients"].as<
cv::Mat>();
159 this->has_distortions =
true;
160 return this->distortions;
std::shared_ptr< widget_type > widget
void process(util::Data &data) override
static MatExpr zeros(int rows, int cols, int type)
dlib::array2d< dlib::bgr_pixel > image
cv::Mat get_and_maybe_read_distortions(const util::Data &data)
void push_back(const value_type &__x)
dlib::full_object_detection landmarks
cv::Matx33d read_or_set_camera_matrix(const util::Data &data)
bool solvePnP(InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false, int flags=SOLVEPNP_ITERATIVE)
Wraps the data acquired per frame into a single instance.
size_type size() const noexcept
void projectPoints(InputArray objectPoints, InputArray rvec, InputArray tvec, InputArray cameraMatrix, InputArray distCoeffs, OutputArray imagePoints, OutputArray jacobian=noArray(), double aspectRatio=0)
void visualize(util::Data &data) override