1 #include "gaze/pipeline_steps/eye_like.h"
5 #include "opencv2/opencv.hpp"
6 #include "yaml-cpp/yaml.h"
8 #include "gaze/util/config.h"
9 #include "gaze/util/data.h"
10 #include "gaze/util/dlibcv.h"
11 #include "gaze/util/pipeline_utils.h"
41 double compute_dynamic_threshold(
const cv::Mat& mat,
double std_dev_factor) {
44 double std_dev = stdMagnGrad[0];
45 return std_dev_factor * std_dev + meanMagnGrad[0];
60 for (
auto y = decltype(image.
rows){0}; y < image.
rows; ++y) {
62 double *out_row = out.
ptr<
double>(y);
64 out_row[0] = row[1] - row[0];
65 for (
auto x = decltype(image.
cols){1}; x < image.
cols - 1; ++x) {
66 out_row[x] = (row[x + 1] - row[x - 1]) / 2.0;
68 out_row[image.
cols - 1] = row[image.
cols - 1] - row[image.
cols - 2];
83 for (
auto y = decltype(mat_x.
rows){0}; y < mat_x.
rows; ++y) {
84 const double *Xr = mat_x.
ptr<
double>(y), *Yr = mat_y.
ptr<
double>(y);
85 double *row = mags.
ptr<
double>(y);
86 for (
auto x = decltype(mat_x.
cols){0}; x < mat_x.
cols; ++x) {
87 double gX = Xr[x], gY = Yr[x];
111 void test_possible_centers_formula(
114 double gx,
double gy,
116 for (
auto cy = decltype(out.
rows){0}; cy < out.
rows; ++cy) {
117 double *out_row = out.
ptr<
double>(cy);
118 const unsigned char *Wr = weight.
ptr<
unsigned char>(cy);
119 for (
auto cx = decltype(out.
cols){0}; cx < out.
cols; ++cx) {
120 if (x == cx && y == cy) {
129 double dotProduct = dx * gx + dy * gy;
130 dotProduct =
std::max(0.0, dotProduct);
131 out_row[cx] += dotProduct * dotProduct * Wr[cx];
146 double fast_eye_width) {
147 double ratio = fast_eye_width / orig_size.
width;
148 int x = std::round(point.
x / ratio);
149 int y = std::round(point.
y / ratio);
167 double gradient_threshold,
double fast_eye_width = 50) {
174 cv::Mat eye_roi_unscaled = face(eye_roi_cut);
180 fast_eye_width / eye_roi_unscaled.
cols * eye_roi_unscaled.
rows));
182 cv::Mat gradientX = compute_x_gradient(eye_roi);
183 cv::Mat gradientY = compute_x_gradient(eye_roi.
t()).t();
184 cv::Mat mags = matrix_magnitude(gradientX, gradientY);
185 double gradientThresh = compute_dynamic_threshold(mags,
188 for (
auto y = decltype(eye_roi.
rows){0}; y < eye_roi.
rows; ++y) {
189 double *x_row = gradientX.
ptr<
double>(y);
190 double *y_row = gradientY.
ptr<
double>(y);
191 const double *M_ROW = mags.
ptr<
double>(y);
192 for (
auto x = decltype(eye_roi.
cols){0}; x < eye_roi.
cols; ++x) {
193 if (M_ROW[x] > gradientThresh) {
194 x_row[x] /= M_ROW[x];
195 y_row[x] /= M_ROW[x];
205 weight = 255 - weight;
208 for (
int y = 0; y < weight.
rows; ++y) {
209 const double *X_ROW = gradientX.
ptr<
double>(y);
210 const double *Y_ROW = gradientY.
ptr<
double>(y);
211 for (
int x = 0; x < weight.
cols; ++x) {
212 if (X_ROW[x] == 0.0 && Y_ROW[x] == 0.0) {
215 test_possible_centers_formula(x, y, weight, X_ROW[x], Y_ROW[x], outSum);
223 return unscale_point(maxP, eye, fast_eye_width);
240 dlib::full_object_detection object_detection) {
243 if (object_detection.num_parts() == 5) {
261 auto get_rectangle = [](dlib::point
one, dlib::point two)
264 double scale = (one - two).length() * 1.5;
265 return dlib::centered_rect(result, scale, scale);
268 return get_rectangle(object_detection.part(index_ex),
269 object_detection.part(index_en));
277 : relative_threshold_factor(0.3),
278 sigma_factor(0.005) {
279 YAML::Node config = util::get_config(this->number);
280 this->name = config[
"name"] ?
283 if (config[
"relative_threshold"]) {
284 this->relative_threshold_factor =
285 config[
"relative_threshold"]
286 .as<decltype(this->relative_threshold_factor)>();
298 face = face.intersect(
305 for (
int i = 0; i < 2; ++i) {
307 eye.set_left(eye.left() - face.left());
308 eye.set_right(eye.right() - face.left());
309 eye.set_top(eye.top() - face.top());
310 eye.set_bottom(eye.bottom() - face.top());
312 cv::Point pupil = eyelike::find_eye_center(face_mat,
313 util::dlib_to_cv(eye),
314 this->relative_threshold_factor, 50);
316 data.
centers[i] = util::cv_to_dlib(pupil);
328 dlib::point offset_x(5, 0);
329 dlib::point offset_y(0, 5);
331 dlib::extract_image_chips(data.
image,
336 dlib::array<dlib::array2d<dlib::bgr_pixel>> eyes(3);
337 dlib::assign_image(eyes[2], data.
image);
338 for (
auto i = decltype(data.
eyes.size()){0};
339 i < data.
eyes.size(); ++i) {
341 dlib::assign_image(eyes[i], data.
eyes[i]);
343 dlib::draw_line(eyes[i],
346 dlib::rgb_pixel(255, 0, 0));
347 dlib::draw_line(eyes[i],
350 dlib::rgb_pixel(255, 0, 0));
352 dlib::draw_line(eyes[2],
353 data.
centers[i] + offset_x + eye.tl_corner(),
354 data.
centers[i] - offset_x + eye.tl_corner(),
355 dlib::rgb_pixel(255, 0, 0));
356 dlib::draw_line(eyes[2],
357 data.
centers[i] + offset_y + eye.tl_corner(),
358 data.
centers[i] - offset_y + eye.tl_corner(),
359 dlib::rgb_pixel(255, 0, 0));
361 dlib::resize_image(0.5, eyes[2]);
363 this->widget->set_image(dlib::tile_images(eyes));
void minMaxLoc(InputArray src, double *minVal, double *maxVal=0, Point *minLoc=0, Point *maxLoc=0, InputArray mask=noArray())
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
dlib::rectangle get_eye_region(int eye, dlib::full_object_detection object_detection)
dlib::array< dlib::array2d< double > > eyes
dlib::array< dlib::point > centers
void rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
static MatExpr zeros(int rows, int cols, int type)
void magnitude(InputArray x, InputArray y, OutputArray magnitude)
dlib::array2d< dlib::bgr_pixel > image
_GLIBCXX14_CONSTEXPR const _Tp & max(const _Tp &__a, const _Tp &__b)
dlib::full_object_detection landmarks
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT)
Wraps the data acquired per frame into a single instance.
void meanStdDev(InputArray src, OutputArray mean, OutputArray stddev, InputArray mask=noArray())
_GLIBCXX14_CONSTEXPR const _Tp & min(const _Tp &__a, const _Tp &__b)
complex< _Tp > sqrt(const complex< _Tp > &)