1 #include "gaze/pipeline_steps/pupil_localization.h"
8 #include "dlib/image_processing.h"
9 #include "dlib/image_transforms.h"
10 #include "dlib/matrix.h"
11 #include "dlib/opencv.h"
12 #include "yaml-cpp/yaml.h"
14 #include "gaze/util/config.h"
15 #include "gaze/util/data.h"
16 #include "gaze/util/pipeline_utils.h"
24 dlib::matrix<double>& table_x,
25 dlib::matrix<double>& table_y,
29 if (size <= table_x.nr()) {
34 size += (1 - size & 1);
35 int half_size = (size - 1) / 2;
38 table_x.set_size(size, size);
39 table_y.set_size(size, size);
42 for (
int row = 0; row < table_x.nr(); ++row) {
43 dlib::set_rowm(table_x, row) = dlib::range(-half_size, half_size);
45 table_y = dlib::trans(table_x);
49 for (
int row = 0; row < table_x.nr(); ++row) {
50 for (
int col = 0; col < table_x.nc(); ++col) {
51 table_x(row, col) = table_x(row, col) /
52 (
std::sqrt(table_x(row, col) * table_x(row, col)
53 + table_y(row, col) * table_y(row, col))
58 table_y = dlib::trans(table_x);
65 PupilLocalization::PupilLocalization()
69 : relative_threshold_factor(0.3),
72 this->name = config[
"name"] ?
73 config[
"name"].as<
std::string>() :
"PupilLocalization";
75 if (config[
"relative_threshold"]) {
76 this->relative_threshold_factor =
77 config[
"relative_threshold"]
78 .as<decltype(this->relative_threshold_factor)>();
83 this->displacement_table_x,
84 this->displacement_table_y,
85 config[
"table_size"] ? config[
"table_size"].as<int>() : 131);
96 dlib::extract_image_chips(data.
image, details, data.
eyes);
100 data.
eyes[1].nr(), data.
eyes[1].nc()});
101 if (2 * max_size > this->displacement_table_x.nr()) {
103 this->displacement_table_x,
104 this->displacement_table_y,
108 for (
int i = 0; i < 2; ++i) {
109 dlib::matrix<double> eye_in;
110 dlib::assign_image(eye_in, data.
eyes[i]);
113 dlib::matrix<double> eye_horizontal;
114 dlib::matrix<double> eye_vertical;
115 dlib::sobel_edge_detector(eye_in, eye_horizontal, eye_vertical);
118 this->relative_threshold_factor);
121 int boundary_offset = 6;
122 dlib::matrix<double> eye_gaussian;
123 dlib::gaussian_blur(eye_in, eye_gaussian, this->sigma, boundary_offset);
124 eye_gaussian = 255 - eye_gaussian;
131 int center = (this->displacement_table_x.nr() - 1) / 2;
132 auto nr = eye_in.nr();
133 auto nc = eye_in.nc();
134 dlib::matrix<double>
zero = dlib::zeros_matrix<double>(nr, nc);
135 dlib::matrix<double> ts = dlib::zeros_matrix<double>(nr, nc);
136 for (
auto row = decltype(nr){boundary_offset};
137 row < nr - boundary_offset; ++row) {
138 for (
auto col = decltype(nc){boundary_offset};
139 col < nc - boundary_offset; ++col) {
140 dlib::matrix<double> d_x = dlib::subm(this->displacement_table_x,
141 center - row, center - col, nr, nc);
142 dlib::matrix<double> d_y = dlib::subm(this->displacement_table_y,
143 center - row, center - col, nr, nc);
147 dlib::squared(dlib::max_pointwise(
148 dlib::pointwise_multiply(d_x, eye_horizontal) +
149 dlib::pointwise_multiply(d_y, eye_vertical), zero))) *
150 eye_gaussian(row, col);
158 data.
centers[i] = dlib::point(argmax_c, argmax_r);
170 dlib::point offset_x(5, 0);
171 dlib::point offset_y(0, 5);
176 dlib::array<dlib::array2d<dlib::bgr_pixel>> eyes(3);
177 dlib::assign_image(eyes[2], data.
image);
178 for (
auto i = decltype(data.
eyes.size()){0};
179 i < data.
eyes.size(); ++i) {
180 dlib::assign_image(eyes[i], data.
eyes[i]);
182 dlib::draw_line(eyes[i],
185 dlib::rgb_pixel(255, 0, 0));
186 dlib::draw_line(eyes[i],
189 dlib::rgb_pixel(255, 0, 0));
191 dlib::draw_line(eyes[2],
192 data.
centers[i] + offset_x + chips[i].rect.tl_corner(),
193 data.
centers[i] - offset_x + chips[i].rect.tl_corner(),
194 dlib::rgb_pixel(255, 0, 0));
195 dlib::draw_line(eyes[2],
196 data.
centers[i] + offset_y + chips[i].rect.tl_corner(),
197 data.
centers[i] - offset_y + chips[i].rect.tl_corner(),
198 dlib::rgb_pixel(255, 0, 0));
200 dlib::resize_image(0.5, eyes[2]);
202 this->widget->set_image(dlib::tile_images(eyes));
std::vector< dlib::chip_details > get_eyes_chip_details(const dlib::full_object_detection object_detection)
dlib::array< dlib::array2d< double > > eyes
dlib::array< dlib::point > centers
dlib::array2d< dlib::bgr_pixel > image
void fill_displacement_tables(dlib::matrix< double > &table_x, dlib::matrix< double > &table_y, int size)
_GLIBCXX14_CONSTEXPR const _Tp & max(const _Tp &__a, const _Tp &__b)
static constexpr _Tp min() noexcept
dlib::full_object_detection landmarks
Wraps the data acquired per frame into a single instance.
complex< _Tp > sqrt(const complex< _Tp > &)
void normalize_and_threshold_gradients(dlib::matrix< T > &horizontal, dlib::matrix< T > &vertical, double relative_threshold=-1)